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,1149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Polynomial = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const array_1 = require("../../../utils/array");
|
|
9
|
+
const object_1 = require("../../../utils/object");
|
|
10
|
+
const common_1 = require("../../common/common");
|
|
11
|
+
const errors_1 = require("../../errors");
|
|
12
|
+
const expand_1 = require("../../functions/expand/expand");
|
|
13
|
+
const utils_1 = require("../../functions/utils");
|
|
14
|
+
const analysis_1 = require("../expression/analysis");
|
|
15
|
+
const Expression_1 = require("../expression/Expression");
|
|
16
|
+
const shortcuts_1 = require("../expression/shortcuts");
|
|
17
|
+
const constants_1 = require("../parser/constants");
|
|
18
|
+
const Rational_1 = require("../rational/Rational");
|
|
19
|
+
const Term_1 = require("./Term");
|
|
20
|
+
const utils_2 = require("./utils");
|
|
21
|
+
/**
|
|
22
|
+
* Represents a polynomial as ordered {@link Term} objects with symbolic coefficients.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Construction accepts polynomial-like expression input, expands bracketed or powered
|
|
26
|
+
* sums when necessary, and collects coefficients using either the supplied variable
|
|
27
|
+
* order or the expression's alphabetically sorted variables. Negative variable powers
|
|
28
|
+
* and other non-polynomial forms are rejected.
|
|
29
|
+
*
|
|
30
|
+
* The object is mutable: ordering methods sort {@link Polynomial.terms} in place, and
|
|
31
|
+
* `gcdFree(..., true)` edits term coefficients and powers. Arithmetic methods such as
|
|
32
|
+
* {@link Polynomial.plus}, {@link Polynomial.minus}, and {@link Polynomial.times}
|
|
33
|
+
* normally return new polynomials. Public arrays and terms expose mutable internal
|
|
34
|
+
* references; callers that edit them directly must preserve ordering and keep cached
|
|
35
|
+
* term data consistent.
|
|
36
|
+
*
|
|
37
|
+
* Coefficients are stored as `Expression` values. Operations such as
|
|
38
|
+
* {@link Polynomial.evaluate} convert supplied values to {@link Rational} and use exact
|
|
39
|
+
* rational arithmetic; {@link Polynomial.at} and numeric array conversions instead use
|
|
40
|
+
* JavaScript numbers and may lose precision.
|
|
41
|
+
*
|
|
42
|
+
* Supported orderings include lexicographic, reverse lexicographic, graded
|
|
43
|
+
* lexicographic, and graded reverse lexicographic order. Univariate polynomials always
|
|
44
|
+
* use descending degree order regardless of the requested multivariate ordering.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const polynomial = new Polynomial('x^2 + 2*x + 1', ['x']);
|
|
49
|
+
*
|
|
50
|
+
* polynomial.deg(); // 2
|
|
51
|
+
* polynomial.toArray().map(String); // ["1", "2", "1"]
|
|
52
|
+
* polynomial.evaluateToRational({ x: 2 }).toString(); // "5"
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
class Polynomial {
|
|
56
|
+
/** Default ordering chosen for newly parsed multivariate polynomials. */
|
|
57
|
+
static defaultOrdering = 'lex';
|
|
58
|
+
/** Runtime tag used by Nerdamer's polynomial type guard. */
|
|
59
|
+
dataType = constants_1.POLYNOMIAL;
|
|
60
|
+
/** Expression retained from construction or the most recent explicit rebuild. */
|
|
61
|
+
expression;
|
|
62
|
+
/** Whether the polynomial's variable list contains more than one variable. */
|
|
63
|
+
isMultivariate;
|
|
64
|
+
/** Current monomial ordering of {@link terms}. */
|
|
65
|
+
ordering = 'none';
|
|
66
|
+
/** Terms in their current monomial order. The array is mutable. */
|
|
67
|
+
terms;
|
|
68
|
+
/** Variable order used to interpret term multidegrees. The array is mutable. */
|
|
69
|
+
variables;
|
|
70
|
+
/**
|
|
71
|
+
* Constructs a polynomial from expression input or deep-copies another polynomial.
|
|
72
|
+
*
|
|
73
|
+
* @param p - Polynomial-like input or an existing polynomial to copy.
|
|
74
|
+
* @param vars - Variable names in the order used for multidegrees and monomial comparison.
|
|
75
|
+
* When omitted, variables are collected and sorted alphabetically.
|
|
76
|
+
* @param ordering - Requested monomial ordering for parsed multivariate input.
|
|
77
|
+
* @throws {@link core!PolynomialError} Thrown when the parsed expression is not polynomial-like.
|
|
78
|
+
* @throws {@link core!UnsupportedOperationError} Thrown when input cannot be converted to
|
|
79
|
+
* an expression supported by the polynomial representation.
|
|
80
|
+
*/
|
|
81
|
+
constructor(p, vars, ordering) {
|
|
82
|
+
if (Polynomial.isPolynomial(p)) {
|
|
83
|
+
this.expression = new Expression_1.Expression(p.expression);
|
|
84
|
+
this.variables = [...p.variables];
|
|
85
|
+
this.ordering = p.ordering;
|
|
86
|
+
this.isMultivariate = p.isMultivariate;
|
|
87
|
+
this.terms = p.terms.map(t => t.copy());
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Set the default ordering if none was provided
|
|
91
|
+
ordering ??= Polynomial.defaultOrdering;
|
|
92
|
+
// Parse it to a Expression
|
|
93
|
+
let x = Expression_1.Expression.create(p);
|
|
94
|
+
// Disqualify all other types except for Expression. This needs to be updated if other types
|
|
95
|
+
// are supported in the future.
|
|
96
|
+
if (!Expression_1.Expression.isExpression(x)) {
|
|
97
|
+
throw new errors_1.UnsupportedOperationError((0, errors_1.message)('unsupportedType', { type: typeof x }));
|
|
98
|
+
}
|
|
99
|
+
if (!x.isPolynomialLike()) {
|
|
100
|
+
throw new errors_1.PolynomialError((0, errors_1.message)('notAPolynomial'));
|
|
101
|
+
}
|
|
102
|
+
// Expand the expression but only if needed. This will be needed if the value has a bracket
|
|
103
|
+
// or if the expression has a power greater than one.
|
|
104
|
+
if (x.value.includes('(') || (x.isSum() && x.getPower().gt('1'))) {
|
|
105
|
+
x = (0, expand_1.expand)(x);
|
|
106
|
+
}
|
|
107
|
+
this.expression = x;
|
|
108
|
+
let variables;
|
|
109
|
+
if (!vars) {
|
|
110
|
+
variables = x.variables();
|
|
111
|
+
if (!(0, utils_1.isSorted)(variables)) {
|
|
112
|
+
variables.sort();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
variables = vars;
|
|
117
|
+
}
|
|
118
|
+
this.variables = variables;
|
|
119
|
+
// Mark it as univariate or multivariate
|
|
120
|
+
this.isMultivariate = this.variables.length > 1;
|
|
121
|
+
// Add the elements to the terms array
|
|
122
|
+
this.terms = [];
|
|
123
|
+
// Calculate the coefficients. Coeffs will come back as a collection of objects so for instance
|
|
124
|
+
// a*x*y + b*x^2*y will come back as [a, '1,1'] & [b, '2,1']. It's preferred to have it in object form
|
|
125
|
+
// TODO: this should probably be done with `coeffs`.
|
|
126
|
+
x.coeffs(...this.variables).each((coeff, powers) => {
|
|
127
|
+
this.terms.push(new Term_1.Term(coeff, powers, this.variables));
|
|
128
|
+
});
|
|
129
|
+
// Set a blank array if none was provided or calculated
|
|
130
|
+
this.variables = this.variables || [];
|
|
131
|
+
// Order it
|
|
132
|
+
this.order(ordering);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Constructs a polynomial from dense ascending-power coefficients.
|
|
137
|
+
*
|
|
138
|
+
* @remarks
|
|
139
|
+
* Entry `arr[i]` becomes the coefficient of power `i`. When multiple variable names
|
|
140
|
+
* are supplied, their product is treated as one repeated base; this is not a general
|
|
141
|
+
* multidimensional coefficient tensor.
|
|
142
|
+
*
|
|
143
|
+
* @param arr - Coefficients ordered from constant term upward.
|
|
144
|
+
* @param vars - Variable names forming the polynomial base.
|
|
145
|
+
*/
|
|
146
|
+
static fromArray(arr, vars) {
|
|
147
|
+
const coefficients = [];
|
|
148
|
+
let requiresCanonicalization = false;
|
|
149
|
+
for (const input of arr) {
|
|
150
|
+
const coefficient = Expression_1.Expression.isExpression(input)
|
|
151
|
+
? input
|
|
152
|
+
: Expression_1.Expression.create(String(input));
|
|
153
|
+
coefficients.push(coefficient);
|
|
154
|
+
if (vars.some(variable => coefficient.hasVariable(variable))) {
|
|
155
|
+
requiresCanonicalization = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
let retval;
|
|
159
|
+
if (requiresCanonicalization) {
|
|
160
|
+
retval = Polynomial.fromArrayCanonicalized(coefficients, vars);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
retval = new Polynomial((0, shortcuts_1.zero)(), vars);
|
|
164
|
+
retval.terms = [];
|
|
165
|
+
for (let i = 0; i < coefficients.length; i++) {
|
|
166
|
+
const coefficient = coefficients[i];
|
|
167
|
+
if (!coefficient.isZero()) {
|
|
168
|
+
const powers = {};
|
|
169
|
+
for (const variable of vars) {
|
|
170
|
+
powers[variable] = i;
|
|
171
|
+
}
|
|
172
|
+
retval.terms.push(new Term_1.Term(new Expression_1.Expression(coefficient), powers, vars));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
retval.order();
|
|
176
|
+
retval.updateExpression();
|
|
177
|
+
}
|
|
178
|
+
return retval;
|
|
179
|
+
}
|
|
180
|
+
/** Reconstructs dense coefficients through the normal constructor when powers overlap coefficients. */
|
|
181
|
+
static fromArrayCanonicalized(coefficients, vars) {
|
|
182
|
+
let base = (0, shortcuts_1.one)();
|
|
183
|
+
for (const variable of vars) {
|
|
184
|
+
base = base.times(Expression_1.Expression.Variable(variable));
|
|
185
|
+
}
|
|
186
|
+
let expression = (0, shortcuts_1.zero)();
|
|
187
|
+
for (let i = 0; i < coefficients.length; i++) {
|
|
188
|
+
expression = expression.plus(coefficients[i].times(base.pow(i)));
|
|
189
|
+
}
|
|
190
|
+
const retval = new Polynomial(expression, vars);
|
|
191
|
+
return retval;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Sorts by graded lexicographic order. The abs(power) is first compared and then
|
|
195
|
+
* revlex is used to break ties.
|
|
196
|
+
*
|
|
197
|
+
* @param a - First term to compare.
|
|
198
|
+
* @param b - Second term to compare.
|
|
199
|
+
* @returns A comparator value suitable for `Array.sort`.
|
|
200
|
+
*/
|
|
201
|
+
static grevlex(a, b) {
|
|
202
|
+
if (a.getTotalPower() === b.getTotalPower()) {
|
|
203
|
+
return Polynomial.revlex(a, b);
|
|
204
|
+
}
|
|
205
|
+
return a.getTotalPower() > b.getTotalPower() ? -1 : 1;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Sorts by graded lexicographic order. The abs(power) is first compared and then
|
|
209
|
+
* lex is used to break ties.
|
|
210
|
+
*
|
|
211
|
+
* @param a - First term to compare.
|
|
212
|
+
* @param b - Second term to compare.
|
|
213
|
+
* @returns A comparator value suitable for `Array.sort`.
|
|
214
|
+
*/
|
|
215
|
+
static grlex(a, b) {
|
|
216
|
+
if (a.getTotalPower() === b.getTotalPower()) {
|
|
217
|
+
return Polynomial.lex(a, b);
|
|
218
|
+
}
|
|
219
|
+
return a.getTotalPower() > b.getTotalPower() ? -1 : 1;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Checks if the given object is a Polynomial
|
|
223
|
+
*
|
|
224
|
+
* @param obj - Value to test.
|
|
225
|
+
* @returns Whether `obj` carries Nerdamer's polynomial discriminator.
|
|
226
|
+
*/
|
|
227
|
+
static isPolynomial(obj) {
|
|
228
|
+
return (0, common_1.isNerdamerNativeType)(obj, constants_1.POLYNOMIAL);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Sorts by lexicographic order. The power tuples are subtracted and the first
|
|
232
|
+
* non-negative value from the left is used to sort. Note that variables are
|
|
233
|
+
* first sorted in alphabetical order.
|
|
234
|
+
*
|
|
235
|
+
* @param a - First term to compare.
|
|
236
|
+
* @param b - Second term to compare.
|
|
237
|
+
* @returns A comparator value suitable for `Array.sort`.
|
|
238
|
+
*/
|
|
239
|
+
static lex(a, b) {
|
|
240
|
+
const difference = a.difference(b);
|
|
241
|
+
for (let i = 0; i < difference.length; i++) {
|
|
242
|
+
if (difference[i] !== 0) {
|
|
243
|
+
return Math.sign(difference[i]) === -1 ? 1 : -1;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return 1;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Sorts an array given a specific ordering using their LT
|
|
250
|
+
*
|
|
251
|
+
* @param polyArray - Polynomials to reorder. The array itself is sorted in place.
|
|
252
|
+
* @param ordering - Monomial ordering used for each polynomial and its leading term.
|
|
253
|
+
* @returns The same sorted array after each polynomial has also been reordered.
|
|
254
|
+
*/
|
|
255
|
+
static polyArraySort(polyArray, ordering) {
|
|
256
|
+
ordering ??= Polynomial.defaultOrdering;
|
|
257
|
+
// First put all the polynomials in the correct ordering
|
|
258
|
+
polyArray = polyArray.map(x => {
|
|
259
|
+
return x.order(ordering);
|
|
260
|
+
});
|
|
261
|
+
let sortFunction;
|
|
262
|
+
switch (ordering) {
|
|
263
|
+
case 'lex':
|
|
264
|
+
sortFunction = Polynomial.lex;
|
|
265
|
+
break;
|
|
266
|
+
case 'grevlex':
|
|
267
|
+
sortFunction = Polynomial.grevlex;
|
|
268
|
+
break;
|
|
269
|
+
case 'revlex':
|
|
270
|
+
sortFunction = Polynomial.revlex;
|
|
271
|
+
break;
|
|
272
|
+
case 'grlex':
|
|
273
|
+
default:
|
|
274
|
+
sortFunction = Polynomial.grlex;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
polyArray = polyArray.sort((a, b) => {
|
|
278
|
+
return sortFunction(a.LT(), b.LT());
|
|
279
|
+
});
|
|
280
|
+
return polyArray;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Converts a Rational to a string suitable for polynomial construction.
|
|
284
|
+
* Handles both integers and fractions.
|
|
285
|
+
*
|
|
286
|
+
* @param r - Rational value to convert.
|
|
287
|
+
* @returns Parser text preserving an integer or fraction exactly.
|
|
288
|
+
*/
|
|
289
|
+
static rationalToString(r) {
|
|
290
|
+
if (r.denominator === 1n) {
|
|
291
|
+
return r.numerator.toString();
|
|
292
|
+
}
|
|
293
|
+
return `(${r.numerator}/${r.denominator})`;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Sorts by reverse lexicographic order. The power tuples are subtracted and the first
|
|
297
|
+
* non-negative value from the right is used to sort
|
|
298
|
+
*
|
|
299
|
+
* @param a - First term to compare.
|
|
300
|
+
* @param b - Second term to compare.
|
|
301
|
+
* @returns A comparator value suitable for `Array.sort`.
|
|
302
|
+
*/
|
|
303
|
+
static revlex(a, b) {
|
|
304
|
+
const difference = a.difference(b);
|
|
305
|
+
for (let i = difference.length - 1; i >= 0; i--) {
|
|
306
|
+
if (difference[i] !== 0) {
|
|
307
|
+
return Math.sign(difference[i]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return -1;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Fetches the expression from the given object.
|
|
314
|
+
*
|
|
315
|
+
* @param p - Polynomial, expression, or parser text to convert.
|
|
316
|
+
* @returns The polynomial's stored expression reference, or the parsed expression for
|
|
317
|
+
* non-polynomial input.
|
|
318
|
+
*/
|
|
319
|
+
static toExpression(p) {
|
|
320
|
+
if (!Polynomial.isPolynomial(p)) {
|
|
321
|
+
return Expression_1.Expression.create(p);
|
|
322
|
+
}
|
|
323
|
+
return p.getExpression();
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Converts a string to a Polynomial. If a polynomial is provided, it's returned untouched.
|
|
327
|
+
* If a polynomial is provided and no ordering, then the polynomial's ordering will be used.
|
|
328
|
+
* If no ordering is provided for all others then the Polynomial.defaultOrdering will be used.
|
|
329
|
+
*
|
|
330
|
+
* @param p - Value to convert.
|
|
331
|
+
* @param ordering - Ordering to apply. Passing an existing polynomial may reorder it in place.
|
|
332
|
+
* @param variables - Variable order used only when constructing a new polynomial.
|
|
333
|
+
* @returns The existing polynomial or a newly constructed one.
|
|
334
|
+
*/
|
|
335
|
+
static toPolynomial(p, ordering, variables) {
|
|
336
|
+
if (!Polynomial.isPolynomial(p)) {
|
|
337
|
+
p = new Polynomial(p, variables, ordering || Polynomial.defaultOrdering);
|
|
338
|
+
}
|
|
339
|
+
else if (p.ordering !== ordering) {
|
|
340
|
+
p.order(ordering);
|
|
341
|
+
}
|
|
342
|
+
return p;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Creates a copy and adds or subtracts every supplied term.
|
|
346
|
+
*
|
|
347
|
+
* @param x - Term or polynomial whose terms should be combined.
|
|
348
|
+
* @param action - Whether matching coefficients are added or subtracted.
|
|
349
|
+
* @returns A new combined polynomial.
|
|
350
|
+
*/
|
|
351
|
+
append(x, action) {
|
|
352
|
+
const retval = new Polynomial(this);
|
|
353
|
+
retval.variables = (0, utils_1.arrayAddUnique)(x.variables, retval.variables);
|
|
354
|
+
// Sort if variables were added
|
|
355
|
+
if (retval.variables && x.variables && retval.variables.length > x.variables.length) {
|
|
356
|
+
retval.variables.sort();
|
|
357
|
+
}
|
|
358
|
+
retval.isMultivariate = retval.variables.length > 1;
|
|
359
|
+
if (Polynomial.isPolynomial(x)) {
|
|
360
|
+
for (const ta of x.terms) {
|
|
361
|
+
retval.appendTerm(ta, action);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
retval.appendTerm(x, action);
|
|
366
|
+
}
|
|
367
|
+
if (retval.terms.length !== 0) {
|
|
368
|
+
retval.updateExpression();
|
|
369
|
+
}
|
|
370
|
+
return retval.terms.length === 0 ? new Polynomial('0') : retval;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Adds or removes a term from the terms array of the polynomial
|
|
374
|
+
*
|
|
375
|
+
* @param t - Term to combine or append.
|
|
376
|
+
* @param action - Coefficient operation for a matching term.
|
|
377
|
+
*/
|
|
378
|
+
appendTerm(t, action) {
|
|
379
|
+
// Try to add it to an existing
|
|
380
|
+
for (let i = 0; i < this.terms.length; i++) {
|
|
381
|
+
const e = this.terms[i];
|
|
382
|
+
if (e.canAddOrSubtract(t)) {
|
|
383
|
+
e.coeff = e.coeff[action](t.coeff);
|
|
384
|
+
if (e.coeff.isZero()) {
|
|
385
|
+
(0, array_1.remove)(this.terms, e);
|
|
386
|
+
}
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const c = t.copy();
|
|
391
|
+
if (action === 'minus') {
|
|
392
|
+
c.coeff = c.coeff.neg();
|
|
393
|
+
}
|
|
394
|
+
// No existing was found so add it to the terms
|
|
395
|
+
this.terms.push(c);
|
|
396
|
+
// Update since the ordering may have changes
|
|
397
|
+
this.order();
|
|
398
|
+
}
|
|
399
|
+
monomialGCDTerm(other) {
|
|
400
|
+
const vars = [...new Set([...this.variables, ...other.variables])].sort();
|
|
401
|
+
const a = this.commonTermVariables();
|
|
402
|
+
const b = other.commonTermVariables();
|
|
403
|
+
const powers = {};
|
|
404
|
+
for (const v of vars) {
|
|
405
|
+
const ea = a[v] ?? 0;
|
|
406
|
+
const eb = b[v] ?? 0;
|
|
407
|
+
const e = Math.min(ea, eb);
|
|
408
|
+
if (e > 0) {
|
|
409
|
+
powers[v] = e;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return new Term_1.Term('1', powers, vars);
|
|
413
|
+
}
|
|
414
|
+
updateExpression() {
|
|
415
|
+
let retval = (0, shortcuts_1.zero)();
|
|
416
|
+
for (const term of this.terms) {
|
|
417
|
+
// Rebuild from the current term fields rather than trusting a potentially stale cache.
|
|
418
|
+
retval = retval.plus(term.copy().getExpression());
|
|
419
|
+
}
|
|
420
|
+
this.expression = retval;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Numerically evaluates the univariate polynomial at a given point
|
|
424
|
+
* @param n - JavaScript number at which to evaluate the sole variable.
|
|
425
|
+
* @returns A JavaScript-number approximation.
|
|
426
|
+
* @throws {@link core!UnsupportedOperationError} Thrown for multivariate polynomials.
|
|
427
|
+
*/
|
|
428
|
+
at(n) {
|
|
429
|
+
if (this.variables.length > 1) {
|
|
430
|
+
throw new errors_1.UnsupportedOperationError((0, errors_1.message)('univariatePolynomialOnly'));
|
|
431
|
+
}
|
|
432
|
+
let sum = 0;
|
|
433
|
+
const v = this.variables[0];
|
|
434
|
+
for (let i = 0; i < this.terms.length; i++) {
|
|
435
|
+
const term = this.terms[i];
|
|
436
|
+
const pow = term.powers[v];
|
|
437
|
+
sum += Math.pow(n, pow) * Number(term.coeff);
|
|
438
|
+
}
|
|
439
|
+
return sum;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Collects coefficients by power or multidegree.
|
|
443
|
+
*
|
|
444
|
+
* @param variable - Optional single main variable. When omitted, keys use all
|
|
445
|
+
* polynomial variables in their stored order.
|
|
446
|
+
* @returns A mutable coefficient object whose expressions are derived from this polynomial.
|
|
447
|
+
*/
|
|
448
|
+
coeffs(variable) {
|
|
449
|
+
const c = (0, analysis_1.coeffs)(this.getExpression(), variable ? [variable] : this.variables);
|
|
450
|
+
return c;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Returns the positive variable powers shared by every term.
|
|
454
|
+
*
|
|
455
|
+
* @returns A new variable-to-minimum-power record; variables absent from any term are omitted.
|
|
456
|
+
*/
|
|
457
|
+
commonTermVariables() {
|
|
458
|
+
const common = {};
|
|
459
|
+
// Collect common variables
|
|
460
|
+
for (const v of this.variables) {
|
|
461
|
+
let min;
|
|
462
|
+
for (const t of this.terms) {
|
|
463
|
+
const deg = t.deg(v);
|
|
464
|
+
if (deg === 0) {
|
|
465
|
+
// Remove the min
|
|
466
|
+
min = undefined;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
// Set the min common degree
|
|
470
|
+
min = min === undefined ? deg : Math.min(min, deg);
|
|
471
|
+
}
|
|
472
|
+
// Mark it
|
|
473
|
+
if (min) {
|
|
474
|
+
common[v] = min;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return common;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Returns the coefficient of the trailing constant term.
|
|
481
|
+
*
|
|
482
|
+
* @returns The stored coefficient reference when a constant term is present, otherwise
|
|
483
|
+
* a new zero expression.
|
|
484
|
+
*/
|
|
485
|
+
constantTerm() {
|
|
486
|
+
const t = this.terms.at(-1);
|
|
487
|
+
if (t && t.isConstant()) {
|
|
488
|
+
return t.coeff;
|
|
489
|
+
}
|
|
490
|
+
return (0, shortcuts_1.zero)();
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Returns the content of the polynomial (GCD of all coefficients).
|
|
494
|
+
* Does not rely on the Expression class.
|
|
495
|
+
*
|
|
496
|
+
* @returns A new exact rational greatest common divisor of the numeric coefficients.
|
|
497
|
+
*/
|
|
498
|
+
content() {
|
|
499
|
+
const coefficients = this.numericCoeffs();
|
|
500
|
+
if (coefficients.length === 0) {
|
|
501
|
+
return Rational_1.Rational.create('1');
|
|
502
|
+
}
|
|
503
|
+
return Rational_1.Rational.GCD(...coefficients);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Returns the degree of the polynomial.
|
|
507
|
+
*
|
|
508
|
+
* With no variable, this is the total degree: the largest sum of powers in any term.
|
|
509
|
+
* When a variable is supplied, this is the largest power of that variable across all
|
|
510
|
+
* terms, with every other variable treated as part of the coefficient.
|
|
511
|
+
*
|
|
512
|
+
* @param variable - Optional variable whose degree should be returned.
|
|
513
|
+
* @returns The total degree, or the degree with respect to `variable`.
|
|
514
|
+
*/
|
|
515
|
+
deg(variable) {
|
|
516
|
+
let retval = 0;
|
|
517
|
+
for (const term of this.terms) {
|
|
518
|
+
const degree = variable === undefined ? term.getTotalPower() : term.deg(variable);
|
|
519
|
+
retval = Math.max(retval, degree);
|
|
520
|
+
}
|
|
521
|
+
return retval;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Performs a derivative with respect to a variable using Term-based operations.
|
|
525
|
+
* Does not rely on the Expression class for differentiation.
|
|
526
|
+
*
|
|
527
|
+
* @param v - Variable to differentiate; defaults to the first stored variable.
|
|
528
|
+
* @param n - Non-negative derivative order.
|
|
529
|
+
* @returns A newly constructed polynomial; order zero returns a deep copy.
|
|
530
|
+
*/
|
|
531
|
+
diff(v, n = 1) {
|
|
532
|
+
v = v || this.variables[0];
|
|
533
|
+
// Zero-th derivative is just a copy
|
|
534
|
+
if (n === 0) {
|
|
535
|
+
return new Polynomial(this);
|
|
536
|
+
}
|
|
537
|
+
// If no variable specified and polynomial has no variables, derivative is zero
|
|
538
|
+
if (!v) {
|
|
539
|
+
return new Polynomial('0');
|
|
540
|
+
}
|
|
541
|
+
// Differentiate each term and collect non-zero results
|
|
542
|
+
const diffTerms = [];
|
|
543
|
+
for (const term of this.terms) {
|
|
544
|
+
const diffTerm = term.diff(v, n);
|
|
545
|
+
if (!diffTerm.isZero()) {
|
|
546
|
+
// Ensure the differentiated term has proper variables
|
|
547
|
+
diffTerm.variables = [...this.variables];
|
|
548
|
+
diffTerms.push(diffTerm);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
// If all terms differentiated to zero, return zero polynomial
|
|
552
|
+
if (diffTerms.length === 0) {
|
|
553
|
+
return new Polynomial('0');
|
|
554
|
+
}
|
|
555
|
+
// Build polynomial from differentiated terms
|
|
556
|
+
// Start with first term and add the rest
|
|
557
|
+
const result = new Polynomial('0', this.variables, this.ordering);
|
|
558
|
+
result.terms = [];
|
|
559
|
+
for (const t of diffTerms) {
|
|
560
|
+
result.terms.push(t);
|
|
561
|
+
}
|
|
562
|
+
// Ensure proper ordering and synchronize the stored expression.
|
|
563
|
+
result.order(this.ordering);
|
|
564
|
+
result.updateExpression();
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Divides this polynomial by another polynomial.
|
|
569
|
+
*
|
|
570
|
+
* @param p - Divisor polynomial.
|
|
571
|
+
* @returns A two-element array containing quotient and remainder as new polynomials.
|
|
572
|
+
*/
|
|
573
|
+
div(p) {
|
|
574
|
+
return (0, utils_2.divide)(this, p).map(x => new Polynomial(x));
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Checks to see if a polynomial divides the given polynomial
|
|
578
|
+
*
|
|
579
|
+
* @param p - Polynomial whose leading term is tested as the dividend.
|
|
580
|
+
* @returns Whether this polynomial's leading term divides `p`'s leading term. This is
|
|
581
|
+
* a monomial divisibility test, not proof that the complete polynomial divides `p`.
|
|
582
|
+
*/
|
|
583
|
+
divides(p) {
|
|
584
|
+
return this.LT().divides(p.LT());
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Checks if two polynomials are equal
|
|
588
|
+
*
|
|
589
|
+
* @param p - Polynomial to compare.
|
|
590
|
+
* @returns Whether subtracting `p` produces the zero polynomial.
|
|
591
|
+
*/
|
|
592
|
+
eq(p) {
|
|
593
|
+
return this.minus(p).isZero();
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Evaluates the polynomial at given values using Term-based operations.
|
|
597
|
+
* Supports partial evaluation (substituting some variables while keeping others symbolic).
|
|
598
|
+
* Does not rely on the Expression class for computation.
|
|
599
|
+
*
|
|
600
|
+
* @param values - Variable names mapped to exact rational-compatible values.
|
|
601
|
+
* @returns A new partially evaluated polynomial; unmentioned variables remain symbolic.
|
|
602
|
+
*/
|
|
603
|
+
evaluate(values) {
|
|
604
|
+
// Determine which variables remain after substitution
|
|
605
|
+
const remainingVars = this.variables.filter(v => !(v in values));
|
|
606
|
+
// Convert input values to Rationals for consistent arithmetic
|
|
607
|
+
const rationalValues = {};
|
|
608
|
+
for (const v in values) {
|
|
609
|
+
const val = values[v];
|
|
610
|
+
if (Rational_1.Rational.isRational(val)) {
|
|
611
|
+
rationalValues[v] = val;
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
rationalValues[v] = Rational_1.Rational.create(val.toString());
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
// Accumulate result terms together with the powers needed to rebuild them natively.
|
|
618
|
+
const resultTerms = new Map();
|
|
619
|
+
for (const term of this.terms) {
|
|
620
|
+
// Start with the term's coefficient
|
|
621
|
+
let coeff = term.coeff.getMultiplier();
|
|
622
|
+
const newPowers = {};
|
|
623
|
+
// Process each variable in the polynomial
|
|
624
|
+
for (const v of this.variables) {
|
|
625
|
+
const power = term.deg(v);
|
|
626
|
+
if (v in rationalValues) {
|
|
627
|
+
// Substitute this variable: multiply coefficient by value^power
|
|
628
|
+
if (power !== 0) {
|
|
629
|
+
const valPow = rationalValues[v].pow(power.toString());
|
|
630
|
+
coeff = coeff.times(valPow);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
// Keep this variable
|
|
635
|
+
if (power !== 0) {
|
|
636
|
+
newPowers[v] = power;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
// Skip zero coefficients
|
|
641
|
+
if (coeff.isZero()) {
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
// Create a key for combining like terms. The key is only an internal map key;
|
|
645
|
+
// the retained power object is used for reconstruction.
|
|
646
|
+
const termKey = remainingVars.length > 0
|
|
647
|
+
? remainingVars.map(v => `${v}:${newPowers[v] || 0}`).join(',')
|
|
648
|
+
: 'constant';
|
|
649
|
+
const existing = resultTerms.get(termKey);
|
|
650
|
+
if (existing) {
|
|
651
|
+
existing.coefficient = existing.coefficient.plus(coeff);
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
resultTerms.set(termKey, { coefficient: coeff, powers: newPowers });
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
let retval;
|
|
658
|
+
if (resultTerms.size === 0) {
|
|
659
|
+
retval = new Polynomial((0, shortcuts_1.zero)());
|
|
660
|
+
}
|
|
661
|
+
else if (remainingVars.length === 0) {
|
|
662
|
+
const result = resultTerms.get('constant');
|
|
663
|
+
const coefficient = result ? result.coefficient : Rational_1.Rational.create('0');
|
|
664
|
+
retval = new Polynomial(Expression_1.Expression.Number(coefficient.value));
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
retval = new Polynomial((0, shortcuts_1.zero)(), remainingVars, this.ordering);
|
|
668
|
+
retval.terms = [];
|
|
669
|
+
for (const result of resultTerms.values()) {
|
|
670
|
+
if (!result.coefficient.isZero()) {
|
|
671
|
+
retval.terms.push(new Term_1.Term(Expression_1.Expression.Number(result.coefficient.value), { ...result.powers }, remainingVars));
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
retval.order(this.ordering);
|
|
675
|
+
retval.updateExpression();
|
|
676
|
+
}
|
|
677
|
+
return retval;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Numerically evaluates the polynomial at given values.
|
|
681
|
+
* All variables must be provided values.
|
|
682
|
+
*
|
|
683
|
+
* @param values - Values for every variable stored by the polynomial.
|
|
684
|
+
* @returns The exact rational result.
|
|
685
|
+
* @throws {@link core!UnsupportedOperationError} Thrown when any stored variable is missing.
|
|
686
|
+
*/
|
|
687
|
+
evaluateToRational(values) {
|
|
688
|
+
// Verify all variables have values
|
|
689
|
+
for (const v of this.variables) {
|
|
690
|
+
if (!(v in values)) {
|
|
691
|
+
throw new errors_1.UnsupportedOperationError((0, errors_1.message)('unknownVariable', { variable: v }));
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
// Convert input values to Rationals
|
|
695
|
+
const rationalValues = {};
|
|
696
|
+
for (const v in values) {
|
|
697
|
+
const val = values[v];
|
|
698
|
+
if (Rational_1.Rational.isRational(val)) {
|
|
699
|
+
rationalValues[v] = val;
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
rationalValues[v] = Rational_1.Rational.create(val.toString());
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
let sum = Rational_1.Rational.create('0');
|
|
706
|
+
for (const term of this.terms) {
|
|
707
|
+
let termValue = term.coeff.getMultiplier();
|
|
708
|
+
for (const v of this.variables) {
|
|
709
|
+
const power = term.deg(v);
|
|
710
|
+
if (power !== 0) {
|
|
711
|
+
termValue = termValue.times(rationalValues[v].pow(power.toString()));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
sum = sum.plus(termValue);
|
|
715
|
+
}
|
|
716
|
+
return sum;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Divides all terms by their exact numeric content and optionally their common monomial.
|
|
720
|
+
*
|
|
721
|
+
* @param reduceVariables - Also subtract the minimum shared positive power of each variable.
|
|
722
|
+
* @param mutate - Modify and return this polynomial instead of a deep copy.
|
|
723
|
+
* @returns The normalized target polynomial.
|
|
724
|
+
*/
|
|
725
|
+
gcdFree(reduceVariables = false, mutate = false) {
|
|
726
|
+
const target = mutate ? this : new Polynomial(this);
|
|
727
|
+
// If it's a constant then there's nothing left to do
|
|
728
|
+
if (target.isConstant()) {
|
|
729
|
+
return target;
|
|
730
|
+
}
|
|
731
|
+
let common;
|
|
732
|
+
let gcd = target.content();
|
|
733
|
+
if (target.LC().sign() === -1) {
|
|
734
|
+
gcd = gcd.neg();
|
|
735
|
+
}
|
|
736
|
+
if (reduceVariables) {
|
|
737
|
+
common = target.commonTermVariables();
|
|
738
|
+
}
|
|
739
|
+
for (let i = 0; i < target.terms.length; i++) {
|
|
740
|
+
const term = target.terms[i];
|
|
741
|
+
// If reduction of the variable is requested then do so.
|
|
742
|
+
if (common) {
|
|
743
|
+
// Reduce the variables
|
|
744
|
+
for (const x in common) {
|
|
745
|
+
term.powers[x] -= common[x];
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// Divide coefficient by GCD using Rational arithmetic
|
|
749
|
+
const currentCoeff = term.coeff.getMultiplier();
|
|
750
|
+
const newCoeff = currentCoeff.div(gcd);
|
|
751
|
+
term.coeff = Expression_1.Expression.fromRational(newCoeff);
|
|
752
|
+
}
|
|
753
|
+
target.updateExpression();
|
|
754
|
+
return target;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Returns the expression retained by the polynomial.
|
|
758
|
+
*
|
|
759
|
+
* @remarks
|
|
760
|
+
* This is an internal reference, not a copy. The term array is the operative
|
|
761
|
+
* representation for many methods, and direct term mutation is not guaranteed to
|
|
762
|
+
* rebuild this stored expression automatically.
|
|
763
|
+
*/
|
|
764
|
+
getExpression() {
|
|
765
|
+
return this.expression;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Sorts the terms by graded lexicographic order
|
|
769
|
+
* grevlex first compares their powers. If their powers are equal then it breaks ties using {@link revlex} reverse lexicographic order.
|
|
770
|
+
*
|
|
771
|
+
* @returns This polynomial after sorting its terms in place.
|
|
772
|
+
*/
|
|
773
|
+
grevlexSort() {
|
|
774
|
+
this.terms.sort((a, b) => {
|
|
775
|
+
return Polynomial.grevlex(a, b);
|
|
776
|
+
});
|
|
777
|
+
// Mark it
|
|
778
|
+
this.ordering = 'grevlex';
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Sorts the terms by graded lexicographic order
|
|
783
|
+
* grlex first compares their powers. If their powers are equal then it breaks ties using {@link lex} lexicographic order.
|
|
784
|
+
*
|
|
785
|
+
* @returns This polynomial after sorting its terms in place.
|
|
786
|
+
*/
|
|
787
|
+
grlexSort() {
|
|
788
|
+
this.terms.sort((a, b) => {
|
|
789
|
+
return Polynomial.grlex(a, b);
|
|
790
|
+
});
|
|
791
|
+
//Mark it
|
|
792
|
+
this.ordering = 'grlex';
|
|
793
|
+
return this;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Tests whether the polynomial consists of one constant term.
|
|
797
|
+
*
|
|
798
|
+
* @returns `true` only for the one-term constant representation.
|
|
799
|
+
*/
|
|
800
|
+
isConstant() {
|
|
801
|
+
return this.terms.length === 1 && this.terms[0].isConstant();
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Tests whether this polynomial has no terms or a zero leading term.
|
|
805
|
+
*
|
|
806
|
+
* @returns Whether the current term representation is zero.
|
|
807
|
+
*/
|
|
808
|
+
isZero() {
|
|
809
|
+
return this.terms.length === 0 || this.LT().isZero();
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Returns the leading coefficient under the current ordering.
|
|
813
|
+
*
|
|
814
|
+
* @returns The leading term's internal coefficient reference.
|
|
815
|
+
*/
|
|
816
|
+
LC() {
|
|
817
|
+
return this.LT().coeff;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Sorts the terms by {@link lex} lexicographic order
|
|
821
|
+
*
|
|
822
|
+
* @returns This polynomial after sorting its terms in place.
|
|
823
|
+
*/
|
|
824
|
+
lexSort() {
|
|
825
|
+
this.terms.sort((a, b) => {
|
|
826
|
+
return Polynomial.lex(a, b);
|
|
827
|
+
});
|
|
828
|
+
// Mark it
|
|
829
|
+
this.ordering = 'lex';
|
|
830
|
+
return this;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Returns the leading monomial with unit coefficient.
|
|
834
|
+
*
|
|
835
|
+
* @returns A new term with copied powers and variables.
|
|
836
|
+
*/
|
|
837
|
+
LM() {
|
|
838
|
+
const LT = this.LT();
|
|
839
|
+
return new Term_1.Term('1', { ...LT.powers }, [...LT.variables]);
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Returns the leading term under the current ordering.
|
|
843
|
+
*
|
|
844
|
+
* @returns The internal first term reference.
|
|
845
|
+
*/
|
|
846
|
+
LT() {
|
|
847
|
+
return this.terms[0];
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Gets the maximum variable occurrence in the polynomial. If two or more variables have
|
|
851
|
+
* an equal number of occurrences then they will be included in the set
|
|
852
|
+
*
|
|
853
|
+
* @returns A new record containing every variable tied for the greatest term-occurrence count.
|
|
854
|
+
* @example
|
|
855
|
+
* ```ts
|
|
856
|
+
* new Polynomial('q^3*a+2*q^2*a').maxVariableFrequency();
|
|
857
|
+
* // { a: { variable: 'a', count: 2, deg: 2 },
|
|
858
|
+
* // q: { variable: 'q', count: 2, deg: 5 } }
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
maxVariableFrequency() {
|
|
862
|
+
const freq = this.variableFrequency();
|
|
863
|
+
let max = [];
|
|
864
|
+
for (const v in freq) {
|
|
865
|
+
const c = freq[v].count;
|
|
866
|
+
if (!max[0] || max[0].count < c) {
|
|
867
|
+
// Either set it or wipe the whole thing
|
|
868
|
+
max = [freq[v]];
|
|
869
|
+
}
|
|
870
|
+
else if (max[0].count === c) {
|
|
871
|
+
max.push(freq[v]);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return (0, object_1.arrayToObject)(max, k => {
|
|
875
|
+
return k.variable;
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Subtracts a Polynomial or a Term
|
|
880
|
+
*
|
|
881
|
+
* @param x - Term or polynomial to subtract.
|
|
882
|
+
* @returns A new polynomial. Both operands are left unchanged.
|
|
883
|
+
*/
|
|
884
|
+
minus(x) {
|
|
885
|
+
return this.append(x, 'minus');
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Reduces each collected coefficient modulo `n`.
|
|
889
|
+
*
|
|
890
|
+
* @remarks
|
|
891
|
+
* The polynomial itself is not modified. The returned coefficient object is derived from
|
|
892
|
+
* the current polynomial and stores the reduced coefficient expressions at the same power
|
|
893
|
+
* keys.
|
|
894
|
+
*
|
|
895
|
+
* @param n - Modulus passed to the symbolic `mod` operation.
|
|
896
|
+
* @returns A coefficient object containing the coefficient remainders.
|
|
897
|
+
*/
|
|
898
|
+
mod(n) {
|
|
899
|
+
n = Expression_1.Expression.create(n);
|
|
900
|
+
const coeffs = this.coeffs();
|
|
901
|
+
coeffs.each((x, p) => {
|
|
902
|
+
coeffs.coeffs[p] = x.mod(n);
|
|
903
|
+
});
|
|
904
|
+
return coeffs;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Returns a copy with the leading nonconstant coefficient normalized to one.
|
|
908
|
+
*
|
|
909
|
+
* Constant polynomials are copied without coefficient normalization.
|
|
910
|
+
*
|
|
911
|
+
* @returns A new polynomial with a unit leading coefficient when normalization applies.
|
|
912
|
+
*/
|
|
913
|
+
monic() {
|
|
914
|
+
const p = new Polynomial(this);
|
|
915
|
+
const LT = this.LT();
|
|
916
|
+
// If it's a constant the we're done
|
|
917
|
+
if (LT && !LT.isConstant()) {
|
|
918
|
+
const c = LT.coeff;
|
|
919
|
+
for (const t of p.terms) {
|
|
920
|
+
t.coeff = t.coeff.div(c);
|
|
921
|
+
}
|
|
922
|
+
p.updateExpression();
|
|
923
|
+
}
|
|
924
|
+
return p;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Returns the leading term's multidegree under the current ordering.
|
|
928
|
+
*
|
|
929
|
+
* @returns The leading term's cached internal multidegree array.
|
|
930
|
+
*/
|
|
931
|
+
multideg() {
|
|
932
|
+
return this.terms[0].multidegArray;
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Gets all the numeric coefficients in the polynomial as Rationals.
|
|
936
|
+
*
|
|
937
|
+
* @returns New array containing each term coefficient's internal rational multiplier.
|
|
938
|
+
*/
|
|
939
|
+
numericCoeffs() {
|
|
940
|
+
return this.terms.map(t => t.coeff.getMultiplier());
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Reorders the polynomial in the requested ordering if it's not already in that particular ordering.
|
|
944
|
+
*
|
|
945
|
+
* @param ordering - Requested multivariate ordering. Univariate input is always degree-sorted.
|
|
946
|
+
* @returns This polynomial after sorting its term array in place.
|
|
947
|
+
*/
|
|
948
|
+
order(ordering) {
|
|
949
|
+
if (this.variables.length < 2) {
|
|
950
|
+
this.sort();
|
|
951
|
+
this.ordering = 'deg';
|
|
952
|
+
}
|
|
953
|
+
else {
|
|
954
|
+
// Set the new ordering if provided
|
|
955
|
+
if (ordering) {
|
|
956
|
+
this.ordering = ordering;
|
|
957
|
+
}
|
|
958
|
+
switch (this.ordering) {
|
|
959
|
+
case 'lex':
|
|
960
|
+
this.lexSort();
|
|
961
|
+
break;
|
|
962
|
+
case 'grevlex':
|
|
963
|
+
this.grevlexSort();
|
|
964
|
+
break;
|
|
965
|
+
case 'revlex':
|
|
966
|
+
this.revlexSort();
|
|
967
|
+
break;
|
|
968
|
+
case 'grlex':
|
|
969
|
+
default:
|
|
970
|
+
this.grlexSort();
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return this;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Adds a Polynomial or a Term.
|
|
978
|
+
*
|
|
979
|
+
* @param x - Term or polynomial to add.
|
|
980
|
+
* @returns A new polynomial. Both operands are left unchanged.
|
|
981
|
+
*/
|
|
982
|
+
plus(x) {
|
|
983
|
+
return this.append(x, 'plus');
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Raises the polynomial to a power.
|
|
987
|
+
*
|
|
988
|
+
* @param p - Exponent accepted by symbolic expression powers.
|
|
989
|
+
* @returns A new polynomial parsed from the powered expression.
|
|
990
|
+
* @throws {@link core!PolynomialError} Thrown when the powered result is not polynomial-like.
|
|
991
|
+
*/
|
|
992
|
+
pow(p) {
|
|
993
|
+
return new Polynomial(this.getExpression().pow(p), undefined, this.ordering);
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Sorts the terms by {@link revlex} reverse lexicographic order
|
|
997
|
+
*
|
|
998
|
+
* @returns This polynomial after sorting its terms in place.
|
|
999
|
+
*/
|
|
1000
|
+
revlexSort() {
|
|
1001
|
+
// There is only one sort for univariate
|
|
1002
|
+
this.terms.sort((a, b) => {
|
|
1003
|
+
return Polynomial.revlex(a, b);
|
|
1004
|
+
});
|
|
1005
|
+
// Mark it
|
|
1006
|
+
this.ordering = 'revlex';
|
|
1007
|
+
return this;
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Sorts the terms in the standard form of decreasing powers.
|
|
1011
|
+
*/
|
|
1012
|
+
sort() {
|
|
1013
|
+
this.terms.sort((a, b) => {
|
|
1014
|
+
return b.getTotalPower() > a.getTotalPower() ? 1 : -1;
|
|
1015
|
+
});
|
|
1016
|
+
return this;
|
|
1017
|
+
}
|
|
1018
|
+
stripMonomialGCD(other) {
|
|
1019
|
+
const m = this.monomialGCDTerm(other);
|
|
1020
|
+
const p = new Polynomial(this);
|
|
1021
|
+
const q = new Polynomial(other);
|
|
1022
|
+
for (let i = 0; i < p.terms.length; i++) {
|
|
1023
|
+
p.terms[i] = p.terms[i].div(m);
|
|
1024
|
+
}
|
|
1025
|
+
for (let i = 0; i < q.terms.length; i++) {
|
|
1026
|
+
q.terms[i] = q.terms[i].div(m);
|
|
1027
|
+
}
|
|
1028
|
+
const mGCD = new Polynomial(m.getExpression());
|
|
1029
|
+
p.updateExpression();
|
|
1030
|
+
q.updateExpression();
|
|
1031
|
+
return { mGCD, p, q };
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Formats the current ordered terms as canonical parser text.
|
|
1035
|
+
*
|
|
1036
|
+
* @returns `"0"` for an empty/zero term representation, otherwise the joined term text.
|
|
1037
|
+
*/
|
|
1038
|
+
text() {
|
|
1039
|
+
if (this.terms.length === 0 || (this.terms.length === 1 && this.terms[0].isZero())) {
|
|
1040
|
+
return '0';
|
|
1041
|
+
}
|
|
1042
|
+
const textArray = [];
|
|
1043
|
+
for (const t of this.terms) {
|
|
1044
|
+
const txt = t.text(this.variables);
|
|
1045
|
+
if (txt !== '0') {
|
|
1046
|
+
textArray.push(txt);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return textArray.join('+').replace(/\+-/g, '-');
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Multiplies this polynomial by a term or polynomial.
|
|
1053
|
+
*
|
|
1054
|
+
* @param x - Multiplier.
|
|
1055
|
+
* @returns A new polynomial. Term multiplication copies this polynomial before
|
|
1056
|
+
* updating its terms; polynomial multiplication rebuilds from symbolic expressions.
|
|
1057
|
+
*/
|
|
1058
|
+
times(x) {
|
|
1059
|
+
let retval;
|
|
1060
|
+
if (Term_1.Term.isTerm(x)) {
|
|
1061
|
+
retval = new Polynomial(this);
|
|
1062
|
+
// Update the variables
|
|
1063
|
+
retval.variables = (0, utils_1.arrayAddUnique)(retval.variables, x.variables);
|
|
1064
|
+
if ((0, utils_1.isSorted)(this.variables)) {
|
|
1065
|
+
retval.variables.sort();
|
|
1066
|
+
}
|
|
1067
|
+
retval.isMultivariate = retval.variables.length > 1;
|
|
1068
|
+
for (let i = 0; i < retval.terms.length; i++) {
|
|
1069
|
+
retval.terms[i] = retval.terms[i].times(x);
|
|
1070
|
+
}
|
|
1071
|
+
retval.updateExpression();
|
|
1072
|
+
}
|
|
1073
|
+
else {
|
|
1074
|
+
retval = new Polynomial(this.getExpression().times(x.getExpression()), undefined, this.ordering);
|
|
1075
|
+
}
|
|
1076
|
+
return retval;
|
|
1077
|
+
}
|
|
1078
|
+
toArray(asNumbers = false, variable) {
|
|
1079
|
+
const arr = [];
|
|
1080
|
+
const n = Number(this.deg(variable));
|
|
1081
|
+
const coeffs = this.coeffs(variable);
|
|
1082
|
+
for (let i = 0; i <= n; i++) {
|
|
1083
|
+
arr.push(coeffs.hasPower(i) ? coeffs.getPower(i) : (0, shortcuts_1.zero)());
|
|
1084
|
+
}
|
|
1085
|
+
if (asNumbers) {
|
|
1086
|
+
return arr.map(x => Number(x));
|
|
1087
|
+
}
|
|
1088
|
+
return arr;
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Converts dense coefficients to numerator `bigint` values.
|
|
1092
|
+
*
|
|
1093
|
+
* @param assertInZ - Reject coefficients whose denominator is not one.
|
|
1094
|
+
* @param variable - Optional variable to collect as the dense power index.
|
|
1095
|
+
* @returns New ascending-power array of coefficient numerators.
|
|
1096
|
+
* @throws Error Thrown when `assertInZ` is true and a coefficient is non-integral.
|
|
1097
|
+
*/
|
|
1098
|
+
toBigIntArray(assertInZ = true, variable) {
|
|
1099
|
+
return this.toArray(false, variable).map(x => {
|
|
1100
|
+
if (assertInZ && !x.isInteger()) {
|
|
1101
|
+
throw new Error((0, errors_1.message)('integerRequired'));
|
|
1102
|
+
}
|
|
1103
|
+
return x.getMultiplier().numerator;
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Converts dense coefficients to new `Decimal` values using their expression text.
|
|
1108
|
+
*
|
|
1109
|
+
* @returns An ascending-power decimal coefficient array.
|
|
1110
|
+
*/
|
|
1111
|
+
toDecimalArray() {
|
|
1112
|
+
return this.toArray().map(x => new decimal_js_1.default(x.text()));
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Returns the polynomial in a form for easy debugging.
|
|
1116
|
+
*
|
|
1117
|
+
* @returns The same canonical term text as {@link Polynomial.text}.
|
|
1118
|
+
*/
|
|
1119
|
+
toString() {
|
|
1120
|
+
return this.text();
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Counts each variable's term occurrences and accumulated degree.
|
|
1124
|
+
*
|
|
1125
|
+
* @returns A new record keyed by variable. Each entry reports its name, number of
|
|
1126
|
+
* nonzero-power terms, and sum of powers across those terms.
|
|
1127
|
+
*/
|
|
1128
|
+
variableFrequency() {
|
|
1129
|
+
const count = {};
|
|
1130
|
+
for (const t of this.terms) {
|
|
1131
|
+
for (const v in t.powers) {
|
|
1132
|
+
// The counter object
|
|
1133
|
+
let o = count[v];
|
|
1134
|
+
if (!o) {
|
|
1135
|
+
count[v] = o = { variable: v, count: 0, deg: 0 };
|
|
1136
|
+
}
|
|
1137
|
+
// Check the degree. We only increment for degrees > 0. Since it's a polynomial,
|
|
1138
|
+
// no negative degrees should exist
|
|
1139
|
+
const deg = t.powers[v];
|
|
1140
|
+
if (deg !== 0) {
|
|
1141
|
+
o.count++;
|
|
1142
|
+
o.deg += deg;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
return count;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
exports.Polynomial = Polynomial;
|