/** * Sparse multivariate polynomial arithmetic over ℤ, backed by a * `Map` keyed by an encoded exponent vector. * * Convention: a `MultiPoly` fixes an ordered variable list `vars`; every * exponent vector has `vars.length` entries, one per variable in that order. * `terms` maps `key(exponents)` to the (always nonzero) coefficient — zero * coefficients are pruned on every construction/operation, so the zero * polynomial is represented by an empty map. * * This module is part of the multivariate factorization engine * (`functions/src/typed/factorization/`, Layer 2) and is `bigint`-only by * design, matching the univariate engine in `integer-poly.ts`. */ /** Sparse multivariate polynomial over ℤ. */ export interface MultiPoly { /** Ordered variable names; every exponent vector has this length. */ vars: string[]; /** Exponent-vector key -> nonzero coefficient. */ terms: Map; } /** Encodes an exponent vector as a stable map key (comma-joined). */ export declare function key(exps: number[]): string; /** Decodes a `key()`-encoded exponent vector back into numbers. */ export declare function unkey(k: string): number[]; /** * Builds a `MultiPoly` over `vars` from `(exponents, coefficient)` entries. * Entries sharing an exponent vector are summed; zero coefficients (after * summing) are pruned. */ export declare function fromTerms(vars: string[], entries: Array<[number[], bigint]>): MultiPoly; /** The degree of `p` in the variable at `varIndex` (max exponent across terms; -1 if zero). */ export declare function degreeIn(p: MultiPoly, varIndex: number): number; /** The total degree of `p` (max sum of exponents across terms; -1 if zero). */ export declare function totalDegree(p: MultiPoly): number; /** True iff `p` has no nonzero terms. */ export declare function isZero(p: MultiPoly): boolean; /** Structural equality: same `vars` (in order) and the same term map. */ export declare function equals(a: MultiPoly, b: MultiPoly): boolean; /** `a + b` (both over the same `vars`). */ export declare function addMP(a: MultiPoly, b: MultiPoly): MultiPoly; /** `a - b` (both over the same `vars`). */ export declare function subMP(a: MultiPoly, b: MultiPoly): MultiPoly; /** `a * b` (both over the same `vars`), via distributed convolution. */ export declare function mulMP(a: MultiPoly, b: MultiPoly): MultiPoly; /** `-p`. */ export declare function negMP(p: MultiPoly): MultiPoly; /** * Total monomial order used for canonicalizing multivariate polynomials: * degree-lex — higher total degree first, then lexicographic comparison of * the exponent vector (earlier variables weighted higher). Returns a * negative number if `expsA` sorts before `expsB` (i.e. `expsA` is the * "larger"/leading monomial), positive if after, 0 if equal. */ export declare function canonicalCompare(expsA: number[], expsB: number[]): number; /** * The leading term of `p` under `canonicalCompare`: the term whose exponent * vector sorts first. Returns `null` for the zero polynomial. */ export declare function leadingTerm(p: MultiPoly): { exps: number[]; coeff: bigint; } | null; /** Non-negative gcd of all coefficients of `p` (0 for the zero polynomial). */ export declare function integerContentMP(p: MultiPoly): bigint; /** * Primitive part of `p`: divide out `integerContentMP(p)`, then flip sign * so the leading term (under `canonicalCompare`) has a positive * coefficient. The zero polynomial maps to itself. */ export declare function primitivePartMP(p: MultiPoly): MultiPoly; /** * Multivariate polynomial long division: returns the quotient `a / b` iff * `b` divides `a` **exactly** over ℤ, else `null`. * * Repeatedly takes the `canonicalCompare`-leading term of the current * remainder and attempts to cancel it against `b`'s leading term: the * exponent vector must dominate `b`'s leading exponents component-wise, and * the coefficient must divide `b`'s leading coefficient exactly in ℤ (bigint * `%` gives an exact `0` remainder regardless of operand signs). Any failure * of either condition means the division is not exact — this function is the * recombination correctness arbiter and must never round or approximate. */ export declare function multiExactDivide(a: MultiPoly, b: MultiPoly): MultiPoly | null; /** * Parses `expr` over `vars` via algebra's exact `polyFromExpression`, then * lifts it to a bigint-backed {@link MultiPoly} — but only if EVERY * coefficient is an exact integer. Returns `null` on any non-integer * coefficient or if parsing throws (unknown symbol, non-integer exponent, * non-constant divisor, etc.). */ export declare function fromAlgebraExpr(expr: string, vars: string[]): MultiPoly | null; /** * Renders `p` back to an expression string in the SAME format as * `polynomial-ideal.polyToString` (term order, `*`/`^` spacing, `+ -` * collapsing, `1*x` unit-coefficient style) — but rendered directly from * `bigint` coefficients so values above 2^53 stay exact. Routing through * `polyToString` would require `Number(v)`, which silently rounds. */ export declare function toAlgebraString(p: MultiPoly): string; //# sourceMappingURL=multi-poly.d.ts.map