nerdamer 1.1.13 → 2.0.0-rc.1
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/LICENSE.md +184 -0
- package/README.md +293 -312
- package/dist/bundle.js +2 -0
- package/dist/bundle.js.LICENSE.txt +7 -0
- package/dist/parser.js +2 -0
- package/dist/parser.js.LICENSE.txt +7 -0
- package/docs-data/parser-functions.json +1960 -0
- package/index.d.ts +10 -426
- package/output/algebra/adapters.d.ts +33 -0
- package/output/algebra/adapters.js +109 -0
- package/output/algebra/algorithms/arith.d.ts +84 -0
- package/output/algebra/algorithms/arith.js +323 -0
- package/output/algebra/algorithms/factor.d.ts +3 -0
- package/output/algebra/algorithms/factor.js +5 -0
- package/output/algebra/algorithms/factorMultivariate.d.ts +23 -0
- package/output/algebra/algorithms/factorMultivariate.js +2393 -0
- package/output/algebra/algorithms/factorUnivariate.d.ts +72 -0
- package/output/algebra/algorithms/factorUnivariate.js +1072 -0
- package/output/algebra/algorithms/gcd.d.ts +22 -0
- package/output/algebra/algorithms/gcd.js +690 -0
- package/output/algebra/algorithms/groebnerBase.d.ts +157 -0
- package/output/algebra/algorithms/groebnerBase.js +1166 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +137 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.js +346 -0
- package/output/algebra/algorithms/poly.d.ts +228 -0
- package/output/algebra/algorithms/poly.js +1299 -0
- package/output/algebra/algorithms/rational.d.ts +17 -0
- package/output/algebra/algorithms/rational.js +115 -0
- package/output/algebra/factor/factor.d.ts +62 -0
- package/output/algebra/factor/factor.js +158 -0
- package/output/algebra/gcd/gcd.d.ts +29 -0
- package/output/algebra/gcd/gcd.js +141 -0
- package/output/algebra/groebner.d.ts +21 -0
- package/output/algebra/groebner.js +42 -0
- package/output/algebra/partfrac.d.ts +19 -0
- package/output/algebra/partfrac.js +398 -0
- package/output/algebra/polynomialize.d.ts +20 -0
- package/output/algebra/polynomialize.js +24 -0
- package/output/algebra/simplify/complexsimp.d.ts +7 -0
- package/output/algebra/simplify/complexsimp.js +24 -0
- package/output/algebra/simplify/factorCommon.d.ts +13 -0
- package/output/algebra/simplify/factorCommon.js +136 -0
- package/output/algebra/simplify/funcsimp.d.ts +26 -0
- package/output/algebra/simplify/funcsimp.js +633 -0
- package/output/algebra/simplify/invtrigrewrite.d.ts +10 -0
- package/output/algebra/simplify/invtrigrewrite.js +96 -0
- package/output/algebra/simplify/ratsimp.d.ts +21 -0
- package/output/algebra/simplify/ratsimp.js +140 -0
- package/output/algebra/simplify/simplify.d.ts +25 -0
- package/output/algebra/simplify/simplify.js +228 -0
- package/output/algebra/simplify/trigreduce.d.ts +38 -0
- package/output/algebra/simplify/trigreduce.js +424 -0
- package/output/algebra/simplify/trigrewrite.d.ts +17 -0
- package/output/algebra/simplify/trigrewrite.js +156 -0
- package/output/algebra/simplify/trigsimp.d.ts +11 -0
- package/output/algebra/simplify/trigsimp.js +369 -0
- package/output/algebra/simplify/utils.d.ts +32 -0
- package/output/algebra/simplify/utils.js +56 -0
- package/output/algebra/utils.d.ts +32 -0
- package/output/algebra/utils.js +48 -0
- package/output/api/advanced.d.ts +7 -0
- package/output/api/advanced.js +18 -0
- package/output/api/algebra.d.ts +17 -0
- package/output/api/algebra.js +32 -0
- package/output/api/assumptions.d.ts +4 -0
- package/output/api/assumptions.js +11 -0
- package/output/api/calculus.d.ts +9 -0
- package/output/api/calculus.js +21 -0
- package/output/api/core.d.ts +17 -0
- package/output/api/core.js +41 -0
- package/output/api/debug.d.ts +16 -0
- package/output/api/debug.js +23 -0
- package/output/api/parser.d.ts +85 -0
- package/output/api/parser.js +16 -0
- package/output/api/solve.d.ts +10 -0
- package/output/api/solve.js +16 -0
- package/output/api/structures.d.ts +10 -0
- package/output/api/structures.js +22 -0
- package/output/calculus/derivative/diff.d.ts +30 -0
- package/output/calculus/derivative/diff.js +238 -0
- package/output/calculus/fresnel.d.ts +16 -0
- package/output/calculus/fresnel.js +39 -0
- package/output/calculus/integrate/byParts.d.ts +18 -0
- package/output/calculus/integrate/byParts.js +339 -0
- package/output/calculus/integrate/bySubstitution.d.ts +135 -0
- package/output/calculus/integrate/bySubstitution.js +411 -0
- package/output/calculus/integrate/integrate.d.ts +38 -0
- package/output/calculus/integrate/integrate.js +652 -0
- package/output/calculus/integrate/integrationTable.d.ts +2 -0
- package/output/calculus/integrate/integrationTable.js +914 -0
- package/output/calculus/integrate/utils.d.ts +28 -0
- package/output/calculus/integrate/utils.js +96 -0
- package/output/calculus/laplace/ilaplace.d.ts +31 -0
- package/output/calculus/laplace/ilaplace.js +192 -0
- package/output/calculus/laplace/ilaplaceTable.d.ts +2 -0
- package/output/calculus/laplace/ilaplaceTable.js +200 -0
- package/output/calculus/laplace/laplace.d.ts +22 -0
- package/output/calculus/laplace/laplace.js +109 -0
- package/output/calculus/laplace/laplaceTable.d.ts +2 -0
- package/output/calculus/laplace/laplaceTable.js +187 -0
- package/output/calculus/limit/limit.d.ts +35 -0
- package/output/calculus/limit/limit.js +1183 -0
- package/output/calculus/limit/limitsTable.d.ts +2 -0
- package/output/calculus/limit/limitsTable.js +7 -0
- package/output/core/Settings.d.ts +32 -0
- package/output/core/Settings.js +68 -0
- package/output/core/adapters.d.ts +18 -0
- package/output/core/adapters.js +40 -0
- package/output/core/classes/assumption/Assumption.d.ts +218 -0
- package/output/core/classes/assumption/Assumption.js +605 -0
- package/output/core/classes/assumption/assertiveFunctions.d.ts +6 -0
- package/output/core/classes/assumption/assertiveFunctions.js +64 -0
- package/output/core/classes/assumption/assume.d.ts +90 -0
- package/output/core/classes/assumption/assume.js +145 -0
- package/output/core/classes/collection/Collection.d.ts +107 -0
- package/output/core/classes/collection/Collection.js +231 -0
- package/output/core/classes/complex/Complex.d.ts +99 -0
- package/output/core/classes/complex/Complex.js +135 -0
- package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
- package/output/core/classes/decimalSet/DecimalSet.js +453 -0
- package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
- package/output/core/classes/dictionary/Dictionary.js +213 -0
- package/output/core/classes/equation/Equation.d.ts +256 -0
- package/output/core/classes/equation/Equation.js +350 -0
- package/output/core/classes/expression/CoeffObject.d.ts +100 -0
- package/output/core/classes/expression/CoeffObject.js +198 -0
- package/output/core/classes/expression/Expression.d.ts +1674 -0
- package/output/core/classes/expression/Expression.js +2332 -0
- package/output/core/classes/expression/analysis.d.ts +25 -0
- package/output/core/classes/expression/analysis.js +218 -0
- package/output/core/classes/expression/collect.d.ts +9 -0
- package/output/core/classes/expression/collect.js +49 -0
- package/output/core/classes/expression/format.d.ts +45 -0
- package/output/core/classes/expression/format.js +217 -0
- package/output/core/classes/expression/products.d.ts +23 -0
- package/output/core/classes/expression/products.js +115 -0
- package/output/core/classes/expression/shortcuts.d.ts +35 -0
- package/output/core/classes/expression/shortcuts.js +129 -0
- package/output/core/classes/expression/traversal.d.ts +31 -0
- package/output/core/classes/expression/traversal.js +216 -0
- package/output/core/classes/expression/trig.d.ts +25 -0
- package/output/core/classes/expression/trig.js +40 -0
- package/output/core/classes/expression/utils.d.ts +52 -0
- package/output/core/classes/expression/utils.js +189 -0
- package/output/core/classes/lookupTable/LookupTable.d.ts +12 -0
- package/output/core/classes/lookupTable/LookupTable.js +55 -0
- package/output/core/classes/matrix/Matrix.d.ts +227 -0
- package/output/core/classes/matrix/Matrix.js +889 -0
- package/output/core/classes/matrix/Sylvester.d.ts +11 -0
- package/output/core/classes/matrix/Sylvester.js +54 -0
- package/output/core/classes/matrix/functions.d.ts +26 -0
- package/output/core/classes/matrix/functions.js +52 -0
- package/output/core/classes/matrix/utils.d.ts +9 -0
- package/output/core/classes/matrix/utils.js +22 -0
- package/output/core/classes/parser/Parser.d.ts +480 -0
- package/output/core/classes/parser/Parser.js +1812 -0
- package/output/core/classes/parser/Token.d.ts +58 -0
- package/output/core/classes/parser/Token.js +137 -0
- package/output/core/classes/parser/constants.d.ts +160 -0
- package/output/core/classes/parser/constants.js +227 -0
- package/output/core/classes/parser/helpers.d.ts +21 -0
- package/output/core/classes/parser/helpers.js +42 -0
- package/output/core/classes/parser/operations/add.d.ts +15 -0
- package/output/core/classes/parser/operations/add.js +238 -0
- package/output/core/classes/parser/operations/comma.d.ts +7 -0
- package/output/core/classes/parser/operations/comma.js +11 -0
- package/output/core/classes/parser/operations/compare.d.ts +21 -0
- package/output/core/classes/parser/operations/compare.js +461 -0
- package/output/core/classes/parser/operations/divide.d.ts +2 -0
- package/output/core/classes/parser/operations/divide.js +72 -0
- package/output/core/classes/parser/operations/functions.d.ts +46 -0
- package/output/core/classes/parser/operations/functions.js +430 -0
- package/output/core/classes/parser/operations/multiply.d.ts +11 -0
- package/output/core/classes/parser/operations/multiply.js +321 -0
- package/output/core/classes/parser/operations/power.d.ts +48 -0
- package/output/core/classes/parser/operations/power.js +673 -0
- package/output/core/classes/parser/operations/subtract.d.ts +3 -0
- package/output/core/classes/parser/operations/subtract.js +35 -0
- package/output/core/classes/parser/preprocess.d.ts +14 -0
- package/output/core/classes/parser/preprocess.js +259 -0
- package/output/core/classes/parser/scripting/controlFlow.d.ts +121 -0
- package/output/core/classes/parser/scripting/controlFlow.js +355 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +10 -0
- package/output/core/classes/parser/scripting/evaluate.js +112 -0
- package/output/core/classes/parser/scripting/functions.d.ts +14 -0
- package/output/core/classes/parser/scripting/functions.js +59 -0
- package/output/core/classes/parser/scripting/scope.d.ts +35 -0
- package/output/core/classes/parser/scripting/scope.js +155 -0
- package/output/core/classes/parser/types.d.ts +125 -0
- package/output/core/classes/parser/types.js +2 -0
- package/output/core/classes/parser/wrappers/IndexedReference.d.ts +31 -0
- package/output/core/classes/parser/wrappers/IndexedReference.js +68 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +24 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.js +51 -0
- package/output/core/classes/polynomial/Polynomial.d.ts +500 -0
- package/output/core/classes/polynomial/Polynomial.js +1149 -0
- package/output/core/classes/polynomial/Term.d.ts +222 -0
- package/output/core/classes/polynomial/Term.js +430 -0
- package/output/core/classes/polynomial/functions.d.ts +69 -0
- package/output/core/classes/polynomial/functions.js +126 -0
- package/output/core/classes/polynomial/utils.d.ts +62 -0
- package/output/core/classes/polynomial/utils.js +206 -0
- package/output/core/classes/rational/Rational.d.ts +504 -0
- package/output/core/classes/rational/Rational.js +779 -0
- package/output/core/classes/seq/SEQ.d.ts +13 -0
- package/output/core/classes/seq/SEQ.js +137 -0
- package/output/core/classes/valuesSet/ValuesSet.d.ts +179 -0
- package/output/core/classes/valuesSet/ValuesSet.js +381 -0
- package/output/core/classes/vector/Vector.d.ts +222 -0
- package/output/core/classes/vector/Vector.js +497 -0
- package/output/core/classes/vector/functions.d.ts +28 -0
- package/output/core/classes/vector/functions.js +47 -0
- package/output/core/common/classes/MathematicalAggregate.d.ts +53 -0
- package/output/core/common/classes/MathematicalAggregate.js +140 -0
- package/output/core/common/classes/Scope.d.ts +62 -0
- package/output/core/common/classes/Scope.js +122 -0
- package/output/core/common/classes/StructuredEntity.d.ts +55 -0
- package/output/core/common/classes/StructuredEntity.js +151 -0
- package/output/core/common/common.d.ts +63 -0
- package/output/core/common/common.js +279 -0
- package/output/core/common/functions/functions.d.ts +14 -0
- package/output/core/common/functions/functions.js +33 -0
- package/output/core/common/functions/structuredEntityUtils.d.ts +27 -0
- package/output/core/common/functions/structuredEntityUtils.js +40 -0
- package/output/core/converters/BaseConverter.d.ts +97 -0
- package/output/core/converters/BaseConverter.js +405 -0
- package/output/core/converters/Converter.d.ts +111 -0
- package/output/core/converters/Converter.js +802 -0
- package/output/core/converters/Pattern.d.ts +71 -0
- package/output/core/converters/Pattern.js +302 -0
- package/output/core/dispatch.d.ts +34 -0
- package/output/core/dispatch.js +304 -0
- package/output/core/errors.d.ts +531 -0
- package/output/core/errors.js +621 -0
- package/output/core/functions/bigint/bigint.d.ts +121 -0
- package/output/core/functions/bigint/bigint.js +392 -0
- package/output/core/functions/bigint/primeFactor.d.ts +49 -0
- package/output/core/functions/bigint/primeFactor.js +267 -0
- package/output/core/functions/bigint/primes.d.ts +1 -0
- package/output/core/functions/bigint/primes.js +11 -0
- package/output/core/functions/build/definitions.d.ts +12 -0
- package/output/core/functions/build/definitions.js +133 -0
- package/output/core/functions/build/index.d.ts +32 -0
- package/output/core/functions/build/index.js +136 -0
- package/output/core/functions/complex.d.ts +90 -0
- package/output/core/functions/complex.js +482 -0
- package/output/core/functions/decimal.d.ts +24 -0
- package/output/core/functions/decimal.js +664 -0
- package/output/core/functions/expand/expand.d.ts +42 -0
- package/output/core/functions/expand/expand.js +376 -0
- package/output/core/functions/fresnelNumeric.d.ts +12 -0
- package/output/core/functions/fresnelNumeric.js +123 -0
- package/output/core/functions/numeric.d.ts +140 -0
- package/output/core/functions/numeric.js +790 -0
- package/output/core/functions/rationalNormalization.d.ts +11 -0
- package/output/core/functions/rationalNormalization.js +117 -0
- package/output/core/functions/setFunction.d.ts +19 -0
- package/output/core/functions/setFunction.js +75 -0
- package/output/core/functions/string.d.ts +26 -0
- package/output/core/functions/string.js +101 -0
- package/output/core/functions/subst.d.ts +90 -0
- package/output/core/functions/subst.js +498 -0
- package/output/core/functions/utils.d.ts +24 -0
- package/output/core/functions/utils.js +51 -0
- package/output/core/types.d.ts +48 -0
- package/output/core/types.js +2 -0
- package/output/index.d.ts +339 -0
- package/output/index.js +715 -0
- package/output/math/defint/defintDecimal.d.ts +37 -0
- package/output/math/defint/defintDecimal.js +320 -0
- package/output/math/defint/defintNative.d.ts +57 -0
- package/output/math/defint/defintNative.js +292 -0
- package/output/math/geometry.d.ts +8 -0
- package/output/math/geometry.js +32 -0
- package/output/math/math.d.ts +655 -0
- package/output/math/math.js +1811 -0
- package/output/math/trig.d.ts +518 -0
- package/output/math/trig.js +1444 -0
- package/output/math/trunc.d.ts +19 -0
- package/output/math/trunc.js +36 -0
- package/output/math/utils.d.ts +60 -0
- package/output/math/utils.js +180 -0
- package/output/solve/classes/DecimalMatrix.d.ts +17 -0
- package/output/solve/classes/DecimalMatrix.js +86 -0
- package/output/solve/classes/FunctionSolver.d.ts +135 -0
- package/output/solve/classes/FunctionSolver.js +433 -0
- package/output/solve/classes/MultivariateSolver.d.ts +84 -0
- package/output/solve/classes/MultivariateSolver.js +240 -0
- package/output/solve/classes/PolynomialSolver.d.ts +85 -0
- package/output/solve/classes/PolynomialSolver.js +292 -0
- package/output/solve/classes/SolutionSet.d.ts +153 -0
- package/output/solve/classes/SolutionSet.js +357 -0
- package/output/solve/classes/Solver.d.ts +17 -0
- package/output/solve/classes/Solver.js +132 -0
- package/output/solve/classes/SymbolicSolver.d.ts +74 -0
- package/output/solve/classes/SymbolicSolver.js +601 -0
- package/output/solve/linsolve.d.ts +51 -0
- package/output/solve/linsolve.js +225 -0
- package/output/solve/solve.d.ts +34 -0
- package/output/solve/solve.js +260 -0
- package/output/solve/solveSystem.d.ts +31 -0
- package/output/solve/solveSystem.js +290 -0
- package/output/solve/utils.d.ts +9 -0
- package/output/solve/utils.js +62 -0
- package/output/utils/array.d.ts +42 -0
- package/output/utils/array.js +98 -0
- package/output/utils/debug.d.ts +131 -0
- package/output/utils/debug.js +295 -0
- package/output/utils/decimal.d.ts +3 -0
- package/output/utils/decimal.js +16 -0
- package/output/utils/numeric.d.ts +14 -0
- package/output/utils/numeric.js +51 -0
- package/output/utils/object.d.ts +26 -0
- package/output/utils/object.js +56 -0
- package/package.json +213 -57
- package/.travis.yml +0 -3
- package/Algebra.js +0 -4568
- package/BREAKING_CHANGES.md +0 -5
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -14
- package/Calculus.js +0 -2675
- package/Extra.js +0 -622
- package/Solve.js +0 -1783
- package/all.js +0 -16
- package/all.min.js +0 -1
- package/gulpfile.js +0 -16
- package/index.html +0 -158
- package/license.txt +0 -19
- package/nerdamer.core.js +0 -12510
- package/spec/LaTeX.spec.js +0 -302
- package/spec/TeXConvert.spec.js +0 -8
- package/spec/algebra.spec.js +0 -287
- package/spec/basic_parser.spec.js +0 -134
- package/spec/build.spec.js +0 -131
- package/spec/calculus.spec.js +0 -183
- package/spec/core.spec.js +0 -2970
- package/spec/extra.spec.js +0 -54
- package/spec/solve.spec.js +0 -126
- package/spec/support/jasmine.json +0 -11
- package/spec/support/utils.js +0 -42
- package/spec/text.spec.js +0 -132
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.zippelGCDMulti = zippelGCDMulti;
|
|
4
|
+
const arith_1 = require("./arith");
|
|
5
|
+
const MultiPoly_1 = require("./multiPoly/MultiPoly");
|
|
6
|
+
const poly_1 = require("./poly");
|
|
7
|
+
const rational_1 = require("./rational");
|
|
8
|
+
const DEFAULT_ZIPPEL_MAX_TRIES = 32;
|
|
9
|
+
const CANDIDATE_VERIFICATION_SAMPLES = 6;
|
|
10
|
+
const CANDIDATE_VERIFICATION_SEED_BASE = 900000;
|
|
11
|
+
const FALLBACK_SPECIALIZATION_ATTEMPTS = 8;
|
|
12
|
+
const MAX_SCHEDULED_GRID_SAMPLES = 64;
|
|
13
|
+
const FALLBACK_ATTEMPT_SEED_STRIDE = 1_000_000;
|
|
14
|
+
const FALLBACK_ROUND_SEED_STRIDE = 100_000;
|
|
15
|
+
const SUPERFLUOUS_VARIABLE_EVALUATION_PRIMES = [
|
|
16
|
+
17n, 19n, 23n, 29n, 31n, 37n, 41n, 43n, 47n, 53n,
|
|
17
|
+
];
|
|
18
|
+
const INTERPOLATION_SAMPLE_PRIMES = [
|
|
19
|
+
2n, 3n, 5n, 7n, 11n, 13n, 17n, 19n, 23n, 29n, 31n, 37n, 41n, 43n, 47n,
|
|
20
|
+
];
|
|
21
|
+
const MIN_INTERPOLATION_POINTS = 3;
|
|
22
|
+
const MAX_INTERPOLATION_POINTS = 15;
|
|
23
|
+
const RANDOM_64_BIT_MASK = (1n << 64n) - 1n;
|
|
24
|
+
const RANDOM_32_BIT_SHIFT = 32n;
|
|
25
|
+
const RANDOM_32_BIT_MASK = 0xffffffffn;
|
|
26
|
+
const RANDOM_LCG_MULTIPLIER = 6364136223846793005n;
|
|
27
|
+
const RANDOM_LCG_INCREMENT = 1442695040888963407n;
|
|
28
|
+
const RANDOM_HASH_OFFSET = 1469598103934665603n;
|
|
29
|
+
const RANDOM_HASH_PRIME = 1099511628211n;
|
|
30
|
+
const RANDOM_HASH_SEED_XOR = 0x9e3779b97f4a7c15n;
|
|
31
|
+
const RANDOM_EVAL_MIN_VALUE = 2n;
|
|
32
|
+
const RANDOM_EVAL_VALUE_RANGE = 96n;
|
|
33
|
+
/**
|
|
34
|
+
* Public API for multivariate integer GCD in the canonical `MultiPoly` representation.
|
|
35
|
+
*/
|
|
36
|
+
function zippelGCDMulti(f, g, vars, opts = {}) {
|
|
37
|
+
return zippelGCD(f, g, vars, opts);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute the greatest common divisor of two multivariate integer polynomials.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* This is a Zippel/Wang-style approach:
|
|
44
|
+
* - reduce to modular images (Fp)
|
|
45
|
+
* - evaluate/specialize variables to univariate instances
|
|
46
|
+
* - lift/interpolate back to a multivariate gcd
|
|
47
|
+
*/
|
|
48
|
+
function zippelGCD(f, g, vars, opts = {}) {
|
|
49
|
+
if (vars.length === 0) {
|
|
50
|
+
throw new Error('zippelGCD: no variables');
|
|
51
|
+
}
|
|
52
|
+
const fNorm = (0, poly_1.mvNormalize)(f);
|
|
53
|
+
const gNorm = (0, poly_1.mvNormalize)(g);
|
|
54
|
+
// Handle zero cases up front
|
|
55
|
+
if (fNorm.terms.size === 0 && gNorm.terms.size === 0) {
|
|
56
|
+
return MultiPoly_1.MultiPoly.zero();
|
|
57
|
+
}
|
|
58
|
+
if (fNorm.terms.size === 0) {
|
|
59
|
+
return normalizeSignLex(gNorm, vars);
|
|
60
|
+
}
|
|
61
|
+
if (gNorm.terms.size === 0) {
|
|
62
|
+
return normalizeSignLex(fNorm, vars);
|
|
63
|
+
}
|
|
64
|
+
// Remove coefficient content first
|
|
65
|
+
const F = (0, poly_1.mvDivideByCoeffContent)(fNorm);
|
|
66
|
+
const G = (0, poly_1.mvDivideByCoeffContent)(gNorm);
|
|
67
|
+
const content = (0, arith_1.gcd)(F.content, G.content);
|
|
68
|
+
// OPTIMIZATION: Detect and substitute out variables that appear in only one polynomial.
|
|
69
|
+
// Such variables cannot appear in the GCD (since the GCD must divide both polynomials).
|
|
70
|
+
// We substitute them with primes, then drop those variables and recurse.
|
|
71
|
+
{
|
|
72
|
+
const fPrimMP0 = new MultiPoly_1.MultiPoly(F.primitive.terms);
|
|
73
|
+
const gPrimMP0 = new MultiPoly_1.MultiPoly(G.primitive.terms);
|
|
74
|
+
const activeInF = fPrimMP0.variables();
|
|
75
|
+
const activeInG = gPrimMP0.variables();
|
|
76
|
+
const superfluousVars = [];
|
|
77
|
+
for (let i = 0; i < vars.length; i++) {
|
|
78
|
+
const inF = activeInF.has(i);
|
|
79
|
+
const inG = activeInG.has(i);
|
|
80
|
+
if (inF !== inG) {
|
|
81
|
+
superfluousVars.push({ idx: i, name: vars[i] });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (superfluousVars.length > 0) {
|
|
85
|
+
let fReducedMP = fPrimMP0;
|
|
86
|
+
let gReducedMP = gPrimMP0;
|
|
87
|
+
const varsReduced = [...vars];
|
|
88
|
+
for (let i = 0; i < superfluousVars.length; i++) {
|
|
89
|
+
const { idx } = superfluousVars[i];
|
|
90
|
+
const prime = SUPERFLUOUS_VARIABLE_EVALUATION_PRIMES[i % SUPERFLUOUS_VARIABLE_EVALUATION_PRIMES.length];
|
|
91
|
+
fReducedMP = (0, poly_1.substituteVarIndex)(fReducedMP, idx, prime);
|
|
92
|
+
gReducedMP = (0, poly_1.substituteVarIndex)(gReducedMP, idx, prime);
|
|
93
|
+
}
|
|
94
|
+
const sortedByIdxDesc = [...superfluousVars].sort((a, b) => b.idx - a.idx);
|
|
95
|
+
for (const { idx } of sortedByIdxDesc) {
|
|
96
|
+
fReducedMP = (0, poly_1.removeVarIndex)(fReducedMP, idx);
|
|
97
|
+
gReducedMP = (0, poly_1.removeVarIndex)(gReducedMP, idx);
|
|
98
|
+
varsReduced.splice(idx, 1);
|
|
99
|
+
}
|
|
100
|
+
// Reduced to constants?
|
|
101
|
+
//
|
|
102
|
+
// IMPORTANT:
|
|
103
|
+
// At this point these constants are evaluation artifacts produced by substituting
|
|
104
|
+
// variables that occur in only one input. Their numeric gcd is NOT, in general,
|
|
105
|
+
// the polynomial gcd. Example:
|
|
106
|
+
// gcd(x+z, y+1) should be 1, but gcd((x+17), 18) can be some accidental integer.
|
|
107
|
+
//
|
|
108
|
+
// So when everything has been reduced away, the only safe gcd to return here is
|
|
109
|
+
// the coefficient content gcd (or 1 for primitive inputs), not gcd(fConst, gConst).
|
|
110
|
+
if (varsReduced.length === 0) {
|
|
111
|
+
return MultiPoly_1.MultiPoly.constant(content === 0n ? 1n : content);
|
|
112
|
+
}
|
|
113
|
+
const fReducedMV = fReducedMP;
|
|
114
|
+
const gReducedMV = gReducedMP;
|
|
115
|
+
let reducedMainVar = opts.mainVar ?? vars[0];
|
|
116
|
+
if (!varsReduced.includes(reducedMainVar)) {
|
|
117
|
+
reducedMainVar = varsReduced[0];
|
|
118
|
+
}
|
|
119
|
+
const reducedGcd = zippelGCD(fReducedMV, gReducedMV, varsReduced, {
|
|
120
|
+
...opts,
|
|
121
|
+
mainVar: reducedMainVar,
|
|
122
|
+
});
|
|
123
|
+
let outMP = reducedGcd.clone();
|
|
124
|
+
const outVars = [...varsReduced];
|
|
125
|
+
const sortedByIdxAsc = [...superfluousVars].sort((a, b) => a.idx - b.idx);
|
|
126
|
+
for (const { idx, name } of sortedByIdxAsc) {
|
|
127
|
+
outMP = (0, poly_1.addVarIndex)(outMP, idx);
|
|
128
|
+
outVars.splice(idx, 0, name);
|
|
129
|
+
}
|
|
130
|
+
let result = outMP;
|
|
131
|
+
if (content !== 1n && content !== 0n) {
|
|
132
|
+
result = (0, poly_1.scalePoly)(result, content);
|
|
133
|
+
}
|
|
134
|
+
return normalizeSignLex((0, poly_1.mvNormalize)(result), vars);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const mainVar = opts.mainVar ?? vars[0];
|
|
138
|
+
const maxTries = opts.maxTries ?? DEFAULT_ZIPPEL_MAX_TRIES;
|
|
139
|
+
const fPrimMP = new MultiPoly_1.MultiPoly(F.primitive.terms);
|
|
140
|
+
const gPrimMP = new MultiPoly_1.MultiPoly(G.primitive.terms);
|
|
141
|
+
// 1) Find a "good" specialization to get a correct univariate gcd in mainVar
|
|
142
|
+
let baseValues = null;
|
|
143
|
+
let hBase = null;
|
|
144
|
+
const gcdDegCounts = new Map();
|
|
145
|
+
let degFMain = -1;
|
|
146
|
+
let degGMain = -1;
|
|
147
|
+
for (let t = 0; t < maxTries; t++) {
|
|
148
|
+
const values = randomEvalPoint(vars, mainVar, t);
|
|
149
|
+
const fu = evalToUnivariate(fPrimMP, vars, mainVar, values);
|
|
150
|
+
const gu = evalToUnivariate(gPrimMP, vars, mainVar, values);
|
|
151
|
+
if (uniIsZeroBig(fu) || uniIsZeroBig(gu)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const dF = fu.length - 1;
|
|
155
|
+
const dG = gu.length - 1;
|
|
156
|
+
if (degFMain < 0) {
|
|
157
|
+
degFMain = dF;
|
|
158
|
+
degGMain = dG;
|
|
159
|
+
}
|
|
160
|
+
if (dF !== degFMain || dG !== degGMain) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const hu = (0, poly_1.zNormalizePrimitiveSign)((0, poly_1.zGcdFull)(fu, gu)).primitive;
|
|
165
|
+
const hdeg = hu.length - 1;
|
|
166
|
+
if (hdeg <= 0) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const prev = gcdDegCounts.get(hdeg) ?? 0;
|
|
170
|
+
const next = prev + 1;
|
|
171
|
+
gcdDegCounts.set(hdeg, next);
|
|
172
|
+
if (next >= 2 && (!hBase || hdeg > hBase.length - 1)) {
|
|
173
|
+
baseValues = values;
|
|
174
|
+
hBase = (0, poly_1.zNormalizePrimitiveSign)(hu).primitive;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!baseValues || !hBase) {
|
|
182
|
+
if (opts.throwOnBudget) {
|
|
183
|
+
const degrees = {};
|
|
184
|
+
for (const [deg, cnt] of gcdDegCounts.entries()) {
|
|
185
|
+
degrees[String(deg)] = cnt;
|
|
186
|
+
}
|
|
187
|
+
throw new arith_1.GcdBudgetExceededError('zippelGCD: could not find a good specialization point within budget', {
|
|
188
|
+
stage: 'base-specialization',
|
|
189
|
+
vars: [...vars],
|
|
190
|
+
mainVar,
|
|
191
|
+
maxTries,
|
|
192
|
+
degFMain,
|
|
193
|
+
degGMain,
|
|
194
|
+
gcdDegreeHistogram: degrees,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return MultiPoly_1.MultiPoly.constant(content === 0n ? 1n : content);
|
|
198
|
+
}
|
|
199
|
+
const mainIdx = vars.indexOf(mainVar);
|
|
200
|
+
const otherVars = vars.filter(v => v !== mainVar);
|
|
201
|
+
const hDeg = hBase.length - 1;
|
|
202
|
+
function sameUni(a, b) {
|
|
203
|
+
const aa = (0, poly_1.zNormalizePrimitiveSign)(a).primitive;
|
|
204
|
+
const bb = (0, poly_1.zNormalizePrimitiveSign)(b).primitive;
|
|
205
|
+
if (aa.length !== bb.length) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
for (let i = 0; i < aa.length; i++) {
|
|
209
|
+
if (aa[i] !== bb[i]) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
function verifyCandidate(Hcand) {
|
|
216
|
+
for (let k = 0; k < CANDIDATE_VERIFICATION_SAMPLES; k++) {
|
|
217
|
+
const values = randomEvalPoint(vars, mainVar, CANDIDATE_VERIFICATION_SEED_BASE + k);
|
|
218
|
+
const fu = evalToUnivariate(fPrimMP, vars, mainVar, values);
|
|
219
|
+
const gu = evalToUnivariate(gPrimMP, vars, mainVar, values);
|
|
220
|
+
if (uniIsZeroBig(fu) || uniIsZeroBig(gu)) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const hu = (0, poly_1.zNormalizePrimitiveSign)((0, poly_1.zGcdFull)(fu, gu)).primitive;
|
|
224
|
+
if (hu.length - 1 !== hDeg) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const Hu = evalToUnivariate(Hcand, vars, mainVar, values);
|
|
228
|
+
if (!sameUni(Hu, hu)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
let best = null;
|
|
235
|
+
for (let attempt = 0; attempt < FALLBACK_SPECIALIZATION_ATTEMPTS; attempt++) {
|
|
236
|
+
const coeffPolys = new Array(hDeg + 1);
|
|
237
|
+
for (let d = 0; d <= hDeg; d++) {
|
|
238
|
+
coeffPolys[d] = MultiPoly_1.MultiPoly.zero();
|
|
239
|
+
}
|
|
240
|
+
// Each sampled point produces the complete univariate GCD. Reuse that result for
|
|
241
|
+
// every coefficient instead of recomputing the same GCD hDeg + 1 times.
|
|
242
|
+
const gcdSampleSets = new Map();
|
|
243
|
+
for (let d = 0; d <= hDeg; d++) {
|
|
244
|
+
let polyDmv = null;
|
|
245
|
+
for (let r = 0; r < 4 && !polyDmv; r++) {
|
|
246
|
+
let gcdSamples = gcdSampleSets.get(r);
|
|
247
|
+
if (!gcdSamples) {
|
|
248
|
+
gcdSamples = sampleGcdAcrossPoints(F.primitive, G.primitive, vars, mainVar, Math.min(maxTries * (r + 1), MAX_SCHEDULED_GRID_SAMPLES), attempt * FALLBACK_ATTEMPT_SEED_STRIDE + r * FALLBACK_ROUND_SEED_STRIDE, opts.gridMap);
|
|
249
|
+
gcdSampleSets.set(r, gcdSamples);
|
|
250
|
+
}
|
|
251
|
+
const samples = gcdSamples.map(sample => ({
|
|
252
|
+
values: sample.values,
|
|
253
|
+
y: d < sample.coefficients.length ? sample.coefficients[d] : 0n,
|
|
254
|
+
}));
|
|
255
|
+
try {
|
|
256
|
+
polyDmv = interpolateCoeffAsMV(vars, otherVars, samples);
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
polyDmv = null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!polyDmv) {
|
|
263
|
+
throw new Error('zippelGCD: coefficient interpolation failed (non-integer)');
|
|
264
|
+
}
|
|
265
|
+
coeffPolys[d] = polyDmv.clone();
|
|
266
|
+
}
|
|
267
|
+
let Hmp = MultiPoly_1.MultiPoly.zero();
|
|
268
|
+
for (let d = 0; d <= hDeg; d++) {
|
|
269
|
+
if (coeffPolys[d].terms.size === 0) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (d === 0) {
|
|
273
|
+
Hmp = (0, poly_1.addPoly)(Hmp, coeffPolys[d]);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const dense = new Array(vars.length).fill(0);
|
|
277
|
+
dense[mainIdx] = d;
|
|
278
|
+
const mon = new MultiPoly_1.MultiPoly();
|
|
279
|
+
mon.terms.set((0, poly_1.denseToKey)(dense), 1n);
|
|
280
|
+
Hmp = (0, poly_1.addPoly)(Hmp, (0, poly_1.mulPoly)(coeffPolys[d], mon));
|
|
281
|
+
}
|
|
282
|
+
if (content !== 1n && content !== 0n) {
|
|
283
|
+
Hmp = (0, poly_1.scalePoly)(Hmp, content);
|
|
284
|
+
}
|
|
285
|
+
Hmp = (0, poly_1.mvNormalize)(Hmp);
|
|
286
|
+
Hmp = stripParamFactorFromMainVarCoeffsMP(Hmp, vars, mainVar);
|
|
287
|
+
let H = Hmp.clone();
|
|
288
|
+
H = normalizeSignLex(H, vars);
|
|
289
|
+
best = H;
|
|
290
|
+
if (verifyCandidate(H)) {
|
|
291
|
+
return H;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return best ? best : (0, poly_1.mvNormalize)(MultiPoly_1.MultiPoly.zero());
|
|
295
|
+
}
|
|
296
|
+
function sampleGcdAcrossPoints(f, g, vars, mainVar, maxTries, seedOffset, gridMap) {
|
|
297
|
+
const out = [];
|
|
298
|
+
const otherVars = vars.filter(v => v !== mainVar);
|
|
299
|
+
function maxDegInVar(p, v) {
|
|
300
|
+
const idx = vars.indexOf(v);
|
|
301
|
+
if (idx < 0) {
|
|
302
|
+
return 0;
|
|
303
|
+
}
|
|
304
|
+
let m = 0;
|
|
305
|
+
for (const k of p.terms.keys()) {
|
|
306
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
307
|
+
const d = exp.get(idx) ?? 0;
|
|
308
|
+
if (d > m) {
|
|
309
|
+
m = d;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return m;
|
|
313
|
+
}
|
|
314
|
+
function pointsForVar(v) {
|
|
315
|
+
const fromMap = gridMap?.[v];
|
|
316
|
+
if (fromMap && fromMap.length) {
|
|
317
|
+
return fromMap.slice();
|
|
318
|
+
}
|
|
319
|
+
// Use small primes as evaluation points to minimize gcd issues.
|
|
320
|
+
// When evaluating ax² - b at points where gcd(a,b) > 1, the univariate
|
|
321
|
+
// GCD content varies, breaking interpolation. Using primes helps avoid this.
|
|
322
|
+
if (otherVars.length && v === otherVars[0]) {
|
|
323
|
+
const bound = Math.min(maxDegInVar(f, v), maxDegInVar(g, v));
|
|
324
|
+
const n = Math.min(Math.max(bound + 1, MIN_INTERPOLATION_POINTS), MAX_INTERPOLATION_POINTS); // cap to avoid combinatorial blowup
|
|
325
|
+
return INTERPOLATION_SAMPLE_PRIMES.slice(0, n);
|
|
326
|
+
}
|
|
327
|
+
return INTERPOLATION_SAMPLE_PRIMES.slice(0, MIN_INTERPOLATION_POINTS);
|
|
328
|
+
}
|
|
329
|
+
let expectedDegF = -1;
|
|
330
|
+
let expectedDegG = -1;
|
|
331
|
+
let expectedDegH = -1;
|
|
332
|
+
// Build a small cartesian grid over otherVars, capped by maxTries.
|
|
333
|
+
const cur = {};
|
|
334
|
+
function rec(i, budget) {
|
|
335
|
+
if (budget.n <= 0) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (i === otherVars.length) {
|
|
339
|
+
const values = { ...cur };
|
|
340
|
+
const fu = evalToUnivariate(f, vars, mainVar, values);
|
|
341
|
+
const gu = evalToUnivariate(g, vars, mainVar, values);
|
|
342
|
+
if (uniIsZeroBig(fu) || uniIsZeroBig(gu)) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const dF = fu.length - 1;
|
|
346
|
+
const dG = gu.length - 1;
|
|
347
|
+
// Prefer maximal degrees - degree drops indicate bad evaluation points
|
|
348
|
+
if (dF > expectedDegF || dG > expectedDegG) {
|
|
349
|
+
expectedDegF = Math.max(expectedDegF, dF);
|
|
350
|
+
expectedDegG = Math.max(expectedDegG, dG);
|
|
351
|
+
out.length = 0;
|
|
352
|
+
expectedDegH = -1;
|
|
353
|
+
}
|
|
354
|
+
if (expectedDegF < 0) {
|
|
355
|
+
expectedDegF = dF;
|
|
356
|
+
expectedDegG = dG;
|
|
357
|
+
}
|
|
358
|
+
if (dF !== expectedDegF || dG !== expectedDegG) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
// Compute the GCD
|
|
362
|
+
const huFull = (0, poly_1.zGcdFull)(fu, gu);
|
|
363
|
+
const hdeg = huFull.length - 1;
|
|
364
|
+
// Prefer the *maximal* gcd degree seen so far.
|
|
365
|
+
if (expectedDegH < 0 || hdeg > expectedDegH) {
|
|
366
|
+
expectedDegH = hdeg;
|
|
367
|
+
out.length = 0;
|
|
368
|
+
}
|
|
369
|
+
if (hdeg !== expectedDegH) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
out.push({ values, coefficients: huFull });
|
|
373
|
+
budget.n--;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const v = otherVars[i];
|
|
377
|
+
for (const pt of pointsForVar(v)) {
|
|
378
|
+
cur[v] = pt;
|
|
379
|
+
rec(i + 1, budget);
|
|
380
|
+
if (budget.n <= 0) {
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
rec(0, { n: maxTries });
|
|
386
|
+
// Fallback: if grid didn't produce enough, use independent random points.
|
|
387
|
+
for (let t = 0; out.length < Math.min(6, maxTries) && t < maxTries * 2; t++) {
|
|
388
|
+
const values = randomEvalPoint(vars, mainVar, seedOffset + 50000 + t);
|
|
389
|
+
const fu = evalToUnivariate(f, vars, mainVar, values);
|
|
390
|
+
const gu = evalToUnivariate(g, vars, mainVar, values);
|
|
391
|
+
if (uniIsZeroBig(fu) || uniIsZeroBig(gu)) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
const dF = fu.length - 1;
|
|
395
|
+
const dG = gu.length - 1;
|
|
396
|
+
if (dF > expectedDegF || dG > expectedDegG) {
|
|
397
|
+
expectedDegF = Math.max(expectedDegF, dF);
|
|
398
|
+
expectedDegG = Math.max(expectedDegG, dG);
|
|
399
|
+
out.length = 0;
|
|
400
|
+
expectedDegH = -1;
|
|
401
|
+
}
|
|
402
|
+
if (expectedDegF < 0) {
|
|
403
|
+
expectedDegF = dF;
|
|
404
|
+
expectedDegG = dG;
|
|
405
|
+
}
|
|
406
|
+
if (dF !== expectedDegF || dG !== expectedDegG) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
const hu = (0, poly_1.zGcdFull)(fu, gu);
|
|
410
|
+
const hdeg = hu.length - 1;
|
|
411
|
+
if (expectedDegH < 0 || hdeg > expectedDegH) {
|
|
412
|
+
expectedDegH = hdeg;
|
|
413
|
+
out.length = 0;
|
|
414
|
+
}
|
|
415
|
+
if (hdeg !== expectedDegH) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
out.push({ values, coefficients: hu });
|
|
419
|
+
}
|
|
420
|
+
if (out.length === 0) {
|
|
421
|
+
return [{ values: randomEvalPoint(vars, mainVar, 9999), coefficients: [] }];
|
|
422
|
+
}
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
// Dense variable-by-variable interpolation for coeff(otherVars).
|
|
426
|
+
// This is the “practical” piece: it assumes low degrees and uses exact integer divisions.
|
|
427
|
+
// For bigger/heavier cases, you’ll want modular interpolation instead.
|
|
428
|
+
function interpolateCoeffAsMV(vars, otherVars, samples) {
|
|
429
|
+
// True nested interpolation over otherVars with rational intermediate coeffs.
|
|
430
|
+
function groupKey(rest, values) {
|
|
431
|
+
return rest.map(v => `${v}=${values[v] ?? 0n}`).join('|');
|
|
432
|
+
}
|
|
433
|
+
function recInterpolate(varsLeft, ss) {
|
|
434
|
+
if (varsLeft.length === 0) {
|
|
435
|
+
const p = zeroMVF(vars);
|
|
436
|
+
p.terms.set((0, poly_1.denseToKey)(new Array(vars.length).fill(0)), ss[0]?.y ?? (0, rational_1.rat)(0n));
|
|
437
|
+
return p;
|
|
438
|
+
}
|
|
439
|
+
const x = varsLeft[0];
|
|
440
|
+
const rest = varsLeft.slice(1);
|
|
441
|
+
const idx = vars.indexOf(x);
|
|
442
|
+
if (idx < 0) {
|
|
443
|
+
throw new Error('interpolateCoeffAsMV: missing var index');
|
|
444
|
+
}
|
|
445
|
+
// group by rest assignments
|
|
446
|
+
const groups = new Map();
|
|
447
|
+
for (const s of ss) {
|
|
448
|
+
const k = groupKey(rest, s.values);
|
|
449
|
+
const arr = groups.get(k) ?? [];
|
|
450
|
+
arr.push({ x: s.values[x] ?? 0n, y: s.y, values: s.values });
|
|
451
|
+
groups.set(k, arr);
|
|
452
|
+
}
|
|
453
|
+
// For each group, interpolate univariate in x to obtain coeffs (Rat[]) at that rest point.
|
|
454
|
+
// IMPORTANT: do this in two passes so early groups are padded if a later group increases max degree.
|
|
455
|
+
const groupUnis = [];
|
|
456
|
+
let maxDeg = 0;
|
|
457
|
+
for (const arr of groups.values()) {
|
|
458
|
+
arr.sort((a, b) => (a.x < b.x ? -1 : a.x > b.x ? 1 : 0));
|
|
459
|
+
const pts = arr.map(p => ({ x: p.x, y: p.y }));
|
|
460
|
+
const uni = (0, rational_1.interpolateUnivariateRat)(pts);
|
|
461
|
+
maxDeg = Math.max(maxDeg, uni.length - 1);
|
|
462
|
+
groupUnis.push({ values: arr[0].values, uni });
|
|
463
|
+
}
|
|
464
|
+
const coeffSamples = new Array(maxDeg + 1);
|
|
465
|
+
for (let d = 0; d <= maxDeg; d++) {
|
|
466
|
+
coeffSamples[d] = [];
|
|
467
|
+
}
|
|
468
|
+
for (const gu of groupUnis) {
|
|
469
|
+
for (let d = 0; d <= maxDeg; d++) {
|
|
470
|
+
coeffSamples[d].push({
|
|
471
|
+
values: gu.values,
|
|
472
|
+
y: d < gu.uni.length ? gu.uni[d] : (0, rational_1.rat)(0n),
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
let outF = zeroMVF(vars);
|
|
477
|
+
for (let d = 0; d < coeffSamples.length; d++) {
|
|
478
|
+
const sub = recInterpolate(rest, coeffSamples[d]);
|
|
479
|
+
outF = addMVF(outF, shiftMVF(sub, idx, d));
|
|
480
|
+
}
|
|
481
|
+
return outF;
|
|
482
|
+
}
|
|
483
|
+
const ssRat = samples.map(s => ({ values: s.values, y: (0, rational_1.rat)(s.y) }));
|
|
484
|
+
const polyF = recInterpolate(otherVars, ssRat);
|
|
485
|
+
return mvfToInt(polyF);
|
|
486
|
+
}
|
|
487
|
+
function zeroMVF(vars) {
|
|
488
|
+
return { vars, terms: new Map() };
|
|
489
|
+
}
|
|
490
|
+
function addMVF(a, b) {
|
|
491
|
+
const out = { vars: a.vars, terms: new Map(a.terms) };
|
|
492
|
+
(0, poly_1.mapCombineInPlace)(out.terms, b.terms, (x, y) => (0, rational_1.ratAdd)(x, y), v => v.n === 0n, () => (0, rational_1.rat)(0n));
|
|
493
|
+
return out;
|
|
494
|
+
}
|
|
495
|
+
function shiftMVF(p, varIdx, pow) {
|
|
496
|
+
const out = zeroMVF(p.vars);
|
|
497
|
+
for (const [k, c] of p.terms.entries()) {
|
|
498
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
499
|
+
exp.set(varIdx, (exp.get(varIdx) ?? 0) + pow);
|
|
500
|
+
out.terms.set((0, MultiPoly_1.expToKey)(exp), c);
|
|
501
|
+
}
|
|
502
|
+
return out;
|
|
503
|
+
}
|
|
504
|
+
function mvfToInt(p) {
|
|
505
|
+
const out = MultiPoly_1.MultiPoly.zero();
|
|
506
|
+
let lcmDen = 1n;
|
|
507
|
+
for (const c of p.terms.values()) {
|
|
508
|
+
if (c.n === 0n) {
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
const d = c.d < 0n ? -c.d : c.d;
|
|
512
|
+
lcmDen = (lcmDen / (0, arith_1.gcd)(lcmDen, d)) * d;
|
|
513
|
+
}
|
|
514
|
+
for (const [k, c] of p.terms.entries()) {
|
|
515
|
+
if (c.n === 0n) {
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const scaled = (0, rational_1.ratMul)(c, (0, rational_1.rat)(lcmDen));
|
|
519
|
+
if (scaled.d !== 1n) {
|
|
520
|
+
throw new Error('interpolateCoeffAsMV: failed to clear denominators');
|
|
521
|
+
}
|
|
522
|
+
out.terms.set(k, scaled.n);
|
|
523
|
+
}
|
|
524
|
+
return (0, poly_1.mvNormalize)(out);
|
|
525
|
+
}
|
|
526
|
+
function randomEvalPoint(vars, mainVar, seed) {
|
|
527
|
+
const values = {};
|
|
528
|
+
let state = BigInt(seed) ^ RANDOM_HASH_SEED_XOR;
|
|
529
|
+
function nextU32() {
|
|
530
|
+
state = (state * RANDOM_LCG_MULTIPLIER + RANDOM_LCG_INCREMENT) & RANDOM_64_BIT_MASK;
|
|
531
|
+
return (state >> RANDOM_32_BIT_SHIFT) & RANDOM_32_BIT_MASK;
|
|
532
|
+
}
|
|
533
|
+
function hashVar(s) {
|
|
534
|
+
let h = RANDOM_HASH_OFFSET;
|
|
535
|
+
for (let i = 0; i < s.length; i++) {
|
|
536
|
+
h ^= BigInt(s.charCodeAt(i));
|
|
537
|
+
h *= RANDOM_HASH_PRIME;
|
|
538
|
+
h &= RANDOM_64_BIT_MASK;
|
|
539
|
+
}
|
|
540
|
+
return h;
|
|
541
|
+
}
|
|
542
|
+
for (const v of vars) {
|
|
543
|
+
if (v === mainVar) {
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
state ^= hashVar(v);
|
|
547
|
+
const r = nextU32();
|
|
548
|
+
values[v] = RANDOM_EVAL_MIN_VALUE + (r % RANDOM_EVAL_VALUE_RANGE);
|
|
549
|
+
}
|
|
550
|
+
return values;
|
|
551
|
+
}
|
|
552
|
+
// Treat H as a univariate in mainVar with coefficients in Z[otherVars].
|
|
553
|
+
// Compute gcd of all coefficient-polynomials in otherVars and divide it out.
|
|
554
|
+
// This removes spurious parameter-only scaling factors that survive specialization.
|
|
555
|
+
function stripParamFactorFromMainVarCoeffsMP(H, vars, mainVar) {
|
|
556
|
+
const mainIdx = vars.indexOf(mainVar);
|
|
557
|
+
if (mainIdx < 0) {
|
|
558
|
+
return H;
|
|
559
|
+
}
|
|
560
|
+
const otherVars = vars.filter(v => v !== mainVar);
|
|
561
|
+
if (otherVars.length === 0) {
|
|
562
|
+
return H;
|
|
563
|
+
}
|
|
564
|
+
let maxDeg = 0;
|
|
565
|
+
for (const k of H.terms.keys()) {
|
|
566
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
567
|
+
const d = exp.get(mainIdx) ?? 0;
|
|
568
|
+
if (d > maxDeg) {
|
|
569
|
+
maxDeg = d;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
const coeffs = new Array(maxDeg + 1);
|
|
573
|
+
for (let d = 0; d <= maxDeg; d++) {
|
|
574
|
+
coeffs[d] = MultiPoly_1.MultiPoly.zero();
|
|
575
|
+
}
|
|
576
|
+
for (const [k, c] of H.terms.entries()) {
|
|
577
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
578
|
+
const d = exp.get(mainIdx) ?? 0;
|
|
579
|
+
const expOther = new Map(exp);
|
|
580
|
+
expOther.delete(mainIdx);
|
|
581
|
+
const kk = (0, MultiPoly_1.expToKey)(expOther);
|
|
582
|
+
coeffs[d].terms.set(kk, (coeffs[d].terms.get(kk) ?? 0n) + c);
|
|
583
|
+
}
|
|
584
|
+
for (const p of coeffs) {
|
|
585
|
+
p.trim();
|
|
586
|
+
}
|
|
587
|
+
let Gc = null;
|
|
588
|
+
for (const cpoly of coeffs) {
|
|
589
|
+
if (cpoly.terms.size === 0) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
Gc = Gc ? zippelGCDMulti(Gc, cpoly, vars, { mainVar: otherVars[0], maxTries: 24 }) : cpoly;
|
|
593
|
+
if (Gc.terms.size !== 0) {
|
|
594
|
+
const gcn = (0, poly_1.mvNormalizePrimitiveSignLex)(Gc).primitive;
|
|
595
|
+
if (gcn.terms.size === 1 && (gcn.terms.get('') ?? 0n) === 1n) {
|
|
596
|
+
Gc = gcn;
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (!Gc) {
|
|
602
|
+
return H;
|
|
603
|
+
}
|
|
604
|
+
Gc = (0, poly_1.mvNormalizePrimitiveSignLex)(Gc).primitive;
|
|
605
|
+
if (Gc.terms.size === 0) {
|
|
606
|
+
return H;
|
|
607
|
+
}
|
|
608
|
+
if (Gc.terms.size === 1 && (Gc.terms.get('') ?? 0n) === 1n) {
|
|
609
|
+
return H;
|
|
610
|
+
}
|
|
611
|
+
const qCoeffs = [];
|
|
612
|
+
for (const cpoly of coeffs) {
|
|
613
|
+
if (cpoly.terms.size === 0) {
|
|
614
|
+
qCoeffs.push(cpoly);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
const q = (0, poly_1.mvExactDiv)(cpoly, Gc);
|
|
618
|
+
if (!q) {
|
|
619
|
+
return H;
|
|
620
|
+
}
|
|
621
|
+
qCoeffs.push(q);
|
|
622
|
+
}
|
|
623
|
+
const Hq = MultiPoly_1.MultiPoly.zero();
|
|
624
|
+
for (let d = 0; d < qCoeffs.length; d++) {
|
|
625
|
+
const q = qCoeffs[d];
|
|
626
|
+
if (q.terms.size === 0) {
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
for (const [kk, c] of q.terms.entries()) {
|
|
630
|
+
const exp = (0, MultiPoly_1.keyToExp)(kk);
|
|
631
|
+
const expFull = new Map(exp);
|
|
632
|
+
if (d !== 0) {
|
|
633
|
+
expFull.set(mainIdx, d);
|
|
634
|
+
}
|
|
635
|
+
const kfull = (0, MultiPoly_1.expToKey)(expFull);
|
|
636
|
+
Hq.terms.set(kfull, (Hq.terms.get(kfull) ?? 0n) + c);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
Hq.trim();
|
|
640
|
+
return Hq;
|
|
641
|
+
}
|
|
642
|
+
// ---------------------------
|
|
643
|
+
// Evaluation to univariate
|
|
644
|
+
// ---------------------------
|
|
645
|
+
function evalToUnivariate(p, vars, mainVar, values) {
|
|
646
|
+
const mainIdx = vars.indexOf(mainVar);
|
|
647
|
+
if (mainIdx < 0) {
|
|
648
|
+
throw new Error(`evalToUnivariate: main var ${mainVar} not in vars`);
|
|
649
|
+
}
|
|
650
|
+
let deg = 0;
|
|
651
|
+
for (const k of p.terms.keys()) {
|
|
652
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
653
|
+
deg = Math.max(deg, exp.get(mainIdx) ?? 0);
|
|
654
|
+
}
|
|
655
|
+
const coeffs = new Array(deg + 1).fill(0n);
|
|
656
|
+
for (const [k, c] of p.terms.entries()) {
|
|
657
|
+
const exp = (0, MultiPoly_1.keyToExp)(k);
|
|
658
|
+
const d = exp.get(mainIdx) ?? 0;
|
|
659
|
+
let m = 1n;
|
|
660
|
+
for (let i = 0; i < vars.length; i++) {
|
|
661
|
+
if (i === mainIdx) {
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
const vname = vars[i];
|
|
665
|
+
const val = values[vname];
|
|
666
|
+
if (val === undefined) {
|
|
667
|
+
throw new Error(`evalToUnivariate: missing value for ${vname}`);
|
|
668
|
+
}
|
|
669
|
+
m *= (0, arith_1.pow)(val, BigInt(exp.get(i) ?? 0));
|
|
670
|
+
}
|
|
671
|
+
coeffs[d] += c * m;
|
|
672
|
+
}
|
|
673
|
+
while (coeffs.length > 1 && coeffs[coeffs.length - 1] === 0n) {
|
|
674
|
+
coeffs.pop();
|
|
675
|
+
}
|
|
676
|
+
return coeffs;
|
|
677
|
+
}
|
|
678
|
+
function uniIsZeroBig(a) {
|
|
679
|
+
return a.length === 0 || (a.length === 1 && a[0] === 0n);
|
|
680
|
+
}
|
|
681
|
+
function normalizeSignLex(p, vars) {
|
|
682
|
+
if (p.terms.size === 0) {
|
|
683
|
+
return p;
|
|
684
|
+
}
|
|
685
|
+
const lt = (0, poly_1.leadTermLex)(p, vars.length);
|
|
686
|
+
if (!lt || lt.coeff >= 0n) {
|
|
687
|
+
return p;
|
|
688
|
+
}
|
|
689
|
+
return (0, poly_1.scalePoly)(p, -1n);
|
|
690
|
+
}
|