nerdamer 1.1.13 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +184 -0
- package/README.md +293 -312
- package/dist/bundle.js +2 -0
- package/dist/bundle.js.LICENSE.txt +7 -0
- package/dist/parser.js +2 -0
- package/dist/parser.js.LICENSE.txt +7 -0
- package/docs-data/parser-functions.json +1960 -0
- package/index.d.ts +10 -426
- package/output/algebra/adapters.d.ts +33 -0
- package/output/algebra/adapters.js +109 -0
- package/output/algebra/algorithms/arith.d.ts +84 -0
- package/output/algebra/algorithms/arith.js +323 -0
- package/output/algebra/algorithms/factor.d.ts +3 -0
- package/output/algebra/algorithms/factor.js +5 -0
- package/output/algebra/algorithms/factorMultivariate.d.ts +23 -0
- package/output/algebra/algorithms/factorMultivariate.js +2393 -0
- package/output/algebra/algorithms/factorUnivariate.d.ts +72 -0
- package/output/algebra/algorithms/factorUnivariate.js +1072 -0
- package/output/algebra/algorithms/gcd.d.ts +22 -0
- package/output/algebra/algorithms/gcd.js +690 -0
- package/output/algebra/algorithms/groebnerBase.d.ts +157 -0
- package/output/algebra/algorithms/groebnerBase.js +1166 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +137 -0
- package/output/algebra/algorithms/multiPoly/MultiPoly.js +346 -0
- package/output/algebra/algorithms/poly.d.ts +228 -0
- package/output/algebra/algorithms/poly.js +1299 -0
- package/output/algebra/algorithms/rational.d.ts +17 -0
- package/output/algebra/algorithms/rational.js +115 -0
- package/output/algebra/factor/factor.d.ts +62 -0
- package/output/algebra/factor/factor.js +158 -0
- package/output/algebra/gcd/gcd.d.ts +29 -0
- package/output/algebra/gcd/gcd.js +141 -0
- package/output/algebra/groebner.d.ts +21 -0
- package/output/algebra/groebner.js +42 -0
- package/output/algebra/partfrac.d.ts +19 -0
- package/output/algebra/partfrac.js +398 -0
- package/output/algebra/polynomialize.d.ts +20 -0
- package/output/algebra/polynomialize.js +24 -0
- package/output/algebra/simplify/complexsimp.d.ts +7 -0
- package/output/algebra/simplify/complexsimp.js +24 -0
- package/output/algebra/simplify/factorCommon.d.ts +13 -0
- package/output/algebra/simplify/factorCommon.js +136 -0
- package/output/algebra/simplify/funcsimp.d.ts +26 -0
- package/output/algebra/simplify/funcsimp.js +633 -0
- package/output/algebra/simplify/invtrigrewrite.d.ts +10 -0
- package/output/algebra/simplify/invtrigrewrite.js +96 -0
- package/output/algebra/simplify/ratsimp.d.ts +21 -0
- package/output/algebra/simplify/ratsimp.js +140 -0
- package/output/algebra/simplify/simplify.d.ts +25 -0
- package/output/algebra/simplify/simplify.js +228 -0
- package/output/algebra/simplify/trigreduce.d.ts +38 -0
- package/output/algebra/simplify/trigreduce.js +424 -0
- package/output/algebra/simplify/trigrewrite.d.ts +17 -0
- package/output/algebra/simplify/trigrewrite.js +156 -0
- package/output/algebra/simplify/trigsimp.d.ts +11 -0
- package/output/algebra/simplify/trigsimp.js +369 -0
- package/output/algebra/simplify/utils.d.ts +32 -0
- package/output/algebra/simplify/utils.js +56 -0
- package/output/algebra/utils.d.ts +32 -0
- package/output/algebra/utils.js +48 -0
- package/output/api/advanced.d.ts +7 -0
- package/output/api/advanced.js +18 -0
- package/output/api/algebra.d.ts +17 -0
- package/output/api/algebra.js +32 -0
- package/output/api/assumptions.d.ts +4 -0
- package/output/api/assumptions.js +11 -0
- package/output/api/calculus.d.ts +9 -0
- package/output/api/calculus.js +21 -0
- package/output/api/core.d.ts +17 -0
- package/output/api/core.js +41 -0
- package/output/api/debug.d.ts +16 -0
- package/output/api/debug.js +23 -0
- package/output/api/parser.d.ts +85 -0
- package/output/api/parser.js +16 -0
- package/output/api/solve.d.ts +10 -0
- package/output/api/solve.js +16 -0
- package/output/api/structures.d.ts +10 -0
- package/output/api/structures.js +22 -0
- package/output/calculus/derivative/diff.d.ts +30 -0
- package/output/calculus/derivative/diff.js +238 -0
- package/output/calculus/fresnel.d.ts +16 -0
- package/output/calculus/fresnel.js +39 -0
- package/output/calculus/integrate/byParts.d.ts +18 -0
- package/output/calculus/integrate/byParts.js +339 -0
- package/output/calculus/integrate/bySubstitution.d.ts +135 -0
- package/output/calculus/integrate/bySubstitution.js +411 -0
- package/output/calculus/integrate/integrate.d.ts +38 -0
- package/output/calculus/integrate/integrate.js +652 -0
- package/output/calculus/integrate/integrationTable.d.ts +2 -0
- package/output/calculus/integrate/integrationTable.js +914 -0
- package/output/calculus/integrate/utils.d.ts +28 -0
- package/output/calculus/integrate/utils.js +96 -0
- package/output/calculus/laplace/ilaplace.d.ts +31 -0
- package/output/calculus/laplace/ilaplace.js +192 -0
- package/output/calculus/laplace/ilaplaceTable.d.ts +2 -0
- package/output/calculus/laplace/ilaplaceTable.js +200 -0
- package/output/calculus/laplace/laplace.d.ts +22 -0
- package/output/calculus/laplace/laplace.js +109 -0
- package/output/calculus/laplace/laplaceTable.d.ts +2 -0
- package/output/calculus/laplace/laplaceTable.js +187 -0
- package/output/calculus/limit/limit.d.ts +35 -0
- package/output/calculus/limit/limit.js +1183 -0
- package/output/calculus/limit/limitsTable.d.ts +2 -0
- package/output/calculus/limit/limitsTable.js +7 -0
- package/output/core/Settings.d.ts +32 -0
- package/output/core/Settings.js +68 -0
- package/output/core/adapters.d.ts +18 -0
- package/output/core/adapters.js +40 -0
- package/output/core/classes/assumption/Assumption.d.ts +218 -0
- package/output/core/classes/assumption/Assumption.js +605 -0
- package/output/core/classes/assumption/assertiveFunctions.d.ts +6 -0
- package/output/core/classes/assumption/assertiveFunctions.js +64 -0
- package/output/core/classes/assumption/assume.d.ts +90 -0
- package/output/core/classes/assumption/assume.js +145 -0
- package/output/core/classes/collection/Collection.d.ts +107 -0
- package/output/core/classes/collection/Collection.js +231 -0
- package/output/core/classes/complex/Complex.d.ts +99 -0
- package/output/core/classes/complex/Complex.js +135 -0
- package/output/core/classes/decimalSet/DecimalSet.d.ts +226 -0
- package/output/core/classes/decimalSet/DecimalSet.js +453 -0
- package/output/core/classes/dictionary/Dictionary.d.ts +102 -0
- package/output/core/classes/dictionary/Dictionary.js +213 -0
- package/output/core/classes/equation/Equation.d.ts +256 -0
- package/output/core/classes/equation/Equation.js +350 -0
- package/output/core/classes/expression/CoeffObject.d.ts +100 -0
- package/output/core/classes/expression/CoeffObject.js +198 -0
- package/output/core/classes/expression/Expression.d.ts +1674 -0
- package/output/core/classes/expression/Expression.js +2332 -0
- package/output/core/classes/expression/analysis.d.ts +25 -0
- package/output/core/classes/expression/analysis.js +218 -0
- package/output/core/classes/expression/collect.d.ts +9 -0
- package/output/core/classes/expression/collect.js +49 -0
- package/output/core/classes/expression/format.d.ts +45 -0
- package/output/core/classes/expression/format.js +217 -0
- package/output/core/classes/expression/products.d.ts +23 -0
- package/output/core/classes/expression/products.js +115 -0
- package/output/core/classes/expression/shortcuts.d.ts +35 -0
- package/output/core/classes/expression/shortcuts.js +129 -0
- package/output/core/classes/expression/traversal.d.ts +31 -0
- package/output/core/classes/expression/traversal.js +216 -0
- package/output/core/classes/expression/trig.d.ts +25 -0
- package/output/core/classes/expression/trig.js +40 -0
- package/output/core/classes/expression/utils.d.ts +52 -0
- package/output/core/classes/expression/utils.js +189 -0
- package/output/core/classes/lookupTable/LookupTable.d.ts +12 -0
- package/output/core/classes/lookupTable/LookupTable.js +55 -0
- package/output/core/classes/matrix/Matrix.d.ts +227 -0
- package/output/core/classes/matrix/Matrix.js +889 -0
- package/output/core/classes/matrix/Sylvester.d.ts +11 -0
- package/output/core/classes/matrix/Sylvester.js +54 -0
- package/output/core/classes/matrix/functions.d.ts +26 -0
- package/output/core/classes/matrix/functions.js +52 -0
- package/output/core/classes/matrix/utils.d.ts +9 -0
- package/output/core/classes/matrix/utils.js +22 -0
- package/output/core/classes/parser/Parser.d.ts +480 -0
- package/output/core/classes/parser/Parser.js +1812 -0
- package/output/core/classes/parser/Token.d.ts +58 -0
- package/output/core/classes/parser/Token.js +137 -0
- package/output/core/classes/parser/constants.d.ts +160 -0
- package/output/core/classes/parser/constants.js +227 -0
- package/output/core/classes/parser/helpers.d.ts +21 -0
- package/output/core/classes/parser/helpers.js +42 -0
- package/output/core/classes/parser/operations/add.d.ts +15 -0
- package/output/core/classes/parser/operations/add.js +238 -0
- package/output/core/classes/parser/operations/comma.d.ts +7 -0
- package/output/core/classes/parser/operations/comma.js +11 -0
- package/output/core/classes/parser/operations/compare.d.ts +21 -0
- package/output/core/classes/parser/operations/compare.js +461 -0
- package/output/core/classes/parser/operations/divide.d.ts +2 -0
- package/output/core/classes/parser/operations/divide.js +72 -0
- package/output/core/classes/parser/operations/functions.d.ts +46 -0
- package/output/core/classes/parser/operations/functions.js +430 -0
- package/output/core/classes/parser/operations/multiply.d.ts +11 -0
- package/output/core/classes/parser/operations/multiply.js +321 -0
- package/output/core/classes/parser/operations/power.d.ts +48 -0
- package/output/core/classes/parser/operations/power.js +673 -0
- package/output/core/classes/parser/operations/subtract.d.ts +3 -0
- package/output/core/classes/parser/operations/subtract.js +35 -0
- package/output/core/classes/parser/preprocess.d.ts +14 -0
- package/output/core/classes/parser/preprocess.js +259 -0
- package/output/core/classes/parser/scripting/controlFlow.d.ts +121 -0
- package/output/core/classes/parser/scripting/controlFlow.js +355 -0
- package/output/core/classes/parser/scripting/evaluate.d.ts +10 -0
- package/output/core/classes/parser/scripting/evaluate.js +112 -0
- package/output/core/classes/parser/scripting/functions.d.ts +14 -0
- package/output/core/classes/parser/scripting/functions.js +59 -0
- package/output/core/classes/parser/scripting/scope.d.ts +35 -0
- package/output/core/classes/parser/scripting/scope.js +155 -0
- package/output/core/classes/parser/types.d.ts +125 -0
- package/output/core/classes/parser/types.js +2 -0
- package/output/core/classes/parser/wrappers/IndexedReference.d.ts +31 -0
- package/output/core/classes/parser/wrappers/IndexedReference.js +68 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +24 -0
- package/output/core/classes/parser/wrappers/KeyValuePair.js +51 -0
- package/output/core/classes/polynomial/Polynomial.d.ts +500 -0
- package/output/core/classes/polynomial/Polynomial.js +1149 -0
- package/output/core/classes/polynomial/Term.d.ts +222 -0
- package/output/core/classes/polynomial/Term.js +430 -0
- package/output/core/classes/polynomial/functions.d.ts +69 -0
- package/output/core/classes/polynomial/functions.js +126 -0
- package/output/core/classes/polynomial/utils.d.ts +62 -0
- package/output/core/classes/polynomial/utils.js +206 -0
- package/output/core/classes/rational/Rational.d.ts +504 -0
- package/output/core/classes/rational/Rational.js +779 -0
- package/output/core/classes/seq/SEQ.d.ts +13 -0
- package/output/core/classes/seq/SEQ.js +137 -0
- package/output/core/classes/valuesSet/ValuesSet.d.ts +179 -0
- package/output/core/classes/valuesSet/ValuesSet.js +381 -0
- package/output/core/classes/vector/Vector.d.ts +222 -0
- package/output/core/classes/vector/Vector.js +497 -0
- package/output/core/classes/vector/functions.d.ts +28 -0
- package/output/core/classes/vector/functions.js +47 -0
- package/output/core/common/classes/MathematicalAggregate.d.ts +53 -0
- package/output/core/common/classes/MathematicalAggregate.js +140 -0
- package/output/core/common/classes/Scope.d.ts +62 -0
- package/output/core/common/classes/Scope.js +122 -0
- package/output/core/common/classes/StructuredEntity.d.ts +55 -0
- package/output/core/common/classes/StructuredEntity.js +151 -0
- package/output/core/common/common.d.ts +63 -0
- package/output/core/common/common.js +279 -0
- package/output/core/common/functions/functions.d.ts +14 -0
- package/output/core/common/functions/functions.js +33 -0
- package/output/core/common/functions/structuredEntityUtils.d.ts +27 -0
- package/output/core/common/functions/structuredEntityUtils.js +40 -0
- package/output/core/converters/BaseConverter.d.ts +97 -0
- package/output/core/converters/BaseConverter.js +405 -0
- package/output/core/converters/Converter.d.ts +111 -0
- package/output/core/converters/Converter.js +802 -0
- package/output/core/converters/Pattern.d.ts +71 -0
- package/output/core/converters/Pattern.js +302 -0
- package/output/core/dispatch.d.ts +34 -0
- package/output/core/dispatch.js +304 -0
- package/output/core/errors.d.ts +531 -0
- package/output/core/errors.js +621 -0
- package/output/core/functions/bigint/bigint.d.ts +121 -0
- package/output/core/functions/bigint/bigint.js +392 -0
- package/output/core/functions/bigint/primeFactor.d.ts +49 -0
- package/output/core/functions/bigint/primeFactor.js +267 -0
- package/output/core/functions/bigint/primes.d.ts +1 -0
- package/output/core/functions/bigint/primes.js +11 -0
- package/output/core/functions/build/definitions.d.ts +12 -0
- package/output/core/functions/build/definitions.js +133 -0
- package/output/core/functions/build/index.d.ts +32 -0
- package/output/core/functions/build/index.js +136 -0
- package/output/core/functions/complex.d.ts +90 -0
- package/output/core/functions/complex.js +482 -0
- package/output/core/functions/decimal.d.ts +24 -0
- package/output/core/functions/decimal.js +664 -0
- package/output/core/functions/expand/expand.d.ts +42 -0
- package/output/core/functions/expand/expand.js +376 -0
- package/output/core/functions/fresnelNumeric.d.ts +12 -0
- package/output/core/functions/fresnelNumeric.js +123 -0
- package/output/core/functions/numeric.d.ts +140 -0
- package/output/core/functions/numeric.js +790 -0
- package/output/core/functions/rationalNormalization.d.ts +11 -0
- package/output/core/functions/rationalNormalization.js +117 -0
- package/output/core/functions/setFunction.d.ts +19 -0
- package/output/core/functions/setFunction.js +75 -0
- package/output/core/functions/string.d.ts +26 -0
- package/output/core/functions/string.js +101 -0
- package/output/core/functions/subst.d.ts +90 -0
- package/output/core/functions/subst.js +498 -0
- package/output/core/functions/utils.d.ts +24 -0
- package/output/core/functions/utils.js +51 -0
- package/output/core/types.d.ts +48 -0
- package/output/core/types.js +2 -0
- package/output/index.d.ts +339 -0
- package/output/index.js +715 -0
- package/output/math/defint/defintDecimal.d.ts +37 -0
- package/output/math/defint/defintDecimal.js +320 -0
- package/output/math/defint/defintNative.d.ts +57 -0
- package/output/math/defint/defintNative.js +292 -0
- package/output/math/geometry.d.ts +8 -0
- package/output/math/geometry.js +32 -0
- package/output/math/math.d.ts +655 -0
- package/output/math/math.js +1811 -0
- package/output/math/trig.d.ts +518 -0
- package/output/math/trig.js +1444 -0
- package/output/math/trunc.d.ts +19 -0
- package/output/math/trunc.js +36 -0
- package/output/math/utils.d.ts +60 -0
- package/output/math/utils.js +180 -0
- package/output/solve/classes/DecimalMatrix.d.ts +17 -0
- package/output/solve/classes/DecimalMatrix.js +86 -0
- package/output/solve/classes/FunctionSolver.d.ts +135 -0
- package/output/solve/classes/FunctionSolver.js +433 -0
- package/output/solve/classes/MultivariateSolver.d.ts +84 -0
- package/output/solve/classes/MultivariateSolver.js +240 -0
- package/output/solve/classes/PolynomialSolver.d.ts +85 -0
- package/output/solve/classes/PolynomialSolver.js +292 -0
- package/output/solve/classes/SolutionSet.d.ts +153 -0
- package/output/solve/classes/SolutionSet.js +357 -0
- package/output/solve/classes/Solver.d.ts +17 -0
- package/output/solve/classes/Solver.js +132 -0
- package/output/solve/classes/SymbolicSolver.d.ts +74 -0
- package/output/solve/classes/SymbolicSolver.js +601 -0
- package/output/solve/linsolve.d.ts +51 -0
- package/output/solve/linsolve.js +225 -0
- package/output/solve/solve.d.ts +34 -0
- package/output/solve/solve.js +260 -0
- package/output/solve/solveSystem.d.ts +31 -0
- package/output/solve/solveSystem.js +290 -0
- package/output/solve/utils.d.ts +9 -0
- package/output/solve/utils.js +62 -0
- package/output/utils/array.d.ts +42 -0
- package/output/utils/array.js +98 -0
- package/output/utils/debug.d.ts +131 -0
- package/output/utils/debug.js +295 -0
- package/output/utils/decimal.d.ts +3 -0
- package/output/utils/decimal.js +16 -0
- package/output/utils/numeric.d.ts +14 -0
- package/output/utils/numeric.js +51 -0
- package/output/utils/object.d.ts +26 -0
- package/output/utils/object.js +56 -0
- package/package.json +213 -57
- package/.travis.yml +0 -3
- package/Algebra.js +0 -4568
- package/BREAKING_CHANGES.md +0 -5
- package/CODE_OF_CONDUCT.md +0 -46
- package/CONTRIBUTING.md +0 -14
- package/Calculus.js +0 -2675
- package/Extra.js +0 -622
- package/Solve.js +0 -1783
- package/all.js +0 -16
- package/all.min.js +0 -1
- package/gulpfile.js +0 -16
- package/index.html +0 -158
- package/license.txt +0 -19
- package/nerdamer.core.js +0 -12510
- package/spec/LaTeX.spec.js +0 -302
- package/spec/TeXConvert.spec.js +0 -8
- package/spec/algebra.spec.js +0 -287
- package/spec/basic_parser.spec.js +0 -134
- package/spec/build.spec.js +0 -131
- package/spec/calculus.spec.js +0 -183
- package/spec/core.spec.js +0 -2970
- package/spec/extra.spec.js +0 -54
- package/spec/solve.spec.js +0 -126
- package/spec/support/jasmine.json +0 -11
- package/spec/support/utils.js +0 -42
- package/spec/text.spec.js +0 -132
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reduceTrigPower = reduceTrigPower;
|
|
4
|
+
exports.trigReduce = trigReduce;
|
|
5
|
+
exports.expandDoubleAngle = expandDoubleAngle;
|
|
6
|
+
exports.productToSum = productToSum;
|
|
7
|
+
exports.convertToDoubleAngle = convertToDoubleAngle;
|
|
8
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
9
|
+
const shortcuts_1 = require("../../core/classes/expression/shortcuts");
|
|
10
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
11
|
+
const trig_1 = require("../../math/trig");
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// POWER REDUCTION (trigreduce)
|
|
14
|
+
//
|
|
15
|
+
// Reduces powers of trig functions using double-angle identities:
|
|
16
|
+
// sin²(u) → (1 - cos(2u)) / 2
|
|
17
|
+
// cos²(u) → (1 + cos(2u)) / 2
|
|
18
|
+
// sin²(u)·cos²(u) → (1 - cos(4u)) / 8 (via sin(2u)²/4)
|
|
19
|
+
//
|
|
20
|
+
// Higher powers are handled recursively:
|
|
21
|
+
// sin³(u) → sin(u)·sin²(u) → sin(u)·(1 - cos(2u))/2
|
|
22
|
+
// sin⁴(u) → (sin²(u))² → ((1 - cos(2u))/2)² → (3 - 4cos(2u) + cos(4u))/8
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Applies power reduction to a single trig function with an integer power ≥ 2.
|
|
26
|
+
*
|
|
27
|
+
* sin(u)^(2k) → expanded using repeated application of half-angle
|
|
28
|
+
* cos(u)^(2k) → expanded using repeated application of half-angle
|
|
29
|
+
* sin(u)^(2k+1) → sin(u) · [sin(u)^(2k) reduced]
|
|
30
|
+
* cos(u)^(2k+1) → cos(u) · [cos(u)^(2k) reduced]
|
|
31
|
+
*
|
|
32
|
+
* Only applies when the power is an integer ≥ 2 (or ≤ -2).
|
|
33
|
+
* Fractional powers like sin(x)^(1/2) are left unchanged.
|
|
34
|
+
*/
|
|
35
|
+
function reduceTrigPower(e) {
|
|
36
|
+
if (!e.isFunction(constants_1.SIN) && !e.isFunction(constants_1.COS)) {
|
|
37
|
+
return e;
|
|
38
|
+
}
|
|
39
|
+
const p = e.getPower();
|
|
40
|
+
const m = e.getMultiplier();
|
|
41
|
+
const args = e.getArguments();
|
|
42
|
+
if (args.length === 0) {
|
|
43
|
+
return e;
|
|
44
|
+
}
|
|
45
|
+
const u = args[0];
|
|
46
|
+
const isSin = e.isFunction(constants_1.SIN);
|
|
47
|
+
// Only reduce integer powers with |n| >= 2.
|
|
48
|
+
// The power is an Expression. Check that it's a pure integer by inspecting
|
|
49
|
+
// its Rational multiplier: it must be an integer (denominator === 1n)
|
|
50
|
+
// and the power itself must be a NUM type (no symbolic component).
|
|
51
|
+
if (!p.isNUM()) {
|
|
52
|
+
return e;
|
|
53
|
+
}
|
|
54
|
+
const pRat = p.getMultiplier(); // Rational
|
|
55
|
+
if (pRat.denominator !== 1n && pRat.denominator !== -1n) {
|
|
56
|
+
// Fractional power — not an integer, leave unchanged
|
|
57
|
+
return e;
|
|
58
|
+
}
|
|
59
|
+
const nBig = pRat.numerator / (pRat.denominator < 0n ? -pRat.denominator : pRat.denominator);
|
|
60
|
+
const nAbs = nBig < 0n ? -nBig : nBig;
|
|
61
|
+
if (nAbs < 2n) {
|
|
62
|
+
return e;
|
|
63
|
+
}
|
|
64
|
+
// For negative powers, reduce the positive power and invert
|
|
65
|
+
if (nBig < 0n) {
|
|
66
|
+
const positive = reduceTrigPower(isSin
|
|
67
|
+
? (0, trig_1.sin)(u).pow(Expression_1.Expression.Number(nAbs))
|
|
68
|
+
: (0, trig_1.cos)(u).pow(Expression_1.Expression.Number(nAbs)));
|
|
69
|
+
return Expression_1.Expression.fromRational(m).times(positive.invert());
|
|
70
|
+
}
|
|
71
|
+
const n = Number(nAbs);
|
|
72
|
+
let result;
|
|
73
|
+
if (n === 2) {
|
|
74
|
+
// sin²(u) = (1 - cos(2u)) / 2
|
|
75
|
+
// cos²(u) = (1 + cos(2u)) / 2
|
|
76
|
+
const twoU = u.times((0, shortcuts_1.two)());
|
|
77
|
+
if (isSin) {
|
|
78
|
+
result = (0, shortcuts_1.one)().minus((0, trig_1.cos)(twoU)).div((0, shortcuts_1.two)());
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
result = (0, shortcuts_1.one)().plus((0, trig_1.cos)(twoU)).div((0, shortcuts_1.two)());
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (n % 2 === 0) {
|
|
85
|
+
// Even power: sin^(2k)(u) = (sin²(u))^k, then reduce sin²
|
|
86
|
+
const halfPower = n / 2;
|
|
87
|
+
const squared = reduceTrigPower(isSin ? (0, trig_1.sin)(u).pow((0, shortcuts_1.two)()) : (0, trig_1.cos)(u).pow((0, shortcuts_1.two)()));
|
|
88
|
+
result = squared.pow(Expression_1.Expression.create(`${halfPower}`));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Odd power: sin^(2k+1)(u) = sin(u) · sin^(2k)(u)
|
|
92
|
+
const evenPart = reduceTrigPower(isSin
|
|
93
|
+
? (0, trig_1.sin)(u).pow(Expression_1.Expression.create(`${n - 1}`))
|
|
94
|
+
: (0, trig_1.cos)(u).pow(Expression_1.Expression.create(`${n - 1}`)));
|
|
95
|
+
result = (isSin ? (0, trig_1.sin)(u) : (0, trig_1.cos)(u)).times(evenPart);
|
|
96
|
+
}
|
|
97
|
+
if (!m.isOne()) {
|
|
98
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Applies power reduction to all trig powers in an expression.
|
|
104
|
+
* Descends into sums and products.
|
|
105
|
+
*/
|
|
106
|
+
function trigReduce(x) {
|
|
107
|
+
// Direct trig function
|
|
108
|
+
if ((x.isFunction(constants_1.SIN) || x.isFunction(constants_1.COS)) && x.getPower().isInteger()) {
|
|
109
|
+
const p = x.getPower();
|
|
110
|
+
if (p.abs().gte((0, shortcuts_1.two)())) {
|
|
111
|
+
return reduceTrigPower(x);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Sum: reduce each term
|
|
115
|
+
if (x.isSum()) {
|
|
116
|
+
const m = x.getMultiplier();
|
|
117
|
+
const p = x.getPower();
|
|
118
|
+
let result = (0, shortcuts_1.zero)();
|
|
119
|
+
for (const term of x.elementsArray()) {
|
|
120
|
+
result = result.plus(trigReduce(term));
|
|
121
|
+
}
|
|
122
|
+
if (!p.isOne()) {
|
|
123
|
+
result = result.pow(p);
|
|
124
|
+
}
|
|
125
|
+
if (!m.isOne()) {
|
|
126
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
// Product: reduce each factor
|
|
131
|
+
if (x.isProduct()) {
|
|
132
|
+
const m = x.getMultiplier();
|
|
133
|
+
const p = x.getPower();
|
|
134
|
+
let result = (0, shortcuts_1.one)();
|
|
135
|
+
for (const element of x.elementsArray()) {
|
|
136
|
+
result = result.times(trigReduce(element));
|
|
137
|
+
}
|
|
138
|
+
if (!p.isOne()) {
|
|
139
|
+
result = result.pow(p);
|
|
140
|
+
}
|
|
141
|
+
if (!m.isOne()) {
|
|
142
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
return x;
|
|
147
|
+
}
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// DOUBLE ANGLE IDENTITIES
|
|
150
|
+
//
|
|
151
|
+
// Expansion direction (useful for simplification):
|
|
152
|
+
// sin(2u) → 2·sin(u)·cos(u)
|
|
153
|
+
// cos(2u) → cos²(u) - sin²(u)
|
|
154
|
+
// → 2·cos²(u) - 1
|
|
155
|
+
// → 1 - 2·sin²(u)
|
|
156
|
+
//
|
|
157
|
+
// Reverse direction (useful for reducing products):
|
|
158
|
+
// 2·sin(u)·cos(u) → sin(2u)
|
|
159
|
+
// cos²(u) - sin²(u) → cos(2u)
|
|
160
|
+
// ============================================================================
|
|
161
|
+
/**
|
|
162
|
+
* Expands double angle: sin(2u) → 2·sin(u)·cos(u)
|
|
163
|
+
* Only applies if the argument has a factor of 2.
|
|
164
|
+
*/
|
|
165
|
+
function expandDoubleAngleSin(e) {
|
|
166
|
+
if (!e.isFunction(constants_1.SIN)) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const args = e.getArguments();
|
|
170
|
+
if (args.length === 0) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const arg = args[0];
|
|
174
|
+
const m = e.getMultiplier();
|
|
175
|
+
const p = e.getPower();
|
|
176
|
+
// Check if argument is 2*u for some u
|
|
177
|
+
const u = extractHalfArgument(arg);
|
|
178
|
+
if (!u) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
// sin(2u) = 2·sin(u)·cos(u)
|
|
182
|
+
let result = (0, shortcuts_1.two)().times((0, trig_1.sin)(u)).times((0, trig_1.cos)(u));
|
|
183
|
+
if (!p.isOne()) {
|
|
184
|
+
result = result.pow(p);
|
|
185
|
+
}
|
|
186
|
+
if (!m.isOne()) {
|
|
187
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Expands double angle: cos(2u) → cos²(u) - sin²(u)
|
|
193
|
+
* Only applies if the argument has a factor of 2.
|
|
194
|
+
*/
|
|
195
|
+
function expandDoubleAngleCos(e) {
|
|
196
|
+
if (!e.isFunction(constants_1.COS)) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const args = e.getArguments();
|
|
200
|
+
if (args.length === 0) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
const arg = args[0];
|
|
204
|
+
const m = e.getMultiplier();
|
|
205
|
+
const p = e.getPower();
|
|
206
|
+
const u = extractHalfArgument(arg);
|
|
207
|
+
if (!u) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
// cos(2u) = cos²(u) - sin²(u)
|
|
211
|
+
let result = (0, trig_1.cos)(u).pow((0, shortcuts_1.two)()).minus((0, trig_1.sin)(u).pow((0, shortcuts_1.two)()));
|
|
212
|
+
if (!p.isOne()) {
|
|
213
|
+
result = result.pow(p);
|
|
214
|
+
}
|
|
215
|
+
if (!m.isOne()) {
|
|
216
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* If the argument is of the form 2*u, returns u. Otherwise returns null.
|
|
222
|
+
*/
|
|
223
|
+
function extractHalfArgument(arg) {
|
|
224
|
+
const m = arg.getMultiplier();
|
|
225
|
+
// Check if the multiplier is even (has a factor of 2)
|
|
226
|
+
if (m.numerator % 2n === 0n) {
|
|
227
|
+
// Divide multiplier by 2
|
|
228
|
+
const half = arg.div((0, shortcuts_1.two)());
|
|
229
|
+
return half;
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Expands all double-angle trig functions in an expression.
|
|
235
|
+
*/
|
|
236
|
+
function expandDoubleAngle(x) {
|
|
237
|
+
if (x.isFunction(constants_1.SIN)) {
|
|
238
|
+
const expanded = expandDoubleAngleSin(x);
|
|
239
|
+
if (expanded) {
|
|
240
|
+
return expanded;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (x.isFunction(constants_1.COS)) {
|
|
244
|
+
const expanded = expandDoubleAngleCos(x);
|
|
245
|
+
if (expanded) {
|
|
246
|
+
return expanded;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (x.isSum()) {
|
|
250
|
+
const m = x.getMultiplier();
|
|
251
|
+
const p = x.getPower();
|
|
252
|
+
let result = (0, shortcuts_1.zero)();
|
|
253
|
+
for (const term of x.elementsArray()) {
|
|
254
|
+
result = result.plus(expandDoubleAngle(term));
|
|
255
|
+
}
|
|
256
|
+
if (!p.isOne()) {
|
|
257
|
+
result = result.pow(p);
|
|
258
|
+
}
|
|
259
|
+
if (!m.isOne()) {
|
|
260
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
if (x.isProduct()) {
|
|
265
|
+
const m = x.getMultiplier();
|
|
266
|
+
const p = x.getPower();
|
|
267
|
+
let result = (0, shortcuts_1.one)();
|
|
268
|
+
for (const element of x.elementsArray()) {
|
|
269
|
+
result = result.times(expandDoubleAngle(element));
|
|
270
|
+
}
|
|
271
|
+
if (!p.isOne()) {
|
|
272
|
+
result = result.pow(p);
|
|
273
|
+
}
|
|
274
|
+
if (!m.isOne()) {
|
|
275
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
return x;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Extracts sin/cos factors from a product for product-to-sum conversion.
|
|
283
|
+
* Only extracts factors with power = 1 (linear trig factors).
|
|
284
|
+
*/
|
|
285
|
+
function extractTrigFactors(x) {
|
|
286
|
+
const trigFactors = [];
|
|
287
|
+
let rest = Expression_1.Expression.fromRational(x.getMultiplier());
|
|
288
|
+
if (!x.isProduct()) {
|
|
289
|
+
// Check if x itself is a single trig function
|
|
290
|
+
if ((x.isFunction(constants_1.SIN) || x.isFunction(constants_1.COS)) && x.getPower().eq((0, shortcuts_1.one)())) {
|
|
291
|
+
const args = x.getArguments();
|
|
292
|
+
if (args.length > 0) {
|
|
293
|
+
trigFactors.push({
|
|
294
|
+
fn: x.isFunction(constants_1.SIN) ? constants_1.SIN : constants_1.COS,
|
|
295
|
+
arg: args[0],
|
|
296
|
+
power: x.getPower(),
|
|
297
|
+
});
|
|
298
|
+
rest = Expression_1.Expression.fromRational(x.getMultiplier());
|
|
299
|
+
return { trigFactors, rest };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return { trigFactors: [], rest: x };
|
|
303
|
+
}
|
|
304
|
+
for (const element of x.elementsArray()) {
|
|
305
|
+
if ((element.isFunction(constants_1.SIN) || element.isFunction(constants_1.COS)) && element.getPower().eq((0, shortcuts_1.one)())) {
|
|
306
|
+
const args = element.getArguments();
|
|
307
|
+
if (args.length > 0) {
|
|
308
|
+
trigFactors.push({
|
|
309
|
+
fn: element.isFunction(constants_1.SIN) ? constants_1.SIN : constants_1.COS,
|
|
310
|
+
arg: args[0],
|
|
311
|
+
power: element.getPower(),
|
|
312
|
+
});
|
|
313
|
+
// Include the element's own multiplier in rest
|
|
314
|
+
if (!element.getMultiplier().isOne()) {
|
|
315
|
+
rest = rest.times(Expression_1.Expression.fromRational(element.getMultiplier()));
|
|
316
|
+
}
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
rest = rest.times(element);
|
|
321
|
+
}
|
|
322
|
+
return { trigFactors, rest };
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Converts a product of two trig functions to a sum using product-to-sum identities.
|
|
326
|
+
*
|
|
327
|
+
* sin(a)·cos(b) → (1/2)[sin(a+b) + sin(a-b)]
|
|
328
|
+
* cos(a)·cos(b) → (1/2)[cos(a-b) + cos(a+b)]
|
|
329
|
+
* sin(a)·sin(b) → (1/2)[cos(a-b) - cos(a+b)]
|
|
330
|
+
*/
|
|
331
|
+
function productToSum(x) {
|
|
332
|
+
const { trigFactors, rest } = extractTrigFactors(x);
|
|
333
|
+
// Need at least 2 trig factors to apply product-to-sum
|
|
334
|
+
if (trigFactors.length < 2) {
|
|
335
|
+
return x;
|
|
336
|
+
}
|
|
337
|
+
// Process pairs of trig factors
|
|
338
|
+
let result = rest;
|
|
339
|
+
let i = 0;
|
|
340
|
+
while (i < trigFactors.length - 1) {
|
|
341
|
+
const f1 = trigFactors[i];
|
|
342
|
+
const f2 = trigFactors[i + 1];
|
|
343
|
+
const a = f1.arg;
|
|
344
|
+
const b = f2.arg;
|
|
345
|
+
const aPlusB = a.plus(b);
|
|
346
|
+
const aMinusB = a.minus(b);
|
|
347
|
+
const half = (0, shortcuts_1.one)().div((0, shortcuts_1.two)());
|
|
348
|
+
let converted;
|
|
349
|
+
if (f1.fn === constants_1.SIN && f2.fn === constants_1.COS) {
|
|
350
|
+
// sin(a)·cos(b) = (1/2)[sin(a+b) + sin(a-b)]
|
|
351
|
+
converted = half.times((0, trig_1.sin)(aPlusB).plus((0, trig_1.sin)(aMinusB)));
|
|
352
|
+
}
|
|
353
|
+
else if (f1.fn === constants_1.COS && f2.fn === constants_1.SIN) {
|
|
354
|
+
// cos(a)·sin(b) = (1/2)[sin(a+b) - sin(a-b)]
|
|
355
|
+
converted = half.times((0, trig_1.sin)(aPlusB).minus((0, trig_1.sin)(aMinusB)));
|
|
356
|
+
}
|
|
357
|
+
else if (f1.fn === constants_1.COS && f2.fn === constants_1.COS) {
|
|
358
|
+
// cos(a)·cos(b) = (1/2)[cos(a-b) + cos(a+b)]
|
|
359
|
+
converted = half.times((0, trig_1.cos)(aMinusB).plus((0, trig_1.cos)(aPlusB)));
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
// sin(a)·sin(b) = (1/2)[cos(a-b) - cos(a+b)]
|
|
363
|
+
converted = half.times((0, trig_1.cos)(aMinusB).minus((0, trig_1.cos)(aPlusB)));
|
|
364
|
+
}
|
|
365
|
+
result = result.times(converted);
|
|
366
|
+
i += 2;
|
|
367
|
+
}
|
|
368
|
+
// If there's an unpaired trig factor, multiply it back in
|
|
369
|
+
if (i < trigFactors.length) {
|
|
370
|
+
const leftover = trigFactors[i];
|
|
371
|
+
const fn = leftover.fn === constants_1.SIN ? trig_1.sin : trig_1.cos;
|
|
372
|
+
result = result.times(fn(leftover.arg));
|
|
373
|
+
}
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Converts sin(u)·cos(u) products into double-angle form.
|
|
378
|
+
*
|
|
379
|
+
* k·sin(u)·cos(u) → (k/2)·sin(2u)
|
|
380
|
+
*
|
|
381
|
+
* This is the reverse of expandDoubleAngle for sin.
|
|
382
|
+
*/
|
|
383
|
+
function convertToDoubleAngle(x) {
|
|
384
|
+
if (!x.isProduct()) {
|
|
385
|
+
return x;
|
|
386
|
+
}
|
|
387
|
+
const { trigFactors, rest } = extractTrigFactors(x);
|
|
388
|
+
// Look for sin(u)·cos(u) pairs with matching arguments
|
|
389
|
+
const usedIndices = new Set();
|
|
390
|
+
let result = rest;
|
|
391
|
+
for (let i = 0; i < trigFactors.length; i++) {
|
|
392
|
+
if (usedIndices.has(i)) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
for (let j = i + 1; j < trigFactors.length; j++) {
|
|
396
|
+
if (usedIndices.has(j)) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const a = trigFactors[i];
|
|
400
|
+
const b = trigFactors[j];
|
|
401
|
+
// Check for sin(u)·cos(u) or cos(u)·sin(u) with same argument
|
|
402
|
+
if (a.arg.eq(b.arg) &&
|
|
403
|
+
((a.fn === constants_1.SIN && b.fn === constants_1.COS) || (a.fn === constants_1.COS && b.fn === constants_1.SIN))) {
|
|
404
|
+
// sin(u)·cos(u) = (1/2)·sin(2u)
|
|
405
|
+
const u = a.arg;
|
|
406
|
+
result = result.times((0, shortcuts_1.one)()
|
|
407
|
+
.div((0, shortcuts_1.two)())
|
|
408
|
+
.times((0, trig_1.sin)(u.times((0, shortcuts_1.two)()))));
|
|
409
|
+
usedIndices.add(i);
|
|
410
|
+
usedIndices.add(j);
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Add back any unmatched trig factors
|
|
416
|
+
for (let i = 0; i < trigFactors.length; i++) {
|
|
417
|
+
if (!usedIndices.has(i)) {
|
|
418
|
+
const f = trigFactors[i];
|
|
419
|
+
const fn = f.fn === constants_1.SIN ? trig_1.sin : trig_1.cos;
|
|
420
|
+
result = result.times(fn(f.arg));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether an expression contains any tan, sec, csc, or cot functions.
|
|
4
|
+
*/
|
|
5
|
+
export declare function hasDerivedTrig(x: Expression): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Recursively rewrites all tan, sec, csc, cot in an expression tree to sin/cos form.
|
|
8
|
+
* This is a deep rewrite — it descends into sums, products, and function arguments.
|
|
9
|
+
*/
|
|
10
|
+
export declare function rewrite(x: Expression): Expression;
|
|
11
|
+
/**
|
|
12
|
+
* Attempts to rewrite derived trig functions to sin/cos and checks if the result
|
|
13
|
+
* is simpler (fewer terms or lower complexity). Returns the simpler form.
|
|
14
|
+
*
|
|
15
|
+
* This is the "only rewrite when it leads to cancellation" strategy.
|
|
16
|
+
*/
|
|
17
|
+
export declare function tryRewriteTrig(x: Expression): Expression;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasDerivedTrig = hasDerivedTrig;
|
|
4
|
+
exports.rewrite = rewrite;
|
|
5
|
+
exports.tryRewriteTrig = tryRewriteTrig;
|
|
6
|
+
const Expression_1 = require("../../core/classes/expression/Expression");
|
|
7
|
+
const shortcuts_1 = require("../../core/classes/expression/shortcuts");
|
|
8
|
+
const constants_1 = require("../../core/classes/parser/constants");
|
|
9
|
+
const trig_1 = require("../../math/trig");
|
|
10
|
+
/**
|
|
11
|
+
* Determines whether an expression contains any tan, sec, csc, or cot functions.
|
|
12
|
+
*/
|
|
13
|
+
function hasDerivedTrig(x) {
|
|
14
|
+
let found = false;
|
|
15
|
+
x.forEveryElement(e => {
|
|
16
|
+
if (e.isFunction(constants_1.TAN) || e.isFunction(constants_1.SEC) || e.isFunction(constants_1.CSC) || e.isFunction(constants_1.COT)) {
|
|
17
|
+
found = true;
|
|
18
|
+
}
|
|
19
|
+
return e;
|
|
20
|
+
});
|
|
21
|
+
return found;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Rewrites a single trig function element in terms of sin and cos.
|
|
25
|
+
*
|
|
26
|
+
* tan(u)^n → sin(u)^n * cos(u)^(-n)
|
|
27
|
+
* cot(u)^n → cos(u)^n * sin(u)^(-n)
|
|
28
|
+
* sec(u)^n → cos(u)^(-n)
|
|
29
|
+
* csc(u)^n → sin(u)^(-n)
|
|
30
|
+
*
|
|
31
|
+
* Multiplier and arguments are preserved.
|
|
32
|
+
*/
|
|
33
|
+
function rewriteTrigElement(e) {
|
|
34
|
+
const m = e.getMultiplier();
|
|
35
|
+
const p = e.getPower();
|
|
36
|
+
const args = e.getArguments();
|
|
37
|
+
if (e.isFunction(constants_1.TAN) && args.length > 0) {
|
|
38
|
+
const u = args[0];
|
|
39
|
+
return Expression_1.Expression.fromRational(m).times((0, trig_1.sin)(u).pow(p)).times((0, trig_1.cos)(u).pow(p.neg()));
|
|
40
|
+
}
|
|
41
|
+
if (e.isFunction(constants_1.COT) && args.length > 0) {
|
|
42
|
+
const u = args[0];
|
|
43
|
+
return Expression_1.Expression.fromRational(m).times((0, trig_1.cos)(u).pow(p)).times((0, trig_1.sin)(u).pow(p.neg()));
|
|
44
|
+
}
|
|
45
|
+
if (e.isFunction(constants_1.SEC) && args.length > 0) {
|
|
46
|
+
const u = args[0];
|
|
47
|
+
return Expression_1.Expression.fromRational(m).times((0, trig_1.cos)(u).pow(p.neg()));
|
|
48
|
+
}
|
|
49
|
+
if (e.isFunction(constants_1.CSC) && args.length > 0) {
|
|
50
|
+
const u = args[0];
|
|
51
|
+
return Expression_1.Expression.fromRational(m).times((0, trig_1.sin)(u).pow(p.neg()));
|
|
52
|
+
}
|
|
53
|
+
return e;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Recursively rewrites all tan, sec, csc, cot in an expression tree to sin/cos form.
|
|
57
|
+
* This is a deep rewrite — it descends into sums, products, and function arguments.
|
|
58
|
+
*/
|
|
59
|
+
function rewrite(x) {
|
|
60
|
+
// If it's a direct derived trig function, rewrite it
|
|
61
|
+
if (x.isFunction(constants_1.TAN) || x.isFunction(constants_1.COT) || x.isFunction(constants_1.SEC) || x.isFunction(constants_1.CSC)) {
|
|
62
|
+
return rewriteTrigElement(x);
|
|
63
|
+
}
|
|
64
|
+
// For sums: rewrite each term
|
|
65
|
+
if (x.isSum()) {
|
|
66
|
+
const m = x.getMultiplier();
|
|
67
|
+
const p = x.getPower();
|
|
68
|
+
let result = (0, shortcuts_1.zero)();
|
|
69
|
+
for (const term of x.elementsArray()) {
|
|
70
|
+
result = result.plus(rewrite(term));
|
|
71
|
+
}
|
|
72
|
+
if (!p.isOne()) {
|
|
73
|
+
result = result.pow(p);
|
|
74
|
+
}
|
|
75
|
+
if (!m.isOne()) {
|
|
76
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
// For products: rewrite each factor
|
|
81
|
+
if (x.isProduct()) {
|
|
82
|
+
const m = x.getMultiplier();
|
|
83
|
+
const p = x.getPower();
|
|
84
|
+
let result = (0, shortcuts_1.one)();
|
|
85
|
+
for (const element of x.elementsArray()) {
|
|
86
|
+
result = result.times(rewrite(element));
|
|
87
|
+
}
|
|
88
|
+
if (!p.isOne()) {
|
|
89
|
+
result = result.pow(p);
|
|
90
|
+
}
|
|
91
|
+
if (!m.isOne()) {
|
|
92
|
+
result = result.times(Expression_1.Expression.fromRational(m));
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
// For other functions (sin, cos, log, etc.): rewrite the arguments
|
|
97
|
+
if (x.isFunction()) {
|
|
98
|
+
// Don't rewrite inside sin/cos arguments — the derived trig functions
|
|
99
|
+
// inside arguments would be unusual, but handle it for completeness
|
|
100
|
+
return x;
|
|
101
|
+
}
|
|
102
|
+
return x;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Attempts to rewrite derived trig functions to sin/cos and checks if the result
|
|
106
|
+
* is simpler (fewer terms or lower complexity). Returns the simpler form.
|
|
107
|
+
*
|
|
108
|
+
* This is the "only rewrite when it leads to cancellation" strategy.
|
|
109
|
+
*/
|
|
110
|
+
function tryRewriteTrig(x) {
|
|
111
|
+
if (!hasDerivedTrig(x)) {
|
|
112
|
+
return x;
|
|
113
|
+
}
|
|
114
|
+
const rewritten = rewrite(x);
|
|
115
|
+
// Heuristic: the rewritten form is "better" if it has fewer elements,
|
|
116
|
+
// fewer distinct function types, or leads to cancellation (becomes simpler text).
|
|
117
|
+
// A simple proxy: compare text length or element count.
|
|
118
|
+
if (complexity(rewritten) <= complexity(x)) {
|
|
119
|
+
return rewritten;
|
|
120
|
+
}
|
|
121
|
+
return x;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Simple complexity metric for an expression.
|
|
125
|
+
* Lower is simpler.
|
|
126
|
+
*/
|
|
127
|
+
function complexity(x) {
|
|
128
|
+
const text = x.text();
|
|
129
|
+
// Count the number of function calls, operations, and terms as a rough proxy
|
|
130
|
+
let score = text.length;
|
|
131
|
+
// Bonus: fewer distinct trig function types is better
|
|
132
|
+
const types = new Set();
|
|
133
|
+
x.forEveryElement(e => {
|
|
134
|
+
if (e.isFunction(constants_1.SIN)) {
|
|
135
|
+
types.add(constants_1.SIN);
|
|
136
|
+
}
|
|
137
|
+
if (e.isFunction(constants_1.COS)) {
|
|
138
|
+
types.add(constants_1.COS);
|
|
139
|
+
}
|
|
140
|
+
if (e.isFunction(constants_1.TAN)) {
|
|
141
|
+
types.add(constants_1.TAN);
|
|
142
|
+
}
|
|
143
|
+
if (e.isFunction(constants_1.SEC)) {
|
|
144
|
+
types.add(constants_1.SEC);
|
|
145
|
+
}
|
|
146
|
+
if (e.isFunction(constants_1.CSC)) {
|
|
147
|
+
types.add(constants_1.CSC);
|
|
148
|
+
}
|
|
149
|
+
if (e.isFunction(constants_1.COT)) {
|
|
150
|
+
types.add(constants_1.COT);
|
|
151
|
+
}
|
|
152
|
+
return e;
|
|
153
|
+
});
|
|
154
|
+
score += types.size * 10;
|
|
155
|
+
return score;
|
|
156
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Expression } from '../../core/classes/expression/Expression';
|
|
2
|
+
/**
|
|
3
|
+
* Simplifies trig identities in a sum expression.
|
|
4
|
+
*
|
|
5
|
+
* Applies:
|
|
6
|
+
* a·sin(u)² + a·cos(u)² = a (Pythagorean)
|
|
7
|
+
* a·sec(u)² - a·tan(u)² = a (sec²-tan²=1)
|
|
8
|
+
* a·csc(u)² - a·cot(u)² = a (csc²-cot²=1)
|
|
9
|
+
* Partial Pythagorean for mismatched coefficients
|
|
10
|
+
*/
|
|
11
|
+
export declare function simplifyTrigSum(x: Expression): Expression;
|