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,411 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bySubstitution = bySubstitution;
|
|
4
|
+
exports.tryIntegrateBySubstitution = tryIntegrateBySubstitution;
|
|
5
|
+
exports.tryIntegrateByWrappedFactorSubstitution = tryIntegrateByWrappedFactorSubstitution;
|
|
6
|
+
exports.tryIntegrateByLogSubstitution = tryIntegrateByLogSubstitution;
|
|
7
|
+
exports.tryIntegrateByPowerSubstitution = tryIntegrateByPowerSubstitution;
|
|
8
|
+
const factor_1 = require("../../algebra/factor/factor");
|
|
9
|
+
const simplify_1 = require("../../algebra/simplify/simplify");
|
|
10
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
11
|
+
const shortcuts_1 = require("../../core/classes/expression/shortcuts");
|
|
12
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
13
|
+
const Pattern_1 = require("../../core/converters/Pattern");
|
|
14
|
+
const subst_1 = require("../../core/functions/subst");
|
|
15
|
+
const diff_1 = require("../derivative/diff");
|
|
16
|
+
const integrationTable_1 = require("./integrationTable");
|
|
17
|
+
const utils_1 = require("./utils");
|
|
18
|
+
const MAX_POWER_SUBSTITUTION_ATTEMPTS = 8;
|
|
19
|
+
/**
|
|
20
|
+
* Tests whether two expressions match the generalized substitution pattern
|
|
21
|
+
*
|
|
22
|
+
* integrand = c * f(x)^n * f'(x)
|
|
23
|
+
*
|
|
24
|
+
* where c is a constant independent of the integration variable
|
|
25
|
+
* and n is any real number (including n=1 for the basic f·f' case,
|
|
26
|
+
* n=-1 for the logarithmic case, and fractional powers).
|
|
27
|
+
*
|
|
28
|
+
* If the relationship holds, the integral becomes
|
|
29
|
+
*
|
|
30
|
+
* ∫ c f^n f' dx = c * f^(n+1) / (n+1) (for n ≠ -1)
|
|
31
|
+
*
|
|
32
|
+
* The n=-1 case (logarithmic) is handled separately by the log substitution
|
|
33
|
+
* detector, so this function focuses on n ≠ -1.
|
|
34
|
+
*
|
|
35
|
+
* Detection strategy:
|
|
36
|
+
* 1. Compute f'(x) for the candidate f(x)
|
|
37
|
+
* 2. Divide `other` by f'(x) to get the residual
|
|
38
|
+
* 3. If the residual is constant → n=1 (basic f·f' case)
|
|
39
|
+
* 4. Otherwise, check if the residual is a pure power of f(x):
|
|
40
|
+
* residual = c·f(x)^m → n = m+1, constant = c
|
|
41
|
+
*
|
|
42
|
+
* @param fx candidate substitution function f(x)
|
|
43
|
+
* @param other remaining multiplicative factor
|
|
44
|
+
* @param x integration variable
|
|
45
|
+
* @returns substitution match information or undefined
|
|
46
|
+
*/
|
|
47
|
+
function testProductSides(fx, other, x) {
|
|
48
|
+
// Quick structural bail-out: if `other` is purely algebraic (no transcendentals)
|
|
49
|
+
// but `fx` contains transcendentals, then other cannot be proportional to f'(x)
|
|
50
|
+
// since differentiating a transcendental always produces transcendentals.
|
|
51
|
+
if (!(0, utils_1.hasTranscendental)(other, x) && (0, utils_1.hasTranscendental)(fx, x)) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
// Compute derivative of the candidate substitution function.
|
|
55
|
+
const df = (0, diff_1.diff)(fx, x);
|
|
56
|
+
// Do not divide by zero
|
|
57
|
+
if (df.isZero()) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Determine whether the other factor differs from f'(x) only by a constant.
|
|
61
|
+
// If other = c*f'(x), then the integrand is c*f(x)*f'(x) → power = 1.
|
|
62
|
+
const residual = (0, simplify_1.simplify)(other.div(df));
|
|
63
|
+
// Case 1: residual is constant → basic f·f' pattern with power = 1
|
|
64
|
+
if (!residual.hasVariable(x)) {
|
|
65
|
+
return { fx, constant: residual, power: (0, shortcuts_1.one)() };
|
|
66
|
+
}
|
|
67
|
+
// Skip the expensive repeated-division loop when fx is a plain variable.
|
|
68
|
+
// If fx = x, the integrand is x·other, and the f^n·f' pattern with fx = x
|
|
69
|
+
// means other = c·x^m — a pure polynomial, already handled by the table.
|
|
70
|
+
if (fx.isVAR()) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
// Case 2: residual might be c·f(x)^m for some constant c and exponent m.
|
|
74
|
+
// If so, the integrand = fx · other = f(x) · c·f'(x)·f(x)^m = c·f(x)^(m+1)·f'(x).
|
|
75
|
+
// The integral is c·f(x)^(m+2)/(m+2).
|
|
76
|
+
// We return power = m+1 so the caller computes fx^(power+1)/(power+1)·constant.
|
|
77
|
+
//
|
|
78
|
+
// Detection: divide residual by fx repeatedly. After k divisions, if the
|
|
79
|
+
// result is independent of x, then m = k and residual = constant·fx^k.
|
|
80
|
+
let quotient = residual;
|
|
81
|
+
let m = 0;
|
|
82
|
+
for (let attempts = 0; attempts < MAX_POWER_SUBSTITUTION_ATTEMPTS; attempts++) {
|
|
83
|
+
const next = (0, simplify_1.simplify)(quotient.div(fx));
|
|
84
|
+
if (!next.hasVariable(x)) {
|
|
85
|
+
// residual = next·fx^(m+1), integrand = f·(next·fx^(m+1)·f') = next·fx^(m+2)·f'
|
|
86
|
+
// Return power = m+2 so caller computes fx^(m+3)/(m+3)·next
|
|
87
|
+
const power = Expression_1.Expression.Number(m + 2);
|
|
88
|
+
const plusOne = Expression_1.Expression.Number(m + 3);
|
|
89
|
+
// n+1 must not be zero (would mean n=-1, the logarithmic case)
|
|
90
|
+
if (plusOne.isZero()) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return { fx, constant: next, power };
|
|
94
|
+
}
|
|
95
|
+
quotient = next;
|
|
96
|
+
m++;
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Attempts to detect an f(x)·f'(x) substitution structure from a list of
|
|
102
|
+
* multiplicative factors.
|
|
103
|
+
*
|
|
104
|
+
* The algorithm performs a contiguous range search over the factors.
|
|
105
|
+
* For each contiguous block it builds a candidate f(x) and compares it
|
|
106
|
+
* against the remaining factors.
|
|
107
|
+
*
|
|
108
|
+
* Example structure detected:
|
|
109
|
+
*
|
|
110
|
+
* (a^x*log(a)*cos(x) - a^x*sin(x)) * a^x*cos(x)
|
|
111
|
+
*
|
|
112
|
+
* which matches
|
|
113
|
+
*
|
|
114
|
+
* f(x) = a^x*cos(x)
|
|
115
|
+
* f'(x) = a^x*log(a)*cos(x) - a^x*sin(x)
|
|
116
|
+
*
|
|
117
|
+
* yielding
|
|
118
|
+
*
|
|
119
|
+
* ∫ f f' dx = f² / 2
|
|
120
|
+
*
|
|
121
|
+
* To reduce symbolic overhead:
|
|
122
|
+
*
|
|
123
|
+
* - The total product is computed once.
|
|
124
|
+
* - The left candidate product grows incrementally.
|
|
125
|
+
* - The complementary product is obtained via division.
|
|
126
|
+
*
|
|
127
|
+
* @param factors multiplicative factors of the integrand
|
|
128
|
+
* @param x integration variable
|
|
129
|
+
* @returns substitution match or undefined if none found
|
|
130
|
+
*/
|
|
131
|
+
function bySubstitution(factors, x) {
|
|
132
|
+
const n = factors.length;
|
|
133
|
+
// Compute the total product once.
|
|
134
|
+
let total = factors[0];
|
|
135
|
+
for (let i = 1; i < n; i++) {
|
|
136
|
+
total = total.times(factors[i]);
|
|
137
|
+
}
|
|
138
|
+
// Iterate over contiguous ranges of factors.
|
|
139
|
+
for (let start = 0; start < n; start++) {
|
|
140
|
+
const left = factors[start];
|
|
141
|
+
let right = undefined;
|
|
142
|
+
for (let i = 0; i < n; i++) {
|
|
143
|
+
if (i === start) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
right = right ? right.times(factors[i]) : factors[i];
|
|
147
|
+
}
|
|
148
|
+
right = right ?? (0, shortcuts_1.one)();
|
|
149
|
+
const a = testProductSides(left, right, x);
|
|
150
|
+
if (a) {
|
|
151
|
+
return a;
|
|
152
|
+
}
|
|
153
|
+
const b = testProductSides(right, left, x);
|
|
154
|
+
if (b) {
|
|
155
|
+
return b;
|
|
156
|
+
}
|
|
157
|
+
// Also try the base of powered factors as candidates.
|
|
158
|
+
// e.g. for tan(x)^2 · sec(x)^2, try tan(x) vs tan(x)·sec(x)^2
|
|
159
|
+
// so testProductSides can detect f·f^n·f' patterns.
|
|
160
|
+
const leftBase = left.getBase();
|
|
161
|
+
const leftPower = left.getPower();
|
|
162
|
+
if (!leftPower.isOne() && leftBase.hasVariable(x)) {
|
|
163
|
+
const adjustedRight = leftBase.pow(leftPower.minus((0, shortcuts_1.one)())).times(right);
|
|
164
|
+
const c = testProductSides(leftBase, adjustedRight, x);
|
|
165
|
+
if (c) {
|
|
166
|
+
return c;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const rightBase = right.getBase();
|
|
170
|
+
const rightPower = right.getPower();
|
|
171
|
+
if (!rightPower.isOne() && rightBase.hasVariable(x)) {
|
|
172
|
+
const adjustedLeft = rightBase.pow(rightPower.minus((0, shortcuts_1.one)())).times(left);
|
|
173
|
+
const d = testProductSides(rightBase, adjustedLeft, x);
|
|
174
|
+
if (d) {
|
|
175
|
+
return d;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Attempts to integrate an expression using product-style substitution.
|
|
183
|
+
*
|
|
184
|
+
* This function prepares the expression for substitution detection
|
|
185
|
+
* by extracting multiplicative factors and then delegating to
|
|
186
|
+
* {@link bySubstitution}.
|
|
187
|
+
*
|
|
188
|
+
* The method specifically searches for integrands of the form
|
|
189
|
+
*
|
|
190
|
+
* c * f(x) * f'(x)
|
|
191
|
+
*
|
|
192
|
+
* which integrate to
|
|
193
|
+
*
|
|
194
|
+
* c * f(x)² / 2
|
|
195
|
+
*
|
|
196
|
+
* Factorization is only performed when necessary to avoid the
|
|
197
|
+
* significant cost of factoring expressions unnecessarily.
|
|
198
|
+
*
|
|
199
|
+
* @param fx expression to integrate
|
|
200
|
+
* @param x integration variable
|
|
201
|
+
* @returns substitution match information or undefined
|
|
202
|
+
*/
|
|
203
|
+
function tryIntegrateBySubstitution(fx, x) {
|
|
204
|
+
// If the expression is not already a product, factor it.
|
|
205
|
+
if (!fx.isProduct()) {
|
|
206
|
+
fx = (0, factor_1.factor)(fx);
|
|
207
|
+
}
|
|
208
|
+
// If it still is not a product, substitution is impossible.
|
|
209
|
+
if (!fx.isProduct()) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
const factors = fx.elementsArray();
|
|
213
|
+
// Substitution requires at least two multiplicative components.
|
|
214
|
+
if (factors.length < 2) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
const result = bySubstitution(factors, x);
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Extracts candidate inner functions from a factor for wrapped-factor substitution.
|
|
222
|
+
*
|
|
223
|
+
* For function calls like cos(x^2), extracts the argument (x^2).
|
|
224
|
+
* For exponentials like e^(x^2), extracts the exponent (x^2).
|
|
225
|
+
* For non-unit powers like (3+2*x^2)^(5/2), extracts the base (3+2*x^2).
|
|
226
|
+
*
|
|
227
|
+
* @param factor a multiplicative factor of the integrand
|
|
228
|
+
* @param x integration variable
|
|
229
|
+
* @returns list of candidate inner expressions for substitution
|
|
230
|
+
*/
|
|
231
|
+
function getWrappedInnerCandidates(factor, x) {
|
|
232
|
+
const candidates = [];
|
|
233
|
+
if (factor.isFunction()) {
|
|
234
|
+
const args = factor.getArguments();
|
|
235
|
+
if (args.length === 1 && args[0].hasVariable(x)) {
|
|
236
|
+
candidates.push(args[0]);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (factor.isEXP()) {
|
|
240
|
+
const base = factor.getBase();
|
|
241
|
+
const power = factor.getPower();
|
|
242
|
+
if (base.hasVariable(x) && !base.eq(factor)) {
|
|
243
|
+
candidates.push(base);
|
|
244
|
+
}
|
|
245
|
+
if (base.isE() && power.hasVariable(x) && !power.eq(factor)) {
|
|
246
|
+
candidates.push(power);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Handle (base)^(non-unit power) — e.g. (3+2*x^2)^(5/2)
|
|
250
|
+
if (!factor.isFunction() && !factor.isEXP()) {
|
|
251
|
+
const base = factor.getBase();
|
|
252
|
+
const power = factor.getPower();
|
|
253
|
+
if (!power.isOne() && base.hasVariable(x) && !base.eq(factor)) {
|
|
254
|
+
candidates.push(base);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return candidates;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Attempts substitution when one factor wraps an inner expression and the
|
|
261
|
+
* remaining factors are proportional to its derivative.
|
|
262
|
+
*
|
|
263
|
+
* @param fx - Complete product integrand, used to select a fresh variable.
|
|
264
|
+
* @param factors - Multiplicative factors to test.
|
|
265
|
+
* @param x - Integration variable.
|
|
266
|
+
* @returns The back-substituted antiderivative, or `undefined` when the outer
|
|
267
|
+
* factor is not covered by the integration table.
|
|
268
|
+
*/
|
|
269
|
+
function tryIntegrateByWrappedFactorSubstitution(fx, factors, x) {
|
|
270
|
+
let total = factors[0];
|
|
271
|
+
for (let i = 1; i < factors.length; i++) {
|
|
272
|
+
total = total.times(factors[i]);
|
|
273
|
+
}
|
|
274
|
+
for (const factor of factors) {
|
|
275
|
+
const others = (0, simplify_1.simplify)(total.div(factor));
|
|
276
|
+
for (const inner of getWrappedInnerCandidates(factor, x)) {
|
|
277
|
+
const df = (0, diff_1.diff)(inner, x);
|
|
278
|
+
if (df.isZero()) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const constant = (0, simplify_1.simplify)(others.div(df));
|
|
282
|
+
if (constant.hasVariable(x)) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
const u = Expression_1.Expression.create((0, subst_1.getU)(fx));
|
|
286
|
+
const factorInU = (0, simplify_1.simplify)((0, subst_1.subst)(factor, inner, u));
|
|
287
|
+
if (factorInU.hasVariable(x) || !factorInU.hasVariable(u.text())) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const outerIntegral = integrationTable_1.tableOfIntegrals.lookup(new Pattern_1.Pattern(factorInU, [u.text()]), 0);
|
|
291
|
+
if (!outerIntegral || outerIntegral.hasFunction(constants_1.INTEGRATE)) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
return (0, simplify_1.simplify)((0, subst_1.subst)(outerIntegral, u, inner).times(constant));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
function testQuotientSides(numerator, denominator, x) {
|
|
300
|
+
// Treat the denominator as the candidate inner function f(x).
|
|
301
|
+
const df = (0, diff_1.diff)(denominator, x);
|
|
302
|
+
// If numerator = c*f'(x), then the integrand is c*f'(x)/f(x).
|
|
303
|
+
const constant = (0, simplify_1.simplify)(numerator.div(df));
|
|
304
|
+
// The proportionality factor must be independent of x.
|
|
305
|
+
if (!constant.hasVariable(x)) {
|
|
306
|
+
return {
|
|
307
|
+
fx: denominator,
|
|
308
|
+
constant,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return undefined;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Attempts to detect a logarithmic substitution structure of the form
|
|
315
|
+
*
|
|
316
|
+
* c * f'(x) / f(x)
|
|
317
|
+
*
|
|
318
|
+
* by extracting the numerator and denominator of the expression and
|
|
319
|
+
* testing whether the numerator is proportional to the derivative of
|
|
320
|
+
* the denominator.
|
|
321
|
+
*
|
|
322
|
+
* This is much cheaper than the contiguous-factor search used for
|
|
323
|
+
* product-style substitution because the denominator already provides
|
|
324
|
+
* the natural candidate for f(x).
|
|
325
|
+
*
|
|
326
|
+
* Examples:
|
|
327
|
+
*
|
|
328
|
+
* (2*x)/(1+x^2) -> f(x) = 1+x^2, constant = 1
|
|
329
|
+
* cos(x)/sin(x) -> f(x) = sin(x), constant = 1
|
|
330
|
+
* 3*cos(x)/sin(x) -> f(x) = sin(x), constant = 3
|
|
331
|
+
*
|
|
332
|
+
* Non-example:
|
|
333
|
+
*
|
|
334
|
+
* f(x)/f'(x)
|
|
335
|
+
*
|
|
336
|
+
* That is not the logarithmic rule and should not be handled here.
|
|
337
|
+
*
|
|
338
|
+
* @param fx expression to analyze
|
|
339
|
+
* @param x integration variable
|
|
340
|
+
* @returns logarithmic substitution match information or undefined
|
|
341
|
+
*/
|
|
342
|
+
function tryIntegrateByLogSubstitution(fx, x) {
|
|
343
|
+
// Extract numerator and denominator directly from the expression.
|
|
344
|
+
const numerator = (0, simplify_1.simplify)(fx.getNumerator());
|
|
345
|
+
const denominator = (0, simplify_1.simplify)(fx.getDenominator());
|
|
346
|
+
// If there is no real denominator, then there is no f'(x)/f(x) structure.
|
|
347
|
+
if (denominator.isOne()) {
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
return testQuotientSides(numerator, denominator, x);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Attempts to detect a generalized power-quotient substitution structure:
|
|
354
|
+
*
|
|
355
|
+
* integrand = c * f'(x) / f(x)^n
|
|
356
|
+
*
|
|
357
|
+
* which integrates to
|
|
358
|
+
*
|
|
359
|
+
* c * f(x)^(1-n) / (1-n) for n ≠ 1
|
|
360
|
+
*
|
|
361
|
+
* The n=1 case is the logarithmic substitution handled by
|
|
362
|
+
* tryIntegrateByLogSubstitution. This function handles n ≠ 1,
|
|
363
|
+
* including fractional powers like n=1/2 (square root denominators).
|
|
364
|
+
*
|
|
365
|
+
* This catches integrands like:
|
|
366
|
+
*
|
|
367
|
+
* x / sqrt(1-x²) → f = 1-x², f' = -2x, n = 1/2
|
|
368
|
+
* x / (1+x²)² → f = 1+x², f' = 2x, n = 2
|
|
369
|
+
*
|
|
370
|
+
* @param fx expression to analyze
|
|
371
|
+
* @param x integration variable
|
|
372
|
+
* @returns match with fx (the inner function), constant, and power (the denominator exponent n)
|
|
373
|
+
*/
|
|
374
|
+
function tryIntegrateByPowerSubstitution(fx, x) {
|
|
375
|
+
const numerator = (0, simplify_1.simplify)(fx.getNumerator());
|
|
376
|
+
const denominator = (0, simplify_1.simplify)(fx.getDenominator());
|
|
377
|
+
// Must have a non-trivial denominator containing the variable
|
|
378
|
+
if (denominator.isOne() || !denominator.hasVariable(x)) {
|
|
379
|
+
return undefined;
|
|
380
|
+
}
|
|
381
|
+
// The denominator may be f(x)^n. Extract the base and power.
|
|
382
|
+
// getBase() returns the base: for (1-x²)^(1/2), getBase() = 1-x²
|
|
383
|
+
// getPower() returns the exponent: for (1-x²)^(1/2), getPower() = 1/2
|
|
384
|
+
const denBase = denominator.getBase();
|
|
385
|
+
const denPower = denominator.getPower();
|
|
386
|
+
// If the base doesn't contain the variable, nothing to substitute
|
|
387
|
+
if (!denBase.hasVariable(x)) {
|
|
388
|
+
return undefined;
|
|
389
|
+
}
|
|
390
|
+
// Compute derivative of the denominator base
|
|
391
|
+
const df = (0, diff_1.diff)(denBase, x);
|
|
392
|
+
if (df.isZero()) {
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
// Check if numerator is proportional to f'(x):
|
|
396
|
+
// If numerator = c·f'(x), then integrand = c·f'(x)/f(x)^n
|
|
397
|
+
const ratio = (0, simplify_1.simplify)(numerator.div(df));
|
|
398
|
+
if (!ratio.hasVariable(x)) {
|
|
399
|
+
const oneMinusN = (0, simplify_1.simplify)((0, shortcuts_1.one)().plus(denPower.times((0, shortcuts_1.minusOne)())));
|
|
400
|
+
// n=1 is the logarithmic case — skip (handled by log substitution)
|
|
401
|
+
if (oneMinusN.isZero()) {
|
|
402
|
+
return undefined;
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
fx: denBase,
|
|
406
|
+
constant: ratio,
|
|
407
|
+
power: denPower,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
return undefined;
|
|
411
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
import type { ExpressionInput } from '../../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Finds a symbolic indefinite integral with respect to a plain variable.
|
|
5
|
+
*
|
|
6
|
+
* Constants and linear sums are separated first. The remaining integrand is
|
|
7
|
+
* tried against the integral table and bounded strategies for radical and
|
|
8
|
+
* algebraic substitution, quadratic radicals, integration by parts,
|
|
9
|
+
* derivative-pattern substitution, rational decomposition, and the
|
|
10
|
+
* Weierstrass tangent half-angle substitution.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* This function returns an antiderivative only; it does not append a constant
|
|
14
|
+
* of integration and it does not accept definite-integration bounds. An
|
|
15
|
+
* unsupported integral, or a strategy that reaches the recursion guard, is
|
|
16
|
+
* represented as an unevaluated `integrate(expr, dx)` Expression rather than an
|
|
17
|
+
* exception.
|
|
18
|
+
*
|
|
19
|
+
* Branch-sensitive transformations are limited to patterns recognized by the
|
|
20
|
+
* implementation. The result should not be read as a global statement about
|
|
21
|
+
* every real or complex branch outside those supported patterns.
|
|
22
|
+
*
|
|
23
|
+
* `depth` is the internal strategy-recursion counter and should normally be
|
|
24
|
+
* omitted by direct callers.
|
|
25
|
+
*
|
|
26
|
+
* @param expr - Integrand to normalize and integrate.
|
|
27
|
+
* @param dx - Plain integration variable.
|
|
28
|
+
* @param depth - Internal recursion depth. Defaults to zero.
|
|
29
|
+
* @returns A symbolic antiderivative without an integration constant, or an
|
|
30
|
+
* unevaluated `integrate(...)` Expression.
|
|
31
|
+
* @throws {@link core!UnexpectedInputError} If `dx` is not a plain variable.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* integrate('2*x*cos(x^2)', 'x').text();
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function integrate(expr: ExpressionInput, dx: ExpressionInput, depth?: number): Expression;
|