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,240 @@
|
|
|
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.MultivariateSolver = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
9
|
+
const DecimalMatrix_1 = require("./DecimalMatrix");
|
|
10
|
+
const DEFAULT_LOWER_BOUND = -10;
|
|
11
|
+
const DEFAULT_UPPER_BOUND = 10;
|
|
12
|
+
const DEFAULT_GRID_POINTS = 5;
|
|
13
|
+
const DEFAULT_MAX_ITERATIONS = 100;
|
|
14
|
+
const DEFAULT_TOLERANCE = 1e-12;
|
|
15
|
+
const DEFAULT_DERIVATIVE_STEP = 1e-8;
|
|
16
|
+
const DEFAULT_DEDUPLICATION_TOLERANCE = 1e-8;
|
|
17
|
+
/**
|
|
18
|
+
* Searches numerically for isolated real solutions of a multivariate system.
|
|
19
|
+
*
|
|
20
|
+
* Each equation is interpreted as `equation = 0`. The solver starts
|
|
21
|
+
* Newton-Raphson at every point in a Cartesian grid, approximates the Jacobian
|
|
22
|
+
* with central differences, and merges nearby converged solutions.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* This is a finite-range heuristic rather than a completeness proof. The number
|
|
26
|
+
* of starts is `gridPoints` raised to the number of variables, so cost grows
|
|
27
|
+
* rapidly with dimension. Singular Jacobians, failed evaluations, and starts
|
|
28
|
+
* that do not converge are discarded. Calculations use the ambient
|
|
29
|
+
* `decimal.js` precision, and the supplied equation and variable arrays are
|
|
30
|
+
* retained by the solver.
|
|
31
|
+
*
|
|
32
|
+
* The numerical linear solve requires a square Jacobian in ordinary use; this
|
|
33
|
+
* class is intended for isolated solutions of systems with as many equations
|
|
34
|
+
* as variables.
|
|
35
|
+
*/
|
|
36
|
+
class MultivariateSolver {
|
|
37
|
+
dedupTol;
|
|
38
|
+
equations;
|
|
39
|
+
gridPoints;
|
|
40
|
+
h;
|
|
41
|
+
lowerBound;
|
|
42
|
+
maxIterations;
|
|
43
|
+
tolerance;
|
|
44
|
+
upperBound;
|
|
45
|
+
variables;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a multi-start solver over the configured limits.
|
|
48
|
+
*
|
|
49
|
+
* @param equations - Expressions interpreted as equations equal to zero.
|
|
50
|
+
* @param variables - Ordered variables corresponding to solution coordinates.
|
|
51
|
+
* @param options - Grid, iteration, differentiation, and deduplication settings.
|
|
52
|
+
*/
|
|
53
|
+
constructor(equations, variables, options = {}) {
|
|
54
|
+
this.equations = equations;
|
|
55
|
+
this.variables = variables;
|
|
56
|
+
this.lowerBound = options.lowerBound ?? DEFAULT_LOWER_BOUND;
|
|
57
|
+
this.upperBound = options.upperBound ?? DEFAULT_UPPER_BOUND;
|
|
58
|
+
this.gridPoints = options.gridPoints ?? DEFAULT_GRID_POINTS;
|
|
59
|
+
this.maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
60
|
+
this.tolerance = new decimal_js_1.default(options.tolerance ?? DEFAULT_TOLERANCE);
|
|
61
|
+
this.h = new decimal_js_1.default(options.derivativeStep ?? DEFAULT_DERIVATIVE_STEP);
|
|
62
|
+
this.dedupTol = new decimal_js_1.default(options.deduplicationTolerance ?? DEFAULT_DEDUPLICATION_TOLERANCE);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Evaluate all equations at a point, returning a vector of Decimal values.
|
|
66
|
+
*/
|
|
67
|
+
evaluateSystem(point) {
|
|
68
|
+
const values = {};
|
|
69
|
+
for (let i = 0; i < this.variables.length; i++) {
|
|
70
|
+
const value = point[i];
|
|
71
|
+
// Preserve the parser's existing handling for non-finite values while keeping
|
|
72
|
+
// ordinary Newton coordinates native.
|
|
73
|
+
values[this.variables[i]] = value.isFinite() ? Expression_1.Expression.Number(value) : value;
|
|
74
|
+
}
|
|
75
|
+
const result = [];
|
|
76
|
+
for (const eq of this.equations) {
|
|
77
|
+
try {
|
|
78
|
+
const evaluated = eq.evaluate(values);
|
|
79
|
+
if (!Expression_1.Expression.isExpression(evaluated)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
result.push(evaluated.getMultiplier().toDecimal());
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Generate grid starting points.
|
|
92
|
+
*/
|
|
93
|
+
generateStartingPoints() {
|
|
94
|
+
const n = this.variables.length;
|
|
95
|
+
const points = [];
|
|
96
|
+
const step = (this.upperBound - this.lowerBound) / (this.gridPoints - 1);
|
|
97
|
+
// Generate all combinations of grid points
|
|
98
|
+
const indices = new Array(n).fill(0);
|
|
99
|
+
while (true) {
|
|
100
|
+
const point = [];
|
|
101
|
+
for (let i = 0; i < n; i++) {
|
|
102
|
+
point.push(new decimal_js_1.default(this.lowerBound + indices[i] * step));
|
|
103
|
+
}
|
|
104
|
+
points.push(point);
|
|
105
|
+
// Increment indices
|
|
106
|
+
let carry = true;
|
|
107
|
+
for (let i = n - 1; i >= 0 && carry; i--) {
|
|
108
|
+
indices[i]++;
|
|
109
|
+
if (indices[i] < this.gridPoints) {
|
|
110
|
+
carry = false;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
indices[i] = 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (carry) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return points;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if a root is a duplicate of an existing one.
|
|
124
|
+
*/
|
|
125
|
+
isDuplicate(root, existing) {
|
|
126
|
+
for (const prev of existing) {
|
|
127
|
+
let maxDiff = new decimal_js_1.default(0);
|
|
128
|
+
for (let i = 0; i < root.length; i++) {
|
|
129
|
+
const diff = root[i].minus(prev[i]).abs();
|
|
130
|
+
if (diff.greaterThan(maxDiff)) {
|
|
131
|
+
maxDiff = diff;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (maxDiff.lessThan(this.dedupTol)) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Compute the Jacobian matrix numerically using central differences.
|
|
142
|
+
*/
|
|
143
|
+
jacobian(point) {
|
|
144
|
+
const n = this.variables.length;
|
|
145
|
+
const m = this.equations.length;
|
|
146
|
+
const data = new Array(m).fill(null).map(() => []);
|
|
147
|
+
const twoH = this.h.times(2);
|
|
148
|
+
// A forward/backward system evaluation contains every Jacobian row for one
|
|
149
|
+
// variable. Evaluate once per variable instead of once per equation-variable pair.
|
|
150
|
+
for (let j = 0; j < n; j++) {
|
|
151
|
+
const forward = point.map(v => new decimal_js_1.default(v));
|
|
152
|
+
const backward = point.map(v => new decimal_js_1.default(v));
|
|
153
|
+
forward[j] = forward[j].plus(this.h);
|
|
154
|
+
backward[j] = backward[j].minus(this.h);
|
|
155
|
+
const fPlus = this.evaluateSystem(forward);
|
|
156
|
+
const fMinus = this.evaluateSystem(backward);
|
|
157
|
+
if (!fPlus || !fMinus) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
for (let i = 0; i < m; i++) {
|
|
161
|
+
data[i].push(fPlus[i].minus(fMinus[i]).div(twoH));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return new DecimalMatrix_1.DecimalMatrix(data);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Run Newton-Raphson from a single starting point.
|
|
168
|
+
* Returns the converged root or null if it didn't converge.
|
|
169
|
+
*/
|
|
170
|
+
newtonRaphson(start) {
|
|
171
|
+
const x = start.map(v => new decimal_js_1.default(v));
|
|
172
|
+
for (let iter = 0; iter < this.maxIterations; iter++) {
|
|
173
|
+
const F = this.evaluateSystem(x);
|
|
174
|
+
if (!F) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
// Check convergence: ||F(x)|| < tolerance
|
|
178
|
+
let norm = new decimal_js_1.default(0);
|
|
179
|
+
for (const fi of F) {
|
|
180
|
+
norm = norm.plus(fi.times(fi));
|
|
181
|
+
}
|
|
182
|
+
norm = norm.sqrt();
|
|
183
|
+
if (norm.lessThan(this.tolerance)) {
|
|
184
|
+
return x;
|
|
185
|
+
}
|
|
186
|
+
const J = this.jacobian(x);
|
|
187
|
+
if (!J) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
// Solve J * delta = -F
|
|
191
|
+
const negF = F.map(fi => fi.neg());
|
|
192
|
+
const delta = DecimalMatrix_1.DecimalMatrix.solve(J, negF);
|
|
193
|
+
if (!delta) {
|
|
194
|
+
return null; // Singular Jacobian
|
|
195
|
+
}
|
|
196
|
+
// Update: x = x + delta
|
|
197
|
+
for (let i = 0; i < x.length; i++) {
|
|
198
|
+
x[i] = x[i].plus(delta[i]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Check if we're close enough after max iterations
|
|
202
|
+
const F = this.evaluateSystem(x);
|
|
203
|
+
if (F) {
|
|
204
|
+
let norm = new decimal_js_1.default(0);
|
|
205
|
+
for (const fi of F) {
|
|
206
|
+
norm = norm.plus(fi.times(fi));
|
|
207
|
+
}
|
|
208
|
+
if (norm.sqrt().lessThan(this.tolerance)) {
|
|
209
|
+
return x;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Searches for roots from every configured grid point.
|
|
216
|
+
*
|
|
217
|
+
* @returns Deduplicated solutions as maps keyed in `variables` order. An empty
|
|
218
|
+
* array means that no start converged; it does not prove that no root exists.
|
|
219
|
+
*/
|
|
220
|
+
roots() {
|
|
221
|
+
const convergedRoots = [];
|
|
222
|
+
const startingPoints = this.generateStartingPoints();
|
|
223
|
+
for (const start of startingPoints) {
|
|
224
|
+
const root = this.newtonRaphson(start);
|
|
225
|
+
if (root && !this.isDuplicate(root, convergedRoots)) {
|
|
226
|
+
convergedRoots.push(root);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Convert to Maps of Expressions
|
|
230
|
+
return convergedRoots.map(root => {
|
|
231
|
+
const solution = new Map();
|
|
232
|
+
for (let i = 0; i < this.variables.length; i++) {
|
|
233
|
+
const value = root[i];
|
|
234
|
+
solution.set(this.variables[i], value.isFinite() ? Expression_1.Expression.Number(value) : Expression_1.Expression.create(value));
|
|
235
|
+
}
|
|
236
|
+
return solution;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
exports.MultivariateSolver = MultivariateSolver;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
import { Complex } from '../../core/classes/complex/Complex';
|
|
3
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
4
|
+
import { Polynomial } from '../../core/classes/polynomial/Polynomial';
|
|
5
|
+
/**
|
|
6
|
+
* Finds all complex roots of a univariate polynomial numerically.
|
|
7
|
+
*
|
|
8
|
+
* Coefficient arrays use ascending powers: the element at index `k` is the
|
|
9
|
+
* coefficient of `x^k`. Polynomial and string inputs are converted to that
|
|
10
|
+
* representation before solving. Linear and quadratic inputs are handled
|
|
11
|
+
* directly; higher degrees use simultaneous Aberth iteration followed by
|
|
12
|
+
* Newton refinement.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* The solver temporarily changes the global `decimal.js` precision while
|
|
16
|
+
* {@link roots} runs and restores the previous precision before returning.
|
|
17
|
+
* The requested precision controls the numerical work, while `epsilon`
|
|
18
|
+
* controls convergence and cleanup of numerical noise. Roots are returned
|
|
19
|
+
* once per polynomial degree, so repeated roots can appear as repeated nearby
|
|
20
|
+
* approximations.
|
|
21
|
+
*
|
|
22
|
+
* This class finds numerical roots; it does not certify completeness or exact
|
|
23
|
+
* multiplicities for ill-conditioned polynomials.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const solver = new PolynomialSolver('x^2+1', 'x');
|
|
28
|
+
* const roots = solver.roots();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class PolynomialSolver {
|
|
32
|
+
private degree;
|
|
33
|
+
private eps;
|
|
34
|
+
private p;
|
|
35
|
+
private precision;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a polynomial root solver.
|
|
38
|
+
*
|
|
39
|
+
* @param input - A polynomial, a polynomial string, or ascending-power
|
|
40
|
+
* coefficients.
|
|
41
|
+
* @param variable - Variable expected in polynomial or string input. It is used to reject
|
|
42
|
+
* a conflicting variable or multivariate polynomial.
|
|
43
|
+
* @param precision - Working `decimal.js` precision used while finding roots.
|
|
44
|
+
* @param epsilon - Numerical convergence tolerance. Defaults to `1e-14`.
|
|
45
|
+
* @throws {@link core!UnexpectedInputError} If polynomial or string input is multivariate or
|
|
46
|
+
* uses a variable different from `variable`.
|
|
47
|
+
*/
|
|
48
|
+
constructor(input: Decimal[] | Polynomial | string, variable?: string, precision?: number, epsilon?: Decimal);
|
|
49
|
+
/**
|
|
50
|
+
* Aberth method: simultaneous approximation of all roots
|
|
51
|
+
* More stable than deflation for high-degree polynomials
|
|
52
|
+
*/
|
|
53
|
+
private aberthMethod;
|
|
54
|
+
/**
|
|
55
|
+
* Compute Cauchy bound for root magnitudes
|
|
56
|
+
*/
|
|
57
|
+
private cauchyBound;
|
|
58
|
+
private complexSqrt;
|
|
59
|
+
private finalize;
|
|
60
|
+
/**
|
|
61
|
+
* Refine a single root using Newton's method
|
|
62
|
+
*/
|
|
63
|
+
private newtonRefine;
|
|
64
|
+
private solveQuadratic;
|
|
65
|
+
/**
|
|
66
|
+
* Synthetic division
|
|
67
|
+
* Returns [P(s), quotient Q] where P(x) = (x-s)*Q(x) + P(s)
|
|
68
|
+
*/
|
|
69
|
+
private syntheticDiv;
|
|
70
|
+
/**
|
|
71
|
+
* Computes the roots of the configured polynomial.
|
|
72
|
+
*
|
|
73
|
+
* Leading zero coefficients are ignored. A constant or zero coefficient
|
|
74
|
+
* array produces an empty result. Passing `false` returns the numeric
|
|
75
|
+
* {@link Complex} values directly; otherwise each root is converted to an
|
|
76
|
+
* {@link Expression} after restoring the caller's Decimal precision.
|
|
77
|
+
*
|
|
78
|
+
* @param asExpressions - Whether to convert roots to symbolic expressions.
|
|
79
|
+
* Defaults to `true`.
|
|
80
|
+
* @returns One root value per effective polynomial degree, including repeated
|
|
81
|
+
* numerical approximations for repeated roots.
|
|
82
|
+
*/
|
|
83
|
+
roots(asExpressions?: true): Expression[];
|
|
84
|
+
roots(asExpressions?: false): Complex[];
|
|
85
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
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.PolynomialSolver = void 0;
|
|
7
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
|
+
const Complex_1 = require("../../core/classes/complex/Complex");
|
|
9
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
10
|
+
const Polynomial_1 = require("../../core/classes/polynomial/Polynomial");
|
|
11
|
+
const errors_1 = require("../../core/errors");
|
|
12
|
+
const DEFAULT_PRECISION = 50;
|
|
13
|
+
const DEFAULT_EPSILON = 1e-14;
|
|
14
|
+
const ABERTH_MAX_ITERATIONS = 100;
|
|
15
|
+
const ABERTH_INITIAL_ANGLE_OFFSET = 0.4;
|
|
16
|
+
const ABERTH_RADIUS_SCALE = 0.9;
|
|
17
|
+
const ABERTH_ROOT_SPACING_SCALE = 0.01;
|
|
18
|
+
const ABERTH_CONVERGENCE_SCALE = 1e-2;
|
|
19
|
+
const NEWTON_MAX_ITERATIONS = 20;
|
|
20
|
+
const NEWTON_CONVERGENCE_SCALE = 1e-6;
|
|
21
|
+
/**
|
|
22
|
+
* Finds all complex roots of a univariate polynomial numerically.
|
|
23
|
+
*
|
|
24
|
+
* Coefficient arrays use ascending powers: the element at index `k` is the
|
|
25
|
+
* coefficient of `x^k`. Polynomial and string inputs are converted to that
|
|
26
|
+
* representation before solving. Linear and quadratic inputs are handled
|
|
27
|
+
* directly; higher degrees use simultaneous Aberth iteration followed by
|
|
28
|
+
* Newton refinement.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* The solver temporarily changes the global `decimal.js` precision while
|
|
32
|
+
* {@link roots} runs and restores the previous precision before returning.
|
|
33
|
+
* The requested precision controls the numerical work, while `epsilon`
|
|
34
|
+
* controls convergence and cleanup of numerical noise. Roots are returned
|
|
35
|
+
* once per polynomial degree, so repeated roots can appear as repeated nearby
|
|
36
|
+
* approximations.
|
|
37
|
+
*
|
|
38
|
+
* This class finds numerical roots; it does not certify completeness or exact
|
|
39
|
+
* multiplicities for ill-conditioned polynomials.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const solver = new PolynomialSolver('x^2+1', 'x');
|
|
44
|
+
* const roots = solver.roots();
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
class PolynomialSolver {
|
|
48
|
+
degree;
|
|
49
|
+
eps;
|
|
50
|
+
p;
|
|
51
|
+
precision;
|
|
52
|
+
/**
|
|
53
|
+
* Creates a polynomial root solver.
|
|
54
|
+
*
|
|
55
|
+
* @param input - A polynomial, a polynomial string, or ascending-power
|
|
56
|
+
* coefficients.
|
|
57
|
+
* @param variable - Variable expected in polynomial or string input. It is used to reject
|
|
58
|
+
* a conflicting variable or multivariate polynomial.
|
|
59
|
+
* @param precision - Working `decimal.js` precision used while finding roots.
|
|
60
|
+
* @param epsilon - Numerical convergence tolerance. Defaults to `1e-14`.
|
|
61
|
+
* @throws {@link core!UnexpectedInputError} If polynomial or string input is multivariate or
|
|
62
|
+
* uses a variable different from `variable`.
|
|
63
|
+
*/
|
|
64
|
+
constructor(input, variable, precision = DEFAULT_PRECISION, epsilon) {
|
|
65
|
+
// Allow for input to be a string
|
|
66
|
+
if (typeof input === 'string') {
|
|
67
|
+
input = new Polynomial_1.Polynomial(input);
|
|
68
|
+
}
|
|
69
|
+
if (Polynomial_1.Polynomial.isPolynomial(input)) {
|
|
70
|
+
const vars = input.variables;
|
|
71
|
+
// Expect the input to be a univariate polynomial
|
|
72
|
+
if (vars.length > 1 || (vars.length === 1 && variable && vars[0] !== variable)) {
|
|
73
|
+
throw new errors_1.UnexpectedInputError((0, errors_1.message)('tooManyUnknowns'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const coefficients = Polynomial_1.Polynomial.isPolynomial(input) ? input.toDecimalArray() : input;
|
|
77
|
+
// Reverse the coefficients so p[0] is the leading coefficient
|
|
78
|
+
this.p = coefficients
|
|
79
|
+
.slice()
|
|
80
|
+
.reverse()
|
|
81
|
+
.map(c => new Complex_1.Complex(c, 0));
|
|
82
|
+
this.degree = this.p.length - 1;
|
|
83
|
+
this.eps = epsilon || new decimal_js_1.default(DEFAULT_EPSILON);
|
|
84
|
+
this.precision = precision;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Aberth method: simultaneous approximation of all roots
|
|
88
|
+
* More stable than deflation for high-degree polynomials
|
|
89
|
+
*/
|
|
90
|
+
aberthMethod(P) {
|
|
91
|
+
const n = P.length - 1;
|
|
92
|
+
// Initialize roots on a circle
|
|
93
|
+
const roots = [];
|
|
94
|
+
const radius = this.cauchyBound(P);
|
|
95
|
+
for (let k = 0; k < n; k++) {
|
|
96
|
+
const angle = new decimal_js_1.default(2).mul(Math.PI).mul(k).div(n).plus(ABERTH_INITIAL_ANGLE_OFFSET);
|
|
97
|
+
const r = radius
|
|
98
|
+
.mul(ABERTH_RADIUS_SCALE)
|
|
99
|
+
.mul(new decimal_js_1.default(1).plus(new decimal_js_1.default(k).mul(ABERTH_ROOT_SPACING_SCALE).div(n)));
|
|
100
|
+
roots.push(new Complex_1.Complex(r.mul(decimal_js_1.default.cos(angle)), r.mul(decimal_js_1.default.sin(angle))));
|
|
101
|
+
}
|
|
102
|
+
// Aberth iterations
|
|
103
|
+
for (let iter = 0; iter < ABERTH_MAX_ITERATIONS; iter++) {
|
|
104
|
+
let maxChange = new decimal_js_1.default(0);
|
|
105
|
+
const newRoots = [];
|
|
106
|
+
for (let i = 0; i < n; i++) {
|
|
107
|
+
const z = roots[i];
|
|
108
|
+
// Compute P(z) and P'(z)
|
|
109
|
+
const [pz, qp] = this.syntheticDiv(n, P, z);
|
|
110
|
+
const [dpz, _] = this.syntheticDiv(n - 1, qp, z);
|
|
111
|
+
if (dpz.abs().lessThan(this.eps)) {
|
|
112
|
+
newRoots.push(z);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Compute Aberth correction
|
|
116
|
+
const newton = pz.div(dpz);
|
|
117
|
+
// Sum of 1/(z_i - z_j) for j != i
|
|
118
|
+
let sum = new Complex_1.Complex(0, 0);
|
|
119
|
+
for (let j = 0; j < n; j++) {
|
|
120
|
+
if (i !== j) {
|
|
121
|
+
const diff = z.sub(roots[j]);
|
|
122
|
+
if (diff.abs().greaterThan(this.eps)) {
|
|
123
|
+
sum = sum.add(new Complex_1.Complex(1, 0).div(diff));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Aberth correction: w = N(z) / (1 - N(z) * sum)
|
|
128
|
+
const denom = new Complex_1.Complex(1, 0).sub(newton.mul(sum));
|
|
129
|
+
const correction = denom.abs().lessThan(this.eps)
|
|
130
|
+
? newton
|
|
131
|
+
: newton.div(denom);
|
|
132
|
+
const newZ = z.sub(correction);
|
|
133
|
+
newRoots.push(newZ);
|
|
134
|
+
const change = correction.abs();
|
|
135
|
+
if (change.greaterThan(maxChange)) {
|
|
136
|
+
maxChange = change;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (let i = 0; i < n; i++) {
|
|
140
|
+
roots[i] = newRoots[i];
|
|
141
|
+
}
|
|
142
|
+
// Check convergence
|
|
143
|
+
if (maxChange.lessThan(this.eps.mul(ABERTH_CONVERGENCE_SCALE))) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Final refinement with Newton's method
|
|
148
|
+
for (let i = 0; i < n; i++) {
|
|
149
|
+
roots[i] = this.newtonRefine(P, roots[i]);
|
|
150
|
+
}
|
|
151
|
+
return roots;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Compute Cauchy bound for root magnitudes
|
|
155
|
+
*/
|
|
156
|
+
cauchyBound(P) {
|
|
157
|
+
const n = P.length - 1;
|
|
158
|
+
let maxRatio = new decimal_js_1.default(0);
|
|
159
|
+
for (let i = 1; i <= n; i++) {
|
|
160
|
+
const ratio = P[i].abs().div(P[0].abs());
|
|
161
|
+
if (ratio.greaterThan(maxRatio)) {
|
|
162
|
+
maxRatio = ratio;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return maxRatio.plus(1);
|
|
166
|
+
}
|
|
167
|
+
complexSqrt(z) {
|
|
168
|
+
const mag = z.abs();
|
|
169
|
+
if (mag.isZero()) {
|
|
170
|
+
return new Complex_1.Complex(0, 0);
|
|
171
|
+
}
|
|
172
|
+
const x = z.re;
|
|
173
|
+
const y = z.im;
|
|
174
|
+
if (y.abs().lessThan(this.eps)) {
|
|
175
|
+
if (x.greaterThanOrEqualTo(0)) {
|
|
176
|
+
return new Complex_1.Complex(x.sqrt(), 0);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
return new Complex_1.Complex(0, x.neg().sqrt());
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const w = mag.plus(x.abs()).div(2).sqrt();
|
|
183
|
+
if (x.greaterThanOrEqualTo(0)) {
|
|
184
|
+
return new Complex_1.Complex(w, y.div(w.mul(2)));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
const absY = y.abs();
|
|
188
|
+
const imPart = y.greaterThanOrEqualTo(0) ? w : w.neg();
|
|
189
|
+
return new Complex_1.Complex(absY.div(w.mul(2)), imPart);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
finalize(roots, asExpressions, precision, cleanupComponents = true) {
|
|
193
|
+
// Restore the precision
|
|
194
|
+
decimal_js_1.default.set({ precision: precision });
|
|
195
|
+
if (asExpressions) {
|
|
196
|
+
return roots.map(root => {
|
|
197
|
+
let re = root.re;
|
|
198
|
+
let im = root.im;
|
|
199
|
+
if (cleanupComponents) {
|
|
200
|
+
const magnitude = root.abs();
|
|
201
|
+
const componentTolerance = magnitude.mul(this.eps);
|
|
202
|
+
re = root.re.abs().lt(componentTolerance) ? new decimal_js_1.default(0) : root.re;
|
|
203
|
+
im = root.im.abs().lt(componentTolerance) ? new decimal_js_1.default(0) : root.im;
|
|
204
|
+
}
|
|
205
|
+
const retval = Expression_1.Expression.create(re).plus(Expression_1.Expression.Img().times(im));
|
|
206
|
+
return retval;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
return roots;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Refine a single root using Newton's method
|
|
213
|
+
*/
|
|
214
|
+
newtonRefine(P, z) {
|
|
215
|
+
for (let iter = 0; iter < NEWTON_MAX_ITERATIONS; iter++) {
|
|
216
|
+
const [pz, qp] = this.syntheticDiv(P.length - 1, P, z);
|
|
217
|
+
if (pz.abs().lessThan(this.eps.mul(NEWTON_CONVERGENCE_SCALE))) {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
const [dpz, _] = this.syntheticDiv(P.length - 2, qp, z);
|
|
221
|
+
if (dpz.abs().lessThan(this.eps)) {
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
const correction = pz.div(dpz);
|
|
225
|
+
const newZ = z.sub(correction);
|
|
226
|
+
if (correction.abs().lessThan(this.eps.mul(NEWTON_CONVERGENCE_SCALE).mul(newZ.abs().plus(1)))) {
|
|
227
|
+
z = newZ;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
z = newZ;
|
|
231
|
+
}
|
|
232
|
+
return z;
|
|
233
|
+
}
|
|
234
|
+
solveQuadratic(p) {
|
|
235
|
+
const a = p[0];
|
|
236
|
+
const b = p[1];
|
|
237
|
+
const c = p[2];
|
|
238
|
+
const b2 = b.mul(b);
|
|
239
|
+
const ac4 = a.mul(c).scale(4);
|
|
240
|
+
const disc = b2.sub(ac4);
|
|
241
|
+
const sqrtDisc = this.complexSqrt(disc);
|
|
242
|
+
const twoA = a.scale(2);
|
|
243
|
+
const negB = b.neg();
|
|
244
|
+
return [negB.add(sqrtDisc).div(twoA), negB.sub(sqrtDisc).div(twoA)];
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Synthetic division
|
|
248
|
+
* Returns [P(s), quotient Q] where P(x) = (x-s)*Q(x) + P(s)
|
|
249
|
+
*/
|
|
250
|
+
syntheticDiv(n, P, s) {
|
|
251
|
+
const Q = [];
|
|
252
|
+
let b = P[0];
|
|
253
|
+
Q[0] = b;
|
|
254
|
+
for (let i = 1; i <= n; i++) {
|
|
255
|
+
b = b.mul(s).add(P[i]);
|
|
256
|
+
if (i < n) {
|
|
257
|
+
Q[i] = b;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return [b, Q];
|
|
261
|
+
}
|
|
262
|
+
roots(asExpressions = true) {
|
|
263
|
+
// Store the currently used precision
|
|
264
|
+
const precision = decimal_js_1.default.precision;
|
|
265
|
+
// Set the precision to a high number. Default = 50
|
|
266
|
+
decimal_js_1.default.set({ precision: this.precision });
|
|
267
|
+
// Remove leading zeros and normalize
|
|
268
|
+
let poly = [...this.p];
|
|
269
|
+
let deg = this.degree;
|
|
270
|
+
while (deg > 0 && poly[0].re.isZero() && poly[0].im.isZero()) {
|
|
271
|
+
poly.shift();
|
|
272
|
+
deg--;
|
|
273
|
+
}
|
|
274
|
+
if (deg === 0) {
|
|
275
|
+
return this.finalize([], asExpressions, precision);
|
|
276
|
+
}
|
|
277
|
+
const lead = poly[0];
|
|
278
|
+
poly = poly.map(c => c.div(lead));
|
|
279
|
+
if (deg === 1) {
|
|
280
|
+
return this.finalize([poly[1].neg()], asExpressions, precision);
|
|
281
|
+
}
|
|
282
|
+
if (deg === 2) {
|
|
283
|
+
// Quadratic roots are computed analytically, so preserve small components instead of
|
|
284
|
+
// treating them as iterative noise.
|
|
285
|
+
return this.finalize(this.solveQuadratic(poly), asExpressions, precision, false);
|
|
286
|
+
}
|
|
287
|
+
// For degree >= 3, use Aberth method for better numerical stability
|
|
288
|
+
const roots = this.aberthMethod(poly);
|
|
289
|
+
return this.finalize(roots, asExpressions, precision);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
exports.PolynomialSolver = PolynomialSolver;
|