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
package/Calculus.js
DELETED
|
@@ -1,2675 +0,0 @@
|
|
|
1
|
-
/* global module */
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Author : Martin Donk
|
|
5
|
-
* Website : http://www.nerdamer.com
|
|
6
|
-
* Email : martin.r.donk@gmail.com
|
|
7
|
-
* Source : https://github.com/jiggzson/nerdamer
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
if((typeof module) !== 'undefined' && typeof nerdamer === 'undefined') {
|
|
11
|
-
var nerdamer = require('./nerdamer.core.js');
|
|
12
|
-
require('./Algebra.js');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
(function () {
|
|
16
|
-
"use strict";
|
|
17
|
-
|
|
18
|
-
var core = nerdamer.getCore(),
|
|
19
|
-
_ = core.PARSER,
|
|
20
|
-
Frac = core.Frac,
|
|
21
|
-
Settings = core.Settings,
|
|
22
|
-
isSymbol = core.Utils.isSymbol,
|
|
23
|
-
FN = core.groups.FN,
|
|
24
|
-
Symbol = core.Symbol,
|
|
25
|
-
text = core.Utils.text,
|
|
26
|
-
inBrackets = core.Utils.inBrackets,
|
|
27
|
-
isInt = core.Utils.isInt,
|
|
28
|
-
format = core.Utils.format,
|
|
29
|
-
even = core.Utils.even,
|
|
30
|
-
evaluate = core.Utils.evaluate,
|
|
31
|
-
N = core.groups.N,
|
|
32
|
-
S = core.groups.S,
|
|
33
|
-
FN = core.groups.FN,
|
|
34
|
-
PL = core.groups.PL,
|
|
35
|
-
CP = core.groups.CP,
|
|
36
|
-
CB = core.groups.CB,
|
|
37
|
-
EX = core.groups.EX,
|
|
38
|
-
P = core.groups.P,
|
|
39
|
-
LOG = Settings.LOG,
|
|
40
|
-
EXP = 'exp',
|
|
41
|
-
ABS = 'abs',
|
|
42
|
-
SQRT = 'sqrt',
|
|
43
|
-
SIN = 'sin',
|
|
44
|
-
COS = 'cos',
|
|
45
|
-
TAN = 'tan',
|
|
46
|
-
SEC = 'sec',
|
|
47
|
-
CSC = 'csc',
|
|
48
|
-
COT = 'cot',
|
|
49
|
-
ASIN = 'asin',
|
|
50
|
-
ACOS = 'acos',
|
|
51
|
-
ATAN = 'atan',
|
|
52
|
-
ASEC = 'asec',
|
|
53
|
-
ACSC = 'acsc',
|
|
54
|
-
ACOT = 'acot',
|
|
55
|
-
SINH = 'sinh',
|
|
56
|
-
COSH = 'cosh',
|
|
57
|
-
TANH = 'tanh',
|
|
58
|
-
CSCH = 'csch',
|
|
59
|
-
SECH = 'sech',
|
|
60
|
-
COTH = 'coth',
|
|
61
|
-
ASECH = 'asech',
|
|
62
|
-
ACSCH = 'acsch',
|
|
63
|
-
ACOTH = 'acoth';
|
|
64
|
-
|
|
65
|
-
//custom errors
|
|
66
|
-
function NoIntegralFound(msg) {
|
|
67
|
-
this.message = msg || "";
|
|
68
|
-
}
|
|
69
|
-
NoIntegralFound.prototype = new Error();
|
|
70
|
-
|
|
71
|
-
//Preparations
|
|
72
|
-
Symbol.prototype.hasIntegral = function () {
|
|
73
|
-
return this.containsFunction('integrate');
|
|
74
|
-
};
|
|
75
|
-
//transforms a function
|
|
76
|
-
Symbol.prototype.fnTransform = function () {
|
|
77
|
-
if(this.group !== FN)
|
|
78
|
-
return this;
|
|
79
|
-
var retval, a = this.args[0];
|
|
80
|
-
var m = new Symbol(this.multiplier);
|
|
81
|
-
var sym = this.clone().toUnitMultiplier();
|
|
82
|
-
if(this.isLinear()) {
|
|
83
|
-
switch(this.fname) {
|
|
84
|
-
case SINH:
|
|
85
|
-
retval = _.parse(format('(e^({0})-e^(-({0})))/2', a));
|
|
86
|
-
break;
|
|
87
|
-
case COSH:
|
|
88
|
-
retval = _.parse(format('(e^({0})+e^(-({0})))/2', a));
|
|
89
|
-
break;
|
|
90
|
-
case TANH:
|
|
91
|
-
retval = _.parse(format('(e^({0})-e^(-({0})))/(e^({0})+e^(-({0})))', a));
|
|
92
|
-
break;
|
|
93
|
-
case TAN:
|
|
94
|
-
retval = _.parse(format('sin({0})/cos({0})', a));
|
|
95
|
-
break;
|
|
96
|
-
case CSC:
|
|
97
|
-
retval = _.parse(format('1/sin({0})', a));
|
|
98
|
-
break;
|
|
99
|
-
case SEC:
|
|
100
|
-
retval = _.parse(format('1/cos({0})', a));
|
|
101
|
-
break;
|
|
102
|
-
default:
|
|
103
|
-
retval = sym;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
else if(this.power.equals(2)) {
|
|
107
|
-
switch(this.fname) {
|
|
108
|
-
case SIN:
|
|
109
|
-
retval = _.parse(format('1/2-cos(2*({0}))/2', a));
|
|
110
|
-
break;
|
|
111
|
-
case COS:
|
|
112
|
-
retval = _.parse(format('1/2+cos(2*({0}))/2', a));
|
|
113
|
-
break;
|
|
114
|
-
case TAN:
|
|
115
|
-
//retval = _.parse(format('(1-cos(2*({0})))/(1+cos(2*({0})))', a));
|
|
116
|
-
retval = _.parse(format('sin({0})^2/cos({0})^2', a));
|
|
117
|
-
break;
|
|
118
|
-
case COSH:
|
|
119
|
-
retval = _.parse(format('1/2+cosh(2*({0}))/2', a));
|
|
120
|
-
break;
|
|
121
|
-
case SINH:
|
|
122
|
-
retval = _.parse(format('-1/2+cosh(2*({0}))/2', a));
|
|
123
|
-
break;
|
|
124
|
-
case TANH:
|
|
125
|
-
retval = _.parse(format('(1+cosh(2*({0})))/(-1+cosh(2*({0})))', a));
|
|
126
|
-
break;
|
|
127
|
-
case SEC:
|
|
128
|
-
retval = _.parse(format('(1-cos(2*({0})))/(1+cos(2*({0})))+1', a));
|
|
129
|
-
break;
|
|
130
|
-
default:
|
|
131
|
-
retval = sym;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
else if(this.fname === SEC) {
|
|
135
|
-
retval = _.parse(format('1/cos({0})^({1})', this.args[0], this.power));
|
|
136
|
-
}
|
|
137
|
-
else if(this.fname === CSC) {
|
|
138
|
-
retval = _.parse(format('1/sin({0})^({1})', this.args[0], this.power));
|
|
139
|
-
}
|
|
140
|
-
else if(this.fname === TAN) {
|
|
141
|
-
if(this.power.lessThan(0)) {
|
|
142
|
-
retval = _.parse(format('cos({0})^(-({1}))/sin({0})^({1})', this.args[0], this.power.negate()));
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
retval = _.parse(format('sin({0})^({1})/cos({0})^({1})', this.args[0], this.power));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
else if(this.fname === SIN && this.power.lessThan(0)) {
|
|
149
|
-
retval = _.parse(format('csc({0})^(-({1}))', this.args[0], this.power.negate()));
|
|
150
|
-
}
|
|
151
|
-
else if(this.fname === COS && this.power.lessThan(0)) {
|
|
152
|
-
retval = _.parse(format('sec({0})^(-({1}))', this.args[0], this.power.negate()));
|
|
153
|
-
}
|
|
154
|
-
else if(this.fname === SIN && this.power.equals(3)) {
|
|
155
|
-
retval = _.parse(format('(3*sin({0})-sin(3*({0})))/4', this.args[0]));
|
|
156
|
-
}
|
|
157
|
-
else if(this.fname === COS && this.power.equals(3)) {
|
|
158
|
-
retval = _.parse(format('(cos(3*({0}))+3*cos({0}))/4', this.args[0]));
|
|
159
|
-
}
|
|
160
|
-
//cos(a*x)^(2*n) or sin(a*x)^(2*n)
|
|
161
|
-
else if((this.fname === COS || this.fname === SIN) && even(this.power)) {
|
|
162
|
-
var n = this.power / 2;
|
|
163
|
-
//convert to a double angle
|
|
164
|
-
var double_angle = _.pow(this.clone().toLinear(), _.parse(2)).fnTransform();
|
|
165
|
-
//raise to the n and expand
|
|
166
|
-
var transformed = _.expand(_.pow(double_angle, _.parse(n)));
|
|
167
|
-
|
|
168
|
-
retval = new Symbol(0);
|
|
169
|
-
|
|
170
|
-
transformed.each(function (s) {
|
|
171
|
-
var t = s.fnTransform();
|
|
172
|
-
retval = _.add(retval, t);
|
|
173
|
-
}, true);
|
|
174
|
-
}
|
|
175
|
-
else
|
|
176
|
-
retval = sym;
|
|
177
|
-
|
|
178
|
-
return _.multiply(retval, m);
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
Symbol.prototype.hasTrig = function () {
|
|
182
|
-
if(this.isConstant(true) || this.group === S)
|
|
183
|
-
return false;
|
|
184
|
-
if(this.fname && (core.Utils.in_trig(this.fname) || core.Utils.in_inverse_trig(this.fname)))
|
|
185
|
-
return true;
|
|
186
|
-
if(this.symbols) {
|
|
187
|
-
for(var x in this.symbols)
|
|
188
|
-
if(this.symbols[x].hasTrig())
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
return false;
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
core.Expression.prototype.hasIntegral = function () {
|
|
195
|
-
return this.symbol.hasIntegral();
|
|
196
|
-
};
|
|
197
|
-
/**
|
|
198
|
-
* Attempts to rewrite a symbol under one common denominator
|
|
199
|
-
* @param {Symbol} symbol
|
|
200
|
-
*/
|
|
201
|
-
core.Utils.toCommonDenominator = function (symbol) {
|
|
202
|
-
//transform x/a+x -> (ax+x)/a
|
|
203
|
-
if(symbol.isComposite() && symbol.isLinear()) {
|
|
204
|
-
var m = new Symbol(symbol.multiplier);
|
|
205
|
-
var denominator = new Symbol(1);
|
|
206
|
-
var numerator = new Symbol(0);
|
|
207
|
-
symbol.each(function (x) {
|
|
208
|
-
denominator = _.multiply(denominator, x.getDenom());
|
|
209
|
-
}, true);
|
|
210
|
-
|
|
211
|
-
//remove the denomitor in each term
|
|
212
|
-
symbol.each(function (x) {
|
|
213
|
-
var num = x.getNum();
|
|
214
|
-
var den = x.getDenom();
|
|
215
|
-
var factor = _.multiply(num, _.divide(denominator.clone(), den));
|
|
216
|
-
numerator = _.add(numerator, factor);
|
|
217
|
-
});
|
|
218
|
-
var retval = _.multiply(m, core.Algebra.divide(_.expand(numerator), _.expand(denominator)));
|
|
219
|
-
return retval;
|
|
220
|
-
}
|
|
221
|
-
return symbol;
|
|
222
|
-
};
|
|
223
|
-
//A function to check if a function name is an inverse trig function
|
|
224
|
-
core.Utils.in_inverse_trig = function (x) {
|
|
225
|
-
var inv_trig_fns = [ASIN, ACOS, ATAN, ACSC, ASEC, ACOT];
|
|
226
|
-
return inv_trig_fns.indexOf(x) !== -1;
|
|
227
|
-
};
|
|
228
|
-
//A function to check if a function name is a trig function
|
|
229
|
-
core.Utils.in_trig = function (x) {
|
|
230
|
-
var trig_fns = [COS, SIN, TAN, SEC, CSC, COT];
|
|
231
|
-
return trig_fns.indexOf(x) !== -1;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
core.Utils.in_htrig = function (x) {
|
|
235
|
-
var trig_fns = [SINH, COSH, TANH, ACSCH, ASECH, ACOTH];
|
|
236
|
-
return trig_fns.indexOf(x) !== -1;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
// Matrix functions
|
|
240
|
-
core.Matrix.jacobian = function (eqns, vars) {
|
|
241
|
-
var jacobian = new core.Matrix();
|
|
242
|
-
//get the variables if not supplied
|
|
243
|
-
if(!vars) {
|
|
244
|
-
vars = core.Utils.arrayGetVariables(eqns);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
vars.forEach(function (v, i) {
|
|
248
|
-
eqns.forEach(function (eq, j) {
|
|
249
|
-
var e = core.Calculus.diff(eq.clone(), v);
|
|
250
|
-
jacobian.set(j, i, e);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
return jacobian;
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
core.Matrix.prototype.max = function () {
|
|
258
|
-
var max = new Symbol(0);
|
|
259
|
-
this.each(function (x) {
|
|
260
|
-
var e = x.abs();
|
|
261
|
-
if(e.gt(max))
|
|
262
|
-
max = e;
|
|
263
|
-
});
|
|
264
|
-
return max;
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
core.Matrix.cMatrix = function (value, vars) {
|
|
268
|
-
var m = new core.Matrix();
|
|
269
|
-
//make an initial guess
|
|
270
|
-
vars.forEach(function (v, i) {
|
|
271
|
-
m.set(i, 0, _.parse(value));
|
|
272
|
-
});
|
|
273
|
-
return m;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
var all_functions = core.Utils.all_functions = function (arr) {
|
|
277
|
-
for(var i = 0, l = arr.length; i < l; i++)
|
|
278
|
-
if(arr[i].group !== FN)
|
|
279
|
-
return false;
|
|
280
|
-
return true;
|
|
281
|
-
},
|
|
282
|
-
cosAsinBtransform = core.Utils.cosAsinBtranform = function (symbol1, symbol2) {
|
|
283
|
-
var a, b;
|
|
284
|
-
a = symbol1.args[0];
|
|
285
|
-
b = symbol2.args[0];
|
|
286
|
-
return _.parse(format('(sin(({0})+({1}))-sin(({0})-({1})))/2', a, b));
|
|
287
|
-
},
|
|
288
|
-
cosAsinAtransform = core.Utils.cosAsinAtranform = function (symbol1, symbol2) {
|
|
289
|
-
//TODO: temporary fix for integrate(e^x*sin(x)*cos(x)^2).
|
|
290
|
-
//we technically know how to do this transform but more is needed for correct output
|
|
291
|
-
if(Number(symbol2.power) !== 1)
|
|
292
|
-
return _.multiply(symbol1, symbol2);
|
|
293
|
-
var a;
|
|
294
|
-
a = symbol1.args[0];
|
|
295
|
-
return _.parse(format('(sin(2*({0})))/2', a));
|
|
296
|
-
},
|
|
297
|
-
sinAsinBtransform = core.Utils.cosAsinBtranform = function (symbol1, symbol2) {
|
|
298
|
-
var a, b;
|
|
299
|
-
a = symbol1.args[0];
|
|
300
|
-
b = symbol2.args[0];
|
|
301
|
-
return _.parse(format('(cos(({0})+({1}))-cos(({0})-({1})))/2', a, b));
|
|
302
|
-
},
|
|
303
|
-
trigTransform = core.Utils.trigTransform = function (arr) {
|
|
304
|
-
var map = {}, symbol, t,
|
|
305
|
-
retval = new Symbol(1);
|
|
306
|
-
for(var i = 0, l = arr.length; i < l; i++) {
|
|
307
|
-
symbol = arr[i];
|
|
308
|
-
|
|
309
|
-
if(symbol.group === FN) {
|
|
310
|
-
var fname = symbol.fname;
|
|
311
|
-
|
|
312
|
-
if(fname === COS && map[SIN]) {
|
|
313
|
-
|
|
314
|
-
if(map[SIN].args[0].toString() !== symbol.args[0].toString()) {
|
|
315
|
-
t = cosAsinBtransform(symbol, map[SIN]);
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
t = cosAsinAtransform(symbol, map[SIN]);
|
|
319
|
-
}
|
|
320
|
-
delete map[SIN];
|
|
321
|
-
|
|
322
|
-
retval = _.multiply(retval, t);
|
|
323
|
-
}
|
|
324
|
-
else if(fname === SIN && map[COS]) {
|
|
325
|
-
if(map[COS].args[0].toString() !== symbol.args[0].toString()) {
|
|
326
|
-
t = cosAsinBtransform(symbol, map[COS]);
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
t = cosAsinAtransform(symbol, map[COS]);
|
|
330
|
-
}
|
|
331
|
-
delete map[COS];
|
|
332
|
-
|
|
333
|
-
retval = _.multiply(retval, t);
|
|
334
|
-
}
|
|
335
|
-
else if(fname === SIN && map[SIN]) {
|
|
336
|
-
if(map[SIN].args[0].toString() !== symbol.args[0].toString()) {
|
|
337
|
-
t = sinAsinBtransform(symbol, map[SIN]);
|
|
338
|
-
delete map[SIN];
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
//This should actually be redundant code but let's put just in case
|
|
342
|
-
t = _.multiply(symbol, map[SIN]);
|
|
343
|
-
delete map[SIN];
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
retval = t;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
map[fname] = symbol;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
else
|
|
353
|
-
retval = _.multiply(retval, symbol);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
//put back the remaining functions
|
|
357
|
-
for(var x in map)
|
|
358
|
-
retval = _.multiply(retval, map[x]);
|
|
359
|
-
|
|
360
|
-
return retval;
|
|
361
|
-
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
core.Settings.integration_depth = 10;
|
|
365
|
-
|
|
366
|
-
core.Settings.max_lim_depth = 10;
|
|
367
|
-
|
|
368
|
-
var __ = core.Calculus = {
|
|
369
|
-
|
|
370
|
-
version: '1.4.6',
|
|
371
|
-
|
|
372
|
-
sum: function (fn, index, start, end) {
|
|
373
|
-
if(!(index.group === core.groups.S))
|
|
374
|
-
throw new core.exceptions.NerdamerTypeError('Index must be symbol. ' + text(index) + ' provided');
|
|
375
|
-
index = index.value;
|
|
376
|
-
var retval;
|
|
377
|
-
if(core.Utils.isNumericSymbol(start) && core.Utils.isNumericSymbol(end)) {
|
|
378
|
-
var modifier = end - start < 200 ? '' : 'PARSE2NUMBER';
|
|
379
|
-
start = Number(start);
|
|
380
|
-
end = Number(end);
|
|
381
|
-
retval = core.Utils.block(modifier, function () {
|
|
382
|
-
var f = fn.text(),
|
|
383
|
-
subs = {'~': true}, //lock subs. Is this even being used?
|
|
384
|
-
retval = new core.Symbol(0);
|
|
385
|
-
|
|
386
|
-
for(var i = start; i <= end; i++) {
|
|
387
|
-
subs[index] = new Symbol(i);
|
|
388
|
-
var ans = _.parse(f, subs);
|
|
389
|
-
retval = _.add(retval, ans);
|
|
390
|
-
}
|
|
391
|
-
return retval;
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
retval = _.symfunction('sum', arguments);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return retval;
|
|
399
|
-
},
|
|
400
|
-
product: function (fn, index, start, end) {
|
|
401
|
-
if(!(index.group === core.groups.S))
|
|
402
|
-
throw new core.exceptions.NerdamerTypeError('Index must be symbol. ' + text(index) + ' provided');
|
|
403
|
-
index = index.value;
|
|
404
|
-
var retval;
|
|
405
|
-
if(core.Utils.isNumericSymbol(start) && core.Utils.isNumericSymbol(end)) {
|
|
406
|
-
var modifier = end - start < 200 ? '' : 'PARSE2NUMBER';
|
|
407
|
-
retval = core.Utils.block(modifier, function () {
|
|
408
|
-
start = Number(start);
|
|
409
|
-
end = Number(end.multiplier);
|
|
410
|
-
|
|
411
|
-
var f = fn.text(),
|
|
412
|
-
subs = {},
|
|
413
|
-
retval = new core.Symbol(1);
|
|
414
|
-
|
|
415
|
-
for(var i = start; i <= end; i++) {
|
|
416
|
-
subs[index] = new Symbol(i);
|
|
417
|
-
retval = _.multiply(retval, _.parse(f, subs));
|
|
418
|
-
}
|
|
419
|
-
return retval;
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
retval = _.symfunction('product', arguments);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
return retval;
|
|
427
|
-
},
|
|
428
|
-
diff: function (symbol, wrt, nth) {
|
|
429
|
-
if(core.Utils.isVector(symbol)) {
|
|
430
|
-
var vector = new core.Vector([]);
|
|
431
|
-
symbol.each(function (x) {
|
|
432
|
-
vector.elements.push(__.diff(x, wrt, nth));
|
|
433
|
-
});
|
|
434
|
-
return vector;
|
|
435
|
-
}
|
|
436
|
-
else if(core.Utils.isMatrix(symbol)) {
|
|
437
|
-
var matrix = new core.Matrix();
|
|
438
|
-
symbol.each(function (x, i, j) {
|
|
439
|
-
matrix.set(i, j, __.diff(x, wrt, nth));
|
|
440
|
-
});
|
|
441
|
-
return matrix;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
var d = isSymbol(wrt) ? wrt.text() : wrt;
|
|
445
|
-
//the nth derivative
|
|
446
|
-
nth = isSymbol(nth) ? nth.multiplier : nth || 1;
|
|
447
|
-
|
|
448
|
-
if(d === undefined)
|
|
449
|
-
d = core.Utils.variables(symbol)[0];
|
|
450
|
-
|
|
451
|
-
//unwrap sqrt
|
|
452
|
-
if(symbol.group === FN && symbol.fname === SQRT) {
|
|
453
|
-
var s = symbol.args[0],
|
|
454
|
-
sp = symbol.power.clone();
|
|
455
|
-
//these groups go to zero anyway so why waste time?
|
|
456
|
-
if(s.group !== N || s.group !== P) {
|
|
457
|
-
s.power = isSymbol(s.power) ? _.multiply(s.power, _.multiply(new Symbol(1 / 2)), sp) : s.power.multiply(new Frac(0.5)).multiply(sp);
|
|
458
|
-
s.multiplier = s.multiplier.multiply(symbol.multiplier);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
symbol = s;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if(symbol.group === FN && !isSymbol(symbol.power)) {
|
|
465
|
-
var a = derive(_.parse(symbol));
|
|
466
|
-
var b = __.diff(symbol.args[0].clone(), d);
|
|
467
|
-
symbol = _.multiply(a, b);//chain rule
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
symbol = derive(symbol);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
if(nth > 1) {
|
|
474
|
-
nth--;
|
|
475
|
-
symbol = __.diff(symbol, wrt, nth);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return symbol;
|
|
479
|
-
|
|
480
|
-
// Equivalent to "derivative of the outside".
|
|
481
|
-
function polydiff(symbol) {
|
|
482
|
-
if(symbol.value === d || symbol.contains(d, true)) {
|
|
483
|
-
symbol.multiplier = symbol.multiplier.multiply(symbol.power);
|
|
484
|
-
symbol.power = symbol.power.subtract(new Frac(1));
|
|
485
|
-
if(symbol.power.equals(0)) {
|
|
486
|
-
symbol = Symbol(symbol.multiplier);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
return symbol;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
function derive(symbol) {
|
|
494
|
-
var g = symbol.group, a, b, cp;
|
|
495
|
-
|
|
496
|
-
if(g === N || g === S && symbol.value !== d || g === P) {
|
|
497
|
-
symbol = Symbol(0);
|
|
498
|
-
}
|
|
499
|
-
else if(g === S) {
|
|
500
|
-
symbol = polydiff(symbol);
|
|
501
|
-
}
|
|
502
|
-
else if(g === CB) {
|
|
503
|
-
var m = symbol.multiplier.clone();
|
|
504
|
-
symbol.toUnitMultiplier();
|
|
505
|
-
var retval = _.multiply(product_rule(symbol), polydiff(symbol));
|
|
506
|
-
retval.multiplier = retval.multiplier.multiply(m);
|
|
507
|
-
return retval;
|
|
508
|
-
}
|
|
509
|
-
else if(g === FN && symbol.power.equals(1)) {
|
|
510
|
-
// Table of known derivatives
|
|
511
|
-
switch(symbol.fname) {
|
|
512
|
-
case LOG:
|
|
513
|
-
cp = symbol.clone();
|
|
514
|
-
symbol = symbol.args[0].clone();//get the arguments
|
|
515
|
-
symbol.power = symbol.power.negate();
|
|
516
|
-
symbol.multiplier = cp.multiplier.divide(symbol.multiplier);
|
|
517
|
-
break;
|
|
518
|
-
case COS:
|
|
519
|
-
//cos -> -sin
|
|
520
|
-
symbol.fname = SIN;
|
|
521
|
-
symbol.multiplier.negate();
|
|
522
|
-
break;
|
|
523
|
-
case SIN:
|
|
524
|
-
//sin -> cos
|
|
525
|
-
symbol.fname = COS;
|
|
526
|
-
break;
|
|
527
|
-
case TAN:
|
|
528
|
-
//tan -> sec^2
|
|
529
|
-
symbol.fname = SEC;
|
|
530
|
-
symbol.power = new Frac(2);
|
|
531
|
-
break;
|
|
532
|
-
case SEC:
|
|
533
|
-
// Use a clone if this gives errors
|
|
534
|
-
symbol = qdiff(symbol, TAN);
|
|
535
|
-
break;
|
|
536
|
-
case CSC:
|
|
537
|
-
symbol = qdiff(symbol, '-cot');
|
|
538
|
-
break;
|
|
539
|
-
case COT:
|
|
540
|
-
symbol.fname = CSC;
|
|
541
|
-
symbol.multiplier.negate();
|
|
542
|
-
symbol.power = new Frac(2);
|
|
543
|
-
break;
|
|
544
|
-
case ASIN:
|
|
545
|
-
symbol = _.parse('(sqrt(1-(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
546
|
-
break;
|
|
547
|
-
case ACOS:
|
|
548
|
-
symbol = _.parse('-(sqrt(1-(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
549
|
-
break;
|
|
550
|
-
case ATAN:
|
|
551
|
-
symbol = _.parse('(1+(' + text(symbol.args[0]) + ')^2)^(-1)');
|
|
552
|
-
break;
|
|
553
|
-
case ABS:
|
|
554
|
-
m = symbol.multiplier.clone();
|
|
555
|
-
symbol.toUnitMultiplier();
|
|
556
|
-
//depending on the complexity of the symbol it's easier to just parse it into a new symbol
|
|
557
|
-
//this should really be readdressed soon
|
|
558
|
-
b = symbol.args[0].clone();
|
|
559
|
-
b.toUnitMultiplier();
|
|
560
|
-
symbol = _.parse(inBrackets(text(symbol.args[0])) + '/abs' + inBrackets(text(b)));
|
|
561
|
-
symbol.multiplier = m;
|
|
562
|
-
break;
|
|
563
|
-
case 'parens':
|
|
564
|
-
//see product rule: f'.g goes to zero since f' will return zero. This way we only get back
|
|
565
|
-
//1*g'
|
|
566
|
-
symbol = Symbol(1);
|
|
567
|
-
break;
|
|
568
|
-
case 'cosh':
|
|
569
|
-
//cosh -> -sinh
|
|
570
|
-
symbol.fname = 'sinh';
|
|
571
|
-
break;
|
|
572
|
-
case 'sinh':
|
|
573
|
-
//sinh -> cosh
|
|
574
|
-
symbol.fname = 'cosh';
|
|
575
|
-
break;
|
|
576
|
-
case TANH:
|
|
577
|
-
//tanh -> sech^2
|
|
578
|
-
symbol.fname = SECH;
|
|
579
|
-
symbol.power = new Frac(2);
|
|
580
|
-
break;
|
|
581
|
-
case SECH:
|
|
582
|
-
// Use a clone if this gives errors
|
|
583
|
-
symbol = qdiff(symbol, '-tanh');
|
|
584
|
-
break;
|
|
585
|
-
case CSCH:
|
|
586
|
-
var arg = String(symbol.args[0]);
|
|
587
|
-
return _.parse('-coth(' + arg + ')*csch(' + arg + ')');
|
|
588
|
-
break;
|
|
589
|
-
case COTH:
|
|
590
|
-
var arg = String(symbol.args[0]);
|
|
591
|
-
return _.parse('-csch(' + arg + ')^2');
|
|
592
|
-
break;
|
|
593
|
-
case 'asinh':
|
|
594
|
-
symbol = _.parse('(sqrt(1+(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
595
|
-
break;
|
|
596
|
-
case 'acosh':
|
|
597
|
-
symbol = _.parse('(sqrt(-1+(' + text(symbol.args[0]) + ')^2))^(-1)');
|
|
598
|
-
break;
|
|
599
|
-
case 'atanh':
|
|
600
|
-
symbol = _.parse('(1-(' + text(symbol.args[0]) + ')^2)^(-1)');
|
|
601
|
-
break;
|
|
602
|
-
case ASECH:
|
|
603
|
-
var arg = String(symbol.args[0]);
|
|
604
|
-
symbol = _.parse('-1/(sqrt(1/(' + arg + ')^2-1)*(' + arg + ')^2)');
|
|
605
|
-
break;
|
|
606
|
-
case ACOTH:
|
|
607
|
-
symbol = _.parse('-1/((' + symbol.args[0] + ')^2-1)');
|
|
608
|
-
break;
|
|
609
|
-
case ACSCH:
|
|
610
|
-
var arg = String(symbol.args[0]);
|
|
611
|
-
symbol = _.parse('-1/(sqrt(1/(' + arg + ')^2+1)*(' + arg + ')^2)');
|
|
612
|
-
break;
|
|
613
|
-
case ASEC:
|
|
614
|
-
var arg = String(symbol.args[0]);
|
|
615
|
-
symbol = _.parse('1/(sqrt(1-1/(' + arg + ')^2)*(' + arg + ')^2)');
|
|
616
|
-
break;
|
|
617
|
-
case ACSC:
|
|
618
|
-
var arg = String(symbol.args[0]);
|
|
619
|
-
symbol = _.parse('-1/(sqrt(1-1/(' + arg + ')^2)*(' + arg + ')^2)');
|
|
620
|
-
break;
|
|
621
|
-
case ACOT:
|
|
622
|
-
symbol = _.parse('-1/((' + symbol.args[0] + ')^2+1)');
|
|
623
|
-
break;
|
|
624
|
-
case 'S':
|
|
625
|
-
var arg = String(symbol.args[0]);
|
|
626
|
-
symbol = _.parse('sin((pi*(' + arg + ')^2)/2)');
|
|
627
|
-
break;
|
|
628
|
-
case 'C':
|
|
629
|
-
var arg = String(symbol.args[0]);
|
|
630
|
-
symbol = _.parse('cos((pi*(' + arg + ')^2)/2)');
|
|
631
|
-
break;
|
|
632
|
-
case 'Si':
|
|
633
|
-
var arg = symbol.args[0];
|
|
634
|
-
symbol = _.parse('sin(' + arg + ')/(' + arg + ')');
|
|
635
|
-
break;
|
|
636
|
-
case 'Shi':
|
|
637
|
-
var arg = symbol.args[0];
|
|
638
|
-
symbol = _.parse('sinh(' + arg + ')/(' + arg + ')');
|
|
639
|
-
break;
|
|
640
|
-
case 'Ci':
|
|
641
|
-
var arg = symbol.args[0];
|
|
642
|
-
symbol = _.parse('cos(' + arg + ')/(' + arg + ')');
|
|
643
|
-
break;
|
|
644
|
-
case 'Chi':
|
|
645
|
-
var arg = symbol.args[0];
|
|
646
|
-
symbol = _.parse('cosh(' + arg + ')/(' + arg + ')');
|
|
647
|
-
break;
|
|
648
|
-
case 'Ei':
|
|
649
|
-
var arg = symbol.args[0];
|
|
650
|
-
symbol = _.parse('e^(' + arg + ')/(' + arg + ')');
|
|
651
|
-
break;
|
|
652
|
-
case 'Li':
|
|
653
|
-
var arg = symbol.args[0];
|
|
654
|
-
symbol = _.parse('1/' + Settings.LOG + '(' + arg + ')');
|
|
655
|
-
break;
|
|
656
|
-
case 'erf':
|
|
657
|
-
symbol = _.parse('(2*e^(-(' + symbol.args[0] + ')^2))/sqrt(pi)');
|
|
658
|
-
break;
|
|
659
|
-
case 'atan2':
|
|
660
|
-
var x_ = String(symbol.args[0]),
|
|
661
|
-
y_ = String(symbol.args[1]);
|
|
662
|
-
symbol = _.parse('(' + y_ + ')/((' + y_ + ')^2+(' + x_ + ')^2)');
|
|
663
|
-
break;
|
|
664
|
-
case 'sign':
|
|
665
|
-
symbol = new Symbol(0);
|
|
666
|
-
break;
|
|
667
|
-
case 'sinc':
|
|
668
|
-
symbol = _.parse(format('(({0})*cos({0})-sin({0}))*({0})^(-2)', symbol.args[0]));
|
|
669
|
-
break;
|
|
670
|
-
case Settings.LOG10:
|
|
671
|
-
symbol = _.parse('1/((' + symbol.args[0] + ')*' + Settings.LOG + '(10))');
|
|
672
|
-
break;
|
|
673
|
-
default:
|
|
674
|
-
symbol = _.symfunction('diff', [symbol, wrt]);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
else if(g === EX || g === FN && isSymbol(symbol.power)) {
|
|
678
|
-
var value;
|
|
679
|
-
if(g === EX) {
|
|
680
|
-
value = symbol.value;
|
|
681
|
-
}
|
|
682
|
-
else if(g === FN && symbol.contains(d)) {
|
|
683
|
-
value = symbol.fname + inBrackets(text(symbol.args[0]));
|
|
684
|
-
}
|
|
685
|
-
else {
|
|
686
|
-
value = symbol.value + inBrackets(text(symbol.args[0]));
|
|
687
|
-
}
|
|
688
|
-
a = _.multiply(_.parse(LOG + inBrackets(value)), symbol.power.clone());
|
|
689
|
-
b = __.diff(_.multiply(_.parse(LOG + inBrackets(value)), symbol.power.clone()), d);
|
|
690
|
-
symbol = _.multiply(symbol, b);
|
|
691
|
-
}
|
|
692
|
-
else if(g === FN && !symbol.power.equals(1)) {
|
|
693
|
-
b = symbol.clone();
|
|
694
|
-
b.toLinear();
|
|
695
|
-
b.toUnitMultiplier();
|
|
696
|
-
symbol = _.multiply(polydiff(symbol.clone()), derive(b));
|
|
697
|
-
}
|
|
698
|
-
else if(g === CP || g === PL) {
|
|
699
|
-
// Note: Do not use `parse` since this puts back the sqrt and causes a bug as in #610. Use clone.
|
|
700
|
-
var c = symbol.clone();
|
|
701
|
-
var result = new Symbol(0);
|
|
702
|
-
for(var x in symbol.symbols) {
|
|
703
|
-
result = _.add(result, __.diff(symbol.symbols[x].clone(), d));
|
|
704
|
-
}
|
|
705
|
-
symbol = _.multiply(polydiff(c), result);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
symbol.updateHash();
|
|
709
|
-
|
|
710
|
-
return symbol;
|
|
711
|
-
}
|
|
712
|
-
;
|
|
713
|
-
|
|
714
|
-
function qdiff(symbol, val, altVal) {
|
|
715
|
-
return _.multiply(symbol, _.parse(val + inBrackets(altVal || text(symbol.args[0]))));
|
|
716
|
-
}
|
|
717
|
-
;
|
|
718
|
-
|
|
719
|
-
function product_rule(symbol) {
|
|
720
|
-
//grab all the symbols within the CB symbol
|
|
721
|
-
var symbols = symbol.collectSymbols(),
|
|
722
|
-
result = new Symbol(0),
|
|
723
|
-
l = symbols.length;
|
|
724
|
-
//loop over all the symbols
|
|
725
|
-
for(var i = 0; i < l; i++) {
|
|
726
|
-
var df = __.diff(symbols[i].clone(), d);
|
|
727
|
-
for(var j = 0; j < l; j++) {
|
|
728
|
-
//skip the symbol of which we just pulled the derivative
|
|
729
|
-
if(i !== j) {
|
|
730
|
-
//multiply out the remaining symbols
|
|
731
|
-
df = _.multiply(df, symbols[j].clone());
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
//add the derivative to the result
|
|
735
|
-
result = _.add(result, df);
|
|
736
|
-
}
|
|
737
|
-
return result; //done
|
|
738
|
-
}
|
|
739
|
-
;
|
|
740
|
-
},
|
|
741
|
-
integration: {
|
|
742
|
-
u_substitution: function (symbols, dx) {
|
|
743
|
-
function try_combo(a, b, f) {
|
|
744
|
-
var d = __.diff(b, dx);
|
|
745
|
-
var q = f ? f(a, b) : _.divide(a.clone(), d);
|
|
746
|
-
if(!q.contains(dx, true))
|
|
747
|
-
return q;
|
|
748
|
-
return null;
|
|
749
|
-
}
|
|
750
|
-
function do_fn_sub(fname, arg) {
|
|
751
|
-
var subbed = __.integrate(_.symfunction(fname, [new Symbol(u)]), u, 0);
|
|
752
|
-
subbed = subbed.sub(new Symbol(u), arg);
|
|
753
|
-
subbed.updateHash();
|
|
754
|
-
return subbed;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
var a = symbols[0].clone(),
|
|
758
|
-
b = symbols[1].clone(),
|
|
759
|
-
g1 = a.group,
|
|
760
|
-
g2 = b.group,
|
|
761
|
-
//may cause problems if person is using this already. Will need
|
|
762
|
-
//to find algorithm for detecting conflict
|
|
763
|
-
u = '__u__',
|
|
764
|
-
Q;
|
|
765
|
-
if(g1 === FN && g2 !== FN) {
|
|
766
|
-
//e.g. 2*x*cos(x^2)
|
|
767
|
-
var arg = a.args[0];
|
|
768
|
-
Q = try_combo(b, arg.clone());
|
|
769
|
-
if(Q)
|
|
770
|
-
return _.multiply(Q, do_fn_sub(a.fname, arg));
|
|
771
|
-
Q = try_combo(b, a);
|
|
772
|
-
if(Q) {
|
|
773
|
-
return __.integration.poly_integrate(a);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
else if(g2 === FN && g1 !== FN) {
|
|
777
|
-
//e.g. 2*(x+1)*cos((x+1)^2
|
|
778
|
-
var arg = b.args[0];
|
|
779
|
-
Q = try_combo(a, arg.clone());
|
|
780
|
-
if(Q)
|
|
781
|
-
return _.multiply(Q, do_fn_sub(b.fname, arg));
|
|
782
|
-
}
|
|
783
|
-
else if(g1 === FN && g2 === FN) {
|
|
784
|
-
Q = try_combo(a.clone(), b.clone());
|
|
785
|
-
if(Q)
|
|
786
|
-
return _.multiply(__.integration.poly_integrate(b), Q);
|
|
787
|
-
Q = try_combo(b.clone(), a.clone());
|
|
788
|
-
if(Q)
|
|
789
|
-
return _.multiply(__.integration.poly_integrate(b), Q);
|
|
790
|
-
}
|
|
791
|
-
else if(g1 === EX && g2 !== EX) {
|
|
792
|
-
var p = a.power;
|
|
793
|
-
Q = try_combo(b, p.clone());
|
|
794
|
-
if(!Q) {
|
|
795
|
-
//one more try
|
|
796
|
-
var dc = __.integration.decompose_arg(p.clone(), dx);
|
|
797
|
-
//consider the possibility of a^x^(n-1)*x^n dx
|
|
798
|
-
var xp = __.diff(dc[2].clone(), dx);
|
|
799
|
-
var dc2 = __.integration.decompose_arg(xp.clone(), dx);
|
|
800
|
-
//if their powers equal, so if dx*p == b
|
|
801
|
-
if(_.multiply(dc[1], dc2[1]).power.equals(b.power)) {
|
|
802
|
-
var m = _.divide(dc[0].clone(), dc2[0].clone());
|
|
803
|
-
|
|
804
|
-
var new_val = _.multiply(m.clone(), _.pow(new Symbol(a.value), _.multiply(dc[0], new Symbol(u))));
|
|
805
|
-
new_val = _.multiply(new_val, new Symbol(u));
|
|
806
|
-
return __.integration.by_parts(new_val, u, 0, {}).sub(u, dc[1].clone());
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
}
|
|
810
|
-
var integrated = __.integrate(a.sub(p.clone(), new Symbol(u)), u, 0),
|
|
811
|
-
retval = _.multiply(integrated.sub(new Symbol(u), p), Q);
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
return retval;
|
|
815
|
-
}
|
|
816
|
-
else if(g2 === EX && g1 !== EX) {
|
|
817
|
-
var p = b.power;
|
|
818
|
-
Q = try_combo(a, p.clone());
|
|
819
|
-
var integrated = __.integrate(b.sub(p, new Symbol(u)), u, 0);
|
|
820
|
-
return _.multiply(integrated.sub(new Symbol(u), p), Q);
|
|
821
|
-
}
|
|
822
|
-
else if(a.isComposite() || b.isComposite()) {
|
|
823
|
-
var f = function (a, b) {
|
|
824
|
-
var d = __.diff(b, dx);
|
|
825
|
-
var A = core.Algebra.Factor.factor(a),
|
|
826
|
-
B = core.Algebra.Factor.factor(d);
|
|
827
|
-
var q = _.divide(A, B);
|
|
828
|
-
return q;
|
|
829
|
-
};
|
|
830
|
-
var f1 = a.isComposite() ? a.clone().toLinear() : a.clone(),
|
|
831
|
-
f2 = b.isComposite() ? b.clone().toLinear() : b.clone();
|
|
832
|
-
Q = try_combo(f1.clone(), f2.clone(), f);
|
|
833
|
-
if(Q)
|
|
834
|
-
return _.multiply(__.integration.poly_integrate(b), Q);
|
|
835
|
-
Q = try_combo(f2.clone(), f1.clone(), f);
|
|
836
|
-
if(Q)
|
|
837
|
-
return _.multiply(__.integration.poly_integrate(a), Q);
|
|
838
|
-
}
|
|
839
|
-
},
|
|
840
|
-
//simple integration of a single polynomial x^(n+1)/(n+1)
|
|
841
|
-
poly_integrate: function (x) {
|
|
842
|
-
var p = x.power.toString(),
|
|
843
|
-
m = x.multiplier.toDecimal(),
|
|
844
|
-
s = x.toUnitMultiplier().toLinear();
|
|
845
|
-
if(Number(p) === -1) {
|
|
846
|
-
return _.multiply(new Symbol(m), _.symfunction(LOG, [s]));
|
|
847
|
-
}
|
|
848
|
-
return _.parse(format('({0})*({1})^(({2})+1)/(({2})+1)', m, s, p));
|
|
849
|
-
},
|
|
850
|
-
//If we're just spinning wheels we want to stop. This is why we
|
|
851
|
-
//wrap integration in a try catch block and call this to stop.
|
|
852
|
-
stop: function (msg) {
|
|
853
|
-
msg = msg || 'Unable to compute integral!';
|
|
854
|
-
core.Utils.warn(msg);
|
|
855
|
-
throw new NoIntegralFound(msg);
|
|
856
|
-
},
|
|
857
|
-
partial_fraction: function (input, dx, depth, opt) {
|
|
858
|
-
//TODO: This whole thing needs to be rolled into one but for now I'll leave it as two separate parts
|
|
859
|
-
if(!isSymbol(dx))
|
|
860
|
-
dx = _.parse(dx);
|
|
861
|
-
|
|
862
|
-
var result, partial_fractions;
|
|
863
|
-
result = new Symbol(0);
|
|
864
|
-
partial_fractions = core.Algebra.PartFrac.partfrac(input, dx);
|
|
865
|
-
|
|
866
|
-
if(partial_fractions.group === CB && partial_fractions.isLinear()) {
|
|
867
|
-
//perform a quick check to make sure that all partial fractions are linear
|
|
868
|
-
partial_fractions.each(function (x) {
|
|
869
|
-
if(!x.isLinear())
|
|
870
|
-
__.integration.stop();
|
|
871
|
-
});
|
|
872
|
-
partial_fractions.each(function (x) {
|
|
873
|
-
result = _.add(result, __.integrate(x, dx, depth, opt));
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
result = _.add(result, __.integrate(partial_fractions, dx, depth, opt));
|
|
878
|
-
}
|
|
879
|
-
return result;
|
|
880
|
-
},
|
|
881
|
-
get_udv: function (symbol) {
|
|
882
|
-
var parts = [[/*L*/], [/*I*/], [/*A*/], [/*T*/], [/*E*/]];
|
|
883
|
-
//first we sort them
|
|
884
|
-
var setSymbol = function (x) {
|
|
885
|
-
var g = x.group;
|
|
886
|
-
if(g === FN) {
|
|
887
|
-
var fname = x.fname;
|
|
888
|
-
if(core.Utils.in_trig(fname) || core.Utils.in_htrig(fname))
|
|
889
|
-
parts[3].push(x);
|
|
890
|
-
else if(core.Utils.in_inverse_trig(fname))
|
|
891
|
-
parts[1].push(x);
|
|
892
|
-
else if(fname === LOG)
|
|
893
|
-
parts[0].push(x);
|
|
894
|
-
else {
|
|
895
|
-
__.integration.stop();
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
else if(g === S || x.isComposite() && x.isLinear() || g === CB && x.isLinear()) {
|
|
899
|
-
parts[2].push(x);
|
|
900
|
-
}
|
|
901
|
-
else if(g === EX || x.isComposite() && !x.isLinear())
|
|
902
|
-
parts[4].push(x);
|
|
903
|
-
else
|
|
904
|
-
__.integration.stop();
|
|
905
|
-
};
|
|
906
|
-
|
|
907
|
-
if(symbol.group === CB)
|
|
908
|
-
symbol.each(function (x) {
|
|
909
|
-
setSymbol(Symbol.unwrapSQRT(x, true));
|
|
910
|
-
});
|
|
911
|
-
else
|
|
912
|
-
setSymbol(symbol);
|
|
913
|
-
var u, dv = new Symbol(1);
|
|
914
|
-
//compile u and dv
|
|
915
|
-
for(var i = 0; i < 5; i++) {
|
|
916
|
-
var part = parts[i], t,
|
|
917
|
-
l = part.length;
|
|
918
|
-
if(l > 0) {
|
|
919
|
-
if(l > 1) {
|
|
920
|
-
t = new Symbol(1);
|
|
921
|
-
for(var j = 0; j < l; j++)
|
|
922
|
-
t = _.multiply(t, part[j].clone());
|
|
923
|
-
}
|
|
924
|
-
else
|
|
925
|
-
t = part[0].clone();
|
|
926
|
-
|
|
927
|
-
if(!u) {
|
|
928
|
-
u = t;//the first u encountered gets chosen
|
|
929
|
-
u.multiplier = u.multiplier.multiply(symbol.multiplier); //the first one gets the mutliplier
|
|
930
|
-
}
|
|
931
|
-
else
|
|
932
|
-
dv = _.multiply(dv, t); //everything else belongs to dv
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
return [u, dv];
|
|
937
|
-
},
|
|
938
|
-
|
|
939
|
-
trig_sub: function (symbol, dx, depth, opt, parts, symbols) {
|
|
940
|
-
parts = parts || __.integration.decompose_arg(symbol.clone().toLinear(), dx);
|
|
941
|
-
var b = parts[3],
|
|
942
|
-
ax = parts[2],
|
|
943
|
-
a = parts[0],
|
|
944
|
-
x = parts[1];
|
|
945
|
-
if(x.power.equals(2) && a.greaterThan(0)) {
|
|
946
|
-
//use tan(x)
|
|
947
|
-
var t = core.Utils.getU(symbol), //get an appropriate u
|
|
948
|
-
u = _.parse(TAN + inBrackets(t)), //u
|
|
949
|
-
du = _.parse(SEC + inBrackets(t) + '^2'), //du
|
|
950
|
-
f = _.multiply(symbol.sub(x, u), du);
|
|
951
|
-
var integral = __.integrate(f, t, depth, opt).sub(u, x);
|
|
952
|
-
core.Utils.clearU(u);
|
|
953
|
-
return integral;
|
|
954
|
-
}
|
|
955
|
-
},
|
|
956
|
-
|
|
957
|
-
by_parts: function (symbol, dx, depth, o) {
|
|
958
|
-
o.previous = o.previous || [];
|
|
959
|
-
var udv, u, dv, du, v, vdu, uv, retval, integral_vdu, m, c, vdu_s;
|
|
960
|
-
//first LIATE
|
|
961
|
-
udv = __.integration.get_udv(symbol);
|
|
962
|
-
u = udv[0];
|
|
963
|
-
dv = udv[1];
|
|
964
|
-
du = Symbol.unwrapSQRT(_.expand(__.diff(u.clone(), dx)), true);
|
|
965
|
-
c = du.clone().stripVar(dx);
|
|
966
|
-
//strip any coefficients
|
|
967
|
-
du = _.divide(du, c.clone());
|
|
968
|
-
v = __.integrate(dv.clone(), dx, depth || 0);
|
|
969
|
-
vdu = _.multiply(v.clone(), du);
|
|
970
|
-
vdu_s = vdu.toString();
|
|
971
|
-
//currently only supports e^x*(some trig)
|
|
972
|
-
if(o.previous.indexOf(vdu_s) !== -1 && (core.Utils.in_trig(u.fname)) && dv.isE()) {
|
|
973
|
-
//We're going to exploit the fact that vdu can never be constant
|
|
974
|
-
//to work out way out of this cycle. We'll return the length of
|
|
975
|
-
//the this.previous array until we're back at level one
|
|
976
|
-
o.is_cyclic = true;
|
|
977
|
-
//return the integral.
|
|
978
|
-
return new Symbol(1);
|
|
979
|
-
}
|
|
980
|
-
else
|
|
981
|
-
o.previous.push(vdu_s);
|
|
982
|
-
|
|
983
|
-
uv = _.multiply(u, v);
|
|
984
|
-
//clear the multiplier so we're dealing with a bare integral
|
|
985
|
-
m = vdu.multiplier.clone();
|
|
986
|
-
vdu.toUnitMultiplier();
|
|
987
|
-
integral_vdu = _.multiply(__.integrate(vdu.clone(), dx, depth, o), c);
|
|
988
|
-
integral_vdu.multiplier = integral_vdu.multiplier.multiply(m);
|
|
989
|
-
retval = _.subtract(uv, integral_vdu);
|
|
990
|
-
//we know that there cannot be constants so they're a holdover from a cyclic integral
|
|
991
|
-
if(o.is_cyclic) {
|
|
992
|
-
//start popping the previous stack so we know how deep in we are
|
|
993
|
-
o.previous.pop();
|
|
994
|
-
if(o.previous.length === 0) {
|
|
995
|
-
retval = _.expand(retval);
|
|
996
|
-
var rem = new Symbol(0);
|
|
997
|
-
retval.each(function (x) {
|
|
998
|
-
if(!x.contains(dx))
|
|
999
|
-
rem = _.add(rem, x.clone());
|
|
1000
|
-
});
|
|
1001
|
-
//get the actual uv
|
|
1002
|
-
retval = _.divide(_.subtract(retval, rem.clone()), _.subtract(new Symbol(1), rem));
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
return retval;
|
|
1007
|
-
},
|
|
1008
|
-
/*
|
|
1009
|
-
* dependents: [Solve, integrate]
|
|
1010
|
-
*/
|
|
1011
|
-
decompose_arg: core.Utils.decompose_fn
|
|
1012
|
-
},
|
|
1013
|
-
//TODO: nerdamer.integrate('-e^(-a*t)*sin(t)', 't') -> gives incorrect output
|
|
1014
|
-
integrate: function (original_symbol, dt, depth, opt) {
|
|
1015
|
-
//assume integration wrt independent variable if expression only has one variable
|
|
1016
|
-
if(!dt) {
|
|
1017
|
-
var vars = core.Utils.variables(original_symbol);
|
|
1018
|
-
if(vars.length === 1)
|
|
1019
|
-
dt = vars[0];
|
|
1020
|
-
//defaults to x
|
|
1021
|
-
dt = dt || 'x';
|
|
1022
|
-
}
|
|
1023
|
-
//add support for integrating vectors
|
|
1024
|
-
if(core.Utils.isVector(original_symbol)) {
|
|
1025
|
-
var vector = new core.Vector([]);
|
|
1026
|
-
original_symbol.each(function (x) {
|
|
1027
|
-
vector.elements.push(__.integrate(x, dt));
|
|
1028
|
-
});
|
|
1029
|
-
return vector;
|
|
1030
|
-
}
|
|
1031
|
-
if(!isNaN(dt))
|
|
1032
|
-
_.error('variable expected but received ' + dt);
|
|
1033
|
-
//get rid of constants right away
|
|
1034
|
-
if(original_symbol.isConstant(true))
|
|
1035
|
-
return _.multiply(original_symbol.clone(), _.parse(dt));
|
|
1036
|
-
|
|
1037
|
-
//configurations options for integral. This is needed for tracking extra options
|
|
1038
|
-
//e.g. cyclic integrals or additional settings
|
|
1039
|
-
opt = opt || {};
|
|
1040
|
-
return core.Utils.block('PARSE2NUMBER', function () {
|
|
1041
|
-
//make a note of the original symbol. Set only if undefined
|
|
1042
|
-
depth = depth || 0;
|
|
1043
|
-
var dx = isSymbol(dt) ? dt.toString() : dt,
|
|
1044
|
-
//we don't want the symbol in sqrt form. x^(1/2) is prefererred
|
|
1045
|
-
symbol = Symbol.unwrapSQRT(original_symbol.clone(), true),
|
|
1046
|
-
g = symbol.group,
|
|
1047
|
-
retval;
|
|
1048
|
-
|
|
1049
|
-
try {
|
|
1050
|
-
//We stop integration after x amount of recursive calls
|
|
1051
|
-
if(++depth > core.Settings.integration_depth)
|
|
1052
|
-
__.integration.stop('Maximum depth reached. Exiting!');
|
|
1053
|
-
|
|
1054
|
-
//constants. We first eliminate anything that doesn't have dx. Everything after this has
|
|
1055
|
-
//to have dx or else it would have been taken care of below
|
|
1056
|
-
if(!symbol.contains(dx, true)) {
|
|
1057
|
-
retval = _.multiply(symbol.clone(), _.parse(dx));
|
|
1058
|
-
}
|
|
1059
|
-
//e.g. 2*x
|
|
1060
|
-
else if(g === S) {
|
|
1061
|
-
retval = __.integration.poly_integrate(symbol, dx, depth);
|
|
1062
|
-
}
|
|
1063
|
-
else if(g === EX) {
|
|
1064
|
-
if(symbol.previousGroup === FN && !(symbol.fname === 'sqrt' || symbol.fname === Settings.PARENTHESIS))
|
|
1065
|
-
__.integration.stop();
|
|
1066
|
-
//check the base
|
|
1067
|
-
if(symbol.contains(dx) && symbol.previousGroup !== FN) {
|
|
1068
|
-
//if the symbol also contains dx then we stop since we currently
|
|
1069
|
-
//don't know what to do with it e.g. x^x
|
|
1070
|
-
if(symbol.power.contains(dx))
|
|
1071
|
-
__.integration.stop();
|
|
1072
|
-
else {
|
|
1073
|
-
var t = __.diff(symbol.clone().toLinear(), dx);
|
|
1074
|
-
if(t.contains(dx))
|
|
1075
|
-
__.integration.stop();
|
|
1076
|
-
//since at this point it's the base only then we do standard single poly integration
|
|
1077
|
-
//e.g. x^y
|
|
1078
|
-
retval = __.integration.poly_integrate(symbol, dx, depth);
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
//e.g. a^x or 9^x
|
|
1082
|
-
else {
|
|
1083
|
-
var a = __.diff(symbol.power.clone(), dx);
|
|
1084
|
-
if(a.contains(dx)) {
|
|
1085
|
-
var aa = a.stripVar(dx),
|
|
1086
|
-
x = _.divide(a.clone(), aa.clone());
|
|
1087
|
-
if(x.group === S && x.isLinear()) {
|
|
1088
|
-
aa.multiplier = aa.multiplier.divide(new Frac(2));
|
|
1089
|
-
return _.parse(format('({2})*(sqrt(pi)*erf(sqrt(-{0})*{1}))/(2*sqrt(-{0}))', aa, dx, symbol.multiplier));
|
|
1090
|
-
}
|
|
1091
|
-
else
|
|
1092
|
-
__.integration.stop();
|
|
1093
|
-
}
|
|
1094
|
-
if(symbol.isE()) {
|
|
1095
|
-
if(a.isLinear())
|
|
1096
|
-
retval = symbol;
|
|
1097
|
-
else {
|
|
1098
|
-
if(a.isE() && a.power.group === S && a.power.power.equals(1))
|
|
1099
|
-
retval = _.multiply(_.symfunction('Ei', [symbol.power.clone()]), symbol.power);
|
|
1100
|
-
else
|
|
1101
|
-
__.integration.stop();
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
else {
|
|
1105
|
-
var d = _.symfunction(LOG, [_.parse(symbol.value)]);
|
|
1106
|
-
retval = _.divide(symbol, d);
|
|
1107
|
-
}
|
|
1108
|
-
retval = _.divide(retval, a);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
else if(symbol.isComposite() && symbol.isLinear()) {
|
|
1112
|
-
var m = _.parse(symbol.multiplier);
|
|
1113
|
-
symbol.toUnitMultiplier();
|
|
1114
|
-
retval = new Symbol(0);
|
|
1115
|
-
symbol.each(function (x) {
|
|
1116
|
-
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1117
|
-
});
|
|
1118
|
-
retval = _.multiply(m, retval);
|
|
1119
|
-
}
|
|
1120
|
-
else if(g === CP) {
|
|
1121
|
-
if(symbol.power.greaterThan(1))
|
|
1122
|
-
symbol = _.expand(symbol);
|
|
1123
|
-
if(symbol.power.equals(1)) {
|
|
1124
|
-
retval = new Symbol(0);
|
|
1125
|
-
symbol.each(function (x) {
|
|
1126
|
-
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1127
|
-
}, true);
|
|
1128
|
-
}
|
|
1129
|
-
else {
|
|
1130
|
-
var p = Number(symbol.power),
|
|
1131
|
-
m = symbol.multiplier.clone();//temporarily remove the multiplier
|
|
1132
|
-
symbol.toUnitMultiplier();
|
|
1133
|
-
var //below we consider the form ax+b
|
|
1134
|
-
fn = symbol.clone().toLinear(), //get just the pure function without the power
|
|
1135
|
-
decomp = __.integration.decompose_arg(fn, dx),
|
|
1136
|
-
//I have no idea why I used bx+a and not ax+b. TODO change this to something that makes sense
|
|
1137
|
-
b = decomp[3],
|
|
1138
|
-
ax = decomp[2],
|
|
1139
|
-
a = decomp[0],
|
|
1140
|
-
x = decomp[1];
|
|
1141
|
-
if(p === -1 && x.group !== PL && x.power.equals(2)) {
|
|
1142
|
-
var b_is_positive = isInt(b) ? b > 0 : true;
|
|
1143
|
-
//we can now check for atan
|
|
1144
|
-
if(x.group === S && x.power.equals(2) && b_is_positive) {
|
|
1145
|
-
////then we have atan
|
|
1146
|
-
//abs is redundants since the sign appears in both denom and num.
|
|
1147
|
-
var unwrapAbs = function (s) {
|
|
1148
|
-
var result = new Symbol(1);
|
|
1149
|
-
s.each(function (x) {
|
|
1150
|
-
result = _.multiply(result, x.fname === 'abs' ? x.args[0] : x);
|
|
1151
|
-
});
|
|
1152
|
-
return result;
|
|
1153
|
-
};
|
|
1154
|
-
var A = a.clone(),
|
|
1155
|
-
B = b.clone();
|
|
1156
|
-
A = _.pow(A, new Symbol(1 / 2));
|
|
1157
|
-
B = _.pow(B, new Symbol(1 / 2));
|
|
1158
|
-
//unwrap abs
|
|
1159
|
-
|
|
1160
|
-
var d = _.multiply(unwrapAbs(B), unwrapAbs(A)),
|
|
1161
|
-
f = _.symfunction(ATAN, [_.divide(_.multiply(a, x.toLinear()), d.clone())]);
|
|
1162
|
-
retval = _.divide(f, d);
|
|
1163
|
-
}
|
|
1164
|
-
else if(x.group === S && x.isLinear()) {
|
|
1165
|
-
retval = _.divide(__.integration.poly_integrate(symbol), a);
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
//1/(x^4+1)
|
|
1169
|
-
if(x.power.equals(4)) {
|
|
1170
|
-
//https://www.freemathhelp.com/forum/threads/55678-difficult-integration-int-1-(1-x-4)-dx
|
|
1171
|
-
var A, B, C, D, E, F, f1, f2, f3, f4, L1, L2;
|
|
1172
|
-
var br = inBrackets;
|
|
1173
|
-
//apply rule: ax^4+b = (√ax^2+√2∜a∜bx+√b)(√ax^2-√2∜a∜bx+√b)
|
|
1174
|
-
//get quadratic factors
|
|
1175
|
-
A = _.parse(SQRT + br(a) + '*' + dx + '^2');
|
|
1176
|
-
B = _.parse(SQRT + br(2) + '*' + br(a) + '^' + br('1/4') + '*' + br(b) + '^' + br('1/4') + '*' + dx);
|
|
1177
|
-
C = _.parse(SQRT + br(b));
|
|
1178
|
-
f1 = _.add(_.add(A.clone(), B.clone()), C.clone());
|
|
1179
|
-
f2 = _.add(_.subtract(A, B), C);
|
|
1180
|
-
//calculate numerators: [D+E, D-E] -> [√2*b^(3/4)+√b∜ax, √2*b^(3/4)-√b∜ax]
|
|
1181
|
-
D = _.parse(SQRT + br(2) + '*' + br(b) + '^' + br('3/4'));
|
|
1182
|
-
E = _.parse(SQRT + br(b) + '*' + br(b) + '^' + br('1/4') + '*' + dx);
|
|
1183
|
-
//let F = 2b√2∜b
|
|
1184
|
-
F = _.parse(2 + '*' + br(b) + '*' + SQRT + br(2) + '*' + br(b) + '^' + br('1/4'));
|
|
1185
|
-
//calculate the factors
|
|
1186
|
-
L1 = _.divide(_.subtract(D.clone(), E.clone()), _.multiply(F.clone(), f2));
|
|
1187
|
-
L2 = _.divide(_.add(D, E), _.multiply(F, f1.clone()));
|
|
1188
|
-
retval = _.add(
|
|
1189
|
-
__.integrate(L1, dx, depth, opt),
|
|
1190
|
-
__.integrate(L2, dx, depth, opt)
|
|
1191
|
-
);
|
|
1192
|
-
}
|
|
1193
|
-
else
|
|
1194
|
-
//let's try partial fractions
|
|
1195
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
else if(p === -1 / 2) {
|
|
1199
|
-
//detect asin and atan
|
|
1200
|
-
if(x.group === S && x.power.equals(2)) {
|
|
1201
|
-
if(ax.multiplier.lessThan(0) && !b.multiplier.lessThan(0)) {
|
|
1202
|
-
a.negate();
|
|
1203
|
-
//it's asin
|
|
1204
|
-
if(b.isConstant() && a.isConstant()) {
|
|
1205
|
-
var d = _.symfunction(SQRT, [a.clone()]),
|
|
1206
|
-
d2 = _.symfunction(SQRT, [_.multiply(a.clone(), b)]);
|
|
1207
|
-
retval = _.divide(_.symfunction(ASIN, [_.divide(ax.toLinear(), d2)]), d);
|
|
1208
|
-
}
|
|
1209
|
-
//I'm not sure about this one. I'm trusting Wolfram Alpha here
|
|
1210
|
-
else {
|
|
1211
|
-
var sqrt_a = _.symfunction(SQRT, [a]),
|
|
1212
|
-
sqrt_ax = _.multiply(sqrt_a.clone(), x.clone().toLinear());
|
|
1213
|
-
retval = _.divide(_.symfunction(ATAN, [_.divide(sqrt_ax, _.symfunction(SQRT, [fn.clone()]))]), sqrt_a);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
else {
|
|
1217
|
-
/*WHAT HAPPENS HERE???? e.g. integrate(3/sqrt(-a+b*x^2),x) or integrate(3/sqrt(a+b*x^2),x)*/
|
|
1218
|
-
__.integration.stop();
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
else {
|
|
1222
|
-
//This would be a case like 1/(sqrt(1-x^3) or 1/(1-(x+1)^2)
|
|
1223
|
-
__.integration.stop();
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
else if(p === 1/2 && x.power.equals(2) && a.greaterThan(0)) {
|
|
1227
|
-
// TODO: Revisit
|
|
1228
|
-
__.integration.stop();
|
|
1229
|
-
}
|
|
1230
|
-
else {
|
|
1231
|
-
if(x.isLinear() && x.group !== PL)
|
|
1232
|
-
retval = _.divide(__.integration.poly_integrate(symbol), a);
|
|
1233
|
-
else if(x.power.equals(2) && a.greaterThan(0)) {
|
|
1234
|
-
var sqa, sqb, aob, bsqi, n, integral, u, v, uv;
|
|
1235
|
-
//1/(a*x^2+b^2)^n
|
|
1236
|
-
//strip the value of b so b = 1
|
|
1237
|
-
sqa = _.parse(SQRT + inBrackets(a)); //strip a so b = 1
|
|
1238
|
-
sqb = _.parse(SQRT + inBrackets(b));
|
|
1239
|
-
aob = _.multiply(sqa.clone(), sqb.clone()).invert();
|
|
1240
|
-
bsqi = _.pow(b, new Symbol(symbol.power));
|
|
1241
|
-
uv = core.Utils.getU(symbol);
|
|
1242
|
-
u = _.multiply(aob, x.clone().toLinear());
|
|
1243
|
-
v = _.parse(ATAN + inBrackets(u));
|
|
1244
|
-
//the conversion will be 1+tan(x)^2 -> sec(x)^2
|
|
1245
|
-
//since the denominator is now (sec(x)^2)^n and the numerator is sec(x)^2
|
|
1246
|
-
//then the remaining sec will be (n-1)*2;
|
|
1247
|
-
var n = (Math.abs(symbol.power) - 1) * 2;
|
|
1248
|
-
//1/sec(x)^n can now be converted to cos(x)^n and we can pull the integral of that
|
|
1249
|
-
var integral = __.integrate(_.parse(COS + inBrackets(uv) + '^' + n));
|
|
1250
|
-
core.Utils.clearU(uv);
|
|
1251
|
-
return _.multiply(integral.sub(uv, v), bsqi);
|
|
1252
|
-
}
|
|
1253
|
-
else {
|
|
1254
|
-
if(symbol.group !== CB && !symbol.power.lessThan(0)) {
|
|
1255
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1256
|
-
}
|
|
1257
|
-
else {
|
|
1258
|
-
var f = symbol.clone().toLinear();
|
|
1259
|
-
var factored = core.Algebra.Factor.factor(f);
|
|
1260
|
-
var was_factored = factored.toString() !== f.toString();
|
|
1261
|
-
if(core.Algebra.degree(f, _.parse(dx)).equals(2) && !was_factored) {
|
|
1262
|
-
try {
|
|
1263
|
-
var f1, fx, u, sq;
|
|
1264
|
-
sq = core.Algebra.sqComplete(f, dx);
|
|
1265
|
-
u = core.Utils.getU(f);
|
|
1266
|
-
f1 = sq.f.sub(sq.a, u);
|
|
1267
|
-
fx = _.pow(f1, _.parse(symbol.power));
|
|
1268
|
-
retval = __.integrate(fx, u).sub(u, sq.a);
|
|
1269
|
-
}
|
|
1270
|
-
catch(e) {
|
|
1271
|
-
__.integration.stop();
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
else
|
|
1275
|
-
retval = __.integration.partial_fraction(symbol, dx, depth, opt);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
retval.multiplier = retval.multiplier.multiply(m);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
else if(g === FN) {
|
|
1283
|
-
var arg = symbol.args[0],
|
|
1284
|
-
m = symbol.multiplier.clone();
|
|
1285
|
-
symbol.toUnitMultiplier();
|
|
1286
|
-
var decomp = __.integration.decompose_arg(arg, dx);
|
|
1287
|
-
//easies way I can think of to get the coefficient and to make sure
|
|
1288
|
-
//that the symbol is linear wrt dx. I'm not actually trying to get the
|
|
1289
|
-
//derivative
|
|
1290
|
-
var a = decomp[0],
|
|
1291
|
-
x = decomp[1],
|
|
1292
|
-
fname = symbol.fname;
|
|
1293
|
-
//log is a special case that can be handled with integration by parts
|
|
1294
|
-
if(fname === LOG || (fname === ASIN || fname === ACOS || fname === ATAN && x.isLinear())) {
|
|
1295
|
-
/*integration by parts */
|
|
1296
|
-
var p = symbol.power.toString();
|
|
1297
|
-
if(isInt(p))
|
|
1298
|
-
depth = depth - p; //it needs more room to find the integral
|
|
1299
|
-
|
|
1300
|
-
if(!arg.isComposite())
|
|
1301
|
-
retval = _.multiply(_.parse(m), __.integration.by_parts(symbol, dx, depth, opt));
|
|
1302
|
-
else {
|
|
1303
|
-
//integral u du
|
|
1304
|
-
var u = core.Utils.getU(symbol);
|
|
1305
|
-
var f = _.pow(_.parse(LOG + inBrackets(u)), new Symbol(p));
|
|
1306
|
-
var du = __.diff(arg, dx);
|
|
1307
|
-
var u_du = _.multiply(f, du);
|
|
1308
|
-
var integral = __.integrate(u_du, u, depth, opt);
|
|
1309
|
-
retval = _.multiply(_.parse(m), integral.sub(u, arg));
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
}
|
|
1313
|
-
else if(fname === TAN && symbol.power.lessThan(0)) {
|
|
1314
|
-
//convert to cotangent
|
|
1315
|
-
var sym = symbol.clone();
|
|
1316
|
-
sym.power.negate();
|
|
1317
|
-
sym.fname = COT;
|
|
1318
|
-
return _.multiply(_.parse(m), __.integrate(sym, dx, depth));
|
|
1319
|
-
}
|
|
1320
|
-
else {
|
|
1321
|
-
if(!a.contains(dx, true) && symbol.isLinear()) { //perform a deep search for safety
|
|
1322
|
-
//first handle the special cases
|
|
1323
|
-
if(fname === ABS) {
|
|
1324
|
-
//REVISIT **TODO**
|
|
1325
|
-
var x = _.divide(arg.clone(), a.clone());
|
|
1326
|
-
if(x.group === S && !x.power.lessThan(0)) {
|
|
1327
|
-
if(core.Utils.even(x.power)) {
|
|
1328
|
-
retval = __.integrate(arg, dx, depth);
|
|
1329
|
-
}
|
|
1330
|
-
else {
|
|
1331
|
-
var integrated = __.integrate(x, dx, depth);
|
|
1332
|
-
integrated.power = integrated.power.subtract(new Frac(1));
|
|
1333
|
-
retval = _.multiply(_.multiply(_.symfunction(ABS, [x.toLinear()]), integrated), a);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
else
|
|
1337
|
-
__.integration.stop();
|
|
1338
|
-
}
|
|
1339
|
-
else {
|
|
1340
|
-
var ag = symbol.args[0].group,
|
|
1341
|
-
decomposed = __.integration.decompose_arg(arg, dx);
|
|
1342
|
-
|
|
1343
|
-
if(!(ag === CP || ag === S || ag === CB) || !decomposed[1].power.equals(1) || arg.hasFunc())
|
|
1344
|
-
__.integration.stop();
|
|
1345
|
-
/**TODO**/ //ASIN, ACOS, ATAN
|
|
1346
|
-
switch(fname) {
|
|
1347
|
-
case COS:
|
|
1348
|
-
retval = _.symfunction(SIN, [arg]);
|
|
1349
|
-
break;
|
|
1350
|
-
case SIN:
|
|
1351
|
-
retval = _.symfunction(COS, [arg]);
|
|
1352
|
-
retval.negate();
|
|
1353
|
-
break;
|
|
1354
|
-
case TAN:
|
|
1355
|
-
retval = _.parse(format(Settings.LOG + '(sec({0}))', arg));
|
|
1356
|
-
break;
|
|
1357
|
-
case SEC:
|
|
1358
|
-
retval = _.parse(format(Settings.LOG + '(tan({0})+sec({0}))', arg));
|
|
1359
|
-
break;
|
|
1360
|
-
case CSC:
|
|
1361
|
-
retval = _.parse(format('-' + Settings.LOG + '(csc({0})+cot({0}))', arg));
|
|
1362
|
-
break;
|
|
1363
|
-
case COT:
|
|
1364
|
-
retval = _.parse(format(Settings.LOG + '(sin({0}))', arg));
|
|
1365
|
-
break;
|
|
1366
|
-
case SINH:
|
|
1367
|
-
retval = _.symfunction(COSH, [arg]);
|
|
1368
|
-
break;
|
|
1369
|
-
case COSH:
|
|
1370
|
-
retval = _.symfunction(SINH, [arg]);
|
|
1371
|
-
break;
|
|
1372
|
-
case TANH:
|
|
1373
|
-
retval = _.parse(format(Settings.LOG + '(cosh({0}))', arg));
|
|
1374
|
-
break;
|
|
1375
|
-
case ASEC:
|
|
1376
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1377
|
-
break;
|
|
1378
|
-
case ACSC:
|
|
1379
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1380
|
-
break;
|
|
1381
|
-
case ACOT:
|
|
1382
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1383
|
-
break;
|
|
1384
|
-
//inverse htrig
|
|
1385
|
-
case ASECH:
|
|
1386
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1387
|
-
break;
|
|
1388
|
-
case ACSCH:
|
|
1389
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1390
|
-
break;
|
|
1391
|
-
case ACOTH:
|
|
1392
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1393
|
-
break;
|
|
1394
|
-
//end inverse htrig
|
|
1395
|
-
//htrigh
|
|
1396
|
-
case SECH:
|
|
1397
|
-
retval = _.parse(format('atan(sinh({0}))', arg));
|
|
1398
|
-
break;
|
|
1399
|
-
case CSCH:
|
|
1400
|
-
retval = _.parse(format(Settings.LOG + '(tanh(({0})/2))', arg));
|
|
1401
|
-
break;
|
|
1402
|
-
case COTH:
|
|
1403
|
-
retval = _.parse(format(Settings.LOG + '(sinh({0}))', arg));
|
|
1404
|
-
break;
|
|
1405
|
-
//end htrig
|
|
1406
|
-
case EXP:
|
|
1407
|
-
retval = __.integrate(_.parse(format('e^({0})', arg)), dx, depth);
|
|
1408
|
-
break;
|
|
1409
|
-
case 'S':
|
|
1410
|
-
var arg = symbol.args[0].clone(),
|
|
1411
|
-
dc = __.integration.decompose_arg(arg, dx),
|
|
1412
|
-
x_ = dc[1],
|
|
1413
|
-
a_ = dc[0];
|
|
1414
|
-
var b_ = dc[3];
|
|
1415
|
-
retval = _.parse(format('(cos((1/2)*pi*(({1})+({0})*({2}))^2)+pi*(({1})+({0})*({2}))*S(({1})+({0})*({2})))/(({0})*pi)', a_, b_, x));
|
|
1416
|
-
break;
|
|
1417
|
-
case 'C':
|
|
1418
|
-
var arg = symbol.args[0].clone(),
|
|
1419
|
-
dc = __.integration.decompose_arg(arg, dx),
|
|
1420
|
-
x_ = dc[1],
|
|
1421
|
-
a_ = dc[0];
|
|
1422
|
-
var b_ = dc[3];
|
|
1423
|
-
retval = _.parse(format('(pi*(({1})+({0})*({2}))*C(({1})+({0})*({2}))-sin((1/2)*pi*(({1})+({0})*({2}))^2))/(({0})*pi)', a_, b_, x_));
|
|
1424
|
-
break;
|
|
1425
|
-
case 'erf':
|
|
1426
|
-
var arg = symbol.args[0].clone(),
|
|
1427
|
-
dc = __.integration.decompose_arg(arg, dx),
|
|
1428
|
-
x_ = dc[1],
|
|
1429
|
-
a_ = dc[0];
|
|
1430
|
-
retval = _.parse(format('e^(-(({2}))^2)/(({0})*sqrt(pi))+(1/({0})+({1}))*erf(({2}))', a_, x_, arg));
|
|
1431
|
-
break;
|
|
1432
|
-
case 'sign':
|
|
1433
|
-
retval = _.multiply(symbol.clone(), arg.clone());
|
|
1434
|
-
break;
|
|
1435
|
-
default:
|
|
1436
|
-
__.integration.stop();
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
retval = _.divide(retval, a);
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
else if(x.isLinear()) {
|
|
1443
|
-
if(fname === COS || fname === SIN) {
|
|
1444
|
-
var p = Number(symbol.power);
|
|
1445
|
-
//check to see if it's negative and then just transform it to sec or csc
|
|
1446
|
-
if(p < 0) {
|
|
1447
|
-
symbol.fname = fname === SIN ? CSC : SEC;
|
|
1448
|
-
symbol.invert().updateHash();
|
|
1449
|
-
retval = __.integrate(symbol, dx, depth);
|
|
1450
|
-
}
|
|
1451
|
-
else {
|
|
1452
|
-
var arg = symbol.args[0],
|
|
1453
|
-
rd = symbol.clone(), //cos^(n-1)
|
|
1454
|
-
rd2 = symbol.clone(), //cos^(n-2)
|
|
1455
|
-
q = new Symbol((p - 1) / p), //
|
|
1456
|
-
na = _.multiply(a.clone(), new Symbol(p)).invert(); //1/(n*a)
|
|
1457
|
-
rd.power = rd.power.subtract(new Frac(1));
|
|
1458
|
-
rd2.power = rd2.power.subtract(new Frac(2));
|
|
1459
|
-
|
|
1460
|
-
var t = _.symfunction(fname === COS ? SIN : COS, [arg.clone()]);
|
|
1461
|
-
if(fname === SIN)
|
|
1462
|
-
t.negate();
|
|
1463
|
-
retval = _.add(_.multiply(_.multiply(na, rd), t), _.multiply(q, __.integrate(_.parse(rd2), dx, depth)));
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
//tan(x)^n or cot(x)^n
|
|
1467
|
-
else if(fname === TAN || fname === COT) {
|
|
1468
|
-
//http://www.sosmath.com/calculus/integration/moretrigpower/moretrigpower.html
|
|
1469
|
-
if(symbol.args[0].isLinear(dx)) {
|
|
1470
|
-
var n = symbol.power.subtract(new Frac(1)).toString(),
|
|
1471
|
-
r = symbol.clone().toUnitMultiplier(),
|
|
1472
|
-
w = _.parse(format((fname === COT ? '-' : '') + '1/({2}*{0})*{3}({1})^({0})', n, arg, a, fname));
|
|
1473
|
-
r.power = r.power.subtract(new Frac(2));
|
|
1474
|
-
if(r.power.equals(0))
|
|
1475
|
-
r = _.parse(r);
|
|
1476
|
-
retval = _.subtract(w, __.integrate(r, dx, depth));
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
//sec(x)^n or csc(x)^n
|
|
1480
|
-
else if(fname === SEC || fname === CSC) {
|
|
1481
|
-
//http://www.sosmath.com/calculus/integration/moretrigpower/moretrigpower.html
|
|
1482
|
-
var n1 = symbol.power.subtract(new Frac(1)).toString(),
|
|
1483
|
-
n2 = symbol.power.subtract(new Frac(2)).toString(),
|
|
1484
|
-
f2 = fname === SEC ? TAN : COT,
|
|
1485
|
-
r = symbol.clone().toUnitMultiplier(),
|
|
1486
|
-
parse_str = format((fname === CSC ? '-' : '') + '1/({0}*{1})*{4}({3})^({2})*{5}({3})', a, n1, n2, arg, fname, f2),
|
|
1487
|
-
w = _.parse(parse_str);
|
|
1488
|
-
r.power = r.power.subtract(new Frac(2));
|
|
1489
|
-
if(r.power.equals(0))
|
|
1490
|
-
r = _.parse(r);
|
|
1491
|
-
retval = _.add(w, _.multiply(new Symbol(n2 / n1), __.integrate(r, dx, depth)));
|
|
1492
|
-
}
|
|
1493
|
-
else if((fname === COSH || fname === SINH) && symbol.power.equals(2)) {
|
|
1494
|
-
retval = __.integrate(symbol.fnTransform(), dx, depth);
|
|
1495
|
-
}
|
|
1496
|
-
else
|
|
1497
|
-
__.integration.stop();
|
|
1498
|
-
}
|
|
1499
|
-
else
|
|
1500
|
-
__.integration.stop();
|
|
1501
|
-
|
|
1502
|
-
retval.multiplier = retval.multiplier.multiply(m);
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
else if(g === PL) {
|
|
1506
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1507
|
-
}
|
|
1508
|
-
else if(g === CB) {
|
|
1509
|
-
var den = symbol.getDenom();
|
|
1510
|
-
if(den.group === S)
|
|
1511
|
-
symbol = _.expand(symbol);
|
|
1512
|
-
|
|
1513
|
-
//separate the coefficient since all we care about are symbols containing dx
|
|
1514
|
-
var coeff = symbol.stripVar(dx);
|
|
1515
|
-
//now get only those that apply
|
|
1516
|
-
var cfsymbol = _.divide(symbol.clone(), coeff.clone()); //a coeff free symbol
|
|
1517
|
-
//peform a correction for stripVar. This is a serious TODO!
|
|
1518
|
-
if(coeff.contains(dx)) {
|
|
1519
|
-
cfsymbol = _.multiply(cfsymbol, coeff);
|
|
1520
|
-
coeff = new Symbol(1);
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
//if we only have one symbol left then let's not waste time. Just pull the integral
|
|
1524
|
-
//and let the chips fall where they may
|
|
1525
|
-
if(cfsymbol.group !== CB) {
|
|
1526
|
-
if(cfsymbol.equals(1)) {
|
|
1527
|
-
return __.integrate(_.expand(symbol), dx, depth);
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
//only factor for multivariate which are polynomials
|
|
1531
|
-
if(cfsymbol.clone().toLinear().isPoly(true) && core.Utils.variables(cfsymbol).length > 1) {
|
|
1532
|
-
cfsymbol = core.Algebra.Factor.factor(cfsymbol);
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
retval = __.integrate(cfsymbol, dx, depth);
|
|
1536
|
-
}
|
|
1537
|
-
else {
|
|
1538
|
-
//we collect the symbols and sort them descending group, descending power, descending alpabethically
|
|
1539
|
-
var symbols = cfsymbol.collectSymbols().sort(function (a, b) {
|
|
1540
|
-
if(a.group === b.group) {
|
|
1541
|
-
if(Number(a.power) === Number(b.power))
|
|
1542
|
-
if(a < b)
|
|
1543
|
-
return 1; //I want sin first
|
|
1544
|
-
else
|
|
1545
|
-
return -1;
|
|
1546
|
-
return b.power - a.power; //descending power
|
|
1547
|
-
}
|
|
1548
|
-
return b.group - a.group; //descending groups
|
|
1549
|
-
}).map(function (x) {
|
|
1550
|
-
var unwrapped = Symbol.unwrapSQRT(x, true);
|
|
1551
|
-
if(unwrapped.fname === EXP) {
|
|
1552
|
-
return _.parse(format('({1})*e^({0})', unwrapped.args[0], unwrapped.multiplier));
|
|
1553
|
-
}
|
|
1554
|
-
return unwrapped;
|
|
1555
|
-
});
|
|
1556
|
-
var l = symbols.length;
|
|
1557
|
-
if(symbol.power < 0) {
|
|
1558
|
-
if(l === 2) {
|
|
1559
|
-
return __.integrate(_.expand(symbol), dx, depth, opt);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
//otherwise the denominator is one lumped together symbol
|
|
1563
|
-
else {
|
|
1564
|
-
//generate an image for
|
|
1565
|
-
if(l === 2) {
|
|
1566
|
-
//try u substitution
|
|
1567
|
-
try {
|
|
1568
|
-
retval = __.integration.u_substitution(symbols, dx);
|
|
1569
|
-
}
|
|
1570
|
-
catch(e) {/* failed :`(*/
|
|
1571
|
-
;
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
if(!retval) {
|
|
1575
|
-
//no success with u substitution so let's try known combinations
|
|
1576
|
-
//are they two functions
|
|
1577
|
-
var g1 = symbols[0].group,
|
|
1578
|
-
g2 = symbols[1].group,
|
|
1579
|
-
sym1 = symbols[0],
|
|
1580
|
-
sym2 = symbols[1],
|
|
1581
|
-
fn1 = sym1.fname,
|
|
1582
|
-
fn2 = sym2.fname;
|
|
1583
|
-
//reset the symbol minus the coeff
|
|
1584
|
-
symbol = _.multiply(sym1.clone(), sym2.clone());
|
|
1585
|
-
if(g1 === FN && g2 === FN) {
|
|
1586
|
-
if(fn1 === LOG || fn2 === LOG) {
|
|
1587
|
-
retval = __.integration.by_parts(symbol.clone(), dx, depth, opt);
|
|
1588
|
-
}
|
|
1589
|
-
else {
|
|
1590
|
-
symbols.sort(function (a, b) {
|
|
1591
|
-
return b.fname > a.fname;
|
|
1592
|
-
});
|
|
1593
|
-
var arg1 = sym1.args[0];
|
|
1594
|
-
//make sure the arguments are suitable. We don't know how to integrate non-linear arguments
|
|
1595
|
-
if(!arg1.isLinear() || !(arg1.group === CP || arg1.group === CB || arg1.group === S))
|
|
1596
|
-
__.integration.stop();
|
|
1597
|
-
|
|
1598
|
-
var decomp = __.integration.decompose_arg(arg1, dx);
|
|
1599
|
-
x = decomp[1],
|
|
1600
|
-
a = decomp[0];
|
|
1601
|
-
if(!x.isLinear()) //again... linear arguments only wrt x
|
|
1602
|
-
__.integration.stop();
|
|
1603
|
-
|
|
1604
|
-
//they have to have the same arguments and then we have cleared all the check to
|
|
1605
|
-
//make sure we can integrate FN & FN
|
|
1606
|
-
var arg2 = sym2.args[0];
|
|
1607
|
-
//make sure that their argument matches
|
|
1608
|
-
if(arg1.equals(arg2)) {
|
|
1609
|
-
if(fn1 === SIN && fn2 === COS || fn1 === COS && fn2 === SIN) {
|
|
1610
|
-
if(sym1.power.lessThan(0))
|
|
1611
|
-
__.integration.stop();//we don't know how to handle, sin(x)^n/cos(x)^m where m > n, yet
|
|
1612
|
-
//if it's in the form sin(x)^n*cos(x)^n then we can just return tan(x)^n which we know how to integrate
|
|
1613
|
-
if(fn1 === SIN && sym1.power.add(sym2.power).equals(0)) {
|
|
1614
|
-
sym1.fname = TAN;
|
|
1615
|
-
sym1.updateHash();
|
|
1616
|
-
retval = __.integrate(sym1, dx, depth);
|
|
1617
|
-
}
|
|
1618
|
-
else {
|
|
1619
|
-
if(even(sym1.power) && fn2 === COS && sym2.power.lessThan(0)) {
|
|
1620
|
-
//transform sin^(2*n) to (1-cos^2)^n
|
|
1621
|
-
var n = Number(sym1.power) / 2,
|
|
1622
|
-
new_sym = _.parse(format('(1-cos({0})^2)^({1})', sym1.args[0], n));
|
|
1623
|
-
retval = __.integrate(_.expand(_.multiply(new_sym, sym2.clone())), dx, depth, opt);
|
|
1624
|
-
}
|
|
1625
|
-
else if(even(sym1.power) && fn2 === SIN && sym2.power.lessThan(0)) {
|
|
1626
|
-
//transform cos^(2*n) to (1-sin^2)^n
|
|
1627
|
-
var n = Number(sym1.power) / 2,
|
|
1628
|
-
new_sym = _.parse(format('(1-sin({0})^2)^({1})', sym1.args[0], n));
|
|
1629
|
-
retval = __.integrate(_.expand(_.multiply(new_sym, sym2.clone())), dx, depth, opt);
|
|
1630
|
-
}
|
|
1631
|
-
else {
|
|
1632
|
-
var p1_even = core.Utils.even(sym1.power),
|
|
1633
|
-
p2_even = core.Utils.even(sym2.power);
|
|
1634
|
-
retval = new Symbol(0);
|
|
1635
|
-
if(!p1_even || !p2_even) {
|
|
1636
|
-
var u, r, trans;
|
|
1637
|
-
//since cos(x) is odd it carries du. If sin was odd then it would be the other way around
|
|
1638
|
-
//know that p1 satifies the odd portion in this case. If p2 did than it would contain r
|
|
1639
|
-
if(!p1_even) {
|
|
1640
|
-
//u = sin(x)
|
|
1641
|
-
u = sym2;
|
|
1642
|
-
r = sym1;
|
|
1643
|
-
}
|
|
1644
|
-
else {
|
|
1645
|
-
u = sym1;
|
|
1646
|
-
r = sym2;
|
|
1647
|
-
}
|
|
1648
|
-
//get the sign of du. In this case r carries du as stated before and D(cos(x),x) = -sin(x)
|
|
1649
|
-
var sign = u.fname === COS ? -1 : 1,
|
|
1650
|
-
n = r.power,
|
|
1651
|
-
//remove the du e.g. cos(x)^2*sin(x)^3 dx -> cos(x)^2*sin(x)^2*sin(x). We're left with two
|
|
1652
|
-
//even powers afterwards which can be transformed
|
|
1653
|
-
k = (n - 1) / 2,
|
|
1654
|
-
//make the transformation cos(x)^2 = 1 - sin(x)^2
|
|
1655
|
-
trans = _.parse('(1-' + u.fname + core.Utils.inBrackets(arg1) + '^2)^' + k),
|
|
1656
|
-
sym = _.expand(_.multiply(new Symbol(sign), _.multiply(u.clone(), trans)));
|
|
1657
|
-
//we can now just loop through and integrate each since it's now just a polynomial with functions
|
|
1658
|
-
sym.each(function (x) {
|
|
1659
|
-
retval = _.add(retval, __.integration.poly_integrate(x.clone()));
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
else {
|
|
1663
|
-
//performs double angle transformation
|
|
1664
|
-
var double_angle = function (symbol) {
|
|
1665
|
-
var p = symbol.power,
|
|
1666
|
-
k = p / 2, e;
|
|
1667
|
-
if(symbol.fname === COS)
|
|
1668
|
-
e = '((1/2)+(cos(2*(' + symbol.args[0] + '))/2))^' + k;
|
|
1669
|
-
else
|
|
1670
|
-
e = '((1/2)-(cos(2*(' + symbol.args[0] + '))/2))^' + k;
|
|
1671
|
-
|
|
1672
|
-
return _.parse(e);
|
|
1673
|
-
};
|
|
1674
|
-
//they're both even so transform both using double angle identities and we'll just
|
|
1675
|
-
//be able to integrate by the sum of integrals
|
|
1676
|
-
var a = double_angle(sym1),
|
|
1677
|
-
b = double_angle(sym2),
|
|
1678
|
-
t = _.multiply(a, b);
|
|
1679
|
-
var sym = _.expand(t);
|
|
1680
|
-
sym.each(function (x) {
|
|
1681
|
-
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
1682
|
-
});
|
|
1683
|
-
return _.multiply(retval, coeff);
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
//tan(x)*sec(x)^n
|
|
1689
|
-
else if(fn1 === SEC && fn2 === TAN && x.isLinear() && sym2.isLinear()) {
|
|
1690
|
-
retval = _.parse(format('sec({0})^({1})/({1})', sym1.args[0], sym1.power));
|
|
1691
|
-
}
|
|
1692
|
-
else if(fn1 === TAN && fn2 === SEC && x.isLinear()) {
|
|
1693
|
-
//remaining: tan(x)^3*sec(x)^6
|
|
1694
|
-
if(sym1.isLinear() && sym2.isLinear()) {
|
|
1695
|
-
retval = _.divide(_.symfunction(SEC, [arg1.clone()]), a);
|
|
1696
|
-
}
|
|
1697
|
-
else if(even(sym1.power)) {
|
|
1698
|
-
var p = Number(sym1.power) / 2;
|
|
1699
|
-
//transform tangent
|
|
1700
|
-
var t = _.parse(format('(sec({0})^2-1)^({1})', sym1.args[0], p));
|
|
1701
|
-
retval = __.integrate(_.expand(_.multiply(t, sym2)), dx, depth);
|
|
1702
|
-
}
|
|
1703
|
-
else
|
|
1704
|
-
__.integration.stop();
|
|
1705
|
-
}
|
|
1706
|
-
else if(fn1 === SEC && fn2 === COS) {
|
|
1707
|
-
sym1.fname = COS;
|
|
1708
|
-
sym1.invert().updateHash();
|
|
1709
|
-
retval = __.integrate(_.multiply(sym1, sym2), dx, depth);
|
|
1710
|
-
}
|
|
1711
|
-
else if(fn1 === SIN && fn2 === CSC) {
|
|
1712
|
-
sym2.fname = SIN;
|
|
1713
|
-
sym2.invert().updateHash();
|
|
1714
|
-
retval = __.integrate(_.multiply(sym1, sym2), dx, depth);
|
|
1715
|
-
}
|
|
1716
|
-
//tan/cos
|
|
1717
|
-
else if(fn1 === TAN && (fn2 === COS || fn2 === SIN) && sym2.power.lessThan(0)) {
|
|
1718
|
-
var t = _.multiply(sym1.fnTransform(), sym2);
|
|
1719
|
-
retval = __.integrate(_.expand(t), dx, depth);
|
|
1720
|
-
}
|
|
1721
|
-
else {
|
|
1722
|
-
var t = _.multiply(sym1.fnTransform(), sym2.fnTransform());
|
|
1723
|
-
retval = __.integrate(_.expand(t), dx, depth);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
//TODO: In progress
|
|
1727
|
-
else if((fn1 === SIN || fn1 === COS) && (fn2 === SIN || fn2 === COS)) {
|
|
1728
|
-
|
|
1729
|
-
if(sym1.isLinear() && sym2.isLinear()) {
|
|
1730
|
-
//if in the form cos(a*x)*sin(b*x)
|
|
1731
|
-
if(sym1.args[0].isLinear() && sym2.args[0].isLinear()) {
|
|
1732
|
-
//use identity (sin(b*x+a*x)+sin(b*x-a*x))/2
|
|
1733
|
-
var ax, bx;
|
|
1734
|
-
if(fn2 === SIN) {
|
|
1735
|
-
ax = sym1.args[0];
|
|
1736
|
-
bx = sym2.args[0];
|
|
1737
|
-
}
|
|
1738
|
-
else {
|
|
1739
|
-
bx = sym1.args[0];
|
|
1740
|
-
ax = sym2.args[0];
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
|
-
//make the transformation
|
|
1744
|
-
f = _.parse(format('(sin(({1})+({0}))+sin(({1})-({0})))/2', ax.toString(), bx.toString()));
|
|
1745
|
-
|
|
1746
|
-
//integrate it
|
|
1747
|
-
retval = __.integrate(f, dx, depth);
|
|
1748
|
-
}
|
|
1749
|
-
else {
|
|
1750
|
-
var transformed = trigTransform(symbols);
|
|
1751
|
-
retval = __.integrate(_.expand(transformed), dx, depth);
|
|
1752
|
-
}
|
|
1753
|
-
}
|
|
1754
|
-
else {
|
|
1755
|
-
var transformed = new Symbol(1);
|
|
1756
|
-
symbols.map(function (sym) {
|
|
1757
|
-
var s = sym.fnTransform();
|
|
1758
|
-
transformed = _.multiply(transformed, s);
|
|
1759
|
-
});
|
|
1760
|
-
var t = _.expand(transformed);
|
|
1761
|
-
|
|
1762
|
-
retval = __.integrate(t, dx, depth);
|
|
1763
|
-
|
|
1764
|
-
if(retval.hasIntegral()) {
|
|
1765
|
-
retval = __.integrate(trigTransform(transformed.collectSymbols()), dx, depth);
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
else {
|
|
1770
|
-
__.integration.stop();
|
|
1771
|
-
}
|
|
1772
|
-
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
else if(g1 === FN && g2 === S) {
|
|
1776
|
-
var sym1_is_linear = sym1.isLinear();
|
|
1777
|
-
if(sym1.fname === COS && sym1_is_linear && sym2.power.equals(-1))
|
|
1778
|
-
retval = _.symfunction('Ci', [sym1.args[0]]);
|
|
1779
|
-
else if(sym1.fname === COS && sym2.power.equals(-1)) {
|
|
1780
|
-
retval = __.integrate(_.multiply(sym1.fnTransform(), sym2.clone()), dx, depth);
|
|
1781
|
-
}
|
|
1782
|
-
else if(sym1.fname === COSH && sym1_is_linear && sym2.power.equals(-1))
|
|
1783
|
-
retval = _.symfunction('Chi', [sym1.args[0]]);
|
|
1784
|
-
else if(sym1.fname === COSH && sym2.power.equals(-1)) {
|
|
1785
|
-
retval = __.integrate(_.multiply(sym1.fnTransform(), sym2.clone()), dx, depth);
|
|
1786
|
-
}
|
|
1787
|
-
else if(sym1.fname === SIN && sym1_is_linear && sym2.power.equals(-1))
|
|
1788
|
-
retval = _.symfunction('Si', [sym1.args[0]]);
|
|
1789
|
-
else if(sym1.fname === SIN && sym2.power.equals(-1)) {
|
|
1790
|
-
retval = __.integrate(_.multiply(sym1.fnTransform(), sym2.clone()), dx, depth);
|
|
1791
|
-
}
|
|
1792
|
-
else if(sym1.fname === SINH && sym1_is_linear && sym2.power.equals(-1))
|
|
1793
|
-
retval = _.symfunction('Shi', [sym1.args[0]]);
|
|
1794
|
-
else if(sym1.fname === SINH && sym2.power.equals(-1)) {
|
|
1795
|
-
retval = __.integrate(_.multiply(sym1.fnTransform(), sym2.clone()), dx, depth);
|
|
1796
|
-
}
|
|
1797
|
-
else if(sym1.fname === LOG && sym2.power.equals(-1)) {
|
|
1798
|
-
//log(x)^n/x = log(x)^(n+1)/(n+1)
|
|
1799
|
-
retval = __.integration.poly_integrate(sym1, dx, depth);
|
|
1800
|
-
}
|
|
1801
|
-
else if(sym1.fname === 'erf') {
|
|
1802
|
-
if(sym2.power.equals(1)) {
|
|
1803
|
-
var dc = __.integration.decompose_arg(sym1.args[0], dx),
|
|
1804
|
-
a_ = dc[0],
|
|
1805
|
-
x_ = dc[1],
|
|
1806
|
-
arg = sym1.args[0].toString();
|
|
1807
|
-
retval = _.parse(format('(e^(-(({2}))^2)*(sqrt(pi)*e^((({2}))^2)*(2*({0})^2*({1})^2-3)*erf(({2}))+2*({0})*({1})-2))/(4*sqrt(pi)*({0})^2)', a_, x_, arg))
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
else {
|
|
1811
|
-
//since group S is guaranteed convergence we need not worry about tracking depth of integration
|
|
1812
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
else if(g1 === EX && g2 === S) {
|
|
1816
|
-
var x = fn1 === LOG ? __.integration.decompose_arg(sym1.args[0], dx)[1] : null;
|
|
1817
|
-
if(sym1.isE() && (sym1.power.group === S || sym1.power.group === CB) && sym2.power.equals(-1)) {
|
|
1818
|
-
retval = _.symfunction('Ei', [sym1.power.clone()]);
|
|
1819
|
-
}
|
|
1820
|
-
else if(fn1 === LOG && x.value === sym2.value) {
|
|
1821
|
-
retval = __.integration.poly_integrate(sym1, dx, depth);
|
|
1822
|
-
}
|
|
1823
|
-
else
|
|
1824
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1825
|
-
}
|
|
1826
|
-
else if(g1 === PL && g2 === S) {
|
|
1827
|
-
//first try to reduce the top
|
|
1828
|
-
if(sym2.value === sym1.value && sym1.power.equals(-1)) {
|
|
1829
|
-
//find the lowest power in the denominator
|
|
1830
|
-
var pd = Math.min.apply(null, core.Utils.keys(sym1.symbols));
|
|
1831
|
-
//get the lowest common value between denominator and numerator
|
|
1832
|
-
var pc = Math.min(pd, sym2.power);
|
|
1833
|
-
//reduce both denominator and numerator by that factor
|
|
1834
|
-
var factor = sym2.clone();
|
|
1835
|
-
factor.power = new Frac(pc);
|
|
1836
|
-
sym2 = _.divide(sym2, factor.clone()); //reduce the denominator
|
|
1837
|
-
var t = new Symbol(0);
|
|
1838
|
-
sym1.each(function (x) {
|
|
1839
|
-
t = _.add(t, _.divide(x.clone(), factor.clone()));
|
|
1840
|
-
});
|
|
1841
|
-
t.multiplier = sym1.multiplier;
|
|
1842
|
-
symbol = _.divide(sym2, t);
|
|
1843
|
-
}
|
|
1844
|
-
else {
|
|
1845
|
-
symbol = _.expand(symbol);
|
|
1846
|
-
}
|
|
1847
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1848
|
-
}
|
|
1849
|
-
else if(g1 === CP && g2 === S) {
|
|
1850
|
-
var f = sym1.clone().toLinear(),
|
|
1851
|
-
f_is_linear = core.Algebra.degree(f, _.parse(dx)).equals(1);
|
|
1852
|
-
//handle cases x^(2*n)/sqrt(1-x^2)
|
|
1853
|
-
if(sym1.power.equals(-1 / 2)) {
|
|
1854
|
-
var decomp = __.integration.decompose_arg(sym1.clone().toLinear(), dx);
|
|
1855
|
-
var a = decomp[0].negate(),
|
|
1856
|
-
x = decomp[1],
|
|
1857
|
-
b = decomp[3],
|
|
1858
|
-
p1 = Number(sym1.power),
|
|
1859
|
-
p2 = Number(sym2.power);
|
|
1860
|
-
if(isInt(p2) && core.Utils.even(p2) && x.power.equals(2)) {
|
|
1861
|
-
//if the substitution
|
|
1862
|
-
var c = _.divide(_.multiply(_.pow(b.clone(), new Symbol(2)),
|
|
1863
|
-
_.symfunction(SQRT, [_.divide(b.clone(), a.clone())])),
|
|
1864
|
-
_.pow(a.clone(), new Symbol(2)));
|
|
1865
|
-
c = _.multiply(c, _.symfunction(SQRT, [b]).invert());
|
|
1866
|
-
var dummy = _.parse('sin(u)');
|
|
1867
|
-
dummy.power = dummy.power.multiply(sym2.power);
|
|
1868
|
-
var integral = __.integrate(dummy, 'u', depth);
|
|
1869
|
-
var bksub = _.parse(ASIN + '(' + SQRT + '(' + a + '/' + b + ')*' + dx + ')');
|
|
1870
|
-
retval = _.multiply(c, integral.sub(new Symbol('u'), bksub));
|
|
1871
|
-
}
|
|
1872
|
-
else if(p1 === -1 / 2) {
|
|
1873
|
-
var u_transform = function (f, u) {
|
|
1874
|
-
var integral = _.parse(__.integrate(f, dx, depth, opt).sub(dx, format(u, dx)));
|
|
1875
|
-
if(!integral.hasIntegral())
|
|
1876
|
-
return integral;
|
|
1877
|
-
}
|
|
1878
|
-
if(p2 === -1) {
|
|
1879
|
-
retval = u_transform(
|
|
1880
|
-
_.expand(_.expand(_.pow(_.multiply(sym1.invert(), sym2.invert()), new Symbol(2)))).invert(),
|
|
1881
|
-
'sqrt(1-1/({0})^2)'
|
|
1882
|
-
);
|
|
1883
|
-
}
|
|
1884
|
-
else if(p2 === -2) {
|
|
1885
|
-
//apply transformation to see if it matches asin(x)
|
|
1886
|
-
retval = u_transform(
|
|
1887
|
-
_.sqrt(_.expand(_.divide(_.pow(symbol, new Symbol(2)).invert(), _.pow(new Symbol(dx), new Symbol(2))).negate())).invert(),
|
|
1888
|
-
'sqrt(1-1/({0})^2)'
|
|
1889
|
-
);
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
else if(sym1.power.equals(-1) && sym2.isLinear() && f_is_linear) {
|
|
1894
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1895
|
-
}
|
|
1896
|
-
else if(!sym1.power.lessThan(0) && isInt(sym1.power)) {
|
|
1897
|
-
//sum of integrals
|
|
1898
|
-
var expanded = _.expand(sym1);
|
|
1899
|
-
retval = new Symbol(0);
|
|
1900
|
-
expanded.each(function (x) {
|
|
1901
|
-
if(x.group === PL) {
|
|
1902
|
-
x.each(function (y) {
|
|
1903
|
-
retval = _.add(retval, __.integrate(_.multiply(sym2.clone(), y), dx, depth));
|
|
1904
|
-
});
|
|
1905
|
-
}
|
|
1906
|
-
else
|
|
1907
|
-
retval = _.add(retval, __.integrate(_.multiply(sym2.clone(), x), dx, depth));
|
|
1908
|
-
});
|
|
1909
|
-
}
|
|
1910
|
-
else if(sym1.power.lessThan(-2)) {
|
|
1911
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1912
|
-
}
|
|
1913
|
-
else if(sym1.power.lessThan(0) && sym2.power.greaterThan(1)) {
|
|
1914
|
-
var decomp = __.integration.decompose_arg(sym1.clone().toLinear(), dx),
|
|
1915
|
-
a = decomp[0].negate(),
|
|
1916
|
-
x = decomp[1],
|
|
1917
|
-
b = decomp[3],
|
|
1918
|
-
fn = sym1.clone().toLinear();
|
|
1919
|
-
|
|
1920
|
-
if(x.group !== PL && x.isLinear()) {
|
|
1921
|
-
var p = Number(sym2.power),
|
|
1922
|
-
du = '_u_',
|
|
1923
|
-
u = new Symbol(du),
|
|
1924
|
-
//pull the integral with the subsitution
|
|
1925
|
-
U = _.expand(_.divide(_.pow(_.subtract(u.clone(), b.clone()), new Symbol(p)), u.clone())),
|
|
1926
|
-
scope = {};
|
|
1927
|
-
|
|
1928
|
-
//generate a scope for resubbing the symbol
|
|
1929
|
-
scope[du] = fn;
|
|
1930
|
-
var U2 = _.parse(U, scope);
|
|
1931
|
-
retval = __.integrate(U2, dx, 0);
|
|
1932
|
-
}
|
|
1933
|
-
else if(sym2.power.greaterThan(x.power) || sym2.power.equals(x.power)) {
|
|
1934
|
-
|
|
1935
|
-
//factor out coefficients
|
|
1936
|
-
var factors = new core.Algebra.Classes.Factors();
|
|
1937
|
-
sym1 = core.Algebra.Factor.coeffFactor(sym1.invert(), factors);
|
|
1938
|
-
var div = core.Algebra.divide(sym2, sym1);
|
|
1939
|
-
//it assumed that the result will be of group CB
|
|
1940
|
-
if(div.group !== CB) {
|
|
1941
|
-
retval = new Symbol(0);
|
|
1942
|
-
div.each(function (t) {
|
|
1943
|
-
retval = _.add(retval, __.integrate(t, dx, depth));
|
|
1944
|
-
});
|
|
1945
|
-
//put back the factors
|
|
1946
|
-
factors.each(function (factor) {
|
|
1947
|
-
retval = _.divide(retval, factor);
|
|
1948
|
-
});
|
|
1949
|
-
|
|
1950
|
-
retval = _.expand(retval);
|
|
1951
|
-
}
|
|
1952
|
-
else {
|
|
1953
|
-
//try something else
|
|
1954
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
else
|
|
1958
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1959
|
-
}
|
|
1960
|
-
else {
|
|
1961
|
-
//handle cases such as (1-x^2)^(n/2)*x^(m) where n is odd ___ cracking knuckles... This can get a little hairy
|
|
1962
|
-
if(sym1.power.den.equals(2)) {
|
|
1963
|
-
//assume the function is in the form (a^2-b*x^n)^(m/2)
|
|
1964
|
-
var dc = __.integration.decompose_arg(sym1.clone().toLinear(), dx),
|
|
1965
|
-
//using the above definition
|
|
1966
|
-
a = dc[3], x = dc[1], b = dc[0], bx = dc[2];
|
|
1967
|
-
if(x.power.equals(2) && b.lessThan(0)) { //if n is even && b is negative
|
|
1968
|
-
//make a equal 1 so we can do a trig sub
|
|
1969
|
-
if(!a.equals(1)) { //divide a out of everything
|
|
1970
|
-
//move a to the coeff
|
|
1971
|
-
coeff = _.multiply(coeff, _.pow(a, new Symbol(2)));
|
|
1972
|
-
}
|
|
1973
|
-
var u = dx;
|
|
1974
|
-
var c = _.divide(_.pow(b.clone().negate(), new Symbol(1 / 2)), _.pow(a, new Symbol(1 / 2))),
|
|
1975
|
-
du = _.symfunction(COS, [new Symbol(u)]),
|
|
1976
|
-
cosn = _.pow(_.symfunction(COS, [new Symbol(u)]), new Symbol(sym1.power.num)),
|
|
1977
|
-
X = _.pow(_.symfunction(SIN, [new Symbol(u)]), new Symbol(sym2.power)),
|
|
1978
|
-
val = _.multiply(_.multiply(cosn, du), X),
|
|
1979
|
-
integral = __.integrate(val, u, depth);
|
|
1980
|
-
//but remember that u = asin(sqrt(b)*a*x)
|
|
1981
|
-
retval = integral.sub(u, _.symfunction(ASIN, [_.multiply(new Symbol(dx), c)]));
|
|
1982
|
-
}
|
|
1983
|
-
else {
|
|
1984
|
-
retval = __.integration.partial_fraction(symbol, dx, depth, opt);
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
else if(f_is_linear) {
|
|
1988
|
-
retval = __.integration.partial_fraction(symbol, dx, depth);
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
|
|
1992
|
-
}
|
|
1993
|
-
else if(sym1.isComposite() && sym2.isComposite()) {
|
|
1994
|
-
//sum of integrals
|
|
1995
|
-
retval = new Symbol(0);
|
|
1996
|
-
if(sym1.power.greaterThan(0) && sym2.power.greaterThan(0)) {
|
|
1997
|
-
//combine and pull the integral of each
|
|
1998
|
-
var sym = _.expand(symbol);
|
|
1999
|
-
sym.each(function (x) {
|
|
2000
|
-
retval = _.add(retval, __.integrate(x, dx, depth));
|
|
2001
|
-
}, true);
|
|
2002
|
-
}
|
|
2003
|
-
else {
|
|
2004
|
-
var p1 = Number(sym1.power),
|
|
2005
|
-
p2 = Number(sym2.power);
|
|
2006
|
-
if(p1 < 0 && p2 > 0) {
|
|
2007
|
-
//swap
|
|
2008
|
-
var t = sym1;
|
|
2009
|
-
sym1 = sym2;
|
|
2010
|
-
sym2 = t;
|
|
2011
|
-
}
|
|
2012
|
-
if(p1 === -1 && p2 === -1) {
|
|
2013
|
-
retval = __.integration.partial_fraction(symbol, dx);
|
|
2014
|
-
}
|
|
2015
|
-
else {
|
|
2016
|
-
sym1.each(function (x) {
|
|
2017
|
-
var k = _.multiply(x, sym2.clone());
|
|
2018
|
-
var integral = __.integrate(k, dx, depth);
|
|
2019
|
-
retval = _.add(retval, integral);
|
|
2020
|
-
});
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
else if(g1 === CP && symbols[0].power.greaterThan(0)) {
|
|
2025
|
-
sym1 = _.expand(sym1);
|
|
2026
|
-
retval = new Symbol(0);
|
|
2027
|
-
sym1.each(function (x) {
|
|
2028
|
-
retval = _.add(retval, __.integrate(_.multiply(x, sym2.clone()), dx, depth));
|
|
2029
|
-
}, true);
|
|
2030
|
-
}
|
|
2031
|
-
else if(g1 === FN && g2 === EX && core.Utils.in_htrig(sym1.fname)) {
|
|
2032
|
-
sym1 = sym1.fnTransform();
|
|
2033
|
-
retval = __.integrate(_.expand(_.multiply(sym1, sym2)), dx, depth);
|
|
2034
|
-
}
|
|
2035
|
-
else if(g1 === FN && g2 === CP || g2 === FN && g1 === CP) {
|
|
2036
|
-
if(g2 === FN && g1 === CP) {
|
|
2037
|
-
var t = sym1;
|
|
2038
|
-
sym1 = sym2;
|
|
2039
|
-
sym2 = t; //swap
|
|
2040
|
-
}
|
|
2041
|
-
var du, sym2_clone, p, q, sa, sb;
|
|
2042
|
-
du = Symbol.unwrapSQRT(__.diff(sym1.clone(), dx), true);
|
|
2043
|
-
sym2_clone = Symbol.unwrapSQRT(sym2, true);
|
|
2044
|
-
if(du.power.equals(sym2_clone.power)) {
|
|
2045
|
-
p = new Symbol(sym2.power);
|
|
2046
|
-
sa = du.clone().toLinear();
|
|
2047
|
-
sb = sym2.clone().toLinear();
|
|
2048
|
-
q = core.Algebra.divide(sa.toLinear(), sb);
|
|
2049
|
-
if(q.isConstant()) {
|
|
2050
|
-
var nq = _.pow(q, p.negate());
|
|
2051
|
-
retval = _.multiply(nq, __.integration.poly_integrate(sym1.clone()));
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
else {
|
|
2055
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
else {
|
|
2059
|
-
var syma = sym1.clone().toLinear();
|
|
2060
|
-
var symb = sym2.clone().toLinear();
|
|
2061
|
-
if(g1 === EX && g2 === EX && sym1.power.contains(dx) && sym2.power.contains(dx)
|
|
2062
|
-
&& !syma.contains(dx) && !symb.contains(dx)) {
|
|
2063
|
-
retval = _.parse(format('(({0})^(({2})*({4}))*({1})^(({3})*({4})))/(log(({0})^({2}))+log(({1})^({3})))',
|
|
2064
|
-
syma.toString(),
|
|
2065
|
-
symb.toString(),
|
|
2066
|
-
sym1.power.multiplier.toString(),
|
|
2067
|
-
sym2.power.multiplier.toString(),
|
|
2068
|
-
dx
|
|
2069
|
-
));
|
|
2070
|
-
}
|
|
2071
|
-
else
|
|
2072
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
else if(l === 3 && (symbols[2].group === S && symbols[2].power.lessThan(2) || symbols[0].group === CP)) {
|
|
2077
|
-
var first = symbols[0];
|
|
2078
|
-
if(first.group === CP) { //TODO {support higher powers of x in the future}
|
|
2079
|
-
if(first.power.greaterThan(1))
|
|
2080
|
-
first = _.expand(first);
|
|
2081
|
-
var r = _.multiply(symbols[1], symbols[2]);
|
|
2082
|
-
retval = new Symbol(0);
|
|
2083
|
-
first.each(function (x) {
|
|
2084
|
-
var t = _.multiply(x, r.clone());
|
|
2085
|
-
var intg = __.integrate(t, dx, depth);
|
|
2086
|
-
retval = _.add(retval, intg);
|
|
2087
|
-
}, true);
|
|
2088
|
-
}
|
|
2089
|
-
else {
|
|
2090
|
-
//try integration by parts although technically it will never work
|
|
2091
|
-
retval = __.integration.by_parts(symbol, dx, depth, opt);
|
|
2092
|
-
}
|
|
2093
|
-
|
|
2094
|
-
}
|
|
2095
|
-
else if(all_functions(symbols)) {
|
|
2096
|
-
var t = new Symbol(1);
|
|
2097
|
-
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2098
|
-
t = _.multiply(t, symbols[i].fnTransform());
|
|
2099
|
-
}
|
|
2100
|
-
t = _.expand(t);
|
|
2101
|
-
retval = __.integrate(t, dx, depth);
|
|
2102
|
-
}
|
|
2103
|
-
else {
|
|
2104
|
-
//one more go
|
|
2105
|
-
var transformed = trigTransform(symbols);
|
|
2106
|
-
retval = __.integrate(_.expand(transformed), dx, depth);
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
retval = _.multiply(retval, coeff);
|
|
2113
|
-
}
|
|
2114
|
-
//if an integral was found then we return it
|
|
2115
|
-
if(retval)
|
|
2116
|
-
return retval;
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
catch(error) {
|
|
2120
|
-
//do nothing if it's a NoIntegralFound error otherwise let it bubble
|
|
2121
|
-
if(!(error instanceof NoIntegralFound || error instanceof core.exceptions.DivisionByZero))
|
|
2122
|
-
throw error;
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
|
-
//no symbol found so we return the integral again
|
|
2126
|
-
return _.symfunction('integrate', [original_symbol, dt]);
|
|
2127
|
-
}, false);
|
|
2128
|
-
},
|
|
2129
|
-
defint: function (symbol, from, to, dx) {
|
|
2130
|
-
dx = dx || 'x'; //make x the default variable of integration
|
|
2131
|
-
var get_value = function (integral, vars, point) {
|
|
2132
|
-
try {
|
|
2133
|
-
return _.parse(integral, vars);
|
|
2134
|
-
}
|
|
2135
|
-
catch(e) {
|
|
2136
|
-
//it failed for some reason so return the limit
|
|
2137
|
-
var lim = __.Limit.limit(integral, dx, point);
|
|
2138
|
-
return lim;
|
|
2139
|
-
}
|
|
2140
|
-
};
|
|
2141
|
-
|
|
2142
|
-
var vars = core.Utils.variables(symbol),
|
|
2143
|
-
hasTrig = symbol.hasTrig();
|
|
2144
|
-
var retval, integral;
|
|
2145
|
-
|
|
2146
|
-
// Fix #593 - Only assume the first variable if dx is not defined.
|
|
2147
|
-
if(vars.length === 1 && !dx)
|
|
2148
|
-
dx = vars[0];
|
|
2149
|
-
|
|
2150
|
-
if(!hasTrig) {
|
|
2151
|
-
integral = __.integrate(symbol, dx);
|
|
2152
|
-
}
|
|
2153
|
-
|
|
2154
|
-
if(!hasTrig && !integral.hasIntegral()) {
|
|
2155
|
-
var upper = {},
|
|
2156
|
-
lower = {},
|
|
2157
|
-
a, b;
|
|
2158
|
-
upper[dx] = to;
|
|
2159
|
-
lower[dx] = from;
|
|
2160
|
-
|
|
2161
|
-
a = get_value(integral, upper, to, dx);
|
|
2162
|
-
b = get_value(integral, lower, from, dx);
|
|
2163
|
-
retval = _.subtract(a, b);
|
|
2164
|
-
}
|
|
2165
|
-
else if(vars.length === 1 && from.isConstant() && to.isConstant()) {
|
|
2166
|
-
|
|
2167
|
-
var f = core.Utils.build(symbol);
|
|
2168
|
-
retval = new Symbol(core.Math2.num_integrate(f, Number(from), Number(to)));
|
|
2169
|
-
}
|
|
2170
|
-
else
|
|
2171
|
-
retval = _.symfunction('defint', [symbol, from, to, dx]);
|
|
2172
|
-
return retval;
|
|
2173
|
-
},
|
|
2174
|
-
|
|
2175
|
-
Limit: {
|
|
2176
|
-
interval: function (start, end) {
|
|
2177
|
-
return _.parse(format('[{0}, {1}]', start, end));
|
|
2178
|
-
},
|
|
2179
|
-
diverges: function () {
|
|
2180
|
-
return __.Limit.interval('-Infinity', 'Infinity');
|
|
2181
|
-
},
|
|
2182
|
-
divide: function (f, g, x, lim, depth) {
|
|
2183
|
-
if(depth++ > Settings.max_lim_depth) {
|
|
2184
|
-
return;
|
|
2185
|
-
}
|
|
2186
|
-
|
|
2187
|
-
var fin = f.clone(), gin = g.clone();
|
|
2188
|
-
|
|
2189
|
-
//But first a little "cheating". x/|x| ends up in an infinite loop since the d/dx |x| -> x/|x|
|
|
2190
|
-
//To break this loop we simply provide the answer. Keep in mind that currently limit only provides
|
|
2191
|
-
//the two-sided limit.
|
|
2192
|
-
//Known limit
|
|
2193
|
-
if(g.fname === ABS) {
|
|
2194
|
-
var sign = f.sign();
|
|
2195
|
-
var lim_sign = lim.sign();
|
|
2196
|
-
|
|
2197
|
-
if(lim.isInfinity)
|
|
2198
|
-
return _.multiply(new Symbol(sign), new Symbol(lim_sign));
|
|
2199
|
-
|
|
2200
|
-
else if(lim.equals(0)) {
|
|
2201
|
-
var fm = _.parse(f.multiplier);
|
|
2202
|
-
var gm = _.parse(g.multiplier);
|
|
2203
|
-
return _.divide(_.multiply(fm, __.Limit.interval('-1', '1')), gm);
|
|
2204
|
-
}
|
|
2205
|
-
else {
|
|
2206
|
-
//TODO: Support more limits
|
|
2207
|
-
__.Limit.diverges();
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
|
|
2211
|
-
var isInfinity = function (L) {
|
|
2212
|
-
if(core.Utils.isVector(L)) {
|
|
2213
|
-
for(var i = 0; i < L.elements.length; i++)
|
|
2214
|
-
if(!L.elements[i].isInfinity)
|
|
2215
|
-
return false;
|
|
2216
|
-
return true;
|
|
2217
|
-
}
|
|
2218
|
-
return L.isInfinity;
|
|
2219
|
-
};
|
|
2220
|
-
|
|
2221
|
-
var equals = function (L, v) {
|
|
2222
|
-
if(core.Utils.isVector(L)) {
|
|
2223
|
-
return false;
|
|
2224
|
-
}
|
|
2225
|
-
return L.equals(v);
|
|
2226
|
-
};
|
|
2227
|
-
|
|
2228
|
-
var retval;
|
|
2229
|
-
do {
|
|
2230
|
-
var lim1 = evaluate(__.Limit.limit(f.clone(), x, lim, depth));
|
|
2231
|
-
var lim2 = evaluate(__.Limit.limit(g.clone(), x, lim, depth));
|
|
2232
|
-
|
|
2233
|
-
//if it's in indeterminate form apply L'Hospital's rule
|
|
2234
|
-
var indeterminate = isInfinity(lim1) && isInfinity(lim2) || equals(lim1, 0) && equals(lim2, 0);
|
|
2235
|
-
//pull the derivatives
|
|
2236
|
-
if(indeterminate) {
|
|
2237
|
-
var ft = __.diff(f.clone(), x);
|
|
2238
|
-
var gt = __.diff(g.clone(), x);
|
|
2239
|
-
|
|
2240
|
-
var t_symbol = _.expand(_.divide(ft, gt));
|
|
2241
|
-
f = t_symbol.getNum();
|
|
2242
|
-
g = t_symbol.getDenom();
|
|
2243
|
-
|
|
2244
|
-
}
|
|
2245
|
-
}
|
|
2246
|
-
while(indeterminate)
|
|
2247
|
-
|
|
2248
|
-
//REMEMBER:
|
|
2249
|
-
//- 1/cos(x)
|
|
2250
|
-
//n/0 is still possible since we only checked for 0/0
|
|
2251
|
-
var den_is_zero = lim2.equals(0);
|
|
2252
|
-
var p = Number(gin.power);
|
|
2253
|
-
|
|
2254
|
-
if(lim.isConstant(true) && den_is_zero) {
|
|
2255
|
-
retval = Symbol.infinity(core.Utils.even(p) && lim1.lessThan(0) ? -1 : undefined);
|
|
2256
|
-
}
|
|
2257
|
-
else if(den_is_zero) {
|
|
2258
|
-
retval = __.Limit.diverges();
|
|
2259
|
-
}
|
|
2260
|
-
else {
|
|
2261
|
-
retval = _.divide(lim1, lim2);
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
return retval;
|
|
2265
|
-
},
|
|
2266
|
-
rewriteToLog: function (symbol) {
|
|
2267
|
-
var p = symbol.power.clone();
|
|
2268
|
-
symbol.toLinear();
|
|
2269
|
-
return _.pow(new Symbol('e'), _.multiply(p, _.symfunction(Settings.LOG + '', [symbol])));
|
|
2270
|
-
},
|
|
2271
|
-
getSubbed: function (f, x, lim) {
|
|
2272
|
-
var retval;
|
|
2273
|
-
//1. rewrite EX with base e
|
|
2274
|
-
if(f.group === EX) {
|
|
2275
|
-
f = __.rewriteToLog(f);
|
|
2276
|
-
}
|
|
2277
|
-
//2. try simple substitution
|
|
2278
|
-
try {
|
|
2279
|
-
retval = f.sub(x, lim);
|
|
2280
|
-
}
|
|
2281
|
-
catch(e) {
|
|
2282
|
-
//Nope. No go, so just return the unsubbed function so we can test the limit instead.
|
|
2283
|
-
retval = f;
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
return retval;
|
|
2287
|
-
},
|
|
2288
|
-
isInterval: function (limit) {
|
|
2289
|
-
return core.Utils.isVector(limit);
|
|
2290
|
-
},
|
|
2291
|
-
isConvergent: function (limit) {
|
|
2292
|
-
//it's not convergent if it lies on the interval -Infinity to Infinity
|
|
2293
|
-
if(
|
|
2294
|
-
//It lies on the interval -Infinity to Infinity
|
|
2295
|
-
__.Limit.isInterval(limit) && limit.elements[0].isInfinity && limit.elements[1].isInfinity ||
|
|
2296
|
-
//We weren't able to calculate the limit
|
|
2297
|
-
limit.containsFunction('limit')
|
|
2298
|
-
) {
|
|
2299
|
-
return false; //Then no
|
|
2300
|
-
}
|
|
2301
|
-
return true; //It is
|
|
2302
|
-
},
|
|
2303
|
-
limit: function (symbol, x, lim, depth) {
|
|
2304
|
-
//Simplify the symbol
|
|
2305
|
-
if(symbol.isLinear() && symbol.isComposite()) {
|
|
2306
|
-
|
|
2307
|
-
//Apply sum of limits
|
|
2308
|
-
var limit = new Symbol(0);
|
|
2309
|
-
symbol.each(function (s) {
|
|
2310
|
-
limit = _.add(limit, __.Limit.limit(s, x, lim, depth));
|
|
2311
|
-
}, true);
|
|
2312
|
-
|
|
2313
|
-
return limit;
|
|
2314
|
-
}
|
|
2315
|
-
;
|
|
2316
|
-
|
|
2317
|
-
symbol = core.Algebra.Simplify.simplify(symbol);
|
|
2318
|
-
|
|
2319
|
-
depth = depth || 1;
|
|
2320
|
-
|
|
2321
|
-
if(depth++ > Settings.max_lim_depth) {
|
|
2322
|
-
return;
|
|
2323
|
-
}
|
|
2324
|
-
|
|
2325
|
-
//store the multiplier
|
|
2326
|
-
var m = _.parse(symbol.multiplier);
|
|
2327
|
-
//strip the multiplier
|
|
2328
|
-
symbol.toUnitMultiplier();
|
|
2329
|
-
try {
|
|
2330
|
-
//https://en.wikipedia.org/wiki/List_of_limits
|
|
2331
|
-
var retval;
|
|
2332
|
-
//we try the simplest option first where c is some limit
|
|
2333
|
-
//lim a as x->c = a where c
|
|
2334
|
-
if(symbol.isConstant(true)) {
|
|
2335
|
-
retval = symbol;
|
|
2336
|
-
}
|
|
2337
|
-
else {
|
|
2338
|
-
var point = {};
|
|
2339
|
-
point[x] = lim;
|
|
2340
|
-
//lim x as x->c = c where c
|
|
2341
|
-
|
|
2342
|
-
try {
|
|
2343
|
-
|
|
2344
|
-
//evaluate the function at the given limit
|
|
2345
|
-
var t = _.parse(symbol.sub(x, lim), point);
|
|
2346
|
-
|
|
2347
|
-
//a constant or infinity is known so we're done
|
|
2348
|
-
if(t.isConstant(true) || t.isInfinity)
|
|
2349
|
-
retval = t;
|
|
2350
|
-
|
|
2351
|
-
}
|
|
2352
|
-
catch(e) { /*Nothing. Maybe we tried to divide by zero.*/
|
|
2353
|
-
}
|
|
2354
|
-
;
|
|
2355
|
-
|
|
2356
|
-
if(!retval) {
|
|
2357
|
-
//split the symbol in the numerator and the denominator
|
|
2358
|
-
var num = symbol.getNum();
|
|
2359
|
-
var den = symbol.getDenom();
|
|
2360
|
-
|
|
2361
|
-
if(den.isConstant(true)) {
|
|
2362
|
-
//We still don't have a limit so we generate tests.
|
|
2363
|
-
if(symbol.group === EX) {
|
|
2364
|
-
//https://en.wikipedia.org/wiki/List_of_limits
|
|
2365
|
-
//Speed boost for exponentials by detecting patterns
|
|
2366
|
-
var f = symbol.clone().toLinear();
|
|
2367
|
-
var p = symbol.power.clone();
|
|
2368
|
-
var _num = f.getNum();
|
|
2369
|
-
var _den = f.getDenom();
|
|
2370
|
-
var fn = core.Utils.decompose_fn(_den, x, true);
|
|
2371
|
-
//start detection of pattern (x/(x+1))^x
|
|
2372
|
-
if(_num.group === S && _num.multiplier.isOne() && fn.ax.group === S && fn.b.isConstant(true) && fn.a.isOne() && fn.b.isConstant(true)) {
|
|
2373
|
-
retval = _.parse(format('(1/e^({0}))', fn.b));
|
|
2374
|
-
}
|
|
2375
|
-
else {
|
|
2376
|
-
var symbol_ = __.Limit.rewriteToLog(symbol.clone());
|
|
2377
|
-
//get the base
|
|
2378
|
-
var pow = symbol_.power.clone();
|
|
2379
|
-
var base = symbol_.clone().toLinear();
|
|
2380
|
-
var lim_base = __.Limit.limit(base, x, lim, depth);
|
|
2381
|
-
var lim_pow = __.Limit.limit(pow, x, lim, depth);
|
|
2382
|
-
retval = _.pow(lim_base, lim_pow);
|
|
2383
|
-
}
|
|
2384
|
-
}
|
|
2385
|
-
else if(symbol.group === FN && symbol.args.length === 1) {
|
|
2386
|
-
var evaluates;
|
|
2387
|
-
//Squeeze theorem lim f(g(x)) = lim f(lim g))
|
|
2388
|
-
var arg = __.Limit.limit(symbol.args[0], x, lim, depth);
|
|
2389
|
-
if(core.Utils.isVector(arg)) {
|
|
2390
|
-
//get the limit over that interval
|
|
2391
|
-
retval = arg.map(function (e) {
|
|
2392
|
-
var clone = symbol.clone();
|
|
2393
|
-
clone.args[0] = e;
|
|
2394
|
-
return __.Limit.limit(_.symfunction(symbol.fname, [e]), x, lim, depth);
|
|
2395
|
-
});
|
|
2396
|
-
|
|
2397
|
-
return _.multiply(m, retval);
|
|
2398
|
-
}
|
|
2399
|
-
//if the argument is constant then we're done
|
|
2400
|
-
else if(arg.isConstant(true)) {
|
|
2401
|
-
|
|
2402
|
-
//double check that it evaluates
|
|
2403
|
-
var trial = _.symfunction(symbol.fname, [arg]);
|
|
2404
|
-
//trial evaluation
|
|
2405
|
-
try {
|
|
2406
|
-
evaluate(trial);
|
|
2407
|
-
evaluates = true;
|
|
2408
|
-
}
|
|
2409
|
-
catch(e) {
|
|
2410
|
-
|
|
2411
|
-
evaluates = false;
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
if(evaluates) {
|
|
2415
|
-
retval = trial;
|
|
2416
|
-
}
|
|
2417
|
-
else {
|
|
2418
|
-
//if the limit converges. We'll deal with non-convergent ones later
|
|
2419
|
-
if(__.Limit.isConvergent(arg)) {
|
|
2420
|
-
if(symbol.fname === LOG) {
|
|
2421
|
-
switch(arg.toString()) {
|
|
2422
|
-
//lim -> 0
|
|
2423
|
-
case '0':
|
|
2424
|
-
retval = Symbol.infinity().negate();
|
|
2425
|
-
break;
|
|
2426
|
-
case 'Infinity':
|
|
2427
|
-
retval = Symbol.infinity();
|
|
2428
|
-
break;
|
|
2429
|
-
case '-Infinity':
|
|
2430
|
-
retval = Symbol.infinity();
|
|
2431
|
-
break;
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
else if((symbol.fname === COS || symbol.fname === SIN) && lim.isInfinity) {
|
|
2435
|
-
retval = __.Limit.interval(-1, 1);
|
|
2436
|
-
}
|
|
2437
|
-
else if((symbol.fname === TAN)) {
|
|
2438
|
-
var s_arg = symbol.args[0];
|
|
2439
|
-
var n = s_arg.getNum();
|
|
2440
|
-
var d = s_arg.getDenom();
|
|
2441
|
-
var pi = n.toUnitMultiplier();
|
|
2442
|
-
if(lim.isInfinity || pi.equals('pi') && d.equals(2)) {
|
|
2443
|
-
retval = divergent();
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
else if(symbol.fname === Settings.FACTORIAL) {
|
|
2447
|
-
if(arg.isInfinity)
|
|
2448
|
-
return Symbol.infinity();
|
|
2449
|
-
}
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
else if(symbol.group === S) {
|
|
2454
|
-
if(symbol.power > 0)
|
|
2455
|
-
//these functions always converge to the limit
|
|
2456
|
-
return _.parse(symbol, point);
|
|
2457
|
-
else {
|
|
2458
|
-
//we're dealing with 1/x^n but remember that infinity has already been dealt
|
|
2459
|
-
//with by substitution
|
|
2460
|
-
if(core.Utils.even(symbol.power)) {
|
|
2461
|
-
//even powers converge to infinity
|
|
2462
|
-
retval = Symbol.infinity();
|
|
2463
|
-
}
|
|
2464
|
-
else {
|
|
2465
|
-
//odd ones don't
|
|
2466
|
-
retval = __.Limit.diverges();
|
|
2467
|
-
}
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
else if(symbol.group === CB) {
|
|
2471
|
-
|
|
2472
|
-
var lim1, lim2;
|
|
2473
|
-
//loop through all the symbols
|
|
2474
|
-
//thus => lim f*g*h = lim (f*g)*h = (lim f*g)*(lim h)
|
|
2475
|
-
//symbols of lower groups are generally easier to differentiatee so get them to the right by first sorting
|
|
2476
|
-
var symbols = symbol.collectSymbols().sort(function (a, b) {
|
|
2477
|
-
return a.group - b.group;
|
|
2478
|
-
});
|
|
2479
|
-
|
|
2480
|
-
var f = symbols.pop();
|
|
2481
|
-
//calculate the first limit so we can keep going down the list
|
|
2482
|
-
lim1 = evaluate(__.Limit.limit(f, x, lim, depth));
|
|
2483
|
-
|
|
2484
|
-
//reduces all the limits one at a time
|
|
2485
|
-
while(symbols.length) {
|
|
2486
|
-
//get the second limit
|
|
2487
|
-
var g = symbols.pop();
|
|
2488
|
-
//get the limit of g
|
|
2489
|
-
lim2 = evaluate(__.Limit.limit(g, x, lim, depth));
|
|
2490
|
-
|
|
2491
|
-
//if the limit is in indeterminate form aplly L'Hospital by inverting g and then f/(1/g)
|
|
2492
|
-
if((lim1.isInfinity || !__.Limit.isConvergent(lim1) && lim2.equals(0) || lim1.equals(0) && __.Limit.isConvergent(lim2))) {
|
|
2493
|
-
if(g.containsFunction(LOG)) {
|
|
2494
|
-
//swap them
|
|
2495
|
-
g = [f, f = g][0];
|
|
2496
|
-
}
|
|
2497
|
-
//invert the symbol
|
|
2498
|
-
g.invert();
|
|
2499
|
-
|
|
2500
|
-
// Product of infinities
|
|
2501
|
-
if(lim1.isInfinity && lim2.isInfinity) {
|
|
2502
|
-
lim1 = Symbol.infinity()
|
|
2503
|
-
}
|
|
2504
|
-
else {
|
|
2505
|
-
lim1 = __.Limit.divide(f, g, x, lim, depth);
|
|
2506
|
-
}
|
|
2507
|
-
}
|
|
2508
|
-
else {
|
|
2509
|
-
//lim f*g = (lim f)*(lim g)
|
|
2510
|
-
lim1 = _.multiply(lim1, lim2);
|
|
2511
|
-
//let f*g equal f and h equal g
|
|
2512
|
-
f = _.multiply(f, g);
|
|
2513
|
-
}
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
//Done, lim1 is the limit we're looking for
|
|
2517
|
-
retval = lim1;
|
|
2518
|
-
}
|
|
2519
|
-
else if(symbol.isComposite()) {
|
|
2520
|
-
var _lim;
|
|
2521
|
-
if(!symbol.isLinear())
|
|
2522
|
-
symbol = _.expand(symbol);
|
|
2523
|
-
//Apply lim f+g = (lim f)+(lim g)
|
|
2524
|
-
retval = new Symbol(0);
|
|
2525
|
-
|
|
2526
|
-
var symbols = symbol.collectSymbols().sort(function (a, b) {
|
|
2527
|
-
return b.group - a.group;
|
|
2528
|
-
});
|
|
2529
|
-
|
|
2530
|
-
var _symbols = [];
|
|
2531
|
-
//Analyze the functions first
|
|
2532
|
-
var fns = new Symbol(0);
|
|
2533
|
-
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2534
|
-
var sym = symbols[i].clone();
|
|
2535
|
-
if(sym.group === FN || sym.group === CB && sym.hasFunc()) {
|
|
2536
|
-
fns = _.add(fns, sym);
|
|
2537
|
-
}
|
|
2538
|
-
else
|
|
2539
|
-
_symbols.push(sym);
|
|
2540
|
-
}
|
|
2541
|
-
_symbols.unshift(fns);
|
|
2542
|
-
|
|
2543
|
-
//make sure that we didn't just repackage the exact same symbol
|
|
2544
|
-
if(_symbols.length !== 1) {
|
|
2545
|
-
symbols = _symbols;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
for(var i = 0, l = symbols.length; i < l; i++) {
|
|
2549
|
-
var sym = symbols[i];
|
|
2550
|
-
//If the addition of the limits is undefined then the limit diverges so return -infinity to infinity
|
|
2551
|
-
try {
|
|
2552
|
-
_lim = __.Limit.limit(sym, x, lim, depth);
|
|
2553
|
-
}
|
|
2554
|
-
catch(e) {
|
|
2555
|
-
_lim = __.Limit.diverges();
|
|
2556
|
-
}
|
|
2557
|
-
|
|
2558
|
-
try {
|
|
2559
|
-
retval = _.add(retval, _lim);
|
|
2560
|
-
}
|
|
2561
|
-
catch(e) {
|
|
2562
|
-
if(depth++ > Settings.max_lim_depth) {
|
|
2563
|
-
return;
|
|
2564
|
-
}
|
|
2565
|
-
;
|
|
2566
|
-
retval = __.Limit.limit(__.diff(symbol, x), x, lim, depth);
|
|
2567
|
-
}
|
|
2568
|
-
}
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
else {
|
|
2572
|
-
retval = __.Limit.divide(num, den, x, lim, depth);
|
|
2573
|
-
}
|
|
2574
|
-
}
|
|
2575
|
-
}
|
|
2576
|
-
|
|
2577
|
-
//if we still don't have a solution
|
|
2578
|
-
if(!retval)
|
|
2579
|
-
//return it symbolically
|
|
2580
|
-
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2581
|
-
}
|
|
2582
|
-
catch(e) {
|
|
2583
|
-
//if all else fails return the symbolic function
|
|
2584
|
-
retval = _.symfunction('limit', [symbol, x, lim]);
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
return _.multiply(m, retval);
|
|
2588
|
-
}
|
|
2589
|
-
},
|
|
2590
|
-
Fresnel: {
|
|
2591
|
-
S: function (x) {
|
|
2592
|
-
if(x.isConstant(true)) {
|
|
2593
|
-
return __.defint(_.parse('sin(pi*x^2/2)'), Symbol(0), x, 'x');
|
|
2594
|
-
}
|
|
2595
|
-
return _.symfunction('S', arguments);
|
|
2596
|
-
},
|
|
2597
|
-
C: function (x) {
|
|
2598
|
-
if(x.isConstant(true)) {
|
|
2599
|
-
return __.defint(_.parse('cos(pi*x^2/2)'), Symbol(0), x, 'x');
|
|
2600
|
-
}
|
|
2601
|
-
return _.symfunction('C', arguments);
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
};
|
|
2605
|
-
|
|
2606
|
-
nerdamer.register([
|
|
2607
|
-
{
|
|
2608
|
-
name: 'diff',
|
|
2609
|
-
visible: true,
|
|
2610
|
-
numargs: [1, 3],
|
|
2611
|
-
build: function () {
|
|
2612
|
-
return __.diff;
|
|
2613
|
-
}
|
|
2614
|
-
},
|
|
2615
|
-
{
|
|
2616
|
-
name: 'sum',
|
|
2617
|
-
visible: true,
|
|
2618
|
-
numargs: 4,
|
|
2619
|
-
build: function () {
|
|
2620
|
-
return __.sum;
|
|
2621
|
-
}
|
|
2622
|
-
},
|
|
2623
|
-
{
|
|
2624
|
-
name: 'product',
|
|
2625
|
-
visible: true,
|
|
2626
|
-
numargs: 4,
|
|
2627
|
-
build: function () {
|
|
2628
|
-
return __.product;
|
|
2629
|
-
}
|
|
2630
|
-
},
|
|
2631
|
-
{
|
|
2632
|
-
name: 'integrate',
|
|
2633
|
-
visible: true,
|
|
2634
|
-
numargs: [1, 2],
|
|
2635
|
-
build: function () {
|
|
2636
|
-
return __.integrate;
|
|
2637
|
-
}
|
|
2638
|
-
},
|
|
2639
|
-
{
|
|
2640
|
-
name: 'defint',
|
|
2641
|
-
visible: true,
|
|
2642
|
-
numargs: [3, 4],
|
|
2643
|
-
build: function () {
|
|
2644
|
-
return __.defint;
|
|
2645
|
-
}
|
|
2646
|
-
},
|
|
2647
|
-
{
|
|
2648
|
-
name: 'S',
|
|
2649
|
-
visible: true,
|
|
2650
|
-
numargs: 1,
|
|
2651
|
-
build: function () {
|
|
2652
|
-
return __.Fresnel.S;
|
|
2653
|
-
}
|
|
2654
|
-
},
|
|
2655
|
-
{
|
|
2656
|
-
name: 'C',
|
|
2657
|
-
visible: true,
|
|
2658
|
-
numargs: 1,
|
|
2659
|
-
build: function () {
|
|
2660
|
-
return __.Fresnel.C;
|
|
2661
|
-
}
|
|
2662
|
-
},
|
|
2663
|
-
{
|
|
2664
|
-
name: 'limit',
|
|
2665
|
-
visible: true,
|
|
2666
|
-
numargs: [3, 4],
|
|
2667
|
-
build: function () {
|
|
2668
|
-
return __.Limit.limit;
|
|
2669
|
-
}
|
|
2670
|
-
}
|
|
2671
|
-
]);
|
|
2672
|
-
//link registered functions externally
|
|
2673
|
-
nerdamer.updateAPI();
|
|
2674
|
-
|
|
2675
|
-
})();
|