nerdamer 1.1.13 → 2.0.0-rc.2
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/BREAKING_CHANGES.md +244 -5
- package/LICENSE.md +184 -0
- package/README.md +232 -318
- 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 +2248 -0
- package/index.d.ts +10 -426
- package/output/algebra/adapters.d.ts +3 -0
- package/output/algebra/adapters.js +11 -0
- package/output/algebra/algorithms/arith.d.ts +84 -0
- package/output/algebra/algorithms/arith.js +324 -0
- package/output/algebra/algorithms/groebnerBase.d.ts +161 -0
- package/output/algebra/algorithms/groebnerBase.js +929 -0
- package/output/algebra/dispatch.d.ts +1 -0
- package/output/algebra/dispatch.js +25 -0
- package/output/algebra/factor/factor.d.ts +77 -0
- package/output/algebra/factor/factor.js +245 -0
- package/output/algebra/gcd/gcd.d.ts +30 -0
- package/output/algebra/gcd/gcd.js +95 -0
- package/output/algebra/groebner.d.ts +21 -0
- package/output/algebra/groebner.js +36 -0
- package/output/algebra/partfrac.d.ts +19 -0
- package/output/algebra/partfrac.js +365 -0
- package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
- package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
- package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
- package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
- package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
- package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
- package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
- package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
- package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
- package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
- package/output/algebra/polynomial/modularGcd.d.ts +40 -0
- package/output/algebra/polynomial/modularGcd.js +365 -0
- package/output/algebra/polynomialize.d.ts +20 -0
- package/output/algebra/polynomialize.js +26 -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 +237 -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 +8 -0
- package/output/api/advanced.js +18 -0
- package/output/api/algebra.d.ts +17 -0
- package/output/api/algebra.js +35 -0
- package/output/api/assumptions.d.ts +4 -0
- package/output/api/assumptions.js +11 -0
- package/output/api/calculus.d.ts +10 -0
- package/output/api/calculus.js +22 -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/languages/deu.d.ts +3 -0
- package/output/api/languages/deu.js +266 -0
- package/output/api/languages/fra.d.ts +3 -0
- package/output/api/languages/fra.js +266 -0
- package/output/api/languages/ita.d.ts +3 -0
- package/output/api/languages/ita.js +266 -0
- package/output/api/languages/nld.d.ts +3 -0
- package/output/api/languages/nld.js +266 -0
- package/output/api/languages/por.d.ts +3 -0
- package/output/api/languages/por.js +266 -0
- package/output/api/languages/spa.d.ts +3 -0
- package/output/api/languages/spa.js +266 -0
- package/output/api/parser.d.ts +93 -0
- package/output/api/parser.js +18 -0
- package/output/api/solve.d.ts +10 -0
- package/output/api/solve.js +17 -0
- package/output/api/structures.d.ts +10 -0
- package/output/api/structures.js +23 -0
- package/output/calculus/adapters.d.ts +8 -0
- package/output/calculus/adapters.js +41 -0
- package/output/calculus/derivative/diff.d.ts +30 -0
- package/output/calculus/derivative/diff.js +241 -0
- package/output/calculus/dispatch.d.ts +1 -0
- package/output/calculus/dispatch.js +25 -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/classes/assumption/Assumption.d.ts +218 -0
- package/output/core/classes/assumption/Assumption.js +609 -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/assumption/dispatch.d.ts +1 -0
- package/output/core/classes/assumption/dispatch.js +11 -0
- package/output/core/classes/collection/Collection.d.ts +107 -0
- package/output/core/classes/collection/Collection.js +240 -0
- package/output/core/classes/complex/Complex.d.ts +109 -0
- package/output/core/classes/complex/Complex.js +153 -0
- package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
- package/output/core/classes/decimalSet/DecimalSet.js +454 -0
- package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
- package/output/core/classes/dictionary/Dictionary.js +216 -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 +197 -0
- package/output/core/classes/expression/Expression.d.ts +1691 -0
- package/output/core/classes/expression/Expression.js +2381 -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 +54 -0
- package/output/core/classes/expression/format.js +340 -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 +61 -0
- package/output/core/classes/expression/utils.js +235 -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 +901 -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/dispatch.d.ts +1 -0
- package/output/core/classes/matrix/dispatch.js +19 -0
- package/output/core/classes/matrix/functions.d.ts +28 -0
- package/output/core/classes/matrix/functions.js +57 -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 +493 -0
- package/output/core/classes/parser/Parser.js +1863 -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 +162 -0
- package/output/core/classes/parser/constants.js +229 -0
- package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
- package/output/core/classes/parser/controlFlowSignals.js +60 -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 +236 -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 +474 -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 +438 -0
- package/output/core/classes/parser/operations/multiply.d.ts +11 -0
- package/output/core/classes/parser/operations/multiply.js +328 -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 +36 -0
- package/output/core/classes/parser/preprocess.d.ts +7 -0
- package/output/core/classes/parser/preprocess.js +246 -0
- package/output/core/classes/parser/scripting/controlFlow.d.ts +23 -0
- package/output/core/classes/parser/scripting/controlFlow.js +279 -0
- package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
- package/output/core/classes/parser/scripting/deferred.js +65 -0
- package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
- package/output/core/classes/parser/scripting/dispatch.js +62 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +23 -0
- package/output/core/classes/parser/scripting/evaluate.js +128 -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 +8 -0
- package/output/core/classes/parser/scripting/scope.js +132 -0
- package/output/core/classes/parser/types.d.ts +130 -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 +504 -0
- package/output/core/classes/polynomial/Polynomial.js +1195 -0
- package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
- package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
- package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
- package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -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/adapters.d.ts +18 -0
- package/output/core/classes/polynomial/adapters.js +33 -0
- package/output/core/classes/polynomial/dispatch.d.ts +1 -0
- package/output/core/classes/polynomial/dispatch.js +14 -0
- package/output/core/classes/polynomial/functions.d.ts +77 -0
- package/output/core/classes/polynomial/functions.js +189 -0
- package/output/core/classes/polynomial/utils.d.ts +62 -0
- package/output/core/classes/polynomial/utils.js +207 -0
- package/output/core/classes/rational/Rational.d.ts +501 -0
- package/output/core/classes/rational/Rational.js +829 -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 +187 -0
- package/output/core/classes/valuesSet/ValuesSet.js +399 -0
- package/output/core/classes/vector/Vector.d.ts +222 -0
- package/output/core/classes/vector/Vector.js +501 -0
- package/output/core/classes/vector/dispatch.d.ts +1 -0
- package/output/core/classes/vector/dispatch.js +11 -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 +149 -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 +62 -0
- package/output/core/common/common.js +74 -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 +806 -0
- package/output/core/converters/Pattern.d.ts +71 -0
- package/output/core/converters/Pattern.js +302 -0
- package/output/core/dispatch.d.ts +52 -0
- package/output/core/dispatch.js +26 -0
- package/output/core/errors.d.ts +316 -0
- package/output/core/errors.js +349 -0
- package/output/core/fullFunctions.d.ts +7 -0
- package/output/core/fullFunctions.js +31 -0
- package/output/core/functions/bigint/bigint.d.ts +133 -0
- package/output/core/functions/bigint/bigint.js +444 -0
- package/output/core/functions/bigint/primeFactor.d.ts +51 -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 +139 -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.dispatch.d.ts +1 -0
- package/output/core/functions/complex.dispatch.js +16 -0
- package/output/core/functions/complex.js +482 -0
- package/output/core/functions/decimal.d.ts +24 -0
- package/output/core/functions/decimal.js +665 -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 +102 -0
- package/output/core/functions/subst.d.ts +90 -0
- package/output/core/functions/subst.js +506 -0
- package/output/core/functions/utils.d.ts +24 -0
- package/output/core/functions/utils.js +51 -0
- package/output/core/parserFunctions.d.ts +7 -0
- package/output/core/parserFunctions.js +25 -0
- package/output/core/types.d.ts +48 -0
- package/output/core/types.js +2 -0
- package/output/index.d.ts +359 -0
- package/output/index.js +739 -0
- package/output/math/defint/defint.d.ts +18 -0
- package/output/math/defint/defint.js +60 -0
- package/output/math/defint/defintDecimal.d.ts +37 -0
- package/output/math/defint/defintDecimal.js +321 -0
- package/output/math/defint/defintNative.d.ts +57 -0
- package/output/math/defint/defintNative.js +281 -0
- package/output/math/dispatch.d.ts +1 -0
- package/output/math/dispatch.js +101 -0
- package/output/math/geometry.d.ts +12 -0
- package/output/math/geometry.js +55 -0
- package/output/math/math.d.ts +695 -0
- package/output/math/math.js +1955 -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 +66 -0
- package/output/math/utils.js +219 -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 +104 -0
- package/output/solve/classes/PolynomialSolver.js +492 -0
- package/output/solve/classes/SolutionSet.d.ts +172 -0
- package/output/solve/classes/SolutionSet.js +434 -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/dispatch.d.ts +1 -0
- package/output/solve/dispatch.js +13 -0
- package/output/solve/linsolve.d.ts +53 -0
- package/output/solve/linsolve.js +233 -0
- package/output/solve/solve.d.ts +44 -0
- package/output/solve/solve.js +368 -0
- package/output/solve/solveSystem.d.ts +31 -0
- package/output/solve/solveSystem.js +266 -0
- package/output/solve/utils.d.ts +10 -0
- package/output/solve/utils.js +58 -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 +296 -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 +178 -57
- package/.travis.yml +0 -3
- package/Algebra.js +0 -4568
- 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,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.diff = diff;
|
|
4
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
5
|
+
const shortcuts_1 = require("../../core/classes/expression/shortcuts");
|
|
6
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
7
|
+
const helpers_1 = require("../../core/classes/parser/helpers");
|
|
8
|
+
const errors_1 = require("../../core/errors");
|
|
9
|
+
const math_1 = require("../../math/math");
|
|
10
|
+
/**
|
|
11
|
+
* Applies the product rule to an expression
|
|
12
|
+
*
|
|
13
|
+
* @param expression
|
|
14
|
+
* @param variable
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
function productRule(expression, variable) {
|
|
18
|
+
//grab all the symbols within the CB symbol
|
|
19
|
+
const elements = expression.elementsArray();
|
|
20
|
+
let result = (0, shortcuts_1.zero)();
|
|
21
|
+
//loop over all the symbols
|
|
22
|
+
for (let i = 0; i < elements.length; i++) {
|
|
23
|
+
let df = diff(elements[i], variable);
|
|
24
|
+
for (let j = 0; j < elements.length; j++) {
|
|
25
|
+
//skip the symbol of which we just pulled the derivative
|
|
26
|
+
if (i !== j) {
|
|
27
|
+
//multiply out the remaining symbols
|
|
28
|
+
df = df.times(elements[j]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//add the derivative to the result
|
|
32
|
+
result = result.plus(df);
|
|
33
|
+
}
|
|
34
|
+
return result; //done
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Differentiates an expression symbolically.
|
|
38
|
+
*
|
|
39
|
+
* The chain, product, sum, and power rules are applied recursively, together
|
|
40
|
+
* with the built-in derivative table for recognized functions. An omitted
|
|
41
|
+
* variable is inferred as the first variable in the expression. Existing
|
|
42
|
+
* Expression input is reused during normalization.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* `n` requests a repeated derivative. A non-integer order, a non-variable
|
|
46
|
+
* differentiation target, or an unsupported derivative is preserved as an
|
|
47
|
+
* unevaluated `diff(...)` expression. Constants and expressions independent of
|
|
48
|
+
* the selected variable differentiate to zero.
|
|
49
|
+
*
|
|
50
|
+
* @param x - Expression to differentiate.
|
|
51
|
+
* @param variable - Variable with respect to which the derivative is taken.
|
|
52
|
+
* @param n - Positive integer derivative order. Defaults to the first derivative.
|
|
53
|
+
* @returns The symbolic derivative, or an unevaluated `diff(...)` call when the
|
|
54
|
+
* requested operation cannot be resolved.
|
|
55
|
+
* @throws {@link core!UnsupportedOperationError} If `variable` is numeric.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* diff('sin(x^2)', 'x').text();
|
|
60
|
+
* diff('x^4', 'x', 2).text();
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
function diff(x, variable, n) {
|
|
64
|
+
x = Expression_1.Expression.create(x);
|
|
65
|
+
const variables = x.variables();
|
|
66
|
+
// Set the variable if none was provided
|
|
67
|
+
variable ??= Expression_1.Expression.Variable(variables[0]);
|
|
68
|
+
variable = Expression_1.Expression.create(variable);
|
|
69
|
+
const nth = typeof n === 'number' ? Expression_1.Expression.create(n) : n;
|
|
70
|
+
// If the variable is a number then complain
|
|
71
|
+
if (variable?.isNUM()) {
|
|
72
|
+
throw new errors_1.UnsupportedOperationError((0, errors_1.message)('unsupportedOperation'));
|
|
73
|
+
}
|
|
74
|
+
let retval;
|
|
75
|
+
if (x.hasFunction(constants_1.SYMBOLIC_ACCESSOR, true)) {
|
|
76
|
+
retval = Expression_1.Expression.toFunction(constants_1.DIFF, [x, variable, nth]);
|
|
77
|
+
}
|
|
78
|
+
else if (variables.length === 0 || !x.hasVariable(variable.value) || x.isConstant()) {
|
|
79
|
+
retval = (0, shortcuts_1.zero)();
|
|
80
|
+
}
|
|
81
|
+
// If the variable is not of type VAR or nth is not an integer then return it untouched until either or both are resolved
|
|
82
|
+
else if ((variable && !variable.isVAR()) || (nth && !nth.isInteger())) {
|
|
83
|
+
retval = Expression_1.Expression.toFunction(constants_1.DIFF, [x, variable, nth]);
|
|
84
|
+
}
|
|
85
|
+
else if (x.isEXP()) {
|
|
86
|
+
// Apply rule a^x*(d/dx x*log(a))
|
|
87
|
+
const a = (0, math_1.log)(x.getBase());
|
|
88
|
+
const p = x.getPower();
|
|
89
|
+
const dx = diff(a.times(p), variable);
|
|
90
|
+
retval = x.times(dx);
|
|
91
|
+
}
|
|
92
|
+
// If the expression doesn't have a variable or if it's a constant then we're done
|
|
93
|
+
else {
|
|
94
|
+
// Reduce the nth call of the derivative
|
|
95
|
+
const n = nth ? Number(nth) - 1 : 0;
|
|
96
|
+
// Pull the derivate of the outside. At this point we've already performed all the required checks.
|
|
97
|
+
const m = x.getMultiplier().times(x.getPower());
|
|
98
|
+
const p = x.getPower().minus('1');
|
|
99
|
+
const f = Expression_1.Expression.create(x.value);
|
|
100
|
+
const fp = p.isZero() ? m : f.pow(p).times(m);
|
|
101
|
+
// Pull the derivative of the inside
|
|
102
|
+
if (f.isVAR()) {
|
|
103
|
+
retval = (0, shortcuts_1.one)();
|
|
104
|
+
}
|
|
105
|
+
else if (f.isSum()) {
|
|
106
|
+
let sum = (0, shortcuts_1.zero)();
|
|
107
|
+
f.elementsArray().forEach(e => {
|
|
108
|
+
sum = sum.plus(diff(e, variable));
|
|
109
|
+
});
|
|
110
|
+
retval = sum;
|
|
111
|
+
}
|
|
112
|
+
else if (f.isProduct()) {
|
|
113
|
+
retval = productRule(f, variable);
|
|
114
|
+
}
|
|
115
|
+
else if (f.isFunction()) {
|
|
116
|
+
const x = f.getArguments()[0];
|
|
117
|
+
const m = f.getMultiplier();
|
|
118
|
+
switch (f.name) {
|
|
119
|
+
case constants_1.LOG:
|
|
120
|
+
retval = (0, helpers_1._)(`(${m})/(${x})`);
|
|
121
|
+
break;
|
|
122
|
+
case constants_1.COS:
|
|
123
|
+
retval = (0, helpers_1._)(`-sin(${x})`);
|
|
124
|
+
break;
|
|
125
|
+
case constants_1.SIN:
|
|
126
|
+
retval = (0, helpers_1._)(`cos(${x})`);
|
|
127
|
+
break;
|
|
128
|
+
case constants_1.TAN:
|
|
129
|
+
retval = (0, helpers_1._)(`sec(${x})^2`);
|
|
130
|
+
break;
|
|
131
|
+
case constants_1.SEC:
|
|
132
|
+
retval = (0, helpers_1._)(`tan(${x})*sec(${x})`);
|
|
133
|
+
break;
|
|
134
|
+
case constants_1.CSC:
|
|
135
|
+
retval = (0, helpers_1._)(`-cot(${x})*csc(${x})`);
|
|
136
|
+
break;
|
|
137
|
+
case constants_1.COT:
|
|
138
|
+
retval = (0, helpers_1._)(`-csc(${x})^2`);
|
|
139
|
+
break;
|
|
140
|
+
case constants_1.ACOS:
|
|
141
|
+
retval = (0, helpers_1._)(`-1/sqrt(1-(${x})^2)`);
|
|
142
|
+
break;
|
|
143
|
+
case constants_1.ASIN:
|
|
144
|
+
retval = (0, helpers_1._)(`1/sqrt(1-(${x})^2)`);
|
|
145
|
+
break;
|
|
146
|
+
case constants_1.ATAN:
|
|
147
|
+
retval = (0, helpers_1._)(`1/(1+(${x})^2)`);
|
|
148
|
+
break;
|
|
149
|
+
case constants_1.ASEC:
|
|
150
|
+
retval = (0, helpers_1._)(`1/(sqrt(1-1/(${x})^2)*(${x})^2)`);
|
|
151
|
+
break;
|
|
152
|
+
case constants_1.ACSC:
|
|
153
|
+
retval = (0, helpers_1._)(`-1/(sqrt(1-1/(${x})^2)*(${x})^2)`);
|
|
154
|
+
break;
|
|
155
|
+
case constants_1.ACOT:
|
|
156
|
+
retval = (0, helpers_1._)(`-1/(1+(${x})^2)`);
|
|
157
|
+
break;
|
|
158
|
+
case constants_1.COSH:
|
|
159
|
+
retval = (0, helpers_1._)(`sinh(${x})`);
|
|
160
|
+
break;
|
|
161
|
+
case constants_1.SINH:
|
|
162
|
+
retval = (0, helpers_1._)(`cosh(${x})`);
|
|
163
|
+
break;
|
|
164
|
+
case constants_1.TANH:
|
|
165
|
+
retval = (0, helpers_1._)(`sech(${x})^2`);
|
|
166
|
+
break;
|
|
167
|
+
case constants_1.SECH:
|
|
168
|
+
retval = (0, helpers_1._)(`-sech(${x})*tanh(${x})`);
|
|
169
|
+
break;
|
|
170
|
+
case constants_1.CSCH:
|
|
171
|
+
retval = (0, helpers_1._)(`-coth(${x})*csch(${x})`);
|
|
172
|
+
break;
|
|
173
|
+
case constants_1.COTH:
|
|
174
|
+
retval = (0, helpers_1._)(`-csch(${x})^2`);
|
|
175
|
+
break;
|
|
176
|
+
case constants_1.ASINH:
|
|
177
|
+
retval = (0, helpers_1._)(`1/sqrt(1+(${x})^2)`);
|
|
178
|
+
break;
|
|
179
|
+
case constants_1.ACOSH:
|
|
180
|
+
retval = (0, helpers_1._)(`1/(sqrt(-1+(${x}))*sqrt(1+(${x})))`);
|
|
181
|
+
break;
|
|
182
|
+
case constants_1.ATANH:
|
|
183
|
+
retval = (0, helpers_1._)(`1/(1-(${x})^2)`);
|
|
184
|
+
break;
|
|
185
|
+
case constants_1.ASECH:
|
|
186
|
+
retval = (0, helpers_1._)(`-1/(sqrt(-1+1/(${x}))*sqrt(1+1/(${x}))*(${x})^2)`);
|
|
187
|
+
break;
|
|
188
|
+
case constants_1.ACSCH:
|
|
189
|
+
retval = (0, helpers_1._)(`-1/(sqrt(1+1/(${x})^2)*(${x})^2)`);
|
|
190
|
+
break;
|
|
191
|
+
case constants_1.ACOTH:
|
|
192
|
+
retval = (0, helpers_1._)(`1/(1-(${x})^2)`);
|
|
193
|
+
break;
|
|
194
|
+
case constants_1.ABS:
|
|
195
|
+
// d/dx abs(u) = sign(u) * u'
|
|
196
|
+
retval = (0, helpers_1._)(`sign(${x})`);
|
|
197
|
+
break;
|
|
198
|
+
case constants_1.CI:
|
|
199
|
+
retval = (0, helpers_1._)(`cos(${x})/${x}`);
|
|
200
|
+
break;
|
|
201
|
+
case constants_1.CHI:
|
|
202
|
+
retval = (0, helpers_1._)(`cosh(${x})/${x}`);
|
|
203
|
+
break;
|
|
204
|
+
case constants_1.SI:
|
|
205
|
+
retval = (0, helpers_1._)(`sin(${x})/${x}`);
|
|
206
|
+
break;
|
|
207
|
+
case constants_1.SHI:
|
|
208
|
+
retval = (0, helpers_1._)(`sinh(${x})/${x}`);
|
|
209
|
+
break;
|
|
210
|
+
case constants_1.EI:
|
|
211
|
+
retval = (0, helpers_1._)(`e^(${x})/${x}`);
|
|
212
|
+
break;
|
|
213
|
+
case constants_1.LI:
|
|
214
|
+
retval = (0, helpers_1._)(`1/${constants_1.LOG}(${x})`);
|
|
215
|
+
break;
|
|
216
|
+
case constants_1.ERF:
|
|
217
|
+
retval = (0, helpers_1._)(`(2*e^(-(${x})^2))/sqrt(pi)`);
|
|
218
|
+
break;
|
|
219
|
+
case constants_1.SGN:
|
|
220
|
+
retval = (0, shortcuts_1.zero)();
|
|
221
|
+
break;
|
|
222
|
+
// Missing: S, Si, Shi, Ci, Chi, Ei, Li, erf, atan2, sinc, heaviside
|
|
223
|
+
// case '':
|
|
224
|
+
// retval = _(``);
|
|
225
|
+
// break;
|
|
226
|
+
}
|
|
227
|
+
// Multiply times the derivative of the inside
|
|
228
|
+
if (retval) {
|
|
229
|
+
retval = retval.times(diff(x, variable));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (retval) {
|
|
233
|
+
retval = retval.times(fp);
|
|
234
|
+
}
|
|
235
|
+
// Pull the nth -1 derivative if that was requested
|
|
236
|
+
if (n > 0 && retval) {
|
|
237
|
+
retval = diff(retval, variable, Expression_1.Expression.Number(n));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return retval || Expression_1.Expression.toFunction(constants_1.DIFF, [x, variable, nth]);
|
|
241
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loadCalculusFunctions(): void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadCalculusFunctions = loadCalculusFunctions;
|
|
4
|
+
const dispatch_1 = require("../core/dispatch");
|
|
5
|
+
const math_1 = require("../math/math");
|
|
6
|
+
const defint_1 = require("../math/defint/defint");
|
|
7
|
+
const adapters_1 = require("./adapters");
|
|
8
|
+
const fresnel_1 = require("./fresnel");
|
|
9
|
+
const ilaplace_1 = require("./laplace/ilaplace");
|
|
10
|
+
const laplace_1 = require("./laplace/laplace");
|
|
11
|
+
const constants_1 = require("../core/classes/parser/constants");
|
|
12
|
+
function loadCalculusFunctions() {
|
|
13
|
+
Object.assign(dispatch_1.mathFunctionRegistry, {
|
|
14
|
+
diff: (0, dispatch_1.systemFunction)({ fn: adapters_1.differentiate, minArgs: 1, maxArgs: 3, equationArgs: [0], distElWise: true }),
|
|
15
|
+
integrate: (0, dispatch_1.systemFunction)({ fn: adapters_1.integrateEquation, minArgs: 1, maxArgs: 2, equationArgs: [0], distElWise: true }),
|
|
16
|
+
limit: (0, dispatch_1.systemFunction)({ fn: adapters_1.directionalLimit, minArgs: 3, maxArgs: 4, distElWise: true }),
|
|
17
|
+
laplace: (0, dispatch_1.systemFunction)({ fn: laplace_1.laplace, minArgs: 3, maxArgs: 3, distElWise: true }),
|
|
18
|
+
ilaplace: (0, dispatch_1.systemFunction)({ fn: ilaplace_1.ilaplace, minArgs: 3, maxArgs: 3, distElWise: true }),
|
|
19
|
+
sum: (0, dispatch_1.systemFunction)({ fn: math_1.sum, minArgs: 4, maxArgs: 4, distElWise: true }),
|
|
20
|
+
product: (0, dispatch_1.systemFunction)({ fn: math_1.product, minArgs: 4, maxArgs: 4, distElWise: true }),
|
|
21
|
+
defint: (0, dispatch_1.systemFunction)({ fn: defint_1.defint, minArgs: 4, maxArgs: 4, distElWise: true }),
|
|
22
|
+
[constants_1.FRESNEL_S]: (0, dispatch_1.systemFunction)({ fn: fresnel_1.S, minArgs: 1, maxArgs: 1, distElWise: true }),
|
|
23
|
+
[constants_1.FRESNEL_C]: (0, dispatch_1.systemFunction)({ fn: fresnel_1.C, minArgs: 1, maxArgs: 1, distElWise: true }),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Expression } from '../core/classes/expression/Expression';
|
|
2
|
+
import type { ExpressionInput } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Computes the normalized Fresnel sine integral
|
|
5
|
+
* `S(x) = integral(sin(pi*t^2/2), t, 0, x)`.
|
|
6
|
+
*
|
|
7
|
+
* Numeric real arguments are evaluated numerically. Symbolic arguments remain as `S(x)`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function S(x: ExpressionInput): Expression;
|
|
10
|
+
/**
|
|
11
|
+
* Computes the normalized Fresnel cosine integral
|
|
12
|
+
* `C(x) = integral(cos(pi*t^2/2), t, 0, x)`.
|
|
13
|
+
*
|
|
14
|
+
* Numeric real arguments are evaluated numerically. Symbolic arguments remain as `C(x)`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function C(x: ExpressionInput): Expression;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S = S;
|
|
4
|
+
exports.C = C;
|
|
5
|
+
const Expression_1 = require("../core/classes/expression/Expression");
|
|
6
|
+
const constants_1 = require("../core/classes/parser/constants");
|
|
7
|
+
const fresnelNumeric_1 = require("../core/functions/fresnelNumeric");
|
|
8
|
+
/** Evaluates a Fresnel integral numerically when the argument can be resolved to a real number. */
|
|
9
|
+
function fresnel(x, name) {
|
|
10
|
+
const argument = Expression_1.Expression.create(x);
|
|
11
|
+
const evaluated = argument.isNUM() ? argument : argument.evaluate();
|
|
12
|
+
let retval;
|
|
13
|
+
if (evaluated.isNUM()) {
|
|
14
|
+
const value = Number(evaluated.getMultiplier().toDecimal());
|
|
15
|
+
retval = Expression_1.Expression.create(name === constants_1.FRESNEL_S ? (0, fresnelNumeric_1.fresnelS)(value) : (0, fresnelNumeric_1.fresnelC)(value));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
retval = Expression_1.Expression.toFunction(name, [argument]);
|
|
19
|
+
}
|
|
20
|
+
return retval;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Computes the normalized Fresnel sine integral
|
|
24
|
+
* `S(x) = integral(sin(pi*t^2/2), t, 0, x)`.
|
|
25
|
+
*
|
|
26
|
+
* Numeric real arguments are evaluated numerically. Symbolic arguments remain as `S(x)`.
|
|
27
|
+
*/
|
|
28
|
+
function S(x) {
|
|
29
|
+
return fresnel(x, constants_1.FRESNEL_S);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Computes the normalized Fresnel cosine integral
|
|
33
|
+
* `C(x) = integral(cos(pi*t^2/2), t, 0, x)`.
|
|
34
|
+
*
|
|
35
|
+
* Numeric real arguments are evaluated numerically. Symbolic arguments remain as `C(x)`.
|
|
36
|
+
*/
|
|
37
|
+
function C(x) {
|
|
38
|
+
return fresnel(x, constants_1.FRESNEL_C);
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
import type { ExpressionInput } from '../../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Attempts integration by parts for a product with two variable-dependent factors.
|
|
5
|
+
*
|
|
6
|
+
* LIATE priority selects `u`; independent multipliers are preserved separately.
|
|
7
|
+
* Category-specific progress checks and a dedicated recursion bound reject
|
|
8
|
+
* cyclic or increasingly complex decompositions.
|
|
9
|
+
*
|
|
10
|
+
* @param x - Product integrand.
|
|
11
|
+
* @param v - Integration variable.
|
|
12
|
+
* @param integrate - Recursive integration strategy supplied by the caller.
|
|
13
|
+
* @param depth - Current outer integration depth.
|
|
14
|
+
* @param ibpDepth - Current integration-by-parts depth.
|
|
15
|
+
* @returns An antiderivative when the transformation makes progress, otherwise
|
|
16
|
+
* `undefined` so another strategy can run.
|
|
17
|
+
*/
|
|
18
|
+
export declare function tryIntegrationByParts(x: Expression, v: string, integrate: (f: ExpressionInput, dx: ExpressionInput, depth: number) => Expression, depth?: number, ibpDepth?: number): Expression | undefined;
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tryIntegrationByParts = tryIntegrationByParts;
|
|
4
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
5
|
+
const shortcuts_1 = require("../../core/classes/expression/shortcuts");
|
|
6
|
+
const trig_1 = require("../../core/classes/expression/trig");
|
|
7
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
8
|
+
const math_1 = require("../../math/math");
|
|
9
|
+
const diff_1 = require("../derivative/diff");
|
|
10
|
+
/**
|
|
11
|
+
* LIATE priority constants.
|
|
12
|
+
* Higher number = should be chosen as u.
|
|
13
|
+
*/
|
|
14
|
+
const LIATE = {
|
|
15
|
+
EXP: 0,
|
|
16
|
+
TRIG: 1,
|
|
17
|
+
ALGEBRAIC: 2,
|
|
18
|
+
INVERSE_TRIG: 3,
|
|
19
|
+
LOG: 4,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Maximum number of recursive IBP applications within a single
|
|
23
|
+
* integration attempt. This is independent of integrate's own
|
|
24
|
+
* MAX_DEPTH and exists to prevent runaway recursion from
|
|
25
|
+
* pathological integrands like e^x·tan(x).
|
|
26
|
+
*/
|
|
27
|
+
const MAX_IBP_DEPTH = 4;
|
|
28
|
+
/**
|
|
29
|
+
* Extracts the maximum power of the integration variable in an expression.
|
|
30
|
+
* For a product like x^3·sin(x), returns 3. For a sum produced by
|
|
31
|
+
* linearity (e.g. 2·x·sin(x) + ...), returns the maximum across terms.
|
|
32
|
+
* Returns 0 if the variable does not appear algebraically (e.g. pure sin(x)).
|
|
33
|
+
*/
|
|
34
|
+
function maxAlgebraicDegree(expr, v) {
|
|
35
|
+
let retval = undefined;
|
|
36
|
+
if (expr.isVAR() && expr.hasVariable(v)) {
|
|
37
|
+
// x^n — getPower() returns the exponent
|
|
38
|
+
retval = expr.getPower();
|
|
39
|
+
}
|
|
40
|
+
else if (expr.isProduct()) {
|
|
41
|
+
let maxDeg = (0, shortcuts_1.zero)();
|
|
42
|
+
for (const factor of expr.elementsArray()) {
|
|
43
|
+
if (factor.isVAR() && factor.hasVariable(v)) {
|
|
44
|
+
const p = factor.getPower();
|
|
45
|
+
maxDeg = (0, math_1.max)(maxDeg, p);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
retval = maxDeg;
|
|
49
|
+
}
|
|
50
|
+
else if (expr.isSum()) {
|
|
51
|
+
let maxDeg = (0, shortcuts_1.zero)();
|
|
52
|
+
expr.each((term) => {
|
|
53
|
+
maxDeg = (0, math_1.max)(maxDeg, maxAlgebraicDegree(term, v));
|
|
54
|
+
});
|
|
55
|
+
retval = maxDeg;
|
|
56
|
+
}
|
|
57
|
+
return retval ?? (0, shortcuts_1.zero)();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Counts the number of function applications (sin, cos, log, etc.)
|
|
61
|
+
* in an expression. Used as a structural complexity measure for
|
|
62
|
+
* non-algebraic IBP progress checking.
|
|
63
|
+
*/
|
|
64
|
+
function functionCount(expr) {
|
|
65
|
+
let count = 0;
|
|
66
|
+
if (expr.isFunction()) {
|
|
67
|
+
count = 1;
|
|
68
|
+
}
|
|
69
|
+
if (expr.isProduct() || expr.isSum()) {
|
|
70
|
+
expr.each((child) => {
|
|
71
|
+
count += functionCount(child);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return count;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Determines whether IBP has made progress by producing a simpler
|
|
78
|
+
* remainder integrand. The definition of "progress" depends on the
|
|
79
|
+
* LIATE category of u:
|
|
80
|
+
*
|
|
81
|
+
* - ALGEBRAIC u (polynomial × trig/exp): progress means the polynomial
|
|
82
|
+
* degree in the integration variable strictly decreased. This is the
|
|
83
|
+
* fundamental guarantee of IBP for x^n·f(x) — each round reduces
|
|
84
|
+
* the degree by 1, terminating after n rounds.
|
|
85
|
+
*
|
|
86
|
+
* - LOG or INVERSE_TRIG u: one round of IBP eliminates the
|
|
87
|
+
* transcendental factor, replacing it with an algebraic derivative.
|
|
88
|
+
* Progress means the new integrand has fewer function nodes than
|
|
89
|
+
* the original.
|
|
90
|
+
*
|
|
91
|
+
* - Anything else: fallback to a structural comparison — the new
|
|
92
|
+
* integrand must have strictly fewer function nodes.
|
|
93
|
+
*
|
|
94
|
+
* Returns true if the new integrand represents progress.
|
|
95
|
+
*/
|
|
96
|
+
function isProgress(original, newIntegrand, uCategory, v) {
|
|
97
|
+
if (uCategory === LIATE.ALGEBRAIC) {
|
|
98
|
+
// Polynomial degree must strictly decrease
|
|
99
|
+
const oldDeg = maxAlgebraicDegree(original, v);
|
|
100
|
+
const newDeg = maxAlgebraicDegree(newIntegrand, v);
|
|
101
|
+
return newDeg < oldDeg;
|
|
102
|
+
}
|
|
103
|
+
if (uCategory === LIATE.LOG || uCategory === LIATE.INVERSE_TRIG) {
|
|
104
|
+
// Function count must decrease (log/invtrig disappears after differentiation)
|
|
105
|
+
return functionCount(newIntegrand) < functionCount(original);
|
|
106
|
+
}
|
|
107
|
+
// Fallback: structural complexity must decrease
|
|
108
|
+
return functionCount(newIntegrand) < functionCount(original);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Classifies an expression by LIATE category.
|
|
112
|
+
* Returns -1 if unclassifiable.
|
|
113
|
+
*/
|
|
114
|
+
function liatePriority(expr) {
|
|
115
|
+
// Algebraic: x^n (variable with a power)
|
|
116
|
+
if (expr.isVAR()) {
|
|
117
|
+
return LIATE.ALGEBRAIC;
|
|
118
|
+
}
|
|
119
|
+
// Exponential: e^(ax) or a^(bx)
|
|
120
|
+
if (expr.isEXP()) {
|
|
121
|
+
return LIATE.EXP;
|
|
122
|
+
}
|
|
123
|
+
if (expr.isFunction()) {
|
|
124
|
+
const name = expr.name;
|
|
125
|
+
// Logarithmic
|
|
126
|
+
if (name === constants_1.LOG || name === constants_1.LN) {
|
|
127
|
+
return LIATE.LOG;
|
|
128
|
+
}
|
|
129
|
+
// Inverse trig
|
|
130
|
+
if ((0, trig_1.isInverseTrig)(expr)) {
|
|
131
|
+
return LIATE.INVERSE_TRIG;
|
|
132
|
+
}
|
|
133
|
+
// Trigonometric
|
|
134
|
+
if ((0, trig_1.isTrig)(expr)) {
|
|
135
|
+
return LIATE.TRIG;
|
|
136
|
+
}
|
|
137
|
+
// Hyperbolic (treat like trig for LIATE purposes)
|
|
138
|
+
if ((0, trig_1.isHyperbolicTrig)(expr)) {
|
|
139
|
+
return LIATE.TRIG;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return -1;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Detects whether a pair of LIATE categories is known to produce
|
|
146
|
+
* non-terminating IBP recursion. This goes beyond the simple
|
|
147
|
+
* same-category check to catch cross-category pathological pairs.
|
|
148
|
+
*
|
|
149
|
+
* Known problematic pairs:
|
|
150
|
+
* - TRIG + TRIG: e.g. sin(x)·cos(x) — cyclic
|
|
151
|
+
* - EXP + EXP: e.g. e^x·2^x — cyclic
|
|
152
|
+
* - EXP + TRIG with non-integrable trig: e.g. e^x·tan(x) —
|
|
153
|
+
* produces increasingly complex trig powers
|
|
154
|
+
*
|
|
155
|
+
* LOG + EXP (e.g. e^x·log(x)) and LOG + TRIG (e.g. sin(x)·log(x))
|
|
156
|
+
* are NOT blocked here. After one IBP round, the remainder is of the
|
|
157
|
+
* form f(x)/x which maps to special functions (Ei, Si, Ci) via the
|
|
158
|
+
* integration table. The isProgress guard prevents spiraling if the
|
|
159
|
+
* table entry is missing.
|
|
160
|
+
*
|
|
161
|
+
* The EXP+TRIG pair is only problematic when the trig function
|
|
162
|
+
* is not one whose integral stays in the same family (sin/cos).
|
|
163
|
+
* e^x·sin(x) and e^x·cos(x) are handled by the table, so they
|
|
164
|
+
* never reach IBP. But e^x·tan(x), e^x·sec(x), etc. spiral.
|
|
165
|
+
*/
|
|
166
|
+
function isCyclicPair(p0, p1, u, dv) {
|
|
167
|
+
// Same category: trig+trig or exp+exp
|
|
168
|
+
if (p0 === p1 && (p0 === LIATE.TRIG || p0 === LIATE.EXP)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
// EXP + TRIG where the trig function is not sin/cos
|
|
172
|
+
// (sin/cos pairs are handled by the integration table and never reach here,
|
|
173
|
+
// but tan, sec, csc, cot produce ever-growing powers under IBP)
|
|
174
|
+
if ((p0 === LIATE.EXP && p1 === LIATE.TRIG) || (p0 === LIATE.TRIG && p1 === LIATE.EXP)) {
|
|
175
|
+
const trigFactor = p0 === LIATE.TRIG ? u : dv;
|
|
176
|
+
if (trigFactor.isFunction()) {
|
|
177
|
+
const name = trigFactor.name;
|
|
178
|
+
// sin and cos are safe (table handles e^x·sin/cos directly)
|
|
179
|
+
// Everything else spirals
|
|
180
|
+
if (name !== constants_1.SIN && name !== constants_1.COS) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
function tryMergeDerivativePair(varFactors, v) {
|
|
188
|
+
if (varFactors.length < 3) {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
const dx = Expression_1.Expression.create(v);
|
|
192
|
+
for (let i = 0; i < varFactors.length; i++) {
|
|
193
|
+
const candidate = varFactors[i];
|
|
194
|
+
const dCandidate = (0, diff_1.diff)(candidate, dx);
|
|
195
|
+
if (dCandidate.isFunction(constants_1.DIFF)) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
for (let j = 0; j < varFactors.length; j++) {
|
|
199
|
+
if (j === i) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
let rest;
|
|
203
|
+
for (let k = 0; k < varFactors.length; k++) {
|
|
204
|
+
if (k === i || k === j) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
rest = rest ? rest.times(varFactors[k]) : varFactors[k];
|
|
208
|
+
}
|
|
209
|
+
if (!rest) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
// Check whether dCandidate is proportional to rest
|
|
213
|
+
const q = dCandidate.div(rest);
|
|
214
|
+
if (!q.hasVariable(v)) {
|
|
215
|
+
return [candidate, varFactors[j]];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Attempts integration by parts for a product with two variable-dependent factors.
|
|
223
|
+
*
|
|
224
|
+
* LIATE priority selects `u`; independent multipliers are preserved separately.
|
|
225
|
+
* Category-specific progress checks and a dedicated recursion bound reject
|
|
226
|
+
* cyclic or increasingly complex decompositions.
|
|
227
|
+
*
|
|
228
|
+
* @param x - Product integrand.
|
|
229
|
+
* @param v - Integration variable.
|
|
230
|
+
* @param integrate - Recursive integration strategy supplied by the caller.
|
|
231
|
+
* @param depth - Current outer integration depth.
|
|
232
|
+
* @param ibpDepth - Current integration-by-parts depth.
|
|
233
|
+
* @returns An antiderivative when the transformation makes progress, otherwise
|
|
234
|
+
* `undefined` so another strategy can run.
|
|
235
|
+
*/
|
|
236
|
+
function tryIntegrationByParts(x, v, integrate, depth = 0, ibpDepth = 0) {
|
|
237
|
+
if (!x.isProduct()) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
// IBP-specific depth guard: prevent runaway recursion independent of
|
|
241
|
+
// integrate's own MAX_DEPTH. This fires much sooner and avoids the
|
|
242
|
+
// long delays caused by exhausting the global depth limit.
|
|
243
|
+
if (ibpDepth >= MAX_IBP_DEPTH) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
const factors = x.elementsArray();
|
|
247
|
+
// Extract the overall multiplier and variable-containing factors
|
|
248
|
+
const varFactors = [];
|
|
249
|
+
// IMPORTANT: elementsArray() does not include the product's own multiplier, so pull it from the expression.
|
|
250
|
+
let coefficient = x.getMultiplier(true);
|
|
251
|
+
for (let factor of factors) {
|
|
252
|
+
if (!factor.hasVariable(v)) {
|
|
253
|
+
// Constant factor: fold it into the coefficient
|
|
254
|
+
coefficient = coefficient.times(factor);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// Variable factor: also peel off its own multiplier so it doesn't get dropped in recursive IBP.
|
|
258
|
+
// Example: 3*x^2*e^x can appear with the 3 sitting on the product multiplier OR on the factor.
|
|
259
|
+
const m = factor.getMultiplier(true);
|
|
260
|
+
if (!m.isOne()) {
|
|
261
|
+
coefficient = coefficient.times(m);
|
|
262
|
+
factor = factor.div(m);
|
|
263
|
+
}
|
|
264
|
+
varFactors.push(factor);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (varFactors.length > 2) {
|
|
268
|
+
const merged = tryMergeDerivativePair(varFactors, v);
|
|
269
|
+
if (merged) {
|
|
270
|
+
varFactors.length = 0;
|
|
271
|
+
varFactors.push(...merged);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// IBP needs exactly 2 variable-containing factors
|
|
275
|
+
if (varFactors.length !== 2) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
// Classify and assign u and dv using LIATE priority
|
|
279
|
+
const p0 = liatePriority(varFactors[0]);
|
|
280
|
+
const p1 = liatePriority(varFactors[1]);
|
|
281
|
+
// If either factor is unclassified, bail
|
|
282
|
+
if (p0 < 0 || p1 < 0) {
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
// Higher priority → u (differentiates to something simpler)
|
|
286
|
+
let u, dv;
|
|
287
|
+
if (p0 >= p1) {
|
|
288
|
+
u = varFactors[0];
|
|
289
|
+
dv = varFactors[1];
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
u = varFactors[1];
|
|
293
|
+
dv = varFactors[0];
|
|
294
|
+
}
|
|
295
|
+
// Detect cyclic or pathological LIATE pairings that will never converge
|
|
296
|
+
const uCategory = p0 >= p1 ? p0 : p1;
|
|
297
|
+
if (isCyclicPair(p0, p1, u, dv)) {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
// Compute du = d/dx(u)
|
|
301
|
+
const du = (0, diff_1.diff)(u, Expression_1.Expression.create(v));
|
|
302
|
+
// If diff returned a symbolic diff(...) expression, it couldn't compute the derivative
|
|
303
|
+
if (du.isFunction(constants_1.DIFF)) {
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
// Compute v_result = ∫ dv dx
|
|
307
|
+
const vResult = integrate(dv, v, depth);
|
|
308
|
+
if (vResult.isFunction(constants_1.INTEGRATE)) {
|
|
309
|
+
return undefined;
|
|
310
|
+
} // dv can't be integrated
|
|
311
|
+
// ∫ u·dv = u·v - ∫ v·du
|
|
312
|
+
const uv = coefficient.times(u).times(vResult);
|
|
313
|
+
// Build the new integrand: v·du (with the original coefficient)
|
|
314
|
+
const newIntegrand = coefficient.times(vResult).times(du);
|
|
315
|
+
// Progress guard: verify IBP is actually simplifying the integrand.
|
|
316
|
+
// The definition of "progress" is LIATE-category-aware:
|
|
317
|
+
// - Algebraic u: polynomial degree must decrease
|
|
318
|
+
// - Log/InvTrig u: function count must decrease
|
|
319
|
+
// - Fallback: structural function count must decrease
|
|
320
|
+
if (!isProgress(x, newIntegrand, uCategory, v)) {
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
// Try to integrate v·du
|
|
324
|
+
const remainder = integrate(newIntegrand, v, depth);
|
|
325
|
+
// If the remainder is fully symbolic (nothing was integrated), IBP didn't help
|
|
326
|
+
// But allow partial results (some terms integrated via linearity)
|
|
327
|
+
let retval;
|
|
328
|
+
if (remainder.isFunction(constants_1.INTEGRATE)) {
|
|
329
|
+
// One more check: try IBP recursively on the remainder
|
|
330
|
+
const innerResult = tryIntegrationByParts(newIntegrand, v, integrate, depth + 1, ibpDepth + 1);
|
|
331
|
+
if (innerResult !== undefined) {
|
|
332
|
+
retval = uv.plus(innerResult.times((0, shortcuts_1.minusOne)()));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
retval = uv.plus(remainder.times((0, shortcuts_1.minusOne)()));
|
|
337
|
+
}
|
|
338
|
+
return retval;
|
|
339
|
+
}
|