@danielsimonjr/mathts-functions 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1705 -399
- package/dist/typed/algebra.d.ts +23 -12
- package/dist/typed/algebra.d.ts.map +1 -1
- package/dist/typed/factorization/finite-field.d.ts +84 -0
- package/dist/typed/factorization/finite-field.d.ts.map +1 -0
- package/dist/typed/factorization/hensel.d.ts +38 -0
- package/dist/typed/factorization/hensel.d.ts.map +1 -0
- package/dist/typed/factorization/index.d.ts +72 -0
- package/dist/typed/factorization/index.d.ts.map +1 -0
- package/dist/typed/factorization/integer-poly.d.ts +82 -0
- package/dist/typed/factorization/integer-poly.d.ts.map +1 -0
- package/dist/typed/factorization/kronecker-factor.d.ts +48 -0
- package/dist/typed/factorization/kronecker-factor.d.ts.map +1 -0
- package/dist/typed/factorization/kronecker.d.ts +65 -0
- package/dist/typed/factorization/kronecker.d.ts.map +1 -0
- package/dist/typed/factorization/multi-poly.d.ts +107 -0
- package/dist/typed/factorization/multi-poly.d.ts.map +1 -0
- package/dist/typed/factorization/square-free.d.ts +37 -0
- package/dist/typed/factorization/square-free.d.ts.map +1 -0
- package/dist/typed/factorization/zassenhaus.d.ts +36 -0
- package/dist/typed/factorization/zassenhaus.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/typed/algebra.d.ts
CHANGED
|
@@ -218,18 +218,29 @@ export declare function expand(expr: string): string;
|
|
|
218
218
|
* Factor an expression string.
|
|
219
219
|
*
|
|
220
220
|
* **Univariate polynomials** (a single variable, integer coefficients,
|
|
221
|
-
* degree ≥ 2) are factored over
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* `factor('x^2-1')` → `'(x - 1)*(x + 1)'
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* into irreducible factors
|
|
232
|
-
*
|
|
221
|
+
* degree ≥ 2) are factored **completely over ℤ/ℚ** into irreducible factors
|
|
222
|
+
* with multiplicity. Rational linear roots are extracted first (rational-root
|
|
223
|
+
* theorem); any higher-degree remainder — and any polynomial with no rational
|
|
224
|
+
* root — is routed through the Zassenhaus engine
|
|
225
|
+
* ({@link factorPolynomialUnivariate}): `factor('x^2-1')` → `'(x - 1)*(x + 1)'`,
|
|
226
|
+
* `factor('x^4-1')` → `'(x - 1)*(x + 1)*(x^2 + 1)'`,
|
|
227
|
+
* `factor('x^4+3*x^2+2')` → `'(x^2 + 1)*(x^2 + 2)'`. Polynomials irreducible
|
|
228
|
+
* over ℚ (`x^4 + 1`, `x^2 + x + 1`) are returned unchanged.
|
|
229
|
+
*
|
|
230
|
+
* **Multivariate polynomials** (`n ≥ 2` variables, integer coefficients) are
|
|
231
|
+
* factored **completely over ℤ/ℚ** into irreducible factors. A fast path (see
|
|
232
|
+
* {@link factorMultivariate}) handles the common cases byte-for-byte — integer
|
|
233
|
+
* content, common-monomial extraction, monomial difference-of-squares
|
|
234
|
+
* (`x^2*y + x*y^2 → 'x*y*(1*y + 1*x)'`, `4*x^2 - 9*y^2 → '(2*x - 3*y)*(2*x + 3*y)'`).
|
|
235
|
+
* Anything the fast path leaves whole or only partially factored is routed
|
|
236
|
+
* through the Kronecker-substitution engine ({@link factorMultivariateString}),
|
|
237
|
+
* which reduces to the univariate ℤ engine and recombines by exact division
|
|
238
|
+
* (`x^2 + 3*x*y + 4*x + 2*y^2 + 5*y + 3 → (1*x + 1*y + 1)*(1*x + 2*y + 3)`). The
|
|
239
|
+
* engine declines (and the caller keeps the fast-path/legacy output) beyond a
|
|
240
|
+
* substituted-degree cap; irreducible multivariate polynomials (`x^2 + y^2`) are
|
|
241
|
+
* returned unchanged. Wang/EEZ is a future performance upgrade, not a
|
|
242
|
+
* capability gap. Because the engine confirms every factor by division, it never
|
|
243
|
+
* emits a wrong factorization.
|
|
233
244
|
*
|
|
234
245
|
* Everything else (no rational root, no common factor) falls back to the
|
|
235
246
|
* original common-integer-factor extraction below.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"algebra.d.ts","sourceRoot":"","sources":["../../src/typed/algebra.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"algebra.d.ts","sourceRoot":"","sources":["../../src/typed/algebra.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dense univariate polynomial arithmetic over the finite field 𝔽_p, backed
|
|
3
|
+
* by the same `bigint[]` representation as `integer-poly.ts` (index =
|
|
4
|
+
* degree). Every coefficient produced by an operation in this module is
|
|
5
|
+
* kept reduced into the canonical range `[0, p)` and trimmed so the
|
|
6
|
+
* highest-degree entry (if any) is nonzero.
|
|
7
|
+
*
|
|
8
|
+
* This module is part of the univariate factorization engine
|
|
9
|
+
* (`functions/src/typed/factorization/`) and is `bigint`-only by design.
|
|
10
|
+
*/
|
|
11
|
+
import { type IntPoly } from './integer-poly.js';
|
|
12
|
+
export type { IntPoly } from './integer-poly.js';
|
|
13
|
+
/**
|
|
14
|
+
* Reduces every coefficient of `a` into `[0, p)`, then trims trailing
|
|
15
|
+
* (highest-degree) zero coefficients. Does not mutate the input.
|
|
16
|
+
*/
|
|
17
|
+
export declare function reduceModP(a: IntPoly, p: bigint): IntPoly;
|
|
18
|
+
/** `a + b` over 𝔽_p, coefficients reduced into `[0, p)`. */
|
|
19
|
+
export declare function addP(a: IntPoly, b: IntPoly, p: bigint): IntPoly;
|
|
20
|
+
/** `a - b` over 𝔽_p, coefficients reduced into `[0, p)`. */
|
|
21
|
+
export declare function subP(a: IntPoly, b: IntPoly, p: bigint): IntPoly;
|
|
22
|
+
/** `a * b` over 𝔽_p via schoolbook convolution, coefficients in `[0, p)`. */
|
|
23
|
+
export declare function mulP(a: IntPoly, b: IntPoly, p: bigint): IntPoly;
|
|
24
|
+
/**
|
|
25
|
+
* Modular inverse of a scalar `a` modulo prime `p`, via the extended
|
|
26
|
+
* Euclidean algorithm. Returns a value in `[1, p)`. Throws if `a ≡ 0 (mod p)`
|
|
27
|
+
* (no inverse exists).
|
|
28
|
+
*/
|
|
29
|
+
export declare function invModP(a: bigint, p: bigint): bigint;
|
|
30
|
+
/**
|
|
31
|
+
* Scales `a` so its leading coefficient becomes 1 (multiplies by
|
|
32
|
+
* `invModP(lc(a), p)`). Returns `[]` unchanged for the zero polynomial.
|
|
33
|
+
*/
|
|
34
|
+
export declare function makeMonicP(a: IntPoly, p: bigint): IntPoly;
|
|
35
|
+
/**
|
|
36
|
+
* Polynomial division over 𝔽_p: `a = q*b + r` with `deg(r) < deg(b)`.
|
|
37
|
+
* `b` must be nonzero. Coefficients of `q` and `r` are reduced into `[0, p)`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function divmodP(a: IntPoly, b: IntPoly, p: bigint): {
|
|
40
|
+
q: IntPoly;
|
|
41
|
+
r: IntPoly;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Monic gcd of `a` and `b` over 𝔽_p via the Euclidean algorithm. Returns
|
|
45
|
+
* `[]` (zero polynomial) only when both inputs are zero; otherwise the
|
|
46
|
+
* result is monic (leading coefficient 1).
|
|
47
|
+
*/
|
|
48
|
+
export declare function gcdP(a: IntPoly, b: IntPoly, p: bigint): IntPoly;
|
|
49
|
+
/**
|
|
50
|
+
* `base^e mod (mod, p)`: modular exponentiation of `base` by non-negative
|
|
51
|
+
* bigint `e`, reducing modulo the polynomial `mod` (via `divmodP`) and
|
|
52
|
+
* modulo `p` at each step, using square-and-multiply. `e` must be >= 0.
|
|
53
|
+
*/
|
|
54
|
+
export declare function powModPolyP(base: IntPoly, e: bigint, mod: IntPoly, p: bigint): IntPoly;
|
|
55
|
+
/**
|
|
56
|
+
* Distinct-degree factorization of a monic, square-free polynomial `f` over
|
|
57
|
+
* 𝔽_p. Returns the distinct-degree decomposition: each entry's `prod` is the
|
|
58
|
+
* product of ALL monic irreducible factors of `f` that have degree exactly
|
|
59
|
+
* `deg`. Uses the standard algorithm built on `x^(p^i) mod f` computed via
|
|
60
|
+
* `powModPolyP`, peeling off `gcd(v, x^(p^i) - x)` at each step and shrinking
|
|
61
|
+
* the working polynomial `v` as factors are removed.
|
|
62
|
+
*
|
|
63
|
+
* Precondition: `f` is monic and square-free over 𝔽_p. The empty array is
|
|
64
|
+
* returned for a constant (degree ≤ 0) input.
|
|
65
|
+
*/
|
|
66
|
+
export declare function distinctDegreeFactor(f: IntPoly, p: bigint): Array<{
|
|
67
|
+
deg: number;
|
|
68
|
+
prod: IntPoly;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* Equal-degree factorization (Cantor–Zassenhaus): given a monic, square-free
|
|
72
|
+
* `f` that is a product of degree-`d` irreducibles over 𝔽_p, returns those
|
|
73
|
+
* monic irreducible factors. The candidate polynomials are enumerated
|
|
74
|
+
* deterministically (see `trialPolys`), so the factorization is reproducible.
|
|
75
|
+
*/
|
|
76
|
+
export declare function equalDegreeFactor(f: IntPoly, d: number, p: bigint): IntPoly[];
|
|
77
|
+
/**
|
|
78
|
+
* Full factorization of a square-free monic polynomial `f` over 𝔽_p into its
|
|
79
|
+
* monic irreducible factors: distinct-degree decomposition followed by
|
|
80
|
+
* Cantor–Zassenhaus equal-degree splitting of each degree class. Constant
|
|
81
|
+
* (degree ≤ 0) inputs yield the empty array; a linear input yields itself.
|
|
82
|
+
*/
|
|
83
|
+
export declare function factorModP(f: IntPoly, p: bigint): IntPoly[];
|
|
84
|
+
//# sourceMappingURL=finite-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finite-field.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/finite-field.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE3E,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAQjD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,6DAA6D;AAC7D,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAS/D;AAED,6DAA6D;AAC7D,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAS/D;AAED,8EAA8E;AAC9E,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAe/D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBpD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,OAAO,CAAA;CAAE,CAqBrF;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAe/D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAetF;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBjG;AAyED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAI7E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAoB3D"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multifactor Hensel lifting for the univariate factorization engine
|
|
3
|
+
* (`functions/src/typed/factorization/`).
|
|
4
|
+
*
|
|
5
|
+
* Given a MONIC integer polynomial `f` and its MONIC irreducible factors over
|
|
6
|
+
* 𝔽_p (whose product is ≡ f mod p), lift that factorization to a factorization
|
|
7
|
+
* modulo `p^k` whose product is ≡ f (mod p^k), with each lifted factor still
|
|
8
|
+
* ≡ its input factor (mod p). The target modulus `p^k` is chosen by the caller
|
|
9
|
+
* so that `p^k ≥ 2·landauMignotte(f)+1`, i.e. large enough that the true
|
|
10
|
+
* integer factors of `f` are uniquely recovered by symmetric reduction.
|
|
11
|
+
*
|
|
12
|
+
* Strategy: LINEAR (iterated) two-factor Hensel lifting from `p^i` to `p^{i+1}`
|
|
13
|
+
* up to `p^k`, combined with a recursive FACTOR TREE for more than two factors.
|
|
14
|
+
* Bézout cofactors `s, t` with `s·g + t·h ≡ 1 (mod p)` are computed once per
|
|
15
|
+
* two-factor split via the extended Euclidean algorithm over 𝔽_p; because the
|
|
16
|
+
* per-step diophantine correction is solved only mod p, the fixed mod-p
|
|
17
|
+
* cofactors remain valid at every lifting step (the standard property of linear
|
|
18
|
+
* Hensel lifting — see Geddes/Czapor/Labahn §6.4 or von zur Gathen & Gerhard
|
|
19
|
+
* §15). All factors are monic and `f` is monic, so the lifted factors stay
|
|
20
|
+
* monic and no leading-coefficient imposition is required.
|
|
21
|
+
*
|
|
22
|
+
* `bigint`-only by design: float64 loses correctness once `p^k > 2^53`.
|
|
23
|
+
*/
|
|
24
|
+
import { type IntPoly } from './integer-poly.js';
|
|
25
|
+
/**
|
|
26
|
+
* Multifactor Hensel lift. Lifts the mod-`p` factorization `factorsModP` of the
|
|
27
|
+
* monic integer polynomial `f` (with `∏ factorsModP ≡ f mod p`) to monic
|
|
28
|
+
* integer factors whose product is `≡ f (mod targetPk)` and each of which is
|
|
29
|
+
* `≡ its input factor (mod p)`. Coefficients are returned in the symmetric
|
|
30
|
+
* range modulo `targetPk = p^k` (via `modSymmetric`).
|
|
31
|
+
*
|
|
32
|
+
* More than two factors are handled by a recursive factor tree: `factorsModP`
|
|
33
|
+
* is split into two halves, the two half-products are lifted together by
|
|
34
|
+
* `henselLiftTwo`, and each lifted half is recursively split into its own
|
|
35
|
+
* factors.
|
|
36
|
+
*/
|
|
37
|
+
export declare function henselLift(f: IntPoly, factorsModP: IntPoly[], p: bigint, targetPk: bigint): IntPoly[];
|
|
38
|
+
//# sourceMappingURL=hensel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hensel.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/hensel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAQL,KAAK,OAAO,EACb,MAAM,mBAAmB,CAAC;AA8H3B;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,CAAC,EAAE,OAAO,EACV,WAAW,EAAE,OAAO,EAAE,EACtB,CAAC,EAAE,MAAM,EACT,QAAQ,EAAE,MAAM,GACf,OAAO,EAAE,CAmBX"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry point of the univariate factorization engine: parse an
|
|
3
|
+
* expression string into an integer polynomial, run the Zassenhaus pipeline
|
|
4
|
+
* (`factorUnivariateZ`), and render the irreducible factorization back to a
|
|
5
|
+
* string that matches `algebra.ts`'s `factor()` output conventions.
|
|
6
|
+
*
|
|
7
|
+
* This module is deliberately self-contained (it does not import `algebra.ts`)
|
|
8
|
+
* so wiring it into `factor()` introduces no import cycle. It reuses the shared
|
|
9
|
+
* polynomial parser from `../polynomial-ideal.js` and the `bigint` engine from
|
|
10
|
+
* this directory.
|
|
11
|
+
*
|
|
12
|
+
* Part of the univariate factorization engine
|
|
13
|
+
* (`functions/src/typed/factorization/`).
|
|
14
|
+
*/
|
|
15
|
+
import { type IntPoly } from './integer-poly.js';
|
|
16
|
+
/**
|
|
17
|
+
* Render a dense integer-coefficient univariate polynomial as a bare (no outer
|
|
18
|
+
* parentheses) human-readable string with the repo's spacing/`*`/`^` style and
|
|
19
|
+
* unit coefficients elided: `[1,0,1] → "x^2 + 1"`, `[-1,0,2] → "2*x^2 - 1"`.
|
|
20
|
+
* Coefficients are rounded for display; zero terms are omitted. Exported so
|
|
21
|
+
* `algebra.ts` can render an unfactorable higher-degree remainder consistently.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cleanUnivariatePoly(coeffs: number[], v: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Render one irreducible factor: linears via {@link renderLinearFactor},
|
|
26
|
+
* higher via {@link renderIntPoly} (bigint-native — see its doc comment for
|
|
27
|
+
* why this must not go through `Number()`) wrapped in parentheses. Exported
|
|
28
|
+
* for direct unit testing of the bigint-fidelity path.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderFactor(poly: IntPoly, v: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Factor a univariate integer polynomial given as an expression string into
|
|
33
|
+
* its irreducible factors over ℤ/ℚ, rendered to a `*`-joined string matching
|
|
34
|
+
* `factor()`'s conventions (constant prefix when ≠ 1, degree-1 factors via the
|
|
35
|
+
* linear formatter, degree ≥ 2 factors wrapped in parentheses, repeated factors
|
|
36
|
+
* for multiplicity > 1).
|
|
37
|
+
*
|
|
38
|
+
* Returns `null` when the input is not an integer polynomial in `v` (parse
|
|
39
|
+
* failure, another variable, non-integer coefficients, degree < 1) OR when the
|
|
40
|
+
* polynomial is already irreducible over ℚ (a single primitive factor with
|
|
41
|
+
* multiplicity 1) — in that "nothing gained" case the caller keeps its existing
|
|
42
|
+
* behavior (leaving the expression whole / doing plain content extraction).
|
|
43
|
+
* Factor order is `factorUnivariateZ`'s deterministic (degree, coefficients)
|
|
44
|
+
* order.
|
|
45
|
+
*/
|
|
46
|
+
export declare function factorPolynomialUnivariate(expr: string, v: string): string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Factor a MULTIVARIATE (`n ≥ 2` variable) integer polynomial given as an
|
|
49
|
+
* expression string, completely over ℤ/ℚ via the Kronecker-substitution engine
|
|
50
|
+
* ({@link factorMultivariateKronecker}), rendered to a string matching
|
|
51
|
+
* `factor()`'s multivariate conventions.
|
|
52
|
+
*
|
|
53
|
+
* Returns `null` when the input is not an integer multivariate polynomial in
|
|
54
|
+
* `vars` (parse failure, non-integer coefficients, single variable, constant,
|
|
55
|
+
* or the degree cap is exceeded — the engine declines) OR when the
|
|
56
|
+
* factorization is not worth substituting for the caller's current output.
|
|
57
|
+
*
|
|
58
|
+
* The "worth it" threshold is `minFactors` (default 2): a result is returned
|
|
59
|
+
* only when it has at least `minFactors` irreducible POLYNOMIAL factors.
|
|
60
|
+
* - Default (the caller's fast path already declined): require ≥ 2 factors —
|
|
61
|
+
* a genuine multi-factor factorization. A single polynomial factor (an
|
|
62
|
+
* irreducible, or a bare integer-content extraction like `2·(3x + 2y)`) is
|
|
63
|
+
* declined so the caller's legacy content-extraction path keeps its exact
|
|
64
|
+
* byte output; the Kronecker rendering's monomial order differs and must not
|
|
65
|
+
* override that contract.
|
|
66
|
+
* - Provided (the caller's fast path produced a partial factorization with
|
|
67
|
+
* `minFactors − 1` irreducible factors): return a result ONLY if it has at
|
|
68
|
+
* least `minFactors` factors, i.e. the engine strictly refined a reducible
|
|
69
|
+
* cofactor the fast path left whole.
|
|
70
|
+
*/
|
|
71
|
+
export declare function factorMultivariateString(expr: string, vars: string[], minFactors?: number): string | null;
|
|
72
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAwBzD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBvE;AA8CD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0BjF;AAmBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,SAAI,GACb,MAAM,GAAG,IAAI,CAQf"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dense univariate polynomial arithmetic over ℤ, backed by `bigint[]`.
|
|
3
|
+
*
|
|
4
|
+
* Convention: index = degree (coefficient of x^i lives at index i).
|
|
5
|
+
* `[]` denotes the zero polynomial. After `trim`, the last entry (highest
|
|
6
|
+
* degree) is guaranteed nonzero. `degree([])` is -1 by convention.
|
|
7
|
+
*
|
|
8
|
+
* This module is part of the univariate factorization engine
|
|
9
|
+
* (`functions/src/typed/factorization/`) and is `bigint`-only by design:
|
|
10
|
+
* float64 loses correctness once coefficients exceed 2^53 during Hensel
|
|
11
|
+
* lifting to p^k.
|
|
12
|
+
*/
|
|
13
|
+
/** Dense polynomial over ℤ: index i holds the coefficient of x^i. */
|
|
14
|
+
export type IntPoly = bigint[];
|
|
15
|
+
/**
|
|
16
|
+
* Removes trailing (highest-degree) zero coefficients so the last entry
|
|
17
|
+
* (if any) is nonzero. Does not mutate the input.
|
|
18
|
+
*/
|
|
19
|
+
export declare function trim(p: IntPoly): IntPoly;
|
|
20
|
+
/** Degree of `p`; the zero polynomial has degree -1 by convention. */
|
|
21
|
+
export declare function degree(p: IntPoly): number;
|
|
22
|
+
/** Leading coefficient of `p` (0n for the zero polynomial). */
|
|
23
|
+
export declare function lc(p: IntPoly): bigint;
|
|
24
|
+
/** True iff `p` is the zero polynomial (ignoring trailing zero padding). */
|
|
25
|
+
export declare function isZero(p: IntPoly): boolean;
|
|
26
|
+
/** `a + b`, trimmed. */
|
|
27
|
+
export declare function add(a: IntPoly, b: IntPoly): IntPoly;
|
|
28
|
+
/** `a - b`, trimmed. */
|
|
29
|
+
export declare function sub(a: IntPoly, b: IntPoly): IntPoly;
|
|
30
|
+
/** `-a`, trimmed. */
|
|
31
|
+
export declare function neg(a: IntPoly): IntPoly;
|
|
32
|
+
/** `a * b` via the schoolbook convolution, trimmed. */
|
|
33
|
+
export declare function mul(a: IntPoly, b: IntPoly): IntPoly;
|
|
34
|
+
/** `p * k` for a scalar `k: bigint`, trimmed. */
|
|
35
|
+
export declare function scalarMul(p: IntPoly, k: bigint): IntPoly;
|
|
36
|
+
/** Structural equality after trimming (so trailing-zero padding is ignored). */
|
|
37
|
+
export declare function equals(a: IntPoly, b: IntPoly): boolean;
|
|
38
|
+
/** Evaluates `p(x)` at a bigint `x` via Horner's method. */
|
|
39
|
+
export declare function evaluate(p: IntPoly, x: bigint): bigint;
|
|
40
|
+
/** Non-negative gcd of two bigints (gcd(0,0) = 0). */
|
|
41
|
+
export declare function bigintGcd(a: bigint, b: bigint): bigint;
|
|
42
|
+
/** Content of `p`: the non-negative gcd of its (trimmed) coefficients. */
|
|
43
|
+
export declare function content(p: IntPoly): bigint;
|
|
44
|
+
/**
|
|
45
|
+
* Primitive part of `p`: divide out the content, then flip sign so the
|
|
46
|
+
* leading coefficient is positive. The zero polynomial maps to itself.
|
|
47
|
+
*/
|
|
48
|
+
export declare function primitivePart(p: IntPoly): IntPoly;
|
|
49
|
+
/**
|
|
50
|
+
* Exact polynomial quotient `a / b` over ℤ: performs schoolbook long division
|
|
51
|
+
* and returns the quotient only if the remainder is exactly zero AND every
|
|
52
|
+
* intermediate coefficient division was integral (no rounding). Returns
|
|
53
|
+
* `null` whenever `b` does not divide `a` exactly over ℤ. This is the
|
|
54
|
+
* recombination correctness test used by subset factor-recombination —
|
|
55
|
+
* it must never silently round.
|
|
56
|
+
*/
|
|
57
|
+
export declare function exactDivide(a: IntPoly, b: IntPoly): IntPoly | null;
|
|
58
|
+
/** Formal derivative `p'` over ℤ: coefficient i*p[i] at index i-1. */
|
|
59
|
+
export declare function derivative(p: IntPoly): IntPoly;
|
|
60
|
+
/**
|
|
61
|
+
* Gcd of two polynomials over ℤ via the Euclidean pseudo-remainder sequence
|
|
62
|
+
* (stays in ℤ throughout via pseudo-division), returned as a primitive
|
|
63
|
+
* polynomial with positive leading coefficient. `gcd(0, b) = primitivePart(b)`
|
|
64
|
+
* and symmetrically for `gcd(a, 0)`; `gcd(0,0) = []`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function polyGcdZ(a: IntPoly, b: IntPoly): IntPoly;
|
|
67
|
+
/**
|
|
68
|
+
* Landau–Mignotte coefficient bound: any integer factor of `p` has all
|
|
69
|
+
* coefficients bounded in absolute value by this quantity. Uses the
|
|
70
|
+
* generous form `ceil(sqrt(deg+1) * 2^deg * |lc(p)|)`, computed entirely
|
|
71
|
+
* with bigint integer arithmetic (integer sqrt rounded UP so the bound
|
|
72
|
+
* stays safe/over-estimating). Always positive.
|
|
73
|
+
*/
|
|
74
|
+
export declare function landauMignotte(p: IntPoly): bigint;
|
|
75
|
+
/**
|
|
76
|
+
* Reduces every coefficient of `p` into the symmetric residue range
|
|
77
|
+
* `(-m/2, m/2]` modulo `m`. `m` must be a positive modulus. Coefficient
|
|
78
|
+
* count is preserved (no trailing-zero trim) — a coefficient that reduces
|
|
79
|
+
* to 0 mod `m` stays as an explicit 0 at its original index.
|
|
80
|
+
*/
|
|
81
|
+
export declare function modSymmetric(p: IntPoly, m: bigint): IntPoly;
|
|
82
|
+
//# sourceMappingURL=integer-poly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integer-poly.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/integer-poly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qEAAqE;AACrE,MAAM,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAMxC;AAED,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAGzC;AAED,+DAA+D;AAC/D,wBAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAGrC;AAED,4EAA4E;AAC5E,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE1C;AAED,wBAAwB;AACxB,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CASnD;AAED,wBAAwB;AACxB,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CASnD;AAED,qBAAqB;AACrB,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEvC;AAED,uDAAuD;AACvD,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAenD;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,gFAAgF;AAChF,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAQtD;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAStD;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAO1C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAYjD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAmClE;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAU9C;AAyBD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAkBxD;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAejD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAa3D"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multivariate factorization over ℤ via Kronecker substitution (Layer 2 v1).
|
|
3
|
+
*
|
|
4
|
+
* The orchestration ties three shipped pieces together:
|
|
5
|
+
* 1. Kronecker substitution (`kronecker.ts`) collapses an `n ≥ 2` variable
|
|
6
|
+
* integer polynomial to a single univariate image whose monomials are in
|
|
7
|
+
* bijection with the original's (mixed-radix place values).
|
|
8
|
+
* 2. The univariate Zassenhaus engine (`zassenhaus.ts`) factors that image
|
|
9
|
+
* into irreducibles over ℤ.
|
|
10
|
+
* 3. Subset recombination lifts each univariate irreducible (or product of
|
|
11
|
+
* several) back to a multivariate candidate and confirms it by EXACT
|
|
12
|
+
* multivariate division (`multiExactDivide`) — division is the sole
|
|
13
|
+
* arbiter, so no unverified factor is ever emitted.
|
|
14
|
+
*
|
|
15
|
+
* Correctness follows because (a) every true multivariate factor's image is a
|
|
16
|
+
* subset of the univariate factors, so recombination is complete up to the
|
|
17
|
+
* caps, and (b) division confirms each candidate, so recombination is sound.
|
|
18
|
+
*
|
|
19
|
+
* Two caps bound the work (each logs, never returns a silently wrong answer):
|
|
20
|
+
* - `KRONECKER_MAX_DEGREE` on the substituted univariate degree
|
|
21
|
+
* (`∏(degᵢ+1) − 1`), the Kronecker analogue of Layer 1's factor-count cap.
|
|
22
|
+
* - `MAX_MODULAR_FACTORS` on the univariate factor-pool size, matching
|
|
23
|
+
* Layer 1's recombination cap.
|
|
24
|
+
*
|
|
25
|
+
* `bigint`-only, matching the rest of the factorization engine.
|
|
26
|
+
*/
|
|
27
|
+
import { type MultiPoly } from './multi-poly.js';
|
|
28
|
+
/** Complete multivariate factorization: `p = constant · ∏ factorsᵢ^multᵢ`. */
|
|
29
|
+
export type MultiFactorization = {
|
|
30
|
+
constant: bigint;
|
|
31
|
+
factors: Array<{
|
|
32
|
+
poly: MultiPoly;
|
|
33
|
+
mult: number;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Factors a multivariate (`n ≥ 2` variables) integer polynomial completely
|
|
38
|
+
* over ℤ into irreducible factors with multiplicity, via Kronecker
|
|
39
|
+
* substitution onto the Layer 1 univariate engine.
|
|
40
|
+
*
|
|
41
|
+
* Returns `null` (declines) when it cannot help — a single variable, the zero
|
|
42
|
+
* or a constant polynomial, or the substituted degree exceeding the cap — so
|
|
43
|
+
* the caller keeps its existing behavior. On success the constant carries the
|
|
44
|
+
* signed integer content and every factor has a positive leading term under
|
|
45
|
+
* the canonical (degree-lex) monomial order.
|
|
46
|
+
*/
|
|
47
|
+
export declare function factorMultivariateKronecker(p: MultiPoly): MultiFactorization | null;
|
|
48
|
+
//# sourceMappingURL=kronecker-factor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kronecker-factor.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/kronecker-factor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAUL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAKzB,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD,CAAC;AA4GF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,SAAS,GAAG,kBAAkB,GAAG,IAAI,CA0HnF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kronecker substitution: reduces a multivariate integer polynomial to a
|
|
3
|
+
* univariate one so it can be factored by the Layer 1 univariate engine
|
|
4
|
+
* (`zassenhaus.ts`), then inverts the map to recover multivariate
|
|
5
|
+
* candidates.
|
|
6
|
+
*
|
|
7
|
+
* The substitution maps `x_k ↦ x^{bases[k]}`, where `bases[0] = 1` and
|
|
8
|
+
* `bases[k] = ∏_{i<k} (degreeIn(p, i) + 1)`. Every monomial
|
|
9
|
+
* `∏_i x_i^{e_i}` then lands at the distinct univariate degree
|
|
10
|
+
* `Σ_i e_i · bases[i]` — distinct because the bases form the place values of
|
|
11
|
+
* a mixed-radix numeral system with radix `degreeIn(p, i) + 1` at position
|
|
12
|
+
* `i`, so no two exponent vectors bounded by the original per-variable
|
|
13
|
+
* degrees can collide. This is what makes the map invertible via
|
|
14
|
+
* {@link backSubstitute}.
|
|
15
|
+
*
|
|
16
|
+
* `bigint`-only per the Layer 2 factorization engine's constraints; the
|
|
17
|
+
* univariate degree used as an array index is a `Number`, guarded against
|
|
18
|
+
* exceeding `Number.MAX_SAFE_INTEGER` before conversion.
|
|
19
|
+
*/
|
|
20
|
+
import { type MultiPoly } from './multi-poly.js';
|
|
21
|
+
import { type IntPoly } from './integer-poly.js';
|
|
22
|
+
/**
|
|
23
|
+
* One substitution base per variable of `p`: `bases[0] = 1`,
|
|
24
|
+
* `bases[k] = ∏_{i<k} (degreeIn(p, i) + 1)`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function substitutionBases(p: MultiPoly): bigint[];
|
|
27
|
+
/**
|
|
28
|
+
* The univariate degree that the substitution `x_k ↦ x^{bases[k]}` sends
|
|
29
|
+
* `p`'s highest-degree corner monomial to: `Σ_i degreeIn(p, i) · bases[i]`.
|
|
30
|
+
* Callers use this (as a `bigint`) to enforce a degree cap BEFORE calling
|
|
31
|
+
* {@link substitute}, which throws if this bound exceeds
|
|
32
|
+
* `Number.MAX_SAFE_INTEGER`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function substitutedDegree(p: MultiPoly, bases: bigint[]): bigint;
|
|
35
|
+
/**
|
|
36
|
+
* Applies the Kronecker substitution `x_k ↦ x^{bases[k]}` to `p`, producing
|
|
37
|
+
* the univariate image as a dense `IntPoly`. Each term's coefficient is
|
|
38
|
+
* placed at univariate degree `Σ_i e_i · bases[i]` (summed with any other
|
|
39
|
+
* term landing at the same degree, though the mixed-radix construction of
|
|
40
|
+
* `bases` guarantees that never happens for exponents within `p`'s own
|
|
41
|
+
* degrees).
|
|
42
|
+
*
|
|
43
|
+
* Throws `RangeError` if the maximum possible substituted degree exceeds
|
|
44
|
+
* `Number.MAX_SAFE_INTEGER` (the array index cannot represent it exactly).
|
|
45
|
+
* Callers should apply the `KRONECKER_MAX_DEGREE` cap via
|
|
46
|
+
* {@link substitutedDegree} before calling this, so this throw is a defensive
|
|
47
|
+
* backstop, not the primary cap enforcement.
|
|
48
|
+
*/
|
|
49
|
+
export declare function substitute(p: MultiPoly, bases: bigint[]): IntPoly;
|
|
50
|
+
/**
|
|
51
|
+
* Inverts {@link substitute}: recovers the `MultiPoly` whose Kronecker image
|
|
52
|
+
* is `u`, given the same `bases` and the ORIGINAL polynomial's per-variable
|
|
53
|
+
* degree bounds `degBounds`.
|
|
54
|
+
*
|
|
55
|
+
* Each nonzero univariate coefficient at degree `e` is decomposed by
|
|
56
|
+
* mixed-radix division — radix `degBounds[i] + 1` at position `i` — into an
|
|
57
|
+
* exponent vector. If `e` doesn't fit within the mixed-radix system sized by
|
|
58
|
+
* `degBounds` (a nonzero remainder after the top digit), the decomposition is
|
|
59
|
+
* an out-of-range carry: `e` cannot correspond to a genuine exponent vector
|
|
60
|
+
* bounded by `degBounds`, so this returns `null` rather than a bogus
|
|
61
|
+
* `MultiPoly`. This is the guard that rejects spurious univariate factors
|
|
62
|
+
* during Kronecker recombination.
|
|
63
|
+
*/
|
|
64
|
+
export declare function backSubstitute(u: IntPoly, bases: bigint[], degBounds: number[], vars: string[]): MultiPoly | null;
|
|
65
|
+
//# sourceMappingURL=kronecker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kronecker.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/kronecker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,EAAE,CAWxD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAQvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAmBjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,OAAO,EACV,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,MAAM,EAAE,GACb,SAAS,GAAG,IAAI,CAsBlB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sparse multivariate polynomial arithmetic over ℤ, backed by a
|
|
3
|
+
* `Map<string, bigint>` keyed by an encoded exponent vector.
|
|
4
|
+
*
|
|
5
|
+
* Convention: a `MultiPoly` fixes an ordered variable list `vars`; every
|
|
6
|
+
* exponent vector has `vars.length` entries, one per variable in that order.
|
|
7
|
+
* `terms` maps `key(exponents)` to the (always nonzero) coefficient — zero
|
|
8
|
+
* coefficients are pruned on every construction/operation, so the zero
|
|
9
|
+
* polynomial is represented by an empty map.
|
|
10
|
+
*
|
|
11
|
+
* This module is part of the multivariate factorization engine
|
|
12
|
+
* (`functions/src/typed/factorization/`, Layer 2) and is `bigint`-only by
|
|
13
|
+
* design, matching the univariate engine in `integer-poly.ts`.
|
|
14
|
+
*/
|
|
15
|
+
/** Sparse multivariate polynomial over ℤ. */
|
|
16
|
+
export interface MultiPoly {
|
|
17
|
+
/** Ordered variable names; every exponent vector has this length. */
|
|
18
|
+
vars: string[];
|
|
19
|
+
/** Exponent-vector key -> nonzero coefficient. */
|
|
20
|
+
terms: Map<string, bigint>;
|
|
21
|
+
}
|
|
22
|
+
/** Encodes an exponent vector as a stable map key (comma-joined). */
|
|
23
|
+
export declare function key(exps: number[]): string;
|
|
24
|
+
/** Decodes a `key()`-encoded exponent vector back into numbers. */
|
|
25
|
+
export declare function unkey(k: string): number[];
|
|
26
|
+
/** The zero polynomial over `vars`. */
|
|
27
|
+
export declare function zeroPoly(vars: string[]): MultiPoly;
|
|
28
|
+
/** The constant polynomial `c` over `vars` (zero exponents throughout). */
|
|
29
|
+
export declare function constPoly(vars: string[], c: bigint): MultiPoly;
|
|
30
|
+
/**
|
|
31
|
+
* Builds a `MultiPoly` over `vars` from `(exponents, coefficient)` entries.
|
|
32
|
+
* Entries sharing an exponent vector are summed; zero coefficients (after
|
|
33
|
+
* summing) are pruned.
|
|
34
|
+
*/
|
|
35
|
+
export declare function fromTerms(vars: string[], entries: Array<[number[], bigint]>): MultiPoly;
|
|
36
|
+
/** The degree of `p` in the variable at `varIndex` (max exponent across terms; -1 if zero). */
|
|
37
|
+
export declare function degreeIn(p: MultiPoly, varIndex: number): number;
|
|
38
|
+
/** The total degree of `p` (max sum of exponents across terms; -1 if zero). */
|
|
39
|
+
export declare function totalDegree(p: MultiPoly): number;
|
|
40
|
+
/** True iff `p` has no nonzero terms. */
|
|
41
|
+
export declare function isZero(p: MultiPoly): boolean;
|
|
42
|
+
/** Structural equality: same `vars` (in order) and the same term map. */
|
|
43
|
+
export declare function equals(a: MultiPoly, b: MultiPoly): boolean;
|
|
44
|
+
/** `a + b` (both over the same `vars`). */
|
|
45
|
+
export declare function addMP(a: MultiPoly, b: MultiPoly): MultiPoly;
|
|
46
|
+
/** `a - b` (both over the same `vars`). */
|
|
47
|
+
export declare function subMP(a: MultiPoly, b: MultiPoly): MultiPoly;
|
|
48
|
+
/** `a * b` (both over the same `vars`), via distributed convolution. */
|
|
49
|
+
export declare function mulMP(a: MultiPoly, b: MultiPoly): MultiPoly;
|
|
50
|
+
/** `p * k` for a scalar `k: bigint`. */
|
|
51
|
+
export declare function scalarMulMP(p: MultiPoly, k: bigint): MultiPoly;
|
|
52
|
+
/** `-p`. */
|
|
53
|
+
export declare function negMP(p: MultiPoly): MultiPoly;
|
|
54
|
+
/**
|
|
55
|
+
* Total monomial order used for canonicalizing multivariate polynomials:
|
|
56
|
+
* degree-lex — higher total degree first, then lexicographic comparison of
|
|
57
|
+
* the exponent vector (earlier variables weighted higher). Returns a
|
|
58
|
+
* negative number if `expsA` sorts before `expsB` (i.e. `expsA` is the
|
|
59
|
+
* "larger"/leading monomial), positive if after, 0 if equal.
|
|
60
|
+
*/
|
|
61
|
+
export declare function canonicalCompare(expsA: number[], expsB: number[]): number;
|
|
62
|
+
/**
|
|
63
|
+
* The leading term of `p` under `canonicalCompare`: the term whose exponent
|
|
64
|
+
* vector sorts first. Returns `null` for the zero polynomial.
|
|
65
|
+
*/
|
|
66
|
+
export declare function leadingTerm(p: MultiPoly): {
|
|
67
|
+
exps: number[];
|
|
68
|
+
coeff: bigint;
|
|
69
|
+
} | null;
|
|
70
|
+
/** Non-negative gcd of all coefficients of `p` (0 for the zero polynomial). */
|
|
71
|
+
export declare function integerContentMP(p: MultiPoly): bigint;
|
|
72
|
+
/**
|
|
73
|
+
* Primitive part of `p`: divide out `integerContentMP(p)`, then flip sign
|
|
74
|
+
* so the leading term (under `canonicalCompare`) has a positive
|
|
75
|
+
* coefficient. The zero polynomial maps to itself.
|
|
76
|
+
*/
|
|
77
|
+
export declare function primitivePartMP(p: MultiPoly): MultiPoly;
|
|
78
|
+
/**
|
|
79
|
+
* Multivariate polynomial long division: returns the quotient `a / b` iff
|
|
80
|
+
* `b` divides `a` **exactly** over ℤ, else `null`.
|
|
81
|
+
*
|
|
82
|
+
* Repeatedly takes the `canonicalCompare`-leading term of the current
|
|
83
|
+
* remainder and attempts to cancel it against `b`'s leading term: the
|
|
84
|
+
* exponent vector must dominate `b`'s leading exponents component-wise, and
|
|
85
|
+
* the coefficient must divide `b`'s leading coefficient exactly in ℤ (bigint
|
|
86
|
+
* `%` gives an exact `0` remainder regardless of operand signs). Any failure
|
|
87
|
+
* of either condition means the division is not exact — this function is the
|
|
88
|
+
* recombination correctness arbiter and must never round or approximate.
|
|
89
|
+
*/
|
|
90
|
+
export declare function multiExactDivide(a: MultiPoly, b: MultiPoly): MultiPoly | null;
|
|
91
|
+
/**
|
|
92
|
+
* Parses `expr` over `vars` via algebra's exact `polyFromExpression`, then
|
|
93
|
+
* lifts it to a bigint-backed {@link MultiPoly} — but only if EVERY
|
|
94
|
+
* coefficient is an exact integer. Returns `null` on any non-integer
|
|
95
|
+
* coefficient or if parsing throws (unknown symbol, non-integer exponent,
|
|
96
|
+
* non-constant divisor, etc.).
|
|
97
|
+
*/
|
|
98
|
+
export declare function fromAlgebraExpr(expr: string, vars: string[]): MultiPoly | null;
|
|
99
|
+
/**
|
|
100
|
+
* Renders `p` back to an expression string in the SAME format as
|
|
101
|
+
* `polynomial-ideal.polyToString` (term order, `*`/`^` spacing, `+ -`
|
|
102
|
+
* collapsing, `1*x` unit-coefficient style) — but rendered directly from
|
|
103
|
+
* `bigint` coefficients so values above 2^53 stay exact. Routing through
|
|
104
|
+
* `polyToString` would require `Number(v)`, which silently rounds.
|
|
105
|
+
*/
|
|
106
|
+
export declare function toAlgebraString(p: MultiPoly): string;
|
|
107
|
+
//# sourceMappingURL=multi-poly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-poly.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/multi-poly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,qEAAqE;IACrE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kDAAkD;IAClD,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,qEAAqE;AACrE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAE1C;AAED,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAKzC;AAED,uCAAuC;AACvC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAElD;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAgBvF;AAED,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS/D;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAUhD;AAED,yCAAyC;AACzC,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE5C;AAED,yEAAyE;AACzE,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,OAAO,CAU1D;AAED,2CAA2C;AAC3C,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,CAW3D;AAED,2CAA2C;AAC3C,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,CAE3D;AAED,wEAAwE;AACxE,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,CAqB3D;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAQ9D;AAED,YAAY;AACZ,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,CAM7C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAYzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASlF;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAMrD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,CAevD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CA+B7E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAmB9E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAcpD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yun's square-free decomposition over ℤ.
|
|
3
|
+
*
|
|
4
|
+
* Given a nonzero integer polynomial `f`, decomposes `primitivePart(f)` into
|
|
5
|
+
* pairwise-coprime square-free factors with multiplicities such that
|
|
6
|
+
* `primitivePart(f) = ∏ factorᵢ^multᵢ` (up to sign — each returned `factor`
|
|
7
|
+
* is normalized to have a positive leading coefficient via `primitivePart`).
|
|
8
|
+
*
|
|
9
|
+
* This is the classical characteristic-0 algorithm (valid over any field of
|
|
10
|
+
* characteristic 0, hence over ℤ via `polyGcdZ`/`exactDivide`): let
|
|
11
|
+
* `g = gcd(f, f')`, `c = f/g`, `w = f'/g`. Then repeatedly peel off the
|
|
12
|
+
* square-free part at multiplicity `i` via `y = gcd(c, w)`,
|
|
13
|
+
* `factor = c/y`, `c = y`, `w = w/y - factor'`.
|
|
14
|
+
*
|
|
15
|
+
* Part of the univariate factorization engine
|
|
16
|
+
* (`functions/src/typed/factorization/`) — bigint-only.
|
|
17
|
+
*/
|
|
18
|
+
import { type IntPoly } from './integer-poly.js';
|
|
19
|
+
/** One square-free factor of the input, with its multiplicity in the input. */
|
|
20
|
+
export interface SquareFreeFactor {
|
|
21
|
+
factor: IntPoly;
|
|
22
|
+
mult: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Yun square-free decomposition of `f` over ℤ. `f` must be nonzero (may be
|
|
26
|
+
* non-primitive; the content is discarded — decomposition operates on
|
|
27
|
+
* `primitivePart(f)`). Trivial degree-0 (constant) factors are never
|
|
28
|
+
* included in the output.
|
|
29
|
+
*
|
|
30
|
+
* Recurrence (standard Yun, char 0): with `g = gcd(f, f')`,
|
|
31
|
+
* `b0 = f/g`, `c0 = f'/g`, `d0 = c0 - b0'`. At each step `i = 1, 2, …`
|
|
32
|
+
* (while `deg(b) > 0`): `aᵢ = gcd(b, d)` is the square-free factor of
|
|
33
|
+
* multiplicity `i` (possibly a unit, i.e. degree 0, meaning multiplicity `i`
|
|
34
|
+
* is absent); `b ← b/aᵢ`, `c ← d/aᵢ`, `d ← c - b'` for the next round.
|
|
35
|
+
*/
|
|
36
|
+
export declare function squareFreeDecompose(f: IntPoly): SquareFreeFactor[];
|
|
37
|
+
//# sourceMappingURL=square-free.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"square-free.d.ts","sourceRoot":"","sources":["../../../src/typed/factorization/square-free.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAOL,KAAK,OAAO,EACb,MAAM,mBAAmB,CAAC;AAE3B,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAkClE"}
|