nerdamer 2.0.0-rc.1 → 2.0.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.
Files changed (236) hide show
  1. package/BREAKING_CHANGES.md +244 -0
  2. package/README.md +168 -229
  3. package/dist/bundle.js +1 -1
  4. package/dist/bundle.js.LICENSE.txt +6 -6
  5. package/output/algebra/adapters.d.ts +3 -33
  6. package/output/algebra/adapters.js +7 -105
  7. package/output/algebra/algorithms/arith.js +10 -9
  8. package/output/algebra/algorithms/groebnerBase.d.ts +24 -20
  9. package/output/algebra/algorithms/groebnerBase.js +486 -723
  10. package/output/algebra/dispatch.d.ts +1 -0
  11. package/output/algebra/dispatch.js +25 -0
  12. package/output/algebra/factor/factor.d.ts +15 -0
  13. package/output/algebra/factor/factor.js +99 -12
  14. package/output/algebra/gcd/gcd.d.ts +8 -7
  15. package/output/algebra/gcd/gcd.js +32 -78
  16. package/output/algebra/groebner.d.ts +2 -2
  17. package/output/algebra/groebner.js +6 -12
  18. package/output/algebra/partfrac.d.ts +3 -3
  19. package/output/algebra/partfrac.js +28 -61
  20. package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
  21. package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
  22. package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
  23. package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
  24. package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
  25. package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
  26. package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
  27. package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
  28. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
  29. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
  30. package/output/algebra/polynomial/modularGcd.d.ts +40 -0
  31. package/output/algebra/polynomial/modularGcd.js +365 -0
  32. package/output/algebra/polynomialize.js +4 -2
  33. package/output/algebra/simplify/funcsimp.js +1 -1
  34. package/output/algebra/simplify/ratsimp.js +1 -1
  35. package/output/algebra/simplify/simplify.js +11 -2
  36. package/output/algebra/utils.d.ts +1 -1
  37. package/output/algebra/utils.js +3 -3
  38. package/output/api/advanced.d.ts +2 -1
  39. package/output/api/advanced.js +3 -3
  40. package/output/api/algebra.d.ts +21 -4
  41. package/output/api/algebra.js +22 -3
  42. package/output/api/assumptions.d.ts +1 -1
  43. package/output/api/assumptions.js +2 -1
  44. package/output/api/calculus.d.ts +2 -1
  45. package/output/api/calculus.js +2 -1
  46. package/output/api/core.d.ts +28 -7
  47. package/output/api/core.js +28 -2
  48. package/output/api/languages/deu.d.ts +3 -0
  49. package/output/api/languages/deu.js +266 -0
  50. package/output/api/languages/fra.d.ts +3 -0
  51. package/output/api/languages/fra.js +266 -0
  52. package/output/api/languages/ita.d.ts +3 -0
  53. package/output/api/languages/ita.js +266 -0
  54. package/output/api/languages/nld.d.ts +3 -0
  55. package/output/api/languages/nld.js +266 -0
  56. package/output/api/languages/por.d.ts +3 -0
  57. package/output/api/languages/por.js +266 -0
  58. package/output/api/languages/spa.d.ts +3 -0
  59. package/output/api/languages/spa.js +266 -0
  60. package/output/api/parser.d.ts +10 -2
  61. package/output/api/parser.js +2 -0
  62. package/output/api/solve.d.ts +1 -1
  63. package/output/api/solve.js +2 -1
  64. package/output/api/structures.d.ts +1 -1
  65. package/output/api/structures.js +2 -1
  66. package/output/calculus/adapters.d.ts +8 -0
  67. package/output/calculus/adapters.js +41 -0
  68. package/output/calculus/derivative/diff.js +6 -3
  69. package/output/calculus/dispatch.d.ts +1 -0
  70. package/output/calculus/dispatch.js +25 -0
  71. package/output/calculus/integrate/integrate.js +4 -4
  72. package/output/calculus/integrate/integrationTable.js +16 -16
  73. package/output/calculus/laplace/ilaplace.js +1 -1
  74. package/output/calculus/laplace/ilaplaceTable.js +18 -17
  75. package/output/calculus/laplace/laplaceTable.js +3 -2
  76. package/output/calculus/limit/limit.js +1 -1
  77. package/output/core/classes/assumption/Assumption.js +14 -10
  78. package/output/core/classes/assumption/assume.d.ts +6 -0
  79. package/output/core/classes/assumption/assume.js +9 -0
  80. package/output/core/classes/assumption/dispatch.d.ts +1 -0
  81. package/output/core/classes/assumption/dispatch.js +11 -0
  82. package/output/core/classes/collection/Collection.js +11 -2
  83. package/output/core/classes/complex/Complex.d.ts +10 -0
  84. package/output/core/classes/complex/Complex.js +19 -1
  85. package/output/core/classes/decimalSet/DecimalSet.js +5 -4
  86. package/output/core/classes/dictionary/Dictionary.js +4 -1
  87. package/output/core/classes/expression/CoeffObject.d.ts +1 -1
  88. package/output/core/classes/expression/CoeffObject.js +1 -2
  89. package/output/core/classes/expression/Expression.d.ts +35 -26
  90. package/output/core/classes/expression/Expression.js +77 -50
  91. package/output/core/classes/expression/analysis.d.ts +1 -1
  92. package/output/core/classes/expression/analysis.js +7 -7
  93. package/output/core/classes/expression/format.d.ts +9 -0
  94. package/output/core/classes/expression/format.js +130 -7
  95. package/output/core/classes/expression/utils.d.ts +9 -0
  96. package/output/core/classes/expression/utils.js +52 -6
  97. package/output/core/classes/matrix/Matrix.d.ts +2 -3
  98. package/output/core/classes/matrix/Matrix.js +26 -23
  99. package/output/core/classes/matrix/dispatch.d.ts +1 -0
  100. package/output/core/classes/matrix/dispatch.js +19 -0
  101. package/output/core/classes/matrix/functions.d.ts +2 -0
  102. package/output/core/classes/matrix/functions.js +5 -0
  103. package/output/core/classes/parser/Parser.d.ts +31 -5
  104. package/output/core/classes/parser/Parser.js +357 -444
  105. package/output/core/classes/parser/constants.d.ts +2 -0
  106. package/output/core/classes/parser/constants.js +4 -2
  107. package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
  108. package/output/core/classes/parser/controlFlowSignals.js +60 -0
  109. package/output/core/classes/parser/operations/add.js +14 -16
  110. package/output/core/classes/parser/operations/compare.js +13 -0
  111. package/output/core/classes/parser/operations/functions.d.ts +3 -4
  112. package/output/core/classes/parser/operations/functions.js +48 -102
  113. package/output/core/classes/parser/operations/multiply.js +22 -15
  114. package/output/core/classes/parser/operations/power.js +11 -11
  115. package/output/core/classes/parser/operations/subtract.js +2 -1
  116. package/output/core/classes/parser/preprocess.d.ts +0 -7
  117. package/output/core/classes/parser/preprocess.js +33 -39
  118. package/output/core/classes/parser/scripting/controlFlow.d.ts +4 -102
  119. package/output/core/classes/parser/scripting/controlFlow.js +134 -186
  120. package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
  121. package/output/core/classes/parser/scripting/deferred.js +65 -0
  122. package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
  123. package/output/core/classes/parser/scripting/dispatch.js +62 -0
  124. package/output/core/classes/parser/scripting/evaluate.d.ts +13 -0
  125. package/output/core/classes/parser/scripting/evaluate.js +17 -1
  126. package/output/core/classes/parser/scripting/scope.d.ts +1 -28
  127. package/output/core/classes/parser/scripting/scope.js +36 -40
  128. package/output/core/classes/parser/types.d.ts +5 -5
  129. package/output/core/classes/parser/wrappers/IndexedReference.d.ts +4 -3
  130. package/output/core/classes/parser/wrappers/IndexedReference.js +8 -0
  131. package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +2 -2
  132. package/output/core/classes/polynomial/Polynomial.d.ts +5 -1
  133. package/output/core/classes/polynomial/Polynomial.js +53 -7
  134. package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
  135. package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
  136. package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
  137. package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -0
  138. package/output/core/classes/polynomial/Term.js +2 -2
  139. package/output/core/{adapters.d.ts → classes/polynomial/adapters.d.ts} +2 -2
  140. package/output/core/classes/polynomial/adapters.js +33 -0
  141. package/output/core/classes/polynomial/dispatch.d.ts +1 -0
  142. package/output/core/classes/polynomial/dispatch.js +14 -0
  143. package/output/core/classes/polynomial/functions.d.ts +8 -0
  144. package/output/core/classes/polynomial/functions.js +71 -8
  145. package/output/core/classes/polynomial/utils.js +2 -1
  146. package/output/core/classes/rational/Rational.d.ts +8 -11
  147. package/output/core/classes/rational/Rational.js +70 -20
  148. package/output/core/classes/seq/SEQ.js +4 -4
  149. package/output/core/classes/valuesSet/ValuesSet.d.ts +9 -1
  150. package/output/core/classes/valuesSet/ValuesSet.js +22 -4
  151. package/output/core/classes/vector/Vector.d.ts +2 -3
  152. package/output/core/classes/vector/Vector.js +11 -15
  153. package/output/core/classes/vector/dispatch.d.ts +1 -0
  154. package/output/core/classes/vector/dispatch.js +11 -0
  155. package/output/core/common/classes/MathematicalAggregate.js +11 -2
  156. package/output/core/common/classes/StructuredEntity.d.ts +0 -17
  157. package/output/core/common/classes/StructuredEntity.js +3 -64
  158. package/output/core/common/common.d.ts +0 -1
  159. package/output/core/common/common.js +29 -234
  160. package/output/core/converters/BaseConverter.js +3 -2
  161. package/output/core/converters/Converter.js +9 -5
  162. package/output/core/converters/Pattern.js +1 -1
  163. package/output/core/dispatch.d.ts +18 -0
  164. package/output/core/dispatch.js +3 -281
  165. package/output/core/errors.d.ts +259 -474
  166. package/output/core/errors.js +270 -542
  167. package/output/core/fullFunctions.d.ts +7 -0
  168. package/output/core/fullFunctions.js +31 -0
  169. package/output/core/functions/bigint/bigint.d.ts +13 -1
  170. package/output/core/functions/bigint/bigint.js +56 -4
  171. package/output/core/functions/bigint/primeFactor.d.ts +2 -0
  172. package/output/core/functions/bigint/primeFactor.js +13 -13
  173. package/output/core/functions/build/definitions.js +6 -0
  174. package/output/core/functions/complex.d.ts +2 -2
  175. package/output/core/functions/complex.dispatch.d.ts +1 -0
  176. package/output/core/functions/complex.dispatch.js +16 -0
  177. package/output/core/functions/complex.js +7 -7
  178. package/output/core/functions/decimal.js +2 -1
  179. package/output/core/functions/expand/expand.js +2 -2
  180. package/output/core/functions/numeric.d.ts +1 -1
  181. package/output/core/functions/string.js +2 -1
  182. package/output/core/functions/subst.js +21 -13
  183. package/output/core/parserFunctions.d.ts +7 -0
  184. package/output/core/parserFunctions.js +25 -0
  185. package/output/index.d.ts +50 -30
  186. package/output/index.js +147 -19
  187. package/output/math/defint/defint.d.ts +18 -0
  188. package/output/math/defint/defint.js +60 -0
  189. package/output/math/defint/defintDecimal.js +6 -5
  190. package/output/math/defint/defintNative.js +7 -18
  191. package/output/math/dispatch.d.ts +1 -0
  192. package/output/math/dispatch.js +101 -0
  193. package/output/math/geometry.d.ts +4 -0
  194. package/output/math/geometry.js +23 -0
  195. package/output/math/math.d.ts +59 -19
  196. package/output/math/math.js +244 -100
  197. package/output/math/trig.js +4 -4
  198. package/output/math/utils.d.ts +6 -0
  199. package/output/math/utils.js +39 -0
  200. package/output/solve/classes/PolynomialSolver.d.ts +33 -14
  201. package/output/solve/classes/PolynomialSolver.js +267 -67
  202. package/output/solve/classes/SolutionSet.d.ts +20 -1
  203. package/output/solve/classes/SolutionSet.js +82 -5
  204. package/output/solve/dispatch.d.ts +1 -0
  205. package/output/solve/dispatch.js +13 -0
  206. package/output/solve/linsolve.d.ts +2 -0
  207. package/output/solve/linsolve.js +13 -5
  208. package/output/solve/solve.d.ts +10 -0
  209. package/output/solve/solve.js +128 -20
  210. package/output/solve/solveSystem.d.ts +1 -1
  211. package/output/solve/solveSystem.js +8 -32
  212. package/output/solve/utils.d.ts +2 -1
  213. package/output/solve/utils.js +18 -22
  214. package/output/utils/array.d.ts +1 -1
  215. package/output/utils/debug.js +2 -1
  216. package/package.json +22 -38
  217. package/dist/parser.js +0 -2
  218. package/dist/parser.js.LICENSE.txt +0 -7
  219. package/docs-data/parser-functions.json +0 -1960
  220. package/output/algebra/algorithms/factor.d.ts +0 -3
  221. package/output/algebra/algorithms/factor.js +0 -5
  222. package/output/algebra/algorithms/factorMultivariate.d.ts +0 -23
  223. package/output/algebra/algorithms/factorMultivariate.js +0 -2393
  224. package/output/algebra/algorithms/factorUnivariate.d.ts +0 -72
  225. package/output/algebra/algorithms/factorUnivariate.js +0 -1072
  226. package/output/algebra/algorithms/gcd.d.ts +0 -22
  227. package/output/algebra/algorithms/gcd.js +0 -690
  228. package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +0 -137
  229. package/output/algebra/algorithms/multiPoly/MultiPoly.js +0 -346
  230. package/output/algebra/algorithms/poly.d.ts +0 -228
  231. package/output/algebra/algorithms/poly.js +0 -1299
  232. package/output/algebra/algorithms/rational.d.ts +0 -17
  233. package/output/algebra/algorithms/rational.js +0 -115
  234. package/output/core/adapters.js +0 -40
  235. package/output/core/classes/parser/operations/comma.d.ts +0 -7
  236. package/output/core/classes/parser/operations/comma.js +0 -11
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @module sparsePolynomialFactor
3
+ *
4
+ * Exact polynomial factorization foundations over the integers.
5
+ *
6
+ * External references consulted for the mathematical algorithms:
7
+ * - SymPy square-free decomposition (Yun's algorithm):
8
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/sqfreetools.py
9
+ * - SymPy integer factorization pipeline (primitive/square-free decomposition before
10
+ * Zassenhaus factor splitting):
11
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/factortools.py
12
+ */
13
+ import { SparsePolynomial } from '../../core/classes/polynomial/SparsePolynomial';
14
+ import { ModularSparsePolynomial } from './ModularSparsePolynomial';
15
+ export type SparsePolynomialFactor = Readonly<{
16
+ factor: SparsePolynomial;
17
+ multiplicity: bigint;
18
+ }>;
19
+ export type SparsePolynomialSquareFreeFactorization = Readonly<{
20
+ content: bigint;
21
+ factors: readonly SparsePolynomialFactor[];
22
+ }>;
23
+ export declare function contentInVariable(polynomial: SparsePolynomial, variableIndex: number, coefficientVariables: readonly number[]): SparsePolynomial;
24
+ /**
25
+ * Recombines Hensel-lifted modular factors into exact integer factors.
26
+ *
27
+ * The modulus must exceed twice the Zassenhaus coefficient bound so symmetric
28
+ * representatives determine integer factor coefficients uniquely. Candidate subsets
29
+ * are accepted only after exact division in Z[x].
30
+ */
31
+ export declare function recombineLiftedUnivariateFactors(polynomial: SparsePolynomial, liftedFactors: readonly ModularSparsePolynomial[], variableIndex: number): readonly SparsePolynomial[];
32
+ /**
33
+ * Factors a primitive square-free univariate polynomial into irreducibles over Z.
34
+ *
35
+ * A prime preserving degree and square-freeness is selected deterministically.
36
+ * Berlekamp factorization supplies the modular factors; reducible modular images are
37
+ * lifted until the coefficient reconstruction bound is exceeded and then recombined
38
+ * by exact integer division.
39
+ */
40
+ export declare function factorSquareFreeUnivariateInteger(polynomial: SparsePolynomial, variableIndex: number): readonly SparsePolynomial[];
41
+ /**
42
+ * Computes square-free decomposition of an integer polynomial in one or more variables.
43
+ *
44
+ * The polynomial is treated recursively as univariate in the first selected variable.
45
+ * Coefficient content is decomposed over the remaining variables and factors with the
46
+ * same multiplicity are multiplied together.
47
+ */
48
+ export declare function squareFreeFactorizationMultivariate(polynomial: SparsePolynomial, variables: readonly number[]): SparsePolynomialSquareFreeFactorization;
49
+ /**
50
+ * Completely factors a univariate integer polynomial.
51
+ *
52
+ * Content and global sign are returned separately. Irreducible primitive factors are
53
+ * paired with the multiplicities obtained from square-free decomposition.
54
+ */
55
+ export declare function factorUnivariateInteger(polynomial: SparsePolynomial, variableIndex: number): SparsePolynomialSquareFreeFactorization;
56
+ /**
57
+ * Computes the square-free decomposition of a univariate integer polynomial.
58
+ *
59
+ * The returned content carries the sign needed to reconstruct the input. Each
60
+ * nonconstant factor is primitive with positive leading coefficient. A common power
61
+ * of the selected variable is extracted before Yun's loop so sparse monomials such
62
+ * as x^N do not require N iterations.
63
+ */
64
+ export declare function squareFreeFactorizationUnivariate(polynomial: SparsePolynomial, variableIndex: number): SparsePolynomialSquareFreeFactorization;
@@ -0,0 +1,492 @@
1
+ "use strict";
2
+ /**
3
+ * @module sparsePolynomialFactor
4
+ *
5
+ * Exact polynomial factorization foundations over the integers.
6
+ *
7
+ * External references consulted for the mathematical algorithms:
8
+ * - SymPy square-free decomposition (Yun's algorithm):
9
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/sqfreetools.py
10
+ * - SymPy integer factorization pipeline (primitive/square-free decomposition before
11
+ * Zassenhaus factor splitting):
12
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/factortools.py
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.contentInVariable = contentInVariable;
16
+ exports.recombineLiftedUnivariateFactors = recombineLiftedUnivariateFactors;
17
+ exports.factorSquareFreeUnivariateInteger = factorSquareFreeUnivariateInteger;
18
+ exports.squareFreeFactorizationMultivariate = squareFreeFactorizationMultivariate;
19
+ exports.factorUnivariateInteger = factorUnivariateInteger;
20
+ exports.squareFreeFactorizationUnivariate = squareFreeFactorizationUnivariate;
21
+ const SparsePolynomial_1 = require("../../core/classes/polynomial/SparsePolynomial");
22
+ const errors_1 = require("../../core/errors");
23
+ const bigint_1 = require("../../core/functions/bigint/bigint");
24
+ const primeFactor_1 = require("../../core/functions/bigint/primeFactor");
25
+ const modularGcd_1 = require("./modularGcd");
26
+ const ModularSparsePolynomial_1 = require("./ModularSparsePolynomial");
27
+ const ModularSparsePolynomialFactor_1 = require("./ModularSparsePolynomialFactor");
28
+ const SparsePolynomialGcd_1 = require("./SparsePolynomialGcd");
29
+ const INITIAL_FACTOR_PRIME = 3n;
30
+ const MAX_FACTOR_PRIME_PROBES = 4;
31
+ function assertUnivariate(polynomial, variableIndex) {
32
+ polynomial.degree(variableIndex);
33
+ for (const term of polynomial.terms()) {
34
+ for (let index = 0; index < polynomial.variableCount; index++) {
35
+ if (index !== variableIndex && term.exponents[index] !== 0n) {
36
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Square-free univariate factorization', requirement: (0, errors_1.message)('polyReqAllOtherVariablesDormant') }));
37
+ }
38
+ }
39
+ }
40
+ }
41
+ function findGoodFactorPrime(polynomial, variableIndex) {
42
+ const leading = polynomial.leadingTerm('lex');
43
+ if (leading === null) {
44
+ throw new RangeError((0, errors_1.message)('polyIntegerFactorPrimeZero'));
45
+ }
46
+ const derivative = polynomial.derivative(variableIndex);
47
+ let prime = (0, primeFactor_1.nextPrimeBig)(INITIAL_FACTOR_PRIME);
48
+ let probes = 0;
49
+ let selected;
50
+ while (true) {
51
+ if (leading.coefficient % prime !== 0n) {
52
+ const modularPolynomial = new ModularSparsePolynomial_1.ModularSparsePolynomial(polynomial.variableCount, prime, polynomial.terms());
53
+ const modularDerivative = new ModularSparsePolynomial_1.ModularSparsePolynomial(polynomial.variableCount, prime, derivative.terms());
54
+ const modularGcd = (0, modularGcd_1.modularGcdUnivariate)(modularPolynomial, modularDerivative, variableIndex);
55
+ if (modularGcd.isConstant()) {
56
+ const modularFactors = (0, ModularSparsePolynomialFactor_1.factorSquareFreeUnivariateFiniteField)(modularPolynomial, variableIndex);
57
+ const candidate = { prime, modularPolynomial, modularFactors };
58
+ probes++;
59
+ // An irreducible image modulo a degree-preserving prime proves the
60
+ // primitive integer polynomial irreducible, so no lifting is needed.
61
+ if (modularFactors.length === 1) {
62
+ return candidate;
63
+ }
64
+ if (selected === undefined ||
65
+ modularFactors.length < selected.modularFactors.length) {
66
+ selected = candidate;
67
+ }
68
+ if (probes >= MAX_FACTOR_PRIME_PROBES) {
69
+ return selected;
70
+ }
71
+ }
72
+ }
73
+ prime = (0, primeFactor_1.nextPrimeBig)(prime + 1n);
74
+ }
75
+ }
76
+ function assertFactorVariables(polynomial, variables) {
77
+ if (variables.length === 0) {
78
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Sparse polynomial factorization', requirement: (0, errors_1.message)('polyReqAtLeastOneVariable') }));
79
+ }
80
+ const selected = new Set();
81
+ let previous = -1;
82
+ for (const variableIndex of variables) {
83
+ polynomial.degree(variableIndex);
84
+ if (selected.has(variableIndex)) {
85
+ throw new RangeError((0, errors_1.message)('polyVariablesUnique', { operation: 'Sparse polynomial factorization' }));
86
+ }
87
+ if (variableIndex <= previous) {
88
+ throw new RangeError((0, errors_1.message)('polyVariablesRingOrder', { operation: 'Sparse polynomial factorization' }));
89
+ }
90
+ selected.add(variableIndex);
91
+ previous = variableIndex;
92
+ }
93
+ for (const activeVariable of polynomial.variables()) {
94
+ if (!selected.has(activeVariable)) {
95
+ throw new RangeError((0, errors_1.message)('polyVariablesIncludeActive', { operation: 'Sparse polynomial factorization' }));
96
+ }
97
+ }
98
+ }
99
+ function contentInVariable(polynomial, variableIndex, coefficientVariables) {
100
+ const grouped = new Map();
101
+ for (const term of polynomial.terms()) {
102
+ const exponent = term.exponents[variableIndex];
103
+ const exponents = [...term.exponents];
104
+ exponents[variableIndex] = 0n;
105
+ const group = grouped.get(exponent) ?? [];
106
+ group.push({ coefficient: term.coefficient, exponents });
107
+ grouped.set(exponent, group);
108
+ }
109
+ let content = null;
110
+ for (const terms of grouped.values()) {
111
+ const coefficient = new SparsePolynomial_1.SparsePolynomial(polynomial.variableCount, terms)
112
+ .primitivePart()
113
+ .normalizeLeadingSign('lex');
114
+ if (content === null) {
115
+ content = coefficient;
116
+ }
117
+ else if (coefficient.divideExact(content) !== null) {
118
+ continue;
119
+ }
120
+ else if (content.divideExact(coefficient) !== null) {
121
+ content = coefficient;
122
+ }
123
+ else {
124
+ content = (0, SparsePolynomialGcd_1.sparsePolynomialGcd)(content, coefficient, coefficientVariables);
125
+ }
126
+ if (content.isConstant()) {
127
+ return SparsePolynomial_1.SparsePolynomial.constant(polynomial.variableCount, 1n);
128
+ }
129
+ }
130
+ return content ?? SparsePolynomial_1.SparsePolynomial.zero(polynomial.variableCount);
131
+ }
132
+ function mergeSquareFreeFactor(factors, factor, multiplicity) {
133
+ if (factor.isConstant()) {
134
+ return;
135
+ }
136
+ const normalized = factor.primitivePart().normalizeLeadingSign('lex');
137
+ const current = factors.get(multiplicity);
138
+ factors.set(multiplicity, current === undefined ? normalized : current.multiply(normalized));
139
+ }
140
+ function squareFreeFactorizationRecursive(polynomial, variables) {
141
+ if (variables.length === 1) {
142
+ return squareFreeFactorizationUnivariate(polynomial, variables[0]);
143
+ }
144
+ let content = polynomial.content();
145
+ let primitive = polynomial.primitivePart();
146
+ const leading = primitive.leadingTerm('lex');
147
+ if (leading !== null && leading.coefficient < 0n) {
148
+ primitive = primitive.negate();
149
+ content = -content;
150
+ }
151
+ if (primitive.isConstant()) {
152
+ return { content, factors: [] };
153
+ }
154
+ const mainVariable = variables[0];
155
+ const coefficientVariables = variables.slice(1);
156
+ const variableContent = contentInVariable(primitive, mainVariable, coefficientVariables);
157
+ const variablePrimitive = divideExactOrThrow(primitive, variableContent);
158
+ const factorsByMultiplicity = new Map();
159
+ const mainDegree = variablePrimitive.degree(mainVariable);
160
+ if (mainDegree !== null && mainDegree > 0n) {
161
+ const derivative = variablePrimitive.derivative(mainVariable);
162
+ let gcd = (0, SparsePolynomialGcd_1.sparsePolynomialGcd)(variablePrimitive, derivative, variables);
163
+ let p = divideExactOrThrow(variablePrimitive, gcd);
164
+ let q = divideExactOrThrow(derivative, gcd);
165
+ let multiplicity = 1n;
166
+ while (true) {
167
+ const difference = q.subtract(p.derivative(mainVariable));
168
+ if (difference.isZero()) {
169
+ mergeSquareFreeFactor(factorsByMultiplicity, p, multiplicity);
170
+ break;
171
+ }
172
+ gcd = (0, SparsePolynomialGcd_1.sparsePolynomialGcd)(p, difference, variables);
173
+ p = divideExactOrThrow(p, gcd);
174
+ q = divideExactOrThrow(difference, gcd);
175
+ mergeSquareFreeFactor(factorsByMultiplicity, gcd, multiplicity);
176
+ multiplicity++;
177
+ }
178
+ }
179
+ const contentFactorization = squareFreeFactorizationRecursive(variableContent, coefficientVariables);
180
+ content *= contentFactorization.content;
181
+ for (const entry of contentFactorization.factors) {
182
+ mergeSquareFreeFactor(factorsByMultiplicity, entry.factor, entry.multiplicity);
183
+ }
184
+ const factors = [...factorsByMultiplicity.entries()]
185
+ .sort(([leftMultiplicity], [rightMultiplicity]) => leftMultiplicity < rightMultiplicity
186
+ ? -1
187
+ : leftMultiplicity > rightMultiplicity
188
+ ? 1
189
+ : 0)
190
+ .map(([multiplicity, squareFreeFactor]) => ({
191
+ factor: squareFreeFactor,
192
+ multiplicity,
193
+ }));
194
+ return { content, factors };
195
+ }
196
+ function divideExactOrThrow(dividend, divisor) {
197
+ const quotient = dividend.divideExact(divisor);
198
+ if (quotient === null) {
199
+ throw new Error((0, errors_1.message)('polySquareFreeNonExactDivision'));
200
+ }
201
+ return quotient;
202
+ }
203
+ function zassenhausCoefficientBound(polynomial, variableIndex) {
204
+ const degree = polynomial.degree(variableIndex);
205
+ if (degree === null || degree === 0n) {
206
+ return polynomial.maxAbsoluteCoefficient();
207
+ }
208
+ const leading = polynomial.leadingTerm('lex');
209
+ if (leading === null) {
210
+ return 0n;
211
+ }
212
+ const leadingAbsolute = leading.coefficient < 0n ? -leading.coefficient : leading.coefficient;
213
+ const maxCoefficient = polynomial.maxAbsoluteCoefficient();
214
+ const root = (0, bigint_1.ceilIntegerSquareRoot)(degree + 1n);
215
+ return root * (1n << degree) * maxCoefficient * leadingAbsolute;
216
+ }
217
+ function modularProduct(factors, indices, variableCount, modulus) {
218
+ let product = ModularSparsePolynomial_1.ModularSparsePolynomial.constant(variableCount, modulus, 1n);
219
+ for (const index of indices) {
220
+ product = product.multiply(factors[index]);
221
+ }
222
+ return product;
223
+ }
224
+ function combinations(values, size) {
225
+ const result = [];
226
+ const selected = [];
227
+ function choose(start) {
228
+ if (selected.length === size) {
229
+ result.push([...selected]);
230
+ return;
231
+ }
232
+ const remainingNeeded = size - selected.length;
233
+ for (let index = start; index <= values.length - remainingNeeded; index++) {
234
+ selected.push(values[index]);
235
+ choose(index + 1);
236
+ selected.pop();
237
+ }
238
+ }
239
+ choose(0);
240
+ return result;
241
+ }
242
+ /**
243
+ * Recombines Hensel-lifted modular factors into exact integer factors.
244
+ *
245
+ * The modulus must exceed twice the Zassenhaus coefficient bound so symmetric
246
+ * representatives determine integer factor coefficients uniquely. Candidate subsets
247
+ * are accepted only after exact division in Z[x].
248
+ */
249
+ function recombineLiftedUnivariateFactors(polynomial, liftedFactors, variableIndex) {
250
+ assertUnivariate(polynomial, variableIndex);
251
+ if (polynomial.isZero()) {
252
+ throw new RangeError((0, errors_1.message)('polyCannotFactorZeroPolynomial', { operation: 'Zassenhaus recombination' }));
253
+ }
254
+ if (polynomial.content() !== 1n) {
255
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqPrimitiveIntegerPolynomial') }));
256
+ }
257
+ const leading = polynomial.leadingTerm('lex');
258
+ if (leading === null || leading.coefficient <= 0n) {
259
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqPositiveLeadingCoefficient') }));
260
+ }
261
+ if (liftedFactors.length === 0) {
262
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqLiftedModularFactors') }));
263
+ }
264
+ const modulus = liftedFactors[0].modulus;
265
+ for (const factor of liftedFactors) {
266
+ if (factor.variableCount !== polynomial.variableCount ||
267
+ factor.modulus !== modulus) {
268
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqLiftedFactorsSameRing') }));
269
+ }
270
+ for (const activeVariable of factor.variables()) {
271
+ if (activeVariable !== variableIndex) {
272
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqUnivariateLiftedFactors') }));
273
+ }
274
+ }
275
+ if (!factor.equals(factor.monic())) {
276
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqMonicLiftedFactors') }));
277
+ }
278
+ }
279
+ const coefficientBound = zassenhausCoefficientBound(polynomial, variableIndex);
280
+ if (modulus <= 2n * coefficientBound) {
281
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Zassenhaus recombination', requirement: (0, errors_1.message)('polyReqLargerHenselModulus') }));
282
+ }
283
+ const modularInput = new ModularSparsePolynomial_1.ModularSparsePolynomial(polynomial.variableCount, modulus, polynomial.terms());
284
+ const allIndices = liftedFactors.map((_factor, index) => index);
285
+ const modularReconstruction = modularProduct(liftedFactors, allIndices, polynomial.variableCount, modulus).scale(leading.coefficient);
286
+ if (!modularReconstruction.equals(modularInput)) {
287
+ throw new RangeError((0, errors_1.message)('polyZassenhausFactorsReconstructModuloLift'));
288
+ }
289
+ const factors = [];
290
+ let remainingPolynomial = polynomial;
291
+ let remainingIndices = [...allIndices];
292
+ let subsetSize = 1;
293
+ while (2 * subsetSize <= remainingIndices.length) {
294
+ let accepted = false;
295
+ for (const subset of combinations(remainingIndices, subsetSize)) {
296
+ const remainingLeading = remainingPolynomial.leadingTerm('lex');
297
+ if (remainingLeading === null) {
298
+ throw new Error((0, errors_1.message)('polyZassenhausLostRemaining'));
299
+ }
300
+ const modularCandidate = modularProduct(liftedFactors, subset, polynomial.variableCount, modulus).scale(remainingLeading.coefficient);
301
+ let candidate = modularCandidate.toSymmetricIntegerPolynomial().primitivePart();
302
+ candidate = candidate.normalizeLeadingSign('lex');
303
+ if (candidate.isConstant()) {
304
+ continue;
305
+ }
306
+ const quotient = remainingPolynomial.divideExact(candidate);
307
+ if (quotient === null) {
308
+ continue;
309
+ }
310
+ factors.push(candidate);
311
+ remainingPolynomial = quotient.primitivePart().normalizeLeadingSign('lex');
312
+ const selected = new Set(subset);
313
+ remainingIndices = remainingIndices.filter(index => !selected.has(index));
314
+ subsetSize = 1;
315
+ accepted = true;
316
+ break;
317
+ }
318
+ if (!accepted) {
319
+ subsetSize++;
320
+ }
321
+ }
322
+ if (!remainingPolynomial.isConstant()) {
323
+ factors.push(remainingPolynomial);
324
+ }
325
+ let reconstruction = SparsePolynomial_1.SparsePolynomial.constant(polynomial.variableCount, 1n);
326
+ for (const factor of factors) {
327
+ reconstruction = reconstruction.multiply(factor);
328
+ }
329
+ if (!reconstruction.equals(polynomial)) {
330
+ throw new Error((0, errors_1.message)('polyZassenhausReconstructionFailed'));
331
+ }
332
+ return factors;
333
+ }
334
+ /**
335
+ * Factors a primitive square-free univariate polynomial into irreducibles over Z.
336
+ *
337
+ * A prime preserving degree and square-freeness is selected deterministically.
338
+ * Berlekamp factorization supplies the modular factors; reducible modular images are
339
+ * lifted until the coefficient reconstruction bound is exceeded and then recombined
340
+ * by exact integer division.
341
+ */
342
+ function factorSquareFreeUnivariateInteger(polynomial, variableIndex) {
343
+ assertUnivariate(polynomial, variableIndex);
344
+ if (polynomial.isZero()) {
345
+ throw new RangeError((0, errors_1.message)('polyCannotFactorZeroPolynomial', { operation: 'Integer factorization' }));
346
+ }
347
+ if (polynomial.content() !== 1n) {
348
+ throw new RangeError((0, errors_1.message)('polyRequires', { operation: 'Integer square-free factorization', requirement: (0, errors_1.message)('polyReqPrimitivePolynomial') }));
349
+ }
350
+ const leading = polynomial.leadingTerm('lex');
351
+ if (leading === null) {
352
+ throw new Error((0, errors_1.message)('polyIntegerFactorLostLeading'));
353
+ }
354
+ const input = leading.coefficient < 0n ? polynomial.negate() : polynomial;
355
+ if (input.isConstant()) {
356
+ return [];
357
+ }
358
+ const degree = input.degree(variableIndex);
359
+ if (degree === 1n) {
360
+ return [input];
361
+ }
362
+ const selected = findGoodFactorPrime(input, variableIndex);
363
+ if (selected.modularFactors.length === 1) {
364
+ return [input];
365
+ }
366
+ const coefficientBound = zassenhausCoefficientBound(input, variableIndex);
367
+ let targetModulus = selected.prime;
368
+ while (targetModulus <= 2n * coefficientBound) {
369
+ targetModulus *= targetModulus;
370
+ }
371
+ const lifted = (0, ModularSparsePolynomialFactor_1.henselLiftUnivariateFactors)(input, selected.prime, selected.modularFactors, variableIndex, targetModulus);
372
+ return recombineLiftedUnivariateFactors(input, lifted, variableIndex);
373
+ }
374
+ /**
375
+ * Computes square-free decomposition of an integer polynomial in one or more variables.
376
+ *
377
+ * The polynomial is treated recursively as univariate in the first selected variable.
378
+ * Coefficient content is decomposed over the remaining variables and factors with the
379
+ * same multiplicity are multiplied together.
380
+ */
381
+ function squareFreeFactorizationMultivariate(polynomial, variables) {
382
+ assertFactorVariables(polynomial, variables);
383
+ if (polynomial.isZero()) {
384
+ return { content: 0n, factors: [] };
385
+ }
386
+ return squareFreeFactorizationRecursive(polynomial, variables);
387
+ }
388
+ /**
389
+ * Completely factors a univariate integer polynomial.
390
+ *
391
+ * Content and global sign are returned separately. Irreducible primitive factors are
392
+ * paired with the multiplicities obtained from square-free decomposition.
393
+ */
394
+ function factorUnivariateInteger(polynomial, variableIndex) {
395
+ const squareFree = squareFreeFactorizationUnivariate(polynomial, variableIndex);
396
+ if (squareFree.content === 0n || squareFree.factors.length === 0) {
397
+ return squareFree;
398
+ }
399
+ const factors = [];
400
+ for (const entry of squareFree.factors) {
401
+ const irreducible = factorSquareFreeUnivariateInteger(entry.factor, variableIndex);
402
+ for (const factor of irreducible) {
403
+ factors.push({
404
+ factor,
405
+ multiplicity: entry.multiplicity,
406
+ });
407
+ }
408
+ }
409
+ return {
410
+ content: squareFree.content,
411
+ factors,
412
+ };
413
+ }
414
+ /**
415
+ * Computes the square-free decomposition of a univariate integer polynomial.
416
+ *
417
+ * The returned content carries the sign needed to reconstruct the input. Each
418
+ * nonconstant factor is primitive with positive leading coefficient. A common power
419
+ * of the selected variable is extracted before Yun's loop so sparse monomials such
420
+ * as x^N do not require N iterations.
421
+ */
422
+ function squareFreeFactorizationUnivariate(polynomial, variableIndex) {
423
+ assertUnivariate(polynomial, variableIndex);
424
+ if (polynomial.isZero()) {
425
+ return { content: 0n, factors: [] };
426
+ }
427
+ let content = polynomial.content();
428
+ let primitive = polynomial.primitivePart();
429
+ const leading = primitive.leadingTerm('lex');
430
+ if (leading !== null && leading.coefficient < 0n) {
431
+ primitive = primitive.negate();
432
+ content = -content;
433
+ }
434
+ if (primitive.isConstant()) {
435
+ return { content, factors: [] };
436
+ }
437
+ const factors = [];
438
+ let minimumExponent = null;
439
+ for (const term of primitive.terms()) {
440
+ const exponent = term.exponents[variableIndex];
441
+ if (minimumExponent === null || exponent < minimumExponent) {
442
+ minimumExponent = exponent;
443
+ }
444
+ }
445
+ if (minimumExponent !== null && minimumExponent > 0n) {
446
+ const exponents = new Array(primitive.variableCount).fill(0n);
447
+ exponents[variableIndex] = minimumExponent;
448
+ const monomial = SparsePolynomial_1.SparsePolynomial.monomial(primitive.variableCount, 1n, exponents);
449
+ primitive = divideExactOrThrow(primitive, monomial);
450
+ factors.push({
451
+ factor: SparsePolynomial_1.SparsePolynomial.variable(primitive.variableCount, variableIndex),
452
+ multiplicity: minimumExponent,
453
+ });
454
+ }
455
+ if (primitive.isConstant()) {
456
+ return { content, factors };
457
+ }
458
+ const derivative = primitive.derivative(variableIndex);
459
+ const variableIndices = [variableIndex];
460
+ let gcd = (0, SparsePolynomialGcd_1.sparsePolynomialGcd)(primitive, derivative, variableIndices);
461
+ let p = divideExactOrThrow(primitive, gcd);
462
+ let q = divideExactOrThrow(derivative, gcd);
463
+ let multiplicity = 1n;
464
+ while (true) {
465
+ const difference = q.subtract(p.derivative(variableIndex));
466
+ if (difference.isZero()) {
467
+ if (!p.isConstant()) {
468
+ factors.push({
469
+ factor: p.normalizeLeadingSign('lex'),
470
+ multiplicity,
471
+ });
472
+ }
473
+ break;
474
+ }
475
+ gcd = (0, SparsePolynomialGcd_1.sparsePolynomialGcd)(p, difference, variableIndices);
476
+ p = divideExactOrThrow(p, gcd);
477
+ q = divideExactOrThrow(difference, gcd);
478
+ if (!gcd.isConstant()) {
479
+ factors.push({
480
+ factor: gcd.normalizeLeadingSign('lex'),
481
+ multiplicity,
482
+ });
483
+ }
484
+ multiplicity++;
485
+ }
486
+ factors.sort((left, right) => left.multiplicity < right.multiplicity
487
+ ? -1
488
+ : left.multiplicity > right.multiplicity
489
+ ? 1
490
+ : 0);
491
+ return { content, factors };
492
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @module sparsePolynomialGcd
3
+ *
4
+ * Integer GCD reconstruction for the exact sparse polynomial representation.
5
+ *
6
+ * External references consulted:
7
+ * - SymPy multivariate Chinese remainder reconstruction and modular GCD loop:
8
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/polys/zippel.py
9
+ * - SymPy Chinese Remainder Theorem implementation:
10
+ * https://github.com/sympy/sympy/blob/120ee85f346f6292b763cc195afda4f907260d4a/sympy/ntheory/modular.py
11
+ */
12
+ import { SparsePolynomial } from '../../core/classes/polynomial/SparsePolynomial';
13
+ /**
14
+ * Combines two sparse polynomial congruences with coprime positive moduli.
15
+ *
16
+ * Missing monomials are treated as zero residues. Exponent vectors are retained
17
+ * from the source term and never reconstructed from the map key.
18
+ */
19
+ export declare function combinePolynomialCongruences(left: SparsePolynomial, leftModulus: bigint, right: SparsePolynomial, rightModulus: bigint): Readonly<{
20
+ polynomial: SparsePolynomial;
21
+ modulus: bigint;
22
+ }>;
23
+ /**
24
+ * Computes the integer GCD of two sparse polynomials by modular images and CRT.
25
+ *
26
+ * variables must follow polynomial-ring order and contain every active variable.
27
+ * The returned GCD has positive leading coefficient under lexicographic order.
28
+ */
29
+ export declare function sparsePolynomialGcd(left: SparsePolynomial, right: SparsePolynomial, variables: readonly number[]): SparsePolynomial;