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,1811 @@
|
|
|
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.sqrt = sqrt;
|
|
7
|
+
exports.nthroot = nthroot;
|
|
8
|
+
exports.cbrt = cbrt;
|
|
9
|
+
exports.parens = parens;
|
|
10
|
+
exports.fibonacci = fibonacci;
|
|
11
|
+
exports.factorial = factorial;
|
|
12
|
+
exports.doubleFactorial = doubleFactorial;
|
|
13
|
+
exports.heaviside = heaviside;
|
|
14
|
+
exports.dirac = dirac;
|
|
15
|
+
exports.numeric = numeric;
|
|
16
|
+
exports.round = round;
|
|
17
|
+
exports.sign = sign;
|
|
18
|
+
exports.floor = floor;
|
|
19
|
+
exports.ceiling = ceiling;
|
|
20
|
+
exports.abs = abs;
|
|
21
|
+
exports.modInv = modInv;
|
|
22
|
+
exports.mod = mod;
|
|
23
|
+
exports.gamma = gamma;
|
|
24
|
+
exports.erfc = erfc;
|
|
25
|
+
exports.erf = erf;
|
|
26
|
+
exports.sinc = sinc;
|
|
27
|
+
exports.Si = Si;
|
|
28
|
+
exports.Shi = Shi;
|
|
29
|
+
exports.Ci = Ci;
|
|
30
|
+
exports.Chi = Chi;
|
|
31
|
+
exports.Ei = Ei;
|
|
32
|
+
exports.Li = Li;
|
|
33
|
+
exports.log = log;
|
|
34
|
+
exports.max = max;
|
|
35
|
+
exports.min = min;
|
|
36
|
+
exports.exp = exp;
|
|
37
|
+
exports.matrix = matrix;
|
|
38
|
+
exports.sum = sum;
|
|
39
|
+
exports.product = product;
|
|
40
|
+
exports.defint = defint;
|
|
41
|
+
exports.contains = contains;
|
|
42
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
43
|
+
const assume_1 = require("../core/classes/assumption/assume");
|
|
44
|
+
const Expression_1 = require("../core/classes/expression/Expression");
|
|
45
|
+
const shortcuts_1 = require("../core/classes/expression/shortcuts");
|
|
46
|
+
const utils_1 = require("../core/classes/expression/utils");
|
|
47
|
+
const Matrix_1 = require("../core/classes/matrix/Matrix");
|
|
48
|
+
const constants_1 = require("../core/classes/parser/constants");
|
|
49
|
+
const constants_2 = require("../core/classes/parser/constants");
|
|
50
|
+
const multiply_1 = require("../core/classes/parser/operations/multiply");
|
|
51
|
+
const power_1 = require("../core/classes/parser/operations/power");
|
|
52
|
+
const subtract_1 = require("../core/classes/parser/operations/subtract");
|
|
53
|
+
const utils_2 = require("../core/classes/polynomial/utils");
|
|
54
|
+
const Rational_1 = require("../core/classes/rational/Rational");
|
|
55
|
+
const errors_1 = require("../core/errors");
|
|
56
|
+
const bigint_1 = require("../core/functions/bigint/bigint");
|
|
57
|
+
const primeFactor_1 = require("../core/functions/bigint/primeFactor");
|
|
58
|
+
const complex_1 = require("../core/functions/complex");
|
|
59
|
+
const decimal_1 = require("../core/functions/decimal");
|
|
60
|
+
const Settings_1 = require("../core/Settings");
|
|
61
|
+
const defintNative_1 = require("./defint/defintNative");
|
|
62
|
+
const geometry_1 = require("./geometry");
|
|
63
|
+
const trig_1 = require("./trig");
|
|
64
|
+
const utils_3 = require("./utils");
|
|
65
|
+
const NATIVE_DEFINITE_INTEGRATION_PRECISION = 17;
|
|
66
|
+
const POSITIVE_INTEGER_PRECISION = 'a positive integer precision';
|
|
67
|
+
/**
|
|
68
|
+
* Computes the square root of an expression. Equivalent to raising to the power of 1/2.
|
|
69
|
+
* Nested square roots are automatically simplified (e.g. `sqrt(sqrt(x))` becomes `x^(1/4)`).
|
|
70
|
+
*
|
|
71
|
+
* @param x - The expression to take the square root of.
|
|
72
|
+
* @returns The square root of `x`.
|
|
73
|
+
* @throws {@link core!UndefinedError} If `x` is `-∞`.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* // Numeric
|
|
78
|
+
* sqrt(4).text() // "2"
|
|
79
|
+
* sqrt('1/4').text() // "1/2"
|
|
80
|
+
*
|
|
81
|
+
* // Symbolic
|
|
82
|
+
* sqrt('x^2').text() // "x"
|
|
83
|
+
* sqrt('x').text() // "sqrt(x)"
|
|
84
|
+
* sqrt(0).text() // "0"
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
function sqrt(x) {
|
|
88
|
+
x = Expression_1.Expression.create(x);
|
|
89
|
+
let retval;
|
|
90
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
91
|
+
if (x.isNegInf()) {
|
|
92
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
93
|
+
}
|
|
94
|
+
retval = Expression_1.Expression.Inf();
|
|
95
|
+
}
|
|
96
|
+
else if (x.isOne()) {
|
|
97
|
+
retval = (0, shortcuts_1.one)();
|
|
98
|
+
}
|
|
99
|
+
else if (x.isZero()) {
|
|
100
|
+
retval = (0, shortcuts_1.zero)();
|
|
101
|
+
}
|
|
102
|
+
// e.g. sqrt(sqrt(x))
|
|
103
|
+
else if (x.isFunction(constants_1.SQRT)) {
|
|
104
|
+
// Unwrap the square root
|
|
105
|
+
retval = (0, multiply_1.multiply)(sqrt(Expression_1.Expression.fromRational(x.getMultiplier())), (0, power_1.power)((0, power_1.sqrtToPow)(x.toUnitMultiplier()), (0, shortcuts_1.half)()));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
retval = (0, power_1.power)(x, (0, shortcuts_1.half)());
|
|
109
|
+
}
|
|
110
|
+
return retval;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Computes the nth root of an expression as its principal power.
|
|
114
|
+
*
|
|
115
|
+
* @param x - The expression whose root is requested.
|
|
116
|
+
* @param n - The root degree.
|
|
117
|
+
* @returns `x^(1/n)`.
|
|
118
|
+
*/
|
|
119
|
+
function nthroot(x, n) {
|
|
120
|
+
return (0, power_1.power)(Expression_1.Expression.create(x), (0, shortcuts_1.one)().div(Expression_1.Expression.create(n)));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Computes the cube root of an expression.
|
|
124
|
+
*
|
|
125
|
+
* For real numeric constants, the *real* cube root is returned (so negative reals stay real).
|
|
126
|
+
* For complex constants, the principal cube root is used.
|
|
127
|
+
* Nested cube roots are simplified (e.g. `cbrt(cbrt(x))` becomes `x^(1/9)`).
|
|
128
|
+
*
|
|
129
|
+
* Unlike {@link sqrt}, `cbrt` is preserved as a function node rather than rewritten to
|
|
130
|
+
* `x^(1/3)` to avoid principal-branch issues during symbolic manipulation.
|
|
131
|
+
*
|
|
132
|
+
* @param x - The expression to take the cube root of.
|
|
133
|
+
* @returns The cube root of `x`.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* cbrt(8).text() // "2"
|
|
138
|
+
* cbrt(-27).text() // "-3"
|
|
139
|
+
* cbrt('x').text() // "cbrt(x)"
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
function cbrt(x) {
|
|
143
|
+
x = Expression_1.Expression.create(x);
|
|
144
|
+
// Resolve simple values before constant evaluation.
|
|
145
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
146
|
+
return x.isNegInf() ? Expression_1.Expression.NegInf() : Expression_1.Expression.Inf();
|
|
147
|
+
}
|
|
148
|
+
if (x.isOne()) {
|
|
149
|
+
return (0, shortcuts_1.one)();
|
|
150
|
+
}
|
|
151
|
+
if (x.isZero()) {
|
|
152
|
+
return (0, shortcuts_1.zero)();
|
|
153
|
+
}
|
|
154
|
+
// If requested, evaluate constant arguments first. This avoids leaving things like
|
|
155
|
+
// cbrt(-1/2 + (sqrt(3)*sqrt(31))/18) unevaluated.
|
|
156
|
+
//
|
|
157
|
+
// For real constants, this uses the *real* cube root (so negative reals stay real).
|
|
158
|
+
// For complex constants, it returns the principal cube root.
|
|
159
|
+
if (Settings_1.Settings.EVALUATE && x.isConstant()) {
|
|
160
|
+
const xe = x.isNUM() || x.isComplex() ? x : x.evaluate();
|
|
161
|
+
if (xe.isNUM()) {
|
|
162
|
+
const d = xe.getMultiplier().toDecimal();
|
|
163
|
+
const oneThird = new decimal_js_1.default(1).div(3);
|
|
164
|
+
const r = d.isNeg() ? d.abs().pow(oneThird).neg() : d.pow(oneThird);
|
|
165
|
+
return new Expression_1.Expression(r);
|
|
166
|
+
}
|
|
167
|
+
if (xe.isComplex()) {
|
|
168
|
+
const re = xe.realPart();
|
|
169
|
+
const im = xe.imagPart();
|
|
170
|
+
const a = Number(re.getMultiplier().toDecimal());
|
|
171
|
+
const b = Number(im.getMultiplier().toDecimal());
|
|
172
|
+
const mag = Math.hypot(a, b);
|
|
173
|
+
const ang = Math.atan2(b, a);
|
|
174
|
+
const mag13 = Math.cbrt(mag);
|
|
175
|
+
const ang13 = ang / 3;
|
|
176
|
+
const rr = mag13 * Math.cos(ang13);
|
|
177
|
+
const ii = mag13 * Math.sin(ang13);
|
|
178
|
+
return Expression_1.Expression.create(rr).plus(Expression_1.Expression.create(ii).times(Expression_1.Expression.Img()));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// e.g. cbrt(cbrt(x))
|
|
182
|
+
if (x.isFunction(constants_1.CBRT)) {
|
|
183
|
+
return (0, multiply_1.multiply)(cbrt(Expression_1.Expression.fromRational(x.getMultiplier())), (0, power_1.power)(x.toUnitMultiplier(), (0, shortcuts_1.third)()));
|
|
184
|
+
}
|
|
185
|
+
// Keep cbrt as a function node (rather than x^(1/3)) to avoid principal-branch
|
|
186
|
+
// issues during symbolic manipulation.
|
|
187
|
+
return Expression_1.Expression.toFunction(constants_1.CBRT, [x]);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Wraps an expression in parentheses. Returns a function node whose only purpose
|
|
191
|
+
* is to visually group `x` with surrounding parentheses in output.
|
|
192
|
+
*
|
|
193
|
+
* @param x - The expression to wrap.
|
|
194
|
+
* @returns A parenthesised form of `x`.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* parens(Expression.create('x+1')).text() // "(x+1)"
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
function parens(x) {
|
|
202
|
+
return Expression_1.Expression.toFunction(constants_1.WRAP, [x]);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Computes the Fibonacci number for an integer index.
|
|
206
|
+
*
|
|
207
|
+
* Integer inputs are evaluated exactly, including negative indices through the
|
|
208
|
+
* negafibonacci identity. Symbolic and non-integer inputs remain unevaluated.
|
|
209
|
+
*
|
|
210
|
+
* @param x - Fibonacci index.
|
|
211
|
+
* @returns The exact Fibonacci number for an integer input, or symbolic `fib(x)`.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* fibonacci(10).text() // "55"
|
|
216
|
+
* fibonacci(-4).text() // "-3"
|
|
217
|
+
* fibonacci('x').text() // "fib(x)"
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
function fibonacci(x) {
|
|
221
|
+
x = Expression_1.Expression.create(x);
|
|
222
|
+
let retval;
|
|
223
|
+
if (x.isNUM() && x.isInteger()) {
|
|
224
|
+
retval = Expression_1.Expression.Number((0, bigint_1.fibonacci)(x.getMultiplier().numerator));
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
retval = Expression_1.Expression.toFunction(constants_2.FIB, [new Expression_1.Expression(x)]);
|
|
228
|
+
}
|
|
229
|
+
return retval;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Computes the factorial of an expression.
|
|
233
|
+
*
|
|
234
|
+
* For non-negative integers, returns the exact integer factorial.
|
|
235
|
+
* For half-integer arguments (e.g. `1/2`, `3/2`, `-1/2`), returns a closed-form
|
|
236
|
+
* expression involving `sqrt(π)`.
|
|
237
|
+
* When `Settings.EVALUATE` is `true` and the input is not an integer, falls back
|
|
238
|
+
* to the {@link gamma} function via Γ(x + 1).
|
|
239
|
+
*
|
|
240
|
+
* @param x - The expression to compute the factorial of.
|
|
241
|
+
* @returns The factorial of `x`.
|
|
242
|
+
* @throws {@link core!UndefinedError} If `x` is `-∞`.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* factorial(Expression.create(5)).text() // "120"
|
|
247
|
+
* factorial(Expression.create(0)).text() // "1"
|
|
248
|
+
* factorial(Expression.create('1/2')).text() // "1/2*sqrt(pi)"
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
function factorial(x) {
|
|
252
|
+
let retval;
|
|
253
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
254
|
+
if (x.isNegInf()) {
|
|
255
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
256
|
+
}
|
|
257
|
+
return Expression_1.Expression.Inf();
|
|
258
|
+
}
|
|
259
|
+
if (x.isInteger()) {
|
|
260
|
+
retval = Expression_1.Expression.Number((0, bigint_1.factorial)(x.getMultiplier().numerator));
|
|
261
|
+
}
|
|
262
|
+
else if (Settings_1.Settings.EVALUATE) {
|
|
263
|
+
retval = gamma(x.plus((0, shortcuts_1.one)()));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// Check if we can simplify half integer factorials
|
|
267
|
+
let m = x.getMultiplier();
|
|
268
|
+
if (x.isNUM() && m.denominator === 2n) {
|
|
269
|
+
const sign = m.sign();
|
|
270
|
+
m = m.abs();
|
|
271
|
+
const n = new Expression_1.Expression(m.numerator - 1n).div((0, shortcuts_1.two)());
|
|
272
|
+
const sqrtPi = sqrt(Expression_1.Expression.Pi());
|
|
273
|
+
if (sign === -1) {
|
|
274
|
+
retval = (0, shortcuts_1.four)()
|
|
275
|
+
.neg()
|
|
276
|
+
.pow(n)
|
|
277
|
+
.times(factorial(n))
|
|
278
|
+
.div(factorial(n.times((0, shortcuts_1.two)())))
|
|
279
|
+
.times(sqrtPi);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
retval = factorial(n.times((0, shortcuts_1.two)()).plus((0, shortcuts_1.one)()))
|
|
283
|
+
.div((0, shortcuts_1.four)().pow(n).times(factorial(n)).times((0, shortcuts_1.two)()))
|
|
284
|
+
.times(sqrtPi);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
retval = Expression_1.Expression.toFunction(constants_2.FACTORIAL, [new Expression_1.Expression(x)]);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return retval;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Computes the double factorial of an expression.
|
|
295
|
+
*
|
|
296
|
+
* For a non-negative integer n, the double factorial is the product of all positive
|
|
297
|
+
* integers up to n that share its parity:
|
|
298
|
+
* - Even: `n!! = 2 · 4 · 6 · … · n`
|
|
299
|
+
* - Odd: `n!! = 1 · 3 · 5 · … · n`
|
|
300
|
+
*
|
|
301
|
+
* For non-integer arguments when `Settings.EVALUATE` is `true`, a generalised
|
|
302
|
+
* formula using the {@link gamma} function is applied.
|
|
303
|
+
*
|
|
304
|
+
* @param x - The expression to compute the double factorial of.
|
|
305
|
+
* @returns The double factorial of `x`.
|
|
306
|
+
* @throws {@link core!UndefinedError} If `x` is `-∞`.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* doubleFactorial(Expression.create(6)).text() // "48"
|
|
311
|
+
* doubleFactorial(Expression.create(7)).text() // "105"
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
function doubleFactorial(x) {
|
|
315
|
+
let retval;
|
|
316
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
317
|
+
if (x.isNegInf()) {
|
|
318
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
319
|
+
}
|
|
320
|
+
return Expression_1.Expression.Inf();
|
|
321
|
+
}
|
|
322
|
+
if (Settings_1.Settings.EVALUATE) {
|
|
323
|
+
if (x.isInteger()) {
|
|
324
|
+
const even = x.isEven();
|
|
325
|
+
const xn = Number(x.getMultiplier().toDecimal());
|
|
326
|
+
// If x = even then n = x/2 else n = (x-1)/2
|
|
327
|
+
const n = even ? xn / 2 : (xn + 1) / 2;
|
|
328
|
+
let r = (0, shortcuts_1.one)();
|
|
329
|
+
for (let i = 1; i <= n; i++) {
|
|
330
|
+
let q = (0, shortcuts_1.two)().times(i);
|
|
331
|
+
if (!even) {
|
|
332
|
+
q = q.minus(1);
|
|
333
|
+
}
|
|
334
|
+
r = r.times(q);
|
|
335
|
+
}
|
|
336
|
+
retval = r;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
const pi = Expression_1.Expression.Pi(true);
|
|
340
|
+
const a = (0, shortcuts_1.two)().pow(x
|
|
341
|
+
.times((0, shortcuts_1.two)())
|
|
342
|
+
.plus((0, shortcuts_1.one)())
|
|
343
|
+
.minus((0, trig_1.cos)(pi.times(x)))
|
|
344
|
+
.div((0, shortcuts_1.four)()));
|
|
345
|
+
const b = pi.pow((0, trig_1.cos)(pi.times(x)).minus((0, shortcuts_1.one)()).div((0, shortcuts_1.four)()));
|
|
346
|
+
const c = gamma(x.div((0, shortcuts_1.two)()).plus(1));
|
|
347
|
+
retval = a.times(b).times(c);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
retval = Expression_1.Expression.toFunction(constants_1.DOUBLE_FACTORIAL, [new Expression_1.Expression(x)]);
|
|
352
|
+
}
|
|
353
|
+
return retval;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Computes the Heaviside step function (unit step function).
|
|
357
|
+
*
|
|
358
|
+
* Uses the half-maximum convention at the origin:
|
|
359
|
+
* - `heaviside(x) = 0` for `x < 0`
|
|
360
|
+
* - `heaviside(0) = 1/2`
|
|
361
|
+
* - `heaviside(x) = 1` for `x > 0`
|
|
362
|
+
*
|
|
363
|
+
* For symbolic inputs, returns an unevaluated `heaviside(x)` node.
|
|
364
|
+
*
|
|
365
|
+
* @param x - The input expression.
|
|
366
|
+
* @returns The Heaviside step value.
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```ts
|
|
370
|
+
* heaviside(Expression.create(3)).text() // "1"
|
|
371
|
+
* heaviside(Expression.create(-2)).text() // "0"
|
|
372
|
+
* heaviside(Expression.create(0)).text() // "1/2"
|
|
373
|
+
* heaviside(Expression.create('t')).text() // "heaviside(t)"
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
376
|
+
function heaviside(x) {
|
|
377
|
+
let retval;
|
|
378
|
+
const useAssumptions = !x.isConstant() && !x.isComplex() && (0, assume_1.hasAssumptions)();
|
|
379
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
380
|
+
retval = x.isNegInf() ? (0, shortcuts_1.zero)() : (0, shortcuts_1.one)();
|
|
381
|
+
}
|
|
382
|
+
else if (x.isNUM()) {
|
|
383
|
+
const s = x.sign();
|
|
384
|
+
if (s === 1) {
|
|
385
|
+
retval = (0, shortcuts_1.one)();
|
|
386
|
+
}
|
|
387
|
+
else if (s === -1) {
|
|
388
|
+
retval = (0, shortcuts_1.zero)();
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// x === 0: half-maximum convention
|
|
392
|
+
retval = (0, shortcuts_1.half)();
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else if (useAssumptions && x.gt(0)) {
|
|
396
|
+
retval = (0, shortcuts_1.one)();
|
|
397
|
+
}
|
|
398
|
+
else if (useAssumptions && x.lt(0)) {
|
|
399
|
+
retval = (0, shortcuts_1.zero)();
|
|
400
|
+
}
|
|
401
|
+
else if (useAssumptions && x.gte(0) && x.lte(0)) {
|
|
402
|
+
retval = (0, shortcuts_1.half)();
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
retval = Expression_1.Expression.toFunction(constants_1.HEAVISIDE, [new Expression_1.Expression(x)]);
|
|
406
|
+
}
|
|
407
|
+
return retval;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Computes the Dirac delta function (distribution).
|
|
411
|
+
*
|
|
412
|
+
* For non-zero numeric inputs, returns `0`. At `x = 0` the symbolic form
|
|
413
|
+
* `dirac(0)` is returned (the Dirac delta is only meaningful under an
|
|
414
|
+
* integral or Laplace transform). For symbolic inputs, returns an
|
|
415
|
+
* unevaluated `dirac(x)` node.
|
|
416
|
+
*
|
|
417
|
+
* @param x - The input expression.
|
|
418
|
+
* @returns The Dirac delta value or symbolic node.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* dirac(Expression.create(5)).text() // "0"
|
|
423
|
+
* dirac(Expression.create(0)).text() // "dirac(0)"
|
|
424
|
+
* dirac(Expression.create('t')).text() // "dirac(t)"
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
function dirac(x) {
|
|
428
|
+
let retval;
|
|
429
|
+
const useAssumptions = !x.isConstant() && !x.isComplex() && (0, assume_1.hasAssumptions)();
|
|
430
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
431
|
+
retval = (0, shortcuts_1.zero)();
|
|
432
|
+
}
|
|
433
|
+
else if (x.isNUM()) {
|
|
434
|
+
if (x.isZero()) {
|
|
435
|
+
// Dirac delta at zero is technically infinite, but we return
|
|
436
|
+
// the symbolic form to avoid misleading numeric results.
|
|
437
|
+
retval = Expression_1.Expression.toFunction(constants_1.DIRAC, [new Expression_1.Expression(x)]);
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
retval = (0, shortcuts_1.zero)();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
else if (useAssumptions && (x.gt(0) || x.lt(0))) {
|
|
444
|
+
retval = (0, shortcuts_1.zero)();
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
retval = Expression_1.Expression.toFunction(constants_1.DIRAC, [new Expression_1.Expression(x)]);
|
|
448
|
+
}
|
|
449
|
+
return retval;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Evaluates a numeric expression to a finite number of significant decimal digits.
|
|
453
|
+
*
|
|
454
|
+
* Exact rational results are converted to decimal-origin values so subsequent numerical
|
|
455
|
+
* arithmetic does not keep expanding their numerators and denominators. Symbolic results
|
|
456
|
+
* remain symbolic after evaluation.
|
|
457
|
+
*
|
|
458
|
+
* @param x - Expression to evaluate numerically.
|
|
459
|
+
* @param precision - Significant digits to retain. Defaults to the active Nerdamer precision.
|
|
460
|
+
* @returns The evaluated numeric value at the requested precision, or the evaluated symbolic result.
|
|
461
|
+
*/
|
|
462
|
+
function numeric(x, precision) {
|
|
463
|
+
x = Expression_1.Expression.create(x);
|
|
464
|
+
return (0, Settings_1.scopedBlock)('DEFER_SIMPLIFICATION', false, () => {
|
|
465
|
+
let digits = Rational_1.Rational.getPrecision();
|
|
466
|
+
if (precision !== undefined) {
|
|
467
|
+
const requested = Expression_1.Expression.create(precision).evaluate();
|
|
468
|
+
if (!requested.isNUM() || !requested.isInteger()) {
|
|
469
|
+
throw new errors_1.UnexpectedInputError((0, errors_1.message)('wrongInput', {
|
|
470
|
+
expected: POSITIVE_INTEGER_PRECISION,
|
|
471
|
+
received: requested.text(),
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
const multiplier = requested.getMultiplier();
|
|
475
|
+
if (multiplier.numerator <= 0n ||
|
|
476
|
+
multiplier.numerator > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
477
|
+
throw new errors_1.UnexpectedInputError((0, errors_1.message)('wrongInput', {
|
|
478
|
+
expected: POSITIVE_INTEGER_PRECISION,
|
|
479
|
+
received: requested.text(),
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
482
|
+
digits = Number(multiplier.numerator);
|
|
483
|
+
}
|
|
484
|
+
const previousPrecision = Rational_1.Rational.getPrecision();
|
|
485
|
+
let retval;
|
|
486
|
+
try {
|
|
487
|
+
if (digits !== previousPrecision) {
|
|
488
|
+
Rational_1.Rational.set({ precision: digits });
|
|
489
|
+
}
|
|
490
|
+
const evaluated = x.isNUM() ? x : x.evaluate();
|
|
491
|
+
if (evaluated.variables().length > 0) {
|
|
492
|
+
retval = evaluated;
|
|
493
|
+
}
|
|
494
|
+
else if (evaluated.isNUM()) {
|
|
495
|
+
const multiplier = evaluated.getMultiplier();
|
|
496
|
+
const decimal = new decimal_js_1.default(multiplier.numerator.toString())
|
|
497
|
+
.div(multiplier.denominator.toString())
|
|
498
|
+
.toSignificantDigits(digits);
|
|
499
|
+
retval = Expression_1.Expression.Number(decimal);
|
|
500
|
+
retval.getMultiplier().asDecimal = true;
|
|
501
|
+
retval.precision = digits;
|
|
502
|
+
}
|
|
503
|
+
else if (evaluated.isComplex()) {
|
|
504
|
+
const real = numeric(evaluated.realPart(), digits);
|
|
505
|
+
const imaginary = numeric(evaluated.imagPart(), digits);
|
|
506
|
+
retval = real.plus(imaginary.times(Expression_1.Expression.Img()));
|
|
507
|
+
retval.precision = digits;
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
retval = evaluated;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
finally {
|
|
514
|
+
if (digits !== previousPrecision) {
|
|
515
|
+
Rational_1.Rational.set({ precision: previousPrecision });
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return retval;
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Rounds a number to the nth decimal place. If no precision is provided, rounds to
|
|
523
|
+
* the nearest integer.
|
|
524
|
+
*
|
|
525
|
+
* @param x - The expression to round.
|
|
526
|
+
* @param n - The number of decimal places to round. Defaults to `0`.
|
|
527
|
+
* @returns The rounded value of `x`.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* ```ts
|
|
531
|
+
* round('3.7').text() // "4"
|
|
532
|
+
* round('2.555', 2).text() // "2.56"
|
|
533
|
+
* round('1/3', 4).text() // "0.3333"
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
function round(x, n) {
|
|
537
|
+
x = Expression_1.Expression.create(x);
|
|
538
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
539
|
+
return x.isNegInf() ? Expression_1.Expression.NegInf() : Expression_1.Expression.Inf();
|
|
540
|
+
}
|
|
541
|
+
n = n ? Expression_1.Expression.create(n) : (0, shortcuts_1.zero)();
|
|
542
|
+
let retval;
|
|
543
|
+
if (x.isNUM() && n.isInteger()) {
|
|
544
|
+
// Convert n & x to a decimals
|
|
545
|
+
const d = x.getMultiplier().toDecimal();
|
|
546
|
+
const s = n.getMultiplier().toDecimal();
|
|
547
|
+
const t = new decimal_js_1.default(10).pow(s);
|
|
548
|
+
retval = new Expression_1.Expression(decimal_js_1.default.round(d.times(t)).div(t));
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
retval = Expression_1.Expression.toFunction(constants_1.ROUND, [x, n]);
|
|
552
|
+
}
|
|
553
|
+
return retval;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Returns the sign of a number as `1`, `-1`, or `0`.
|
|
557
|
+
*
|
|
558
|
+
* For constant expressions that are not plain numerics, the expression is
|
|
559
|
+
* evaluated first to determine its sign.
|
|
560
|
+
*
|
|
561
|
+
* @param x - The expression whose sign to determine.
|
|
562
|
+
* @returns `1`, `-1`, or `0` as an Expression, or a symbolic `sign(x)` node.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```ts
|
|
566
|
+
* sign(5).text() // "1"
|
|
567
|
+
* sign(-3).text() // "-1"
|
|
568
|
+
* sign(0).text() // "0"
|
|
569
|
+
* sign('x').text() // "sign(x)"
|
|
570
|
+
* ```
|
|
571
|
+
*/
|
|
572
|
+
function sign(x) {
|
|
573
|
+
x = Expression_1.Expression.create(x);
|
|
574
|
+
let retval;
|
|
575
|
+
if (x.isComplex()) {
|
|
576
|
+
retval = (0, complex_1.csgn)(x);
|
|
577
|
+
}
|
|
578
|
+
else if (x.isPosInf() || x.isNegInf()) {
|
|
579
|
+
retval = Expression_1.Expression.create(x.isNegInf() ? -1 : 1);
|
|
580
|
+
}
|
|
581
|
+
else if (x.isConstant()) {
|
|
582
|
+
retval = Expression_1.Expression.create((x.isNUM() ? x : x.evaluate()).getMultiplier().sign());
|
|
583
|
+
}
|
|
584
|
+
else if (!(0, assume_1.hasAssumptions)()) {
|
|
585
|
+
retval = Expression_1.Expression.toFunction(constants_1.SGN, [x]);
|
|
586
|
+
}
|
|
587
|
+
else if (x.gt(0)) {
|
|
588
|
+
retval = (0, shortcuts_1.one)();
|
|
589
|
+
}
|
|
590
|
+
else if (x.lt(0)) {
|
|
591
|
+
retval = (0, shortcuts_1.one)().neg();
|
|
592
|
+
}
|
|
593
|
+
else if (x.eq(0)) {
|
|
594
|
+
retval = (0, shortcuts_1.zero)();
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
retval = Expression_1.Expression.toFunction(constants_1.SGN, [x]);
|
|
598
|
+
}
|
|
599
|
+
return retval;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Rounds a number down to the nearest integer (floor function).
|
|
603
|
+
*
|
|
604
|
+
* @param x - The expression to round down.
|
|
605
|
+
* @returns The greatest integer less than or equal to `x`.
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```ts
|
|
609
|
+
* floor('3.7').text() // "3"
|
|
610
|
+
* floor('-2.3').text() // "-3"
|
|
611
|
+
* floor(5).text() // "5"
|
|
612
|
+
* floor('x').text() // "floor(x)"
|
|
613
|
+
* ```
|
|
614
|
+
*/
|
|
615
|
+
function floor(x) {
|
|
616
|
+
x = Expression_1.Expression.create(x);
|
|
617
|
+
let retval;
|
|
618
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
619
|
+
retval = x.isNegInf() ? Expression_1.Expression.NegInf() : Expression_1.Expression.Inf();
|
|
620
|
+
}
|
|
621
|
+
else if (x.isNUM()) {
|
|
622
|
+
// Convert n & x to a decimals
|
|
623
|
+
const d = x.getMultiplier().toDecimal();
|
|
624
|
+
retval = new Expression_1.Expression(d.floor());
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
retval = Expression_1.Expression.toFunction(constants_1.FLOOR, [x]);
|
|
628
|
+
}
|
|
629
|
+
return retval;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Rounds a number up to the nearest integer (ceiling function).
|
|
633
|
+
*
|
|
634
|
+
* @param x - The expression to round up.
|
|
635
|
+
* @returns The least integer greater than or equal to `x`.
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```ts
|
|
639
|
+
* ceiling('3.2').text() // "4"
|
|
640
|
+
* ceiling('-2.7').text() // "-2"
|
|
641
|
+
* ceiling(5).text() // "5"
|
|
642
|
+
* ceiling('x').text() // "ceil(x)"
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
function ceiling(x) {
|
|
646
|
+
x = Expression_1.Expression.create(x);
|
|
647
|
+
let retval;
|
|
648
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
649
|
+
retval = x.isNegInf() ? Expression_1.Expression.NegInf() : Expression_1.Expression.Inf();
|
|
650
|
+
}
|
|
651
|
+
else if (x.isNUM()) {
|
|
652
|
+
// Convert n & x to a decimals
|
|
653
|
+
const d = x.getMultiplier().toDecimal();
|
|
654
|
+
retval = new Expression_1.Expression(d.ceil());
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
retval = Expression_1.Expression.toFunction(constants_1.CEIL, [x]);
|
|
658
|
+
}
|
|
659
|
+
return retval;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Computes the absolute value of an expression.
|
|
663
|
+
*
|
|
664
|
+
* Applies symbolic simplifications where possible:
|
|
665
|
+
* - Even powers are recognised as non-negative (e.g. `abs(x^2)` returns `x^2`).
|
|
666
|
+
* - Complex inputs use the modulus: `abs(a + bi) = sqrt(a² + b²)`.
|
|
667
|
+
* - Fully negative sums are negated (e.g. `abs(-x - y)` becomes `x + y`).
|
|
668
|
+
*
|
|
669
|
+
* @param x - The expression to take the absolute value of.
|
|
670
|
+
* @returns The absolute value of `x`.
|
|
671
|
+
*
|
|
672
|
+
* @example
|
|
673
|
+
* ```ts
|
|
674
|
+
* abs(-5).text() // "5"
|
|
675
|
+
* abs('3/4').text() // "3/4"
|
|
676
|
+
* abs('x^2').text() // "x^2"
|
|
677
|
+
* abs('x').text() // "abs(x)"
|
|
678
|
+
* ```
|
|
679
|
+
*/
|
|
680
|
+
function abs(x) {
|
|
681
|
+
x = Expression_1.Expression.create(x);
|
|
682
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
683
|
+
return Expression_1.Expression.Inf();
|
|
684
|
+
}
|
|
685
|
+
let retval = x;
|
|
686
|
+
let wrap = true;
|
|
687
|
+
const useAssumptions = !x.isConstant() && (0, assume_1.hasAssumptions)();
|
|
688
|
+
if (!x.isConstant() && x.getPower().isEven()) {
|
|
689
|
+
retval = x;
|
|
690
|
+
// Remove the sign
|
|
691
|
+
if (retval.sign() === -1) {
|
|
692
|
+
retval = retval.neg();
|
|
693
|
+
}
|
|
694
|
+
wrap = false;
|
|
695
|
+
}
|
|
696
|
+
else if (x.isComplex()) {
|
|
697
|
+
retval = (0, geometry_1.hypot)(x.realPart(), x.imagPart());
|
|
698
|
+
}
|
|
699
|
+
else if (useAssumptions && x.gte(0)) {
|
|
700
|
+
retval = x;
|
|
701
|
+
wrap = false;
|
|
702
|
+
}
|
|
703
|
+
else if (useAssumptions && x.lte(0)) {
|
|
704
|
+
retval = x.neg();
|
|
705
|
+
wrap = false;
|
|
706
|
+
}
|
|
707
|
+
// Attempt to simplify expression in the for -x-y to |x+y|
|
|
708
|
+
else if (x.isSum()) {
|
|
709
|
+
// We'll loop through and sort out the constants and variables
|
|
710
|
+
// We can use this later to see if it has to be returned as the abs function
|
|
711
|
+
const constants = [];
|
|
712
|
+
const variables = [];
|
|
713
|
+
const elements = x.elementsArray();
|
|
714
|
+
let allNegative = true;
|
|
715
|
+
// Assume a positive sign. We'll flip this if we negate the expression.
|
|
716
|
+
// This is strictly for keeping track of what occurred with the sign.
|
|
717
|
+
// This avoids us having to go through each term again.
|
|
718
|
+
let sign = 1;
|
|
719
|
+
for (let i = 0; i < elements.length; i++) {
|
|
720
|
+
const e = elements[i];
|
|
721
|
+
if (e.isConstant()) {
|
|
722
|
+
constants.push(e);
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
variables.push(e);
|
|
726
|
+
}
|
|
727
|
+
// Check if all are negative. It takes only
|
|
728
|
+
if (e.sign() !== -1) {
|
|
729
|
+
allNegative = false;
|
|
730
|
+
}
|
|
731
|
+
// If all negative
|
|
732
|
+
if (allNegative || (variables.length === 1 && variables[0].sign() === -1)) {
|
|
733
|
+
retval = x.neg().expand();
|
|
734
|
+
sign = -1; // Flip the sign.
|
|
735
|
+
}
|
|
736
|
+
const next = elements[i + 1];
|
|
737
|
+
const isGRP = next && variables.length === 1 && next.value === variables[0].value;
|
|
738
|
+
// Check if it needs to be wrapped. We would prefer to have expressions like |x^2+1| in the form x^2+1
|
|
739
|
+
if (variables.length === 1 && variables[0].getPower().isEven() && !isGRP) {
|
|
740
|
+
// Assume that we won't have wrap
|
|
741
|
+
wrap = false;
|
|
742
|
+
// Check that the rest of the signs are positive
|
|
743
|
+
for (let i = 0; i < constants.length; i++) {
|
|
744
|
+
if (constants[i].sign() * sign === -1) {
|
|
745
|
+
wrap = true;
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
else if (x.sign() === -1) {
|
|
753
|
+
retval = x.neg();
|
|
754
|
+
}
|
|
755
|
+
// Just wrap it in a function if no simplification occurred
|
|
756
|
+
if (!retval) {
|
|
757
|
+
retval = x;
|
|
758
|
+
}
|
|
759
|
+
if (!retval.isConstant() && wrap) {
|
|
760
|
+
retval = Expression_1.Expression.toFunction(constants_1.ABS, [retval]);
|
|
761
|
+
}
|
|
762
|
+
return retval;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Computes the modular multiplicative inverse of `a` modulo `p` using the
|
|
766
|
+
* extended Euclidean algorithm. That is, finds `t` such that `a * t ≡ 1 (mod p)`.
|
|
767
|
+
*
|
|
768
|
+
* @param a - The number whose modular inverse is to be calculated.
|
|
769
|
+
* @param p - The modulus (typically prime).
|
|
770
|
+
* @returns The modular inverse of `a` mod `p`.
|
|
771
|
+
* @throws {@link core!MathError} If the inverse does not exist (i.e. `gcd(a, p) ≠ 1`).
|
|
772
|
+
*
|
|
773
|
+
* @example
|
|
774
|
+
* ```ts
|
|
775
|
+
* modInv(Expression.create(3), Expression.create(7)).text() // "5"
|
|
776
|
+
* modInv(Expression.create(10), Expression.create(17)).text() // "12"
|
|
777
|
+
* ```
|
|
778
|
+
*/
|
|
779
|
+
function modInv(a, p) {
|
|
780
|
+
let t = (0, shortcuts_1.zero)();
|
|
781
|
+
let tp = (0, shortcuts_1.one)(); // newT
|
|
782
|
+
let r = p;
|
|
783
|
+
let rp = mod(a, p); // newR
|
|
784
|
+
while (!rp.isZero()) {
|
|
785
|
+
const q = floor(r.div(rp));
|
|
786
|
+
[t, tp] = [tp, t.minus(q.times(tp))];
|
|
787
|
+
[r, rp] = [rp, r.minus(q.times(rp))];
|
|
788
|
+
}
|
|
789
|
+
if (r.gt(1)) {
|
|
790
|
+
throw new errors_1.MathError((0, errors_1.message)('noInverse'));
|
|
791
|
+
}
|
|
792
|
+
return mod(t, p);
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Computes the modulo (remainder) of `x` divided by `y`.
|
|
796
|
+
*
|
|
797
|
+
* @param x - The dividend.
|
|
798
|
+
* @param y - The divisor.
|
|
799
|
+
* @returns The remainder of `x / y`.
|
|
800
|
+
* @throws {@link core!UndefinedError} If either `x` or `y` is `±∞`.
|
|
801
|
+
*
|
|
802
|
+
* @example
|
|
803
|
+
* ```ts
|
|
804
|
+
* mod(Expression.create(10), Expression.create(3)).text() // "1"
|
|
805
|
+
* mod(Expression.create(7), Expression.create(2)).text() // "1"
|
|
806
|
+
* ```
|
|
807
|
+
*/
|
|
808
|
+
function mod(x, y) {
|
|
809
|
+
let retval;
|
|
810
|
+
if (x.isPosInf() || x.isNegInf() || y.isPosInf() || y.isNegInf()) {
|
|
811
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
812
|
+
}
|
|
813
|
+
if (x.isNUM() && y.isNUM()) {
|
|
814
|
+
retval = Expression_1.Expression.create(x.getMultiplier().mod(y.getMultiplier()));
|
|
815
|
+
}
|
|
816
|
+
else if (x.isPolynomialLike() &&
|
|
817
|
+
y.isPolynomialLike() &&
|
|
818
|
+
(0, utils_2.maxCommonVariableOccurrence)(x, y)) {
|
|
819
|
+
retval = (0, utils_2.polyMod)(x, y).getExpression();
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
retval = Expression_1.Expression.toFunction(constants_1.MOD, [new Expression_1.Expression(x), new Expression_1.Expression(y)]);
|
|
823
|
+
}
|
|
824
|
+
return retval;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Computes the gamma function Γ(x).
|
|
828
|
+
*
|
|
829
|
+
* - For positive integers: `Γ(n) = (n − 1)!`
|
|
830
|
+
* - For half-integers (e.g. `1/2`, `3/2`, `-3/2`): returns a closed-form
|
|
831
|
+
* expression involving `sqrt(π)`.
|
|
832
|
+
* - For other numeric values: uses a high-precision decimal approximation.
|
|
833
|
+
* - For symbolic inputs: returns an unevaluated `gamma(x)` node.
|
|
834
|
+
*
|
|
835
|
+
* @param x - The input expression.
|
|
836
|
+
* @returns The gamma function value Γ(x).
|
|
837
|
+
* @throws {@link core!UndefinedError} If `x` is `-∞`.
|
|
838
|
+
*
|
|
839
|
+
* @see https://en.wikipedia.org/wiki/Gamma_function
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* ```ts
|
|
843
|
+
* gamma(Expression.create(5)).text() // "24"
|
|
844
|
+
* gamma(Expression.create('1/2')).text() // "sqrt(pi)"
|
|
845
|
+
* gamma(Expression.create('x')).text() // "gamma(x)"
|
|
846
|
+
* ```
|
|
847
|
+
*/
|
|
848
|
+
function gamma(x) {
|
|
849
|
+
let retval;
|
|
850
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
851
|
+
if (x.isNegInf()) {
|
|
852
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
853
|
+
}
|
|
854
|
+
return Expression_1.Expression.Inf();
|
|
855
|
+
}
|
|
856
|
+
if (x.isNUM()) {
|
|
857
|
+
const m = x.getMultiplier();
|
|
858
|
+
if (x.isInteger() && !x.isNegative()) {
|
|
859
|
+
// gamma(n) = (n-1)! for positive integers
|
|
860
|
+
if (x.isZero()) {
|
|
861
|
+
retval = Expression_1.Expression.toFunction(constants_1.GAMMA, [x]);
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
retval = factorial(x.minus((0, shortcuts_1.one)()));
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
else if (m.denominator === 2n) {
|
|
868
|
+
const sqrtPi = sqrt(Expression_1.Expression.Pi());
|
|
869
|
+
const k = m.numerator;
|
|
870
|
+
// poles: 0, -1, -2, ...
|
|
871
|
+
if (k <= 0n && k % 2n === 0n) {
|
|
872
|
+
retval = Expression_1.Expression.toFunction(constants_1.GAMMA, [x]);
|
|
873
|
+
}
|
|
874
|
+
else if (k === 1n) {
|
|
875
|
+
// gamma(1/2) = sqrt(pi
|
|
876
|
+
retval = sqrtPi;
|
|
877
|
+
}
|
|
878
|
+
else if (k > 1n) {
|
|
879
|
+
// positive half-integers
|
|
880
|
+
let y = (0, shortcuts_1.half)();
|
|
881
|
+
let r = sqrtPi;
|
|
882
|
+
while (!y.eq(x)) {
|
|
883
|
+
r = y.times(r);
|
|
884
|
+
y = y.plus((0, shortcuts_1.one)());
|
|
885
|
+
}
|
|
886
|
+
retval = r;
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
// negative half-integers via recurrence
|
|
890
|
+
let y = (0, shortcuts_1.half)();
|
|
891
|
+
let r = sqrtPi;
|
|
892
|
+
while (!y.eq(x)) {
|
|
893
|
+
y = y.minus((0, shortcuts_1.one)());
|
|
894
|
+
r = r.div(y);
|
|
895
|
+
}
|
|
896
|
+
retval = r;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
retval = Expression_1.Expression.Number((0, decimal_1.gamma)(m.toDecimal()));
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
retval = Expression_1.Expression.toFunction(constants_1.GAMMA, [x]);
|
|
905
|
+
}
|
|
906
|
+
return retval;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Computes the complementary error function: `erfc(x) = 1 − erf(x)`.
|
|
910
|
+
*
|
|
911
|
+
* @param x - The input expression.
|
|
912
|
+
* @returns The complementary error function value.
|
|
913
|
+
*
|
|
914
|
+
* @see {@link erf}
|
|
915
|
+
*
|
|
916
|
+
* @example
|
|
917
|
+
* ```ts
|
|
918
|
+
* erfc(Expression.create(0)).text() // "0"
|
|
919
|
+
* ```
|
|
920
|
+
*/
|
|
921
|
+
function erfc(x) {
|
|
922
|
+
return (0, subtract_1.subtract)((0, shortcuts_1.one)(), erf(x));
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Computes the error function erf(x).
|
|
926
|
+
*
|
|
927
|
+
* - `erf(+∞) = 1`, `erf(−∞) = −1`
|
|
928
|
+
* - For numeric inputs, returns a high-precision decimal approximation.
|
|
929
|
+
* - For symbolic inputs, returns an unevaluated `erf(x)` node.
|
|
930
|
+
*
|
|
931
|
+
* @param x - The input expression.
|
|
932
|
+
* @returns The error function value.
|
|
933
|
+
*
|
|
934
|
+
* @see https://en.wikipedia.org/wiki/Error_function
|
|
935
|
+
*
|
|
936
|
+
* @example
|
|
937
|
+
* ```ts
|
|
938
|
+
* erf(Expression.create(0)).text() // "0"
|
|
939
|
+
* erf(Expression.create('x')).text() // "erf(x)"
|
|
940
|
+
* ```
|
|
941
|
+
*/
|
|
942
|
+
function erf(x) {
|
|
943
|
+
let retval;
|
|
944
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
945
|
+
retval = x.isNegInf() ? (0, shortcuts_1.one)().neg() : (0, shortcuts_1.one)();
|
|
946
|
+
}
|
|
947
|
+
else if (x.isNUM()) {
|
|
948
|
+
const m = x.getMultiplier();
|
|
949
|
+
// Gives junk values after erf > 6.7
|
|
950
|
+
if (m.gt('6.5')) {
|
|
951
|
+
retval = (0, shortcuts_1.one)();
|
|
952
|
+
}
|
|
953
|
+
else {
|
|
954
|
+
// Calculate it's numeric value
|
|
955
|
+
retval = Expression_1.Expression.Number((0, decimal_1.erf)(m.toDecimal()));
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
else {
|
|
959
|
+
retval = Expression_1.Expression.toFunction(constants_1.ERF, [new Expression_1.Expression(x)]);
|
|
960
|
+
}
|
|
961
|
+
return retval;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Computes the normalized sinc function: `sinc(x) = sin(x) / x`.
|
|
965
|
+
*
|
|
966
|
+
* By convention, `sinc(0) = 1` (the removable singularity).
|
|
967
|
+
* The function is even: `sinc(-x) = sinc(x)`.
|
|
968
|
+
*
|
|
969
|
+
* @param x - The input expression.
|
|
970
|
+
* @returns The sinc function value.
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```ts
|
|
974
|
+
* sinc(Expression.create(0)).text() // "1"
|
|
975
|
+
* sinc(Expression.create('x')).text() // "sinc(x)"
|
|
976
|
+
* ```
|
|
977
|
+
*/
|
|
978
|
+
function sinc(x) {
|
|
979
|
+
let retval;
|
|
980
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
981
|
+
retval = (0, shortcuts_1.zero)();
|
|
982
|
+
}
|
|
983
|
+
else if (x.isZero()) {
|
|
984
|
+
retval = (0, shortcuts_1.one)();
|
|
985
|
+
}
|
|
986
|
+
else if ((0, trig_1.sin)(x).isZero()) {
|
|
987
|
+
retval = (0, shortcuts_1.zero)();
|
|
988
|
+
}
|
|
989
|
+
else if (x.sign() === -1) {
|
|
990
|
+
retval = sinc(x.neg());
|
|
991
|
+
}
|
|
992
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
993
|
+
retval = Expression_1.Expression.Number((0, decimal_1.sinc)(x.getMultiplier().toDecimal()));
|
|
994
|
+
}
|
|
995
|
+
else if (Settings_1.Settings.EVALUATE) {
|
|
996
|
+
retval = (0, trig_1.sin)(x).div(x);
|
|
997
|
+
}
|
|
998
|
+
else {
|
|
999
|
+
retval = Expression_1.Expression.toFunction(constants_1.SINC, [new Expression_1.Expression(x)]);
|
|
1000
|
+
}
|
|
1001
|
+
return retval;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Computes the sine integral: `Si(x) = ∫₀ˣ sin(t)/t dt`.
|
|
1005
|
+
*
|
|
1006
|
+
* - `Si(+∞) = π/2`, `Si(−∞) = −π/2`
|
|
1007
|
+
* - `Si(0) = 0`
|
|
1008
|
+
* - The function is odd: `Si(-x) = -Si(x)`.
|
|
1009
|
+
*
|
|
1010
|
+
* @param x - The input expression.
|
|
1011
|
+
* @returns The sine integral value.
|
|
1012
|
+
*
|
|
1013
|
+
* @example
|
|
1014
|
+
* ```ts
|
|
1015
|
+
* Si(Expression.create(0)).text() // "0"
|
|
1016
|
+
* Si(Expression.create('x')).text() // "Si(x)"
|
|
1017
|
+
* ```
|
|
1018
|
+
*/
|
|
1019
|
+
function Si(x) {
|
|
1020
|
+
let retval;
|
|
1021
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1022
|
+
retval = Expression_1.Expression.Pi().div((0, shortcuts_1.two)());
|
|
1023
|
+
if (x.isNegInf()) {
|
|
1024
|
+
retval = retval.neg();
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
else if (x.isZero()) {
|
|
1028
|
+
retval = (0, shortcuts_1.zero)();
|
|
1029
|
+
}
|
|
1030
|
+
else if (x.sign() === -1) {
|
|
1031
|
+
retval = Si(x.neg()).neg();
|
|
1032
|
+
}
|
|
1033
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1034
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Si)(x.getMultiplier().toDecimal()));
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
retval = Expression_1.Expression.toFunction(constants_1.SI, [new Expression_1.Expression(x)]);
|
|
1038
|
+
}
|
|
1039
|
+
return retval;
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Computes the hyperbolic sine integral: `Shi(x) = ∫₀ˣ sinh(t)/t dt`.
|
|
1043
|
+
*
|
|
1044
|
+
* - `Shi(+∞) = +∞`, `Shi(−∞) = −∞`
|
|
1045
|
+
* - `Shi(0) = 0`
|
|
1046
|
+
* - The function is odd: `Shi(-x) = -Shi(x)`.
|
|
1047
|
+
*
|
|
1048
|
+
* @param x - The input expression.
|
|
1049
|
+
* @returns The hyperbolic sine integral value.
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```ts
|
|
1053
|
+
* Shi(Expression.create(0)).text() // "0"
|
|
1054
|
+
* Shi(Expression.create('x')).text() // "Shi(x)"
|
|
1055
|
+
* ```
|
|
1056
|
+
*/
|
|
1057
|
+
function Shi(x) {
|
|
1058
|
+
let retval;
|
|
1059
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1060
|
+
retval = x.isNegInf() ? Expression_1.Expression.NegInf() : Expression_1.Expression.Inf();
|
|
1061
|
+
}
|
|
1062
|
+
else if (x.isZero()) {
|
|
1063
|
+
retval = (0, shortcuts_1.zero)();
|
|
1064
|
+
}
|
|
1065
|
+
else if (x.sign() === -1) {
|
|
1066
|
+
retval = Shi(x.neg()).neg();
|
|
1067
|
+
}
|
|
1068
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1069
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Shi)(x.getMultiplier().toDecimal()));
|
|
1070
|
+
}
|
|
1071
|
+
else {
|
|
1072
|
+
retval = Expression_1.Expression.toFunction(constants_1.SHI, [new Expression_1.Expression(x)]);
|
|
1073
|
+
}
|
|
1074
|
+
return retval;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Computes the cosine integral: `Ci(x) = γ + ln(x) + ∫₀ˣ (cos(t)−1)/t dt`,
|
|
1078
|
+
* where γ is the Euler–Mascheroni constant.
|
|
1079
|
+
*
|
|
1080
|
+
* - `Ci(+∞) = 0`, `Ci(−∞) = 0`
|
|
1081
|
+
* - `Ci(0) = −∞`
|
|
1082
|
+
* - The function is even for the principal branch: `Ci(-x) = Ci(x)`.
|
|
1083
|
+
*
|
|
1084
|
+
* @param x - The input expression.
|
|
1085
|
+
* @returns The cosine integral value.
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* ```ts
|
|
1089
|
+
* Ci(Expression.create('x')).text() // "Ci(x)"
|
|
1090
|
+
* ```
|
|
1091
|
+
*/
|
|
1092
|
+
function Ci(x) {
|
|
1093
|
+
let retval;
|
|
1094
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1095
|
+
retval = (0, shortcuts_1.zero)();
|
|
1096
|
+
}
|
|
1097
|
+
else if (x.isZero()) {
|
|
1098
|
+
retval = Expression_1.Expression.NegInf();
|
|
1099
|
+
}
|
|
1100
|
+
else if (x.sign() === -1) {
|
|
1101
|
+
retval = Ci(x.neg());
|
|
1102
|
+
}
|
|
1103
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1104
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Ci)(x.getMultiplier().toDecimal()));
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
retval = Expression_1.Expression.toFunction(constants_1.CI, [new Expression_1.Expression(x)]);
|
|
1108
|
+
}
|
|
1109
|
+
return retval;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Computes the hyperbolic cosine integral: `Chi(x) = γ + ln(x) + ∫₀ˣ (cosh(t)−1)/t dt`,
|
|
1113
|
+
* where γ is the Euler–Mascheroni constant.
|
|
1114
|
+
*
|
|
1115
|
+
* - `Chi(±∞) = +∞`
|
|
1116
|
+
* - `Chi(0) = −∞`
|
|
1117
|
+
* - The function is even for the principal branch: `Chi(-x) = Chi(x)`.
|
|
1118
|
+
*
|
|
1119
|
+
* @param x - The input expression.
|
|
1120
|
+
* @returns The hyperbolic cosine integral value.
|
|
1121
|
+
*
|
|
1122
|
+
* @example
|
|
1123
|
+
* ```ts
|
|
1124
|
+
* Chi(Expression.create('x')).text() // "Chi(x)"
|
|
1125
|
+
* ```
|
|
1126
|
+
*/
|
|
1127
|
+
function Chi(x) {
|
|
1128
|
+
let retval;
|
|
1129
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1130
|
+
retval = Expression_1.Expression.Inf();
|
|
1131
|
+
}
|
|
1132
|
+
else if (x.isZero()) {
|
|
1133
|
+
retval = Expression_1.Expression.NegInf();
|
|
1134
|
+
}
|
|
1135
|
+
else if (x.sign() === -1) {
|
|
1136
|
+
retval = Chi(x.neg());
|
|
1137
|
+
}
|
|
1138
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1139
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Chi)(x.getMultiplier().toDecimal()));
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
retval = Expression_1.Expression.toFunction(constants_1.CHI, [new Expression_1.Expression(x)]);
|
|
1143
|
+
}
|
|
1144
|
+
return retval;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Computes the exponential integral: `Ei(x) = −∫₋ₓ^∞ e^(−t)/t dt` (Cauchy principal value).
|
|
1148
|
+
*
|
|
1149
|
+
* - `Ei(+∞) = +∞`, `Ei(−∞) = 0`
|
|
1150
|
+
* - `Ei(0) = −∞`
|
|
1151
|
+
*
|
|
1152
|
+
* @param x - The input expression.
|
|
1153
|
+
* @returns The exponential integral value.
|
|
1154
|
+
*
|
|
1155
|
+
* @example
|
|
1156
|
+
* ```ts
|
|
1157
|
+
* Ei(Expression.create(0)).text() // "-Infinity"
|
|
1158
|
+
* Ei(Expression.create('x')).text() // "Ei(x)"
|
|
1159
|
+
* ```
|
|
1160
|
+
*/
|
|
1161
|
+
function Ei(x) {
|
|
1162
|
+
let retval;
|
|
1163
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1164
|
+
retval = x.isNegInf() ? (0, shortcuts_1.zero)() : Expression_1.Expression.Inf();
|
|
1165
|
+
}
|
|
1166
|
+
else if (x.isZero()) {
|
|
1167
|
+
retval = Expression_1.Expression.NegInf();
|
|
1168
|
+
}
|
|
1169
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1170
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Ei)(x.getMultiplier().toDecimal()));
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
retval = Expression_1.Expression.toFunction(constants_1.EI, [new Expression_1.Expression(x)]);
|
|
1174
|
+
}
|
|
1175
|
+
return retval;
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Computes the logarithmic integral: `Li(x) = ∫₀ˣ 1/ln(t) dt`.
|
|
1179
|
+
*
|
|
1180
|
+
* - `Li(+∞) = +∞`
|
|
1181
|
+
* - `Li(1) = −∞` (the function has a logarithmic singularity at 1)
|
|
1182
|
+
* - For negative numeric inputs, returns the symbolic form.
|
|
1183
|
+
*
|
|
1184
|
+
* @param x - The input expression.
|
|
1185
|
+
* @returns The logarithmic integral value.
|
|
1186
|
+
*
|
|
1187
|
+
* @example
|
|
1188
|
+
* ```ts
|
|
1189
|
+
* Li(Expression.create('x')).text() // "Li(x)"
|
|
1190
|
+
* ```
|
|
1191
|
+
*/
|
|
1192
|
+
function Li(x) {
|
|
1193
|
+
let retval;
|
|
1194
|
+
if (x.isPosInf()) {
|
|
1195
|
+
retval = Expression_1.Expression.Inf();
|
|
1196
|
+
}
|
|
1197
|
+
else if (x.isOne()) {
|
|
1198
|
+
retval = Expression_1.Expression.NegInf();
|
|
1199
|
+
}
|
|
1200
|
+
else if (x.isNUM() && Settings_1.Settings.EVALUATE) {
|
|
1201
|
+
const m = x.getMultiplier();
|
|
1202
|
+
if (m.isNegative()) {
|
|
1203
|
+
retval = Expression_1.Expression.toFunction(constants_1.LI, [new Expression_1.Expression(x)]);
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
retval = Expression_1.Expression.Number((0, decimal_1.Li)(m.toDecimal()));
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
else {
|
|
1210
|
+
retval = Expression_1.Expression.toFunction(constants_1.LI, [new Expression_1.Expression(x)]);
|
|
1211
|
+
}
|
|
1212
|
+
return retval;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Computes the natural (base-e) logarithm, or optionally a logarithm with a specified base.
|
|
1216
|
+
*
|
|
1217
|
+
* When `Settings.EVALUATE` is `false`, real-domain logarithm identities are
|
|
1218
|
+
* applied only when their arguments are provably positive real values. This
|
|
1219
|
+
* keeps product, quotient, and power rewrites from crossing principal complex
|
|
1220
|
+
* branches when a symbolic sign is unknown.
|
|
1221
|
+
*
|
|
1222
|
+
* For known negative real inputs, returns `log(|x|) + iπ`. Complex inputs use the
|
|
1223
|
+
* principal branch: `log(z) = log|z| + i·arg(z)`.
|
|
1224
|
+
*
|
|
1225
|
+
* @param x - The expression to take the logarithm of.
|
|
1226
|
+
* @param base - Optional logarithm base. Defaults to `e` (natural log).
|
|
1227
|
+
* @param expandPrimes - When `true`, decomposes integer arguments into prime factors
|
|
1228
|
+
* (e.g. `log(8)` becomes `3·log(2)`). Defaults to `false`.
|
|
1229
|
+
* @returns The logarithm of `x`.
|
|
1230
|
+
* @throws {@link core!UndefinedError} If `x` is `-∞`.
|
|
1231
|
+
*
|
|
1232
|
+
* @example
|
|
1233
|
+
* ```ts
|
|
1234
|
+
* log('e').text() // "1"
|
|
1235
|
+
* log(1).text() // "0"
|
|
1236
|
+
* log('e^x').text() // "x"
|
|
1237
|
+
*
|
|
1238
|
+
* // With base
|
|
1239
|
+
* log(8, 2).text() // "3"
|
|
1240
|
+
* ```
|
|
1241
|
+
*/
|
|
1242
|
+
function log(x, base, expandPrimes = false) {
|
|
1243
|
+
x = Expression_1.Expression.create(x);
|
|
1244
|
+
const baseExpr = base === undefined ? undefined : Expression_1.Expression.create(base);
|
|
1245
|
+
let exactBaseLog;
|
|
1246
|
+
let retval;
|
|
1247
|
+
if (baseExpr &&
|
|
1248
|
+
x.isInteger() &&
|
|
1249
|
+
baseExpr.isInteger() &&
|
|
1250
|
+
x.gt(0) &&
|
|
1251
|
+
baseExpr.gt(1)) {
|
|
1252
|
+
const target = x.getMultiplier().numerator;
|
|
1253
|
+
const radix = baseExpr.getMultiplier().numerator;
|
|
1254
|
+
let value = 1n;
|
|
1255
|
+
let exponent = 0n;
|
|
1256
|
+
while (value < target) {
|
|
1257
|
+
value *= radix;
|
|
1258
|
+
exponent++;
|
|
1259
|
+
}
|
|
1260
|
+
if (value === target) {
|
|
1261
|
+
exactBaseLog = Expression_1.Expression.Number(exponent);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1265
|
+
if (x.isNegInf()) {
|
|
1266
|
+
throw new errors_1.UndefinedError((0, errors_1.message)('undefinedValue'));
|
|
1267
|
+
}
|
|
1268
|
+
retval = Expression_1.Expression.Inf();
|
|
1269
|
+
}
|
|
1270
|
+
else if (x.isOne()) {
|
|
1271
|
+
retval = (0, shortcuts_1.zero)();
|
|
1272
|
+
}
|
|
1273
|
+
else if (exactBaseLog) {
|
|
1274
|
+
retval = exactBaseLog;
|
|
1275
|
+
}
|
|
1276
|
+
else if (x.isE() && x.getMultiplier().isOne()) {
|
|
1277
|
+
const exponent = x.getPower();
|
|
1278
|
+
// Principal Log(e^z) only simplifies directly when z has no complex component. A complex
|
|
1279
|
+
// exponent can wrap by a multiple of 2*pi*i when mapped back to the
|
|
1280
|
+
// principal branch, so preserve that form instead of returning z.
|
|
1281
|
+
if (!exponent.isComplex()) {
|
|
1282
|
+
retval = (0, shortcuts_1.one)().times(exponent);
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
retval = Expression_1.Expression.toFunction(Expression_1.Expression.LOG, [new Expression_1.Expression(x)]);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
else if (!x.isComplex() && x.lt(0)) {
|
|
1289
|
+
retval = Expression_1.Expression.Pi().times(Expression_1.Expression.Img()).plus(log(x.abs()));
|
|
1290
|
+
}
|
|
1291
|
+
// Handle complex numbers regardless of EVALUATE setting
|
|
1292
|
+
else if (x.isComplex()) {
|
|
1293
|
+
const re = x.realPart();
|
|
1294
|
+
const im = x.imagPart();
|
|
1295
|
+
// Compute |z|
|
|
1296
|
+
const mag = sqrt(re.sq().plus(im.sq()));
|
|
1297
|
+
// log(z) = log(|z|) + i*arg(z)
|
|
1298
|
+
retval = log(mag).plus((0, trig_1.atan2)(im, re).i());
|
|
1299
|
+
}
|
|
1300
|
+
// Don't collapse
|
|
1301
|
+
else if (Settings_1.Settings.EVALUATE) {
|
|
1302
|
+
if (x.isNUM()) {
|
|
1303
|
+
// If a numeric base is provided, compute log_b(x) directly.
|
|
1304
|
+
if (baseExpr && baseExpr.isNUM()) {
|
|
1305
|
+
const lnX = x.getMultiplier().toDecimal().ln();
|
|
1306
|
+
const lnB = baseExpr.getMultiplier().toDecimal().ln();
|
|
1307
|
+
retval = Expression_1.Expression.Number(lnX.div(lnB));
|
|
1308
|
+
}
|
|
1309
|
+
else {
|
|
1310
|
+
retval = Expression_1.Expression.Number(x.getMultiplier().toDecimal().ln());
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
// Symbolic cases
|
|
1315
|
+
else {
|
|
1316
|
+
// Rational number: log(a/b) → log(a) - log(b)
|
|
1317
|
+
// Handle NUM first to avoid infinite recursion with multiplier factoring
|
|
1318
|
+
if (x.isNUM()) {
|
|
1319
|
+
const rat = x.getMultiplier();
|
|
1320
|
+
const num = rat.numerator < 0n ? -rat.numerator : rat.numerator;
|
|
1321
|
+
const den = rat.denominator < 0n ? -rat.denominator : rat.denominator;
|
|
1322
|
+
if (den !== 1n) {
|
|
1323
|
+
// log(a/b) = log(a) - log(b)
|
|
1324
|
+
retval = log(Expression_1.Expression.Number(num)).minus(log(Expression_1.Expression.Number(den)));
|
|
1325
|
+
}
|
|
1326
|
+
else if (expandPrimes) {
|
|
1327
|
+
// Try to decompose into prime factors: log(8) → 3*log(2)
|
|
1328
|
+
const factors = (0, primeFactor_1.primeFactorCounts)(num);
|
|
1329
|
+
const primes = Object.keys(factors);
|
|
1330
|
+
if (primes.length > 0 && (primes.length > 1 || factors[primes[0]] > 1n)) {
|
|
1331
|
+
retval = (0, shortcuts_1.zero)();
|
|
1332
|
+
for (const prime in factors) {
|
|
1333
|
+
const count = factors[prime];
|
|
1334
|
+
const logPrime = Expression_1.Expression.toFunction(Expression_1.Expression.LOG, [
|
|
1335
|
+
Expression_1.Expression.Number(prime),
|
|
1336
|
+
]);
|
|
1337
|
+
retval = retval.plus(logPrime.times(Expression_1.Expression.Number(count)));
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
// else: it's prime, fall through to default
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
// Non-NUM symbolic cases: only apply real-domain logarithm identities
|
|
1344
|
+
// when the relevant factors are provably positive and the powers are real.
|
|
1345
|
+
else {
|
|
1346
|
+
const m = x.getMultiplier();
|
|
1347
|
+
const mFree = x.toUnitMultiplier();
|
|
1348
|
+
let logExpr;
|
|
1349
|
+
let mFreeIsPositive = false;
|
|
1350
|
+
// Product: log(a*b*c) → log(a) + log(b) + log(c), but only
|
|
1351
|
+
// when every factor is known to stay on the positive real axis.
|
|
1352
|
+
if (mFree.isProduct() && mFree.isLinear()) {
|
|
1353
|
+
const elements = mFree.elementsArray();
|
|
1354
|
+
let canSplitProduct = true;
|
|
1355
|
+
for (const element of elements) {
|
|
1356
|
+
let elementIsPositive = false;
|
|
1357
|
+
if (element.isNUM()) {
|
|
1358
|
+
elementIsPositive = element.gt(0);
|
|
1359
|
+
}
|
|
1360
|
+
else {
|
|
1361
|
+
const elementPower = element.getPower();
|
|
1362
|
+
const elementBase = element.isEXP()
|
|
1363
|
+
? element.getBase()
|
|
1364
|
+
: (0, utils_3.stripPower)(element);
|
|
1365
|
+
elementIsPositive =
|
|
1366
|
+
!elementPower.isComplex() &&
|
|
1367
|
+
!elementBase.isComplex() &&
|
|
1368
|
+
elementBase.gt(0);
|
|
1369
|
+
}
|
|
1370
|
+
if (!elementIsPositive) {
|
|
1371
|
+
canSplitProduct = false;
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
if (canSplitProduct) {
|
|
1376
|
+
let sum = (0, shortcuts_1.zero)();
|
|
1377
|
+
for (const element of elements) {
|
|
1378
|
+
sum = sum.plus(log(element));
|
|
1379
|
+
}
|
|
1380
|
+
logExpr = sum;
|
|
1381
|
+
mFreeIsPositive = true;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
else {
|
|
1385
|
+
const pow = mFree.getPower();
|
|
1386
|
+
const baseExpr = mFree.isEXP() ? mFree.getBase() : (0, utils_3.stripPower)(mFree);
|
|
1387
|
+
if (pow.isOne()) {
|
|
1388
|
+
logExpr = Expression_1.Expression.toFunction(Expression_1.Expression.LOG, [mFree]);
|
|
1389
|
+
mFreeIsPositive = !mFree.isComplex() && mFree.gt(0);
|
|
1390
|
+
}
|
|
1391
|
+
// log(a^p) → p*log(a) is branch-safe for a positive real base
|
|
1392
|
+
// and a real exponent. Unknown-sign bases remain attached.
|
|
1393
|
+
else if (!pow.isComplex() && !baseExpr.isComplex() && baseExpr.gt(0)) {
|
|
1394
|
+
logExpr = log(baseExpr).times(pow);
|
|
1395
|
+
mFreeIsPositive = true;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
// log(m*expr) = log(m) + log(expr) is only valid here when
|
|
1399
|
+
// both pieces are known positive. Otherwise preserve the original log.
|
|
1400
|
+
if (logExpr !== undefined && !m.isOne()) {
|
|
1401
|
+
if (m.sign() > 0 && mFreeIsPositive) {
|
|
1402
|
+
retval = logExpr.plus(log(Expression_1.Expression.fromRational(m)));
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
else {
|
|
1406
|
+
retval = logExpr;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
retval = retval || Expression_1.Expression.toFunction(Expression_1.Expression.LOG, [new Expression_1.Expression(x)]);
|
|
1411
|
+
// Handle base conversion: log_b(x) = log(x) / log(b)
|
|
1412
|
+
if (baseExpr && retval && !exactBaseLog) {
|
|
1413
|
+
retval = retval.div(log(baseExpr));
|
|
1414
|
+
}
|
|
1415
|
+
return retval;
|
|
1416
|
+
}
|
|
1417
|
+
function aggregator(args, condition, assumedCondition) {
|
|
1418
|
+
let retval = undefined;
|
|
1419
|
+
const inputs = args.map(e => Expression_1.Expression.create(e));
|
|
1420
|
+
let canCompare = true;
|
|
1421
|
+
const expressions = inputs.map(e => {
|
|
1422
|
+
const value = (0, utils_1.getNumericOrAssumedValue)(e);
|
|
1423
|
+
if (value === undefined) {
|
|
1424
|
+
canCompare = false;
|
|
1425
|
+
}
|
|
1426
|
+
return value;
|
|
1427
|
+
});
|
|
1428
|
+
if (canCompare === true &&
|
|
1429
|
+
expressions.length > 0 &&
|
|
1430
|
+
expressions.every((e) => e !== undefined)) {
|
|
1431
|
+
let m = expressions[0];
|
|
1432
|
+
for (let i = 1; i < expressions.length; i++) {
|
|
1433
|
+
const e = expressions[i];
|
|
1434
|
+
if (condition(e, m)) {
|
|
1435
|
+
m = e;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
retval = m;
|
|
1439
|
+
}
|
|
1440
|
+
else {
|
|
1441
|
+
const useAssumptions = (0, assume_1.hasAssumptions)() &&
|
|
1442
|
+
inputs.every(e => !e.isComplex()) &&
|
|
1443
|
+
inputs.some(e => e.variables().some(v => (0, assume_1.getAssumptionFor)(v) !== undefined));
|
|
1444
|
+
if (useAssumptions) {
|
|
1445
|
+
for (const candidate of inputs) {
|
|
1446
|
+
if (inputs.every(e => assumedCondition(candidate, e))) {
|
|
1447
|
+
retval = candidate;
|
|
1448
|
+
break;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
// Equal values need no ordering when numeric or assumed comparison is unavailable.
|
|
1453
|
+
if (retval === undefined && inputs.length > 0 && inputs.every(e => e.eq(inputs[0]))) {
|
|
1454
|
+
retval = inputs[0];
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
return retval;
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Returns the maximum value from a set of expressions.
|
|
1461
|
+
*
|
|
1462
|
+
* If all arguments can be compared numerically (or have assumed numeric values),
|
|
1463
|
+
* returns the largest. Otherwise returns a symbolic `max(...)` node.
|
|
1464
|
+
*
|
|
1465
|
+
* @param args - Two or more expressions to compare.
|
|
1466
|
+
* @returns The maximum value, or a symbolic `max(...)` node.
|
|
1467
|
+
*
|
|
1468
|
+
* @example
|
|
1469
|
+
* ```ts
|
|
1470
|
+
* max(1, 3, 2).text() // "3"
|
|
1471
|
+
* max(-5, 0).text() // "0"
|
|
1472
|
+
* max('x', 'y').text() // "max(x, y)"
|
|
1473
|
+
* ```
|
|
1474
|
+
*/
|
|
1475
|
+
function max(...args) {
|
|
1476
|
+
const maxValue = aggregator(args, (a, b) => a.gt(b), (a, b) => a.gte(b));
|
|
1477
|
+
return maxValue ?? Expression_1.Expression.toFunction(constants_1.MAX, args);
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Returns the minimum value from a set of expressions.
|
|
1481
|
+
*
|
|
1482
|
+
* If all arguments can be compared numerically (or have assumed numeric values),
|
|
1483
|
+
* returns the smallest. Otherwise returns a symbolic `min(...)` node.
|
|
1484
|
+
*
|
|
1485
|
+
* @param args - Two or more expressions to compare.
|
|
1486
|
+
* @returns The minimum value, or a symbolic `min(...)` node.
|
|
1487
|
+
*
|
|
1488
|
+
* @example
|
|
1489
|
+
* ```ts
|
|
1490
|
+
* min(1, 3, 2).text() // "1"
|
|
1491
|
+
* min(-5, 0).text() // "-5"
|
|
1492
|
+
* min('x', 'y').text() // "min(x, y)"
|
|
1493
|
+
* ```
|
|
1494
|
+
*/
|
|
1495
|
+
function min(...args) {
|
|
1496
|
+
const minValue = aggregator(args, (a, b) => a.lt(b), (a, b) => a.lte(b));
|
|
1497
|
+
return minValue ?? Expression_1.Expression.toFunction(constants_1.MIN, args);
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Computes the exponential function e^x.
|
|
1501
|
+
*
|
|
1502
|
+
* - `exp(0) = 1`
|
|
1503
|
+
* - `exp(+∞) = +∞`, `exp(−∞) = 0`
|
|
1504
|
+
* - For complex inputs `a + bi` where both parts are numeric, applies Euler's formula:
|
|
1505
|
+
* `exp(a + bi) = exp(a) · (cos(b) + i·sin(b))`.
|
|
1506
|
+
* - For symbolic inputs, returns `e^(x)`.
|
|
1507
|
+
*
|
|
1508
|
+
* @param x - The exponent expression.
|
|
1509
|
+
* @returns The value of e raised to the power `x`.
|
|
1510
|
+
*
|
|
1511
|
+
* @example
|
|
1512
|
+
* ```ts
|
|
1513
|
+
* exp(0).text() // "1"
|
|
1514
|
+
* exp(1).text() // "2.71828182845904..."
|
|
1515
|
+
* exp('x').text() // "e^(x)"
|
|
1516
|
+
* ```
|
|
1517
|
+
*/
|
|
1518
|
+
function exp(x) {
|
|
1519
|
+
let retval;
|
|
1520
|
+
let z;
|
|
1521
|
+
let re;
|
|
1522
|
+
let im;
|
|
1523
|
+
let c;
|
|
1524
|
+
let s;
|
|
1525
|
+
let ea;
|
|
1526
|
+
x = Expression_1.Expression.create(x);
|
|
1527
|
+
// Easy simplifications
|
|
1528
|
+
if (x.isPosInf() || x.isNegInf()) {
|
|
1529
|
+
return x.isNegInf() ? (0, shortcuts_1.zero)() : Expression_1.Expression.Inf();
|
|
1530
|
+
}
|
|
1531
|
+
else if (x.isZero()) {
|
|
1532
|
+
retval = (0, shortcuts_1.one)();
|
|
1533
|
+
}
|
|
1534
|
+
else if (Settings_1.Settings.EVALUATE) {
|
|
1535
|
+
// Handle complex
|
|
1536
|
+
if (x.isComplex()) {
|
|
1537
|
+
// Only evaluate if we can guarantee a numeric value in C.
|
|
1538
|
+
// We do this by evaluating x first, then requiring both real and imaginary
|
|
1539
|
+
// parts to be numeric.
|
|
1540
|
+
z = x.evaluate();
|
|
1541
|
+
re = z.realPart();
|
|
1542
|
+
im = z.imagPart();
|
|
1543
|
+
if (re.isNUM() && im.isNUM()) {
|
|
1544
|
+
// exp(a+bi) = exp(a) * (cos(b) + i*sin(b))
|
|
1545
|
+
ea = Expression_1.Expression.Number(re.getMultiplier().toDecimal().exp());
|
|
1546
|
+
c = (0, trig_1.cos)(im);
|
|
1547
|
+
s = (0, trig_1.sin)(im);
|
|
1548
|
+
retval = ea.times(c.plus(s.i()));
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
else if (x.isNUM()) {
|
|
1552
|
+
retval = Expression_1.Expression.Number(x.getMultiplier().toDecimal().exp());
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
return retval ?? Expression_1.Expression.create(`e^(${x})`);
|
|
1556
|
+
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Constructs a {@link Matrix} from the provided rows.
|
|
1559
|
+
*
|
|
1560
|
+
* Each argument is an array representing one row of the matrix. All rows must
|
|
1561
|
+
* have the same length; elements are converted to {@link Expression} instances.
|
|
1562
|
+
*
|
|
1563
|
+
* @param args - One or more arrays, each representing one row of the matrix.
|
|
1564
|
+
* @returns A new {@link Matrix} instance.
|
|
1565
|
+
* @throws {@link core!MathError} If rows have inconsistent lengths.
|
|
1566
|
+
*
|
|
1567
|
+
* @example
|
|
1568
|
+
* ```ts
|
|
1569
|
+
* // 2×2 identity matrix
|
|
1570
|
+
* matrix([1, 0], [0, 1]).text() // "matrix([1, 0], [0, 1])"
|
|
1571
|
+
*
|
|
1572
|
+
* // 2×3 matrix
|
|
1573
|
+
* matrix([1, 2, 3], [4, 5, 6]).text()
|
|
1574
|
+
* ```
|
|
1575
|
+
*/
|
|
1576
|
+
function matrix(...args) {
|
|
1577
|
+
return new Matrix_1.Matrix(...args);
|
|
1578
|
+
}
|
|
1579
|
+
/**
|
|
1580
|
+
* Attempts to extract an integer bigint from an Expression.
|
|
1581
|
+
* Returns null if the expression is not an exact integer.
|
|
1582
|
+
*/
|
|
1583
|
+
function toIntegerBigint(x) {
|
|
1584
|
+
const isInt = x.isInteger();
|
|
1585
|
+
if (!isInt) {
|
|
1586
|
+
return null;
|
|
1587
|
+
}
|
|
1588
|
+
const m = x.getMultiplier();
|
|
1589
|
+
const den = m.denominator;
|
|
1590
|
+
if (den !== 1n) {
|
|
1591
|
+
return null;
|
|
1592
|
+
}
|
|
1593
|
+
const num = m.numerator;
|
|
1594
|
+
return num;
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Computes a finite summation: `sum(expr, k, a, b) = Σ_{k=a}^{b} expr`.
|
|
1598
|
+
*
|
|
1599
|
+
* - If bounds are integers and the number of terms ≤ `Settings.MAX_PRODUCT_AND_SUMMATION_ITERATION`,
|
|
1600
|
+
* evaluates by accumulating each term.
|
|
1601
|
+
* - If `lower > upper`, returns `0` (empty range).
|
|
1602
|
+
* - If `expr` does not depend on the index variable, simplifies to `expr · (b − a + 1)`.
|
|
1603
|
+
* - Otherwise returns a symbolic `sum(expr, k, a, b)` node.
|
|
1604
|
+
*
|
|
1605
|
+
* @param expr - The expression to be summed.
|
|
1606
|
+
* @param index - The index variable (must be a plain symbol).
|
|
1607
|
+
* @param lower - The lower bound (integer required for evaluation).
|
|
1608
|
+
* @param upper - The upper bound (integer required for evaluation).
|
|
1609
|
+
* @returns The summation result or a symbolic `sum` node.
|
|
1610
|
+
*
|
|
1611
|
+
* @example
|
|
1612
|
+
* ```ts
|
|
1613
|
+
* // Σ_{k=1}^{5} k = 15
|
|
1614
|
+
* sum('k', 'k', 1, 5).text() // "15"
|
|
1615
|
+
* ```
|
|
1616
|
+
*/
|
|
1617
|
+
function sum(expr, index, lower, upper) {
|
|
1618
|
+
// Validate index variable
|
|
1619
|
+
if (!index.isPlainVariable()) {
|
|
1620
|
+
return Expression_1.Expression.toFunction(constants_1.SUM_FUNCTION, [expr, index, lower, upper]);
|
|
1621
|
+
}
|
|
1622
|
+
expr = Expression_1.Expression.create(expr);
|
|
1623
|
+
index = Expression_1.Expression.create(index);
|
|
1624
|
+
lower = Expression_1.Expression.create(lower);
|
|
1625
|
+
upper = Expression_1.Expression.create(upper);
|
|
1626
|
+
const indexName = index.text();
|
|
1627
|
+
// Attempt integer bounds extraction
|
|
1628
|
+
const lo = toIntegerBigint(lower);
|
|
1629
|
+
const hi = toIntegerBigint(upper);
|
|
1630
|
+
if (lo === null || hi === null) {
|
|
1631
|
+
// Non-integer bounds → symbolic
|
|
1632
|
+
return Expression_1.Expression.toFunction(constants_1.SUM_FUNCTION, [expr, index, lower, upper]);
|
|
1633
|
+
}
|
|
1634
|
+
// Empty range → 0
|
|
1635
|
+
if (lo > hi) {
|
|
1636
|
+
return (0, shortcuts_1.zero)();
|
|
1637
|
+
}
|
|
1638
|
+
const terms = hi - lo + 1n;
|
|
1639
|
+
// Prevent runaway evaluation
|
|
1640
|
+
if (terms > Settings_1.Settings.MAX_PRODUCT_AND_SUMMATION_ITERATION) {
|
|
1641
|
+
return Expression_1.Expression.toFunction(constants_1.SUM_FUNCTION, [expr, index, lower, upper]);
|
|
1642
|
+
}
|
|
1643
|
+
// If expression does not depend on index, simplify:
|
|
1644
|
+
// sum(c, k, a, b) = c * (b - a + 1)
|
|
1645
|
+
const dependsOnIndex = expr.hasVariable(indexName);
|
|
1646
|
+
if (!dependsOnIndex) {
|
|
1647
|
+
const countExpr = Expression_1.Expression.create(terms);
|
|
1648
|
+
return expr.times(countExpr);
|
|
1649
|
+
}
|
|
1650
|
+
// Numeric accumulation
|
|
1651
|
+
let acc = (0, shortcuts_1.zero)();
|
|
1652
|
+
let i = lo;
|
|
1653
|
+
while (i <= hi) {
|
|
1654
|
+
const values = {};
|
|
1655
|
+
values[indexName] = i;
|
|
1656
|
+
const term = expr.evaluate(values);
|
|
1657
|
+
acc = acc.plus(term);
|
|
1658
|
+
i = i + 1n;
|
|
1659
|
+
}
|
|
1660
|
+
return acc;
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Computes a finite product: `product(expr, k, a, b) = Π_{k=a}^{b} expr`.
|
|
1664
|
+
*
|
|
1665
|
+
* - If bounds are integers and the number of terms ≤ `Settings.MAX_PRODUCT_AND_SUMMATION_ITERATION`,
|
|
1666
|
+
* evaluates by multiplying each term.
|
|
1667
|
+
* - If `lower > upper`, returns `1` (empty product).
|
|
1668
|
+
* - If `expr` does not depend on the index variable, simplifies to `expr^(b − a + 1)`.
|
|
1669
|
+
* - Otherwise returns a symbolic `product(expr, k, a, b)` node.
|
|
1670
|
+
*
|
|
1671
|
+
* @param expr - The expression to be multiplied.
|
|
1672
|
+
* @param index - The index variable (must be a plain symbol).
|
|
1673
|
+
* @param lower - The lower bound (integer required for evaluation).
|
|
1674
|
+
* @param upper - The upper bound (integer required for evaluation).
|
|
1675
|
+
* @returns The product result or a symbolic `product` node.
|
|
1676
|
+
*
|
|
1677
|
+
* @example
|
|
1678
|
+
* ```ts
|
|
1679
|
+
* // Π_{k=1}^{5} k = 120 (same as 5!)
|
|
1680
|
+
* product('k', 'k', 1, 5).text() // "120"
|
|
1681
|
+
* ```
|
|
1682
|
+
*/
|
|
1683
|
+
function product(expr, index, lower, upper) {
|
|
1684
|
+
if (!index.isPlainVariable()) {
|
|
1685
|
+
return Expression_1.Expression.toFunction(constants_1.PRODUCT_FUNCTION, [expr, index, lower, upper]);
|
|
1686
|
+
}
|
|
1687
|
+
expr = Expression_1.Expression.create(expr);
|
|
1688
|
+
index = Expression_1.Expression.create(index);
|
|
1689
|
+
lower = Expression_1.Expression.create(lower);
|
|
1690
|
+
upper = Expression_1.Expression.create(upper);
|
|
1691
|
+
const indexName = index.text();
|
|
1692
|
+
const lo = toIntegerBigint(lower);
|
|
1693
|
+
const hi = toIntegerBigint(upper);
|
|
1694
|
+
if (lo === null || hi === null) {
|
|
1695
|
+
return Expression_1.Expression.toFunction(constants_1.PRODUCT_FUNCTION, [expr, index, lower, upper]);
|
|
1696
|
+
}
|
|
1697
|
+
// Empty range → 1
|
|
1698
|
+
if (lo > hi) {
|
|
1699
|
+
return (0, shortcuts_1.one)();
|
|
1700
|
+
}
|
|
1701
|
+
const terms = hi - lo + 1n;
|
|
1702
|
+
if (terms > Settings_1.Settings.MAX_PRODUCT_AND_SUMMATION_ITERATION) {
|
|
1703
|
+
return Expression_1.Expression.toFunction(constants_1.PRODUCT_FUNCTION, [expr, index, lower, upper]);
|
|
1704
|
+
}
|
|
1705
|
+
// product(c, k, a, b) = c^(b-a+1)
|
|
1706
|
+
const dependsOnIndex = expr.hasVariable(indexName);
|
|
1707
|
+
if (!dependsOnIndex) {
|
|
1708
|
+
const countExpr = Expression_1.Expression.create(terms);
|
|
1709
|
+
return (0, power_1.power)(expr, countExpr);
|
|
1710
|
+
}
|
|
1711
|
+
let acc = (0, shortcuts_1.one)();
|
|
1712
|
+
let i = lo;
|
|
1713
|
+
while (i <= hi) {
|
|
1714
|
+
const values = {};
|
|
1715
|
+
values[indexName] = i;
|
|
1716
|
+
const term = expr.evaluate(values);
|
|
1717
|
+
acc = acc.times(term);
|
|
1718
|
+
i = i + 1n;
|
|
1719
|
+
}
|
|
1720
|
+
return acc;
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* Calculates the definite integral using Adaptive Simpson. Note that this function uses
|
|
1724
|
+
* native JS number due to severe computational overhead when implemented with Decimal.js.
|
|
1725
|
+
*
|
|
1726
|
+
* @param f The function being integrated
|
|
1727
|
+
* @param dx The variable of integration
|
|
1728
|
+
* @param from The lower limit of the integral
|
|
1729
|
+
* @param to The upper limit of the integral
|
|
1730
|
+
* @returns The numeric value if possible else a symbolic function
|
|
1731
|
+
*
|
|
1732
|
+
* @example
|
|
1733
|
+
* ```ts
|
|
1734
|
+
* defint('cos(x)-x^2+6', 'x', 1, 6); // -42.787553149673464
|
|
1735
|
+
* ```
|
|
1736
|
+
*/
|
|
1737
|
+
function defint(f, dx, from, to) {
|
|
1738
|
+
let retval;
|
|
1739
|
+
f = Expression_1.Expression.create(f);
|
|
1740
|
+
dx = Expression_1.Expression.create(dx);
|
|
1741
|
+
from = Expression_1.Expression.create(from);
|
|
1742
|
+
to = Expression_1.Expression.create(to);
|
|
1743
|
+
const inputVars = f.variables();
|
|
1744
|
+
// Get the variable
|
|
1745
|
+
const v = (0, utils_1.assertPlainVariableAndGetString)(dx);
|
|
1746
|
+
// Pull factors that are constant with respect to the integration variable across the bounds.
|
|
1747
|
+
if (!inputVars.includes(v)) {
|
|
1748
|
+
retval = f.times(to.minus(from));
|
|
1749
|
+
}
|
|
1750
|
+
else {
|
|
1751
|
+
let numericFrom = from;
|
|
1752
|
+
let numericTo = to;
|
|
1753
|
+
if (!numericFrom.isNUM() && numericFrom.isConstant()) {
|
|
1754
|
+
numericFrom = numericFrom.evaluate();
|
|
1755
|
+
}
|
|
1756
|
+
if (!numericTo.isNUM() && numericTo.isConstant()) {
|
|
1757
|
+
numericTo = numericTo.evaluate();
|
|
1758
|
+
}
|
|
1759
|
+
if (inputVars.length === 1 &&
|
|
1760
|
+
inputVars[0] === v &&
|
|
1761
|
+
numericFrom.isNUM() &&
|
|
1762
|
+
numericTo.isNUM()) {
|
|
1763
|
+
const a = Number(numericFrom.getMultiplier().toDecimal());
|
|
1764
|
+
const b = Number(numericTo.getMultiplier().toDecimal());
|
|
1765
|
+
retval = Expression_1.Expression.create((0, defintNative_1.definiteIntegrateNative)(f.buildFunction(), a, b));
|
|
1766
|
+
retval.precision = NATIVE_DEFINITE_INTEGRATION_PRECISION; // Mark it as limited precision
|
|
1767
|
+
}
|
|
1768
|
+
else {
|
|
1769
|
+
retval = Expression_1.Expression.toFunction(constants_1.DEFINT, [f, dx, from, to]);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
return retval;
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* Tests whether a value is present in a supported finite container.
|
|
1776
|
+
*
|
|
1777
|
+
* @remarks
|
|
1778
|
+
* `Vector` membership uses the vector's element equality, while `ValuesSet` and
|
|
1779
|
+
* `SolutionSet` delegate to their semantic set membership. `Dictionary` membership checks
|
|
1780
|
+
* keys rather than stored values. Unsupported container types remain symbolic.
|
|
1781
|
+
*
|
|
1782
|
+
* @param x - Vector, finite set, solution set, or dictionary to search.
|
|
1783
|
+
* @param value - Value to look up, or dictionary key when `x` is a Dictionary.
|
|
1784
|
+
* @returns `1` when the value is found and `0` otherwise.
|
|
1785
|
+
*
|
|
1786
|
+
* @example
|
|
1787
|
+
* ```ts
|
|
1788
|
+
* const d = Parser.parse('{x=>1, y=>a}') as Dictionary;
|
|
1789
|
+
* contains(d, 'x').text(); // 1
|
|
1790
|
+
*
|
|
1791
|
+
* const v = new Vector(['x', 1, 2]);
|
|
1792
|
+
* contains(v, 10).text(); // 0
|
|
1793
|
+
* ```
|
|
1794
|
+
*/
|
|
1795
|
+
function contains(x, value) {
|
|
1796
|
+
value = Expression_1.Expression.create(value);
|
|
1797
|
+
let retval;
|
|
1798
|
+
if (x.dataType === constants_1.VECTOR) {
|
|
1799
|
+
retval = Expression_1.Expression.create(Number(x.indexOf(value) !== -1));
|
|
1800
|
+
}
|
|
1801
|
+
else if (x.dataType === constants_1.SET || x.dataType === constants_1.SOLUTIONS_SET) {
|
|
1802
|
+
retval = Expression_1.Expression.create(Number(x.has(value)));
|
|
1803
|
+
}
|
|
1804
|
+
else if (x.dataType === constants_1.DICTIONARY) {
|
|
1805
|
+
retval = Expression_1.Expression.create(Number(x.has(value.text())));
|
|
1806
|
+
}
|
|
1807
|
+
else {
|
|
1808
|
+
retval = Expression_1.Expression.toFunction(constants_1.CONTAINS, [x, value]);
|
|
1809
|
+
}
|
|
1810
|
+
return retval;
|
|
1811
|
+
}
|