nerdamer 2.0.0-rc.1 → 2.0.0

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.
Files changed (236) hide show
  1. package/BREAKING_CHANGES.md +244 -0
  2. package/README.md +168 -229
  3. package/dist/bundle.js +1 -1
  4. package/dist/bundle.js.LICENSE.txt +6 -6
  5. package/output/algebra/adapters.d.ts +3 -33
  6. package/output/algebra/adapters.js +7 -105
  7. package/output/algebra/algorithms/arith.js +10 -9
  8. package/output/algebra/algorithms/groebnerBase.d.ts +24 -20
  9. package/output/algebra/algorithms/groebnerBase.js +486 -723
  10. package/output/algebra/dispatch.d.ts +1 -0
  11. package/output/algebra/dispatch.js +25 -0
  12. package/output/algebra/factor/factor.d.ts +15 -0
  13. package/output/algebra/factor/factor.js +99 -12
  14. package/output/algebra/gcd/gcd.d.ts +8 -7
  15. package/output/algebra/gcd/gcd.js +32 -78
  16. package/output/algebra/groebner.d.ts +2 -2
  17. package/output/algebra/groebner.js +6 -12
  18. package/output/algebra/partfrac.d.ts +3 -3
  19. package/output/algebra/partfrac.js +28 -61
  20. package/output/algebra/polynomial/ModularSparsePolynomial.d.ts +131 -0
  21. package/output/algebra/polynomial/ModularSparsePolynomial.js +378 -0
  22. package/output/algebra/polynomial/ModularSparsePolynomialFactor.d.ts +40 -0
  23. package/output/algebra/polynomial/ModularSparsePolynomialFactor.js +661 -0
  24. package/output/algebra/polynomial/SparsePolynomialFactor.d.ts +64 -0
  25. package/output/algebra/polynomial/SparsePolynomialFactor.js +492 -0
  26. package/output/algebra/polynomial/SparsePolynomialGcd.d.ts +29 -0
  27. package/output/algebra/polynomial/SparsePolynomialGcd.js +259 -0
  28. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.d.ts +82 -0
  29. package/output/algebra/polynomial/SparsePolynomialMultivariateFactor.js +604 -0
  30. package/output/algebra/polynomial/modularGcd.d.ts +40 -0
  31. package/output/algebra/polynomial/modularGcd.js +365 -0
  32. package/output/algebra/polynomialize.js +4 -2
  33. package/output/algebra/simplify/funcsimp.js +1 -1
  34. package/output/algebra/simplify/ratsimp.js +1 -1
  35. package/output/algebra/simplify/simplify.js +11 -2
  36. package/output/algebra/utils.d.ts +1 -1
  37. package/output/algebra/utils.js +3 -3
  38. package/output/api/advanced.d.ts +2 -1
  39. package/output/api/advanced.js +3 -3
  40. package/output/api/algebra.d.ts +21 -4
  41. package/output/api/algebra.js +22 -3
  42. package/output/api/assumptions.d.ts +1 -1
  43. package/output/api/assumptions.js +2 -1
  44. package/output/api/calculus.d.ts +2 -1
  45. package/output/api/calculus.js +2 -1
  46. package/output/api/core.d.ts +28 -7
  47. package/output/api/core.js +28 -2
  48. package/output/api/languages/deu.d.ts +3 -0
  49. package/output/api/languages/deu.js +266 -0
  50. package/output/api/languages/fra.d.ts +3 -0
  51. package/output/api/languages/fra.js +266 -0
  52. package/output/api/languages/ita.d.ts +3 -0
  53. package/output/api/languages/ita.js +266 -0
  54. package/output/api/languages/nld.d.ts +3 -0
  55. package/output/api/languages/nld.js +266 -0
  56. package/output/api/languages/por.d.ts +3 -0
  57. package/output/api/languages/por.js +266 -0
  58. package/output/api/languages/spa.d.ts +3 -0
  59. package/output/api/languages/spa.js +266 -0
  60. package/output/api/parser.d.ts +10 -2
  61. package/output/api/parser.js +2 -0
  62. package/output/api/solve.d.ts +1 -1
  63. package/output/api/solve.js +2 -1
  64. package/output/api/structures.d.ts +1 -1
  65. package/output/api/structures.js +2 -1
  66. package/output/calculus/adapters.d.ts +8 -0
  67. package/output/calculus/adapters.js +41 -0
  68. package/output/calculus/derivative/diff.js +6 -3
  69. package/output/calculus/dispatch.d.ts +1 -0
  70. package/output/calculus/dispatch.js +25 -0
  71. package/output/calculus/integrate/integrate.js +4 -4
  72. package/output/calculus/integrate/integrationTable.js +16 -16
  73. package/output/calculus/laplace/ilaplace.js +1 -1
  74. package/output/calculus/laplace/ilaplaceTable.js +18 -17
  75. package/output/calculus/laplace/laplaceTable.js +3 -2
  76. package/output/calculus/limit/limit.js +1 -1
  77. package/output/core/classes/assumption/Assumption.js +14 -10
  78. package/output/core/classes/assumption/assume.d.ts +6 -0
  79. package/output/core/classes/assumption/assume.js +9 -0
  80. package/output/core/classes/assumption/dispatch.d.ts +1 -0
  81. package/output/core/classes/assumption/dispatch.js +11 -0
  82. package/output/core/classes/collection/Collection.js +11 -2
  83. package/output/core/classes/complex/Complex.d.ts +10 -0
  84. package/output/core/classes/complex/Complex.js +19 -1
  85. package/output/core/classes/decimalSet/DecimalSet.js +5 -4
  86. package/output/core/classes/dictionary/Dictionary.js +4 -1
  87. package/output/core/classes/expression/CoeffObject.d.ts +1 -1
  88. package/output/core/classes/expression/CoeffObject.js +1 -2
  89. package/output/core/classes/expression/Expression.d.ts +35 -26
  90. package/output/core/classes/expression/Expression.js +77 -50
  91. package/output/core/classes/expression/analysis.d.ts +1 -1
  92. package/output/core/classes/expression/analysis.js +7 -7
  93. package/output/core/classes/expression/format.d.ts +9 -0
  94. package/output/core/classes/expression/format.js +130 -7
  95. package/output/core/classes/expression/utils.d.ts +9 -0
  96. package/output/core/classes/expression/utils.js +52 -6
  97. package/output/core/classes/matrix/Matrix.d.ts +2 -3
  98. package/output/core/classes/matrix/Matrix.js +26 -23
  99. package/output/core/classes/matrix/dispatch.d.ts +1 -0
  100. package/output/core/classes/matrix/dispatch.js +19 -0
  101. package/output/core/classes/matrix/functions.d.ts +2 -0
  102. package/output/core/classes/matrix/functions.js +5 -0
  103. package/output/core/classes/parser/Parser.d.ts +31 -5
  104. package/output/core/classes/parser/Parser.js +357 -444
  105. package/output/core/classes/parser/constants.d.ts +2 -0
  106. package/output/core/classes/parser/constants.js +4 -2
  107. package/output/core/classes/parser/controlFlowSignals.d.ts +38 -0
  108. package/output/core/classes/parser/controlFlowSignals.js +60 -0
  109. package/output/core/classes/parser/operations/add.js +14 -16
  110. package/output/core/classes/parser/operations/compare.js +13 -0
  111. package/output/core/classes/parser/operations/functions.d.ts +3 -4
  112. package/output/core/classes/parser/operations/functions.js +48 -102
  113. package/output/core/classes/parser/operations/multiply.js +22 -15
  114. package/output/core/classes/parser/operations/power.js +11 -11
  115. package/output/core/classes/parser/operations/subtract.js +2 -1
  116. package/output/core/classes/parser/preprocess.d.ts +0 -7
  117. package/output/core/classes/parser/preprocess.js +33 -39
  118. package/output/core/classes/parser/scripting/controlFlow.d.ts +4 -102
  119. package/output/core/classes/parser/scripting/controlFlow.js +134 -186
  120. package/output/core/classes/parser/scripting/deferred.d.ts +4 -0
  121. package/output/core/classes/parser/scripting/deferred.js +65 -0
  122. package/output/core/classes/parser/scripting/dispatch.d.ts +1 -0
  123. package/output/core/classes/parser/scripting/dispatch.js +62 -0
  124. package/output/core/classes/parser/scripting/evaluate.d.ts +13 -0
  125. package/output/core/classes/parser/scripting/evaluate.js +17 -1
  126. package/output/core/classes/parser/scripting/scope.d.ts +1 -28
  127. package/output/core/classes/parser/scripting/scope.js +36 -40
  128. package/output/core/classes/parser/types.d.ts +5 -5
  129. package/output/core/classes/parser/wrappers/IndexedReference.d.ts +4 -3
  130. package/output/core/classes/parser/wrappers/IndexedReference.js +8 -0
  131. package/output/core/classes/parser/wrappers/KeyValuePair.d.ts +2 -2
  132. package/output/core/classes/polynomial/Polynomial.d.ts +5 -1
  133. package/output/core/classes/polynomial/Polynomial.js +53 -7
  134. package/output/core/classes/polynomial/SparsePolynomial.d.ts +221 -0
  135. package/output/core/classes/polynomial/SparsePolynomial.js +824 -0
  136. package/output/core/classes/polynomial/SparsePolynomialAdapter.d.ts +56 -0
  137. package/output/core/classes/polynomial/SparsePolynomialAdapter.js +241 -0
  138. package/output/core/classes/polynomial/Term.js +2 -2
  139. package/output/core/{adapters.d.ts → classes/polynomial/adapters.d.ts} +2 -2
  140. package/output/core/classes/polynomial/adapters.js +33 -0
  141. package/output/core/classes/polynomial/dispatch.d.ts +1 -0
  142. package/output/core/classes/polynomial/dispatch.js +14 -0
  143. package/output/core/classes/polynomial/functions.d.ts +8 -0
  144. package/output/core/classes/polynomial/functions.js +71 -8
  145. package/output/core/classes/polynomial/utils.js +2 -1
  146. package/output/core/classes/rational/Rational.d.ts +8 -11
  147. package/output/core/classes/rational/Rational.js +70 -20
  148. package/output/core/classes/seq/SEQ.js +4 -4
  149. package/output/core/classes/valuesSet/ValuesSet.d.ts +9 -1
  150. package/output/core/classes/valuesSet/ValuesSet.js +22 -4
  151. package/output/core/classes/vector/Vector.d.ts +2 -3
  152. package/output/core/classes/vector/Vector.js +11 -15
  153. package/output/core/classes/vector/dispatch.d.ts +1 -0
  154. package/output/core/classes/vector/dispatch.js +11 -0
  155. package/output/core/common/classes/MathematicalAggregate.js +11 -2
  156. package/output/core/common/classes/StructuredEntity.d.ts +0 -17
  157. package/output/core/common/classes/StructuredEntity.js +3 -64
  158. package/output/core/common/common.d.ts +0 -1
  159. package/output/core/common/common.js +29 -234
  160. package/output/core/converters/BaseConverter.js +3 -2
  161. package/output/core/converters/Converter.js +9 -5
  162. package/output/core/converters/Pattern.js +1 -1
  163. package/output/core/dispatch.d.ts +18 -0
  164. package/output/core/dispatch.js +3 -281
  165. package/output/core/errors.d.ts +259 -474
  166. package/output/core/errors.js +270 -542
  167. package/output/core/fullFunctions.d.ts +7 -0
  168. package/output/core/fullFunctions.js +31 -0
  169. package/output/core/functions/bigint/bigint.d.ts +13 -1
  170. package/output/core/functions/bigint/bigint.js +56 -4
  171. package/output/core/functions/bigint/primeFactor.d.ts +2 -0
  172. package/output/core/functions/bigint/primeFactor.js +13 -13
  173. package/output/core/functions/build/definitions.js +6 -0
  174. package/output/core/functions/complex.d.ts +2 -2
  175. package/output/core/functions/complex.dispatch.d.ts +1 -0
  176. package/output/core/functions/complex.dispatch.js +16 -0
  177. package/output/core/functions/complex.js +7 -7
  178. package/output/core/functions/decimal.js +2 -1
  179. package/output/core/functions/expand/expand.js +2 -2
  180. package/output/core/functions/numeric.d.ts +1 -1
  181. package/output/core/functions/string.js +2 -1
  182. package/output/core/functions/subst.js +21 -13
  183. package/output/core/parserFunctions.d.ts +7 -0
  184. package/output/core/parserFunctions.js +25 -0
  185. package/output/index.d.ts +50 -30
  186. package/output/index.js +147 -19
  187. package/output/math/defint/defint.d.ts +18 -0
  188. package/output/math/defint/defint.js +60 -0
  189. package/output/math/defint/defintDecimal.js +6 -5
  190. package/output/math/defint/defintNative.js +7 -18
  191. package/output/math/dispatch.d.ts +1 -0
  192. package/output/math/dispatch.js +101 -0
  193. package/output/math/geometry.d.ts +4 -0
  194. package/output/math/geometry.js +23 -0
  195. package/output/math/math.d.ts +59 -19
  196. package/output/math/math.js +244 -100
  197. package/output/math/trig.js +4 -4
  198. package/output/math/utils.d.ts +6 -0
  199. package/output/math/utils.js +39 -0
  200. package/output/solve/classes/PolynomialSolver.d.ts +33 -14
  201. package/output/solve/classes/PolynomialSolver.js +267 -67
  202. package/output/solve/classes/SolutionSet.d.ts +20 -1
  203. package/output/solve/classes/SolutionSet.js +82 -5
  204. package/output/solve/dispatch.d.ts +1 -0
  205. package/output/solve/dispatch.js +13 -0
  206. package/output/solve/linsolve.d.ts +2 -0
  207. package/output/solve/linsolve.js +13 -5
  208. package/output/solve/solve.d.ts +10 -0
  209. package/output/solve/solve.js +128 -20
  210. package/output/solve/solveSystem.d.ts +1 -1
  211. package/output/solve/solveSystem.js +8 -32
  212. package/output/solve/utils.d.ts +2 -1
  213. package/output/solve/utils.js +18 -22
  214. package/output/utils/array.d.ts +1 -1
  215. package/output/utils/debug.js +2 -1
  216. package/package.json +22 -38
  217. package/dist/parser.js +0 -2
  218. package/dist/parser.js.LICENSE.txt +0 -7
  219. package/docs-data/parser-functions.json +0 -1960
  220. package/output/algebra/algorithms/factor.d.ts +0 -3
  221. package/output/algebra/algorithms/factor.js +0 -5
  222. package/output/algebra/algorithms/factorMultivariate.d.ts +0 -23
  223. package/output/algebra/algorithms/factorMultivariate.js +0 -2393
  224. package/output/algebra/algorithms/factorUnivariate.d.ts +0 -72
  225. package/output/algebra/algorithms/factorUnivariate.js +0 -1072
  226. package/output/algebra/algorithms/gcd.d.ts +0 -22
  227. package/output/algebra/algorithms/gcd.js +0 -690
  228. package/output/algebra/algorithms/multiPoly/MultiPoly.d.ts +0 -137
  229. package/output/algebra/algorithms/multiPoly/MultiPoly.js +0 -346
  230. package/output/algebra/algorithms/poly.d.ts +0 -228
  231. package/output/algebra/algorithms/poly.js +0 -1299
  232. package/output/algebra/algorithms/rational.d.ts +0 -17
  233. package/output/algebra/algorithms/rational.js +0 -115
  234. package/output/core/adapters.js +0 -40
  235. package/output/core/classes/parser/operations/comma.d.ts +0 -7
  236. package/output/core/classes/parser/operations/comma.js +0 -11
@@ -42,6 +42,8 @@ export declare class Complex {
42
42
  * @returns A new Decimal containing the nonnegative magnitude.
43
43
  */
44
44
  abs(): Decimal;
45
+ /** Returns the squared modulus `re^2 + im^2` without computing a square root. */
46
+ absSquared(): Decimal;
45
47
  /**
46
48
  * Adds another complex value component-wise.
47
49
  *
@@ -82,6 +84,14 @@ export declare class Complex {
82
84
  * @returns A new complex value with both components negated.
83
85
  */
84
86
  neg(): Complex;
87
+ /**
88
+ * Returns the multiplicative inverse of this complex value.
89
+ *
90
+ * @returns A new complex value equal to `1 / this`.
91
+ * @throws {@link core!DivisionByZeroError}
92
+ * Thrown when both components are exactly zero at the current Decimal value.
93
+ */
94
+ reciprocal(): Complex;
85
95
  /**
86
96
  * Multiplies both complex components by a real scalar.
87
97
  *
@@ -54,7 +54,11 @@ class Complex {
54
54
  * @returns A new Decimal containing the nonnegative magnitude.
55
55
  */
56
56
  abs() {
57
- return this.re.mul(this.re).plus(this.im.mul(this.im)).sqrt();
57
+ return this.absSquared().sqrt();
58
+ }
59
+ /** Returns the squared modulus `re^2 + im^2` without computing a square root. */
60
+ absSquared() {
61
+ return this.re.mul(this.re).plus(this.im.mul(this.im));
58
62
  }
59
63
  /**
60
64
  * Adds another complex value component-wise.
@@ -112,6 +116,20 @@ class Complex {
112
116
  neg() {
113
117
  return new Complex(this.re.neg(), this.im.neg());
114
118
  }
119
+ /**
120
+ * Returns the multiplicative inverse of this complex value.
121
+ *
122
+ * @returns A new complex value equal to `1 / this`.
123
+ * @throws {@link core!DivisionByZeroError}
124
+ * Thrown when both components are exactly zero at the current Decimal value.
125
+ */
126
+ reciprocal() {
127
+ const denom = this.re.mul(this.re).plus(this.im.mul(this.im));
128
+ if (denom.isZero()) {
129
+ throw new errors_1.DivisionByZeroError((0, errors_1.message)('divisionByZero'));
130
+ }
131
+ return new Complex(this.re.div(denom), this.im.neg().div(denom));
132
+ }
115
133
  /**
116
134
  * Multiplies both complex components by a real scalar.
117
135
  *
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DecimalSet = void 0;
7
7
  const decimal_js_1 = __importDefault(require("decimal.js"));
8
+ const errors_1 = require("../../errors");
8
9
  /**
9
10
  * A high-performance set implementation for Decimal.js numbers.
10
11
  *
@@ -60,10 +61,10 @@ class DecimalSet {
60
61
  const endDec = new decimal_js_1.default(end);
61
62
  const stepDec = new decimal_js_1.default(step);
62
63
  if (!startDec.isFinite() || !endDec.isFinite() || !stepDec.isFinite()) {
63
- throw new Error('Range values must be finite');
64
+ throw new Error((0, errors_1.message)('rangeValuesFinite'));
64
65
  }
65
66
  if (stepDec.isZero()) {
66
- throw new Error('Step cannot be zero');
67
+ throw new Error((0, errors_1.message)('rangeStepNonzero'));
67
68
  }
68
69
  if (stepDec.isPositive()) {
69
70
  let current = startDec;
@@ -71,7 +72,7 @@ class DecimalSet {
71
72
  result.add(current);
72
73
  const next = current.plus(stepDec);
73
74
  if (next.equals(current)) {
74
- throw new Error('Step does not advance range at current precision');
75
+ throw new Error((0, errors_1.message)('rangeStepNoAdvance'));
75
76
  }
76
77
  current = next;
77
78
  }
@@ -82,7 +83,7 @@ class DecimalSet {
82
83
  result.add(current);
83
84
  const next = current.plus(stepDec);
84
85
  if (next.equals(current)) {
85
- throw new Error('Step does not advance range at current precision');
86
+ throw new Error((0, errors_1.message)('rangeStepNoAdvance'));
86
87
  }
87
88
  current = next;
88
89
  }
@@ -54,7 +54,10 @@ class Dictionary extends StructuredEntity_1.StructuredEntity {
54
54
  const key = typeof indices === 'string' ? indices : String(indices[0]);
55
55
  const value = this._entries.get(key);
56
56
  if (value === undefined) {
57
- throw new errors_1.UnexpectedDataType(`Key "${key}" not found in Dictionary. Available keys: ${this.keys().join(', ')}`);
57
+ throw new errors_1.UnexpectedDataType((0, errors_1.message)('dictionaryKeyNotFound', {
58
+ key,
59
+ keys: this.keys().join(', '),
60
+ }));
58
61
  }
59
62
  return value;
60
63
  }
@@ -1,6 +1,6 @@
1
1
  import { Polynomial } from '../polynomial/Polynomial';
2
2
  import { Vector } from '../vector/Vector';
3
- import { Expression } from './Expression';
3
+ import type { Expression } from './Expression';
4
4
  /**
5
5
  * Stores coefficients indexed by the power or multidegree collected from an expression.
6
6
  *
@@ -5,7 +5,6 @@ const errors_1 = require("../../errors");
5
5
  const Polynomial_1 = require("../polynomial/Polynomial");
6
6
  const Term_1 = require("../polynomial/Term");
7
7
  const Vector_1 = require("../vector/Vector");
8
- const Expression_1 = require("./Expression");
9
8
  const shortcuts_1 = require("./shortcuts");
10
9
  /**
11
10
  * Stores coefficients indexed by the power or multidegree collected from an expression.
@@ -39,7 +38,7 @@ class CoeffObject {
39
38
  buildTerms() {
40
39
  const retval = [];
41
40
  for (const powers in this.coeffs) {
42
- retval.push(new Term_1.Term(new Expression_1.Expression(this.coeffs[powers]), powers, this.variables));
41
+ retval.push(new Term_1.Term(this.coeffs[powers].copy(), powers, this.variables));
43
42
  }
44
43
  return retval;
45
44
  }
@@ -21,9 +21,20 @@ export type ElementsSortType = (a: Expression, b: Expression) => number;
21
21
  * initialize and return internal objects. Use {@link Expression.copy} when an
22
22
  * independently mutable expression tree is required.
23
23
  *
24
- * {@link Expression.create} is the preferred construction API. In particular,
25
- * `Expression.create(existingExpression)` preserves object identity unless its
26
- * `copy` argument is set to `true`.
24
+ * {@link Expression.create} is the preferred construction API for ordinary
25
+ * expression construction and coercion. It centralizes supported input handling and
26
+ * normalization. When the input is already an `Expression`, it preserves object
27
+ * identity unless its `copy` argument is set to `true`.
28
+ *
29
+ * When the source is already known to be an `Expression` and an independent tree is
30
+ * required, use {@link Expression.copy}. When a caller accepts broader input but must
31
+ * guarantee a clone for an existing expression, use
32
+ * `Expression.create(input, undefined, true)`.
33
+ *
34
+ * Direct `new Expression(...)` construction is reserved for representation-level
35
+ * internals that require constructor semantics, such as the `plainConstruct` path and
36
+ * the implementation of {@link Expression.copy}. Ordinary callers should not use the
37
+ * constructor for coercion or cloning.
27
38
  *
28
39
  * The internal expression groups are organizational categories used by Nerdamer's
29
40
  * canonicalization logic. They should not be confused with general mathematical
@@ -111,6 +122,13 @@ export declare class Expression implements Base<Expression> {
111
122
  VEC: number;
112
123
  MAT: number;
113
124
  };
125
+ /**
126
+ * Cached ordinary lookup key for SUM and PRD nodes.
127
+ *
128
+ * Copies intentionally start without this cache. Aggregate reconstruction clears it
129
+ * through updateValue() before the node is used again.
130
+ */
131
+ private _keyValueCache?;
114
132
  /**
115
133
  * Arguments stored by a function node.
116
134
  *
@@ -162,6 +180,8 @@ export declare class Expression implements Base<Expression> {
162
180
  * If set, this is the maximum known precision of any of the intermediate operations
163
181
  */
164
182
  precision?: number;
183
+ /** Significant digits requested by the legacy scientific-formatting helper. */
184
+ scientific?: number;
165
185
  /**
166
186
  * The default type is a number for the expression since the default value
167
187
  * for an expression is "1". The assert flag is used because TypeScript
@@ -184,20 +204,12 @@ export declare class Expression implements Base<Expression> {
184
204
  * {@link Expression.create}, and JavaScript constructor return semantics therefore
185
205
  * allow that factory-created expression to become the result of `new Expression(...)`.
186
206
  *
187
- * For ordinary user input, prefer {@link Expression.create}; it makes parsing and
188
- * identity behavior explicit.
207
+ * Ordinary code should use {@link Expression.create} for construction/coercion and
208
+ * {@link Expression.copy} when an independent tree is required. Direct constructor
209
+ * calls are reserved for low-level representation code.
189
210
  *
190
211
  * @param x - The expression or Nerdamer input used to construct the value.
191
212
  * @param plainConstruct - Store a string as a raw internal value instead of parsing it.
192
- *
193
- * @example
194
- * ```ts
195
- * const expression = Expression.create('x + 1');
196
- * const copy = new Expression(expression);
197
- *
198
- * copy === expression; // false
199
- * copy.text(); // "1+x"
200
- * ```
201
213
  */
202
214
  constructor(x: NerdamerInput, plainConstruct?: boolean);
203
215
  /**
@@ -262,14 +274,6 @@ export declare class Expression implements Base<Expression> {
262
274
  * ```
263
275
  */
264
276
  static fromRational(x: Rational): Expression;
265
- /**
266
- * Converts a structured entity carrying symbolic bracket access into the scalar
267
- * Expression form used by ordinary algebra and function nodes.
268
- *
269
- * Structured entities without symbolic access are left unchanged by returning
270
- * `undefined`; callers can then apply their normal conversion rules.
271
- */
272
- static fromSymbolicAccess(x: NerdamerInput): Expression | undefined;
273
277
  /**
274
278
  * Creates a symbolic function node with the given name.
275
279
  *
@@ -667,7 +671,8 @@ export declare class Expression implements Base<Expression> {
667
671
  * Re-evaluates this expression numerically, optionally substituting variable values.
668
672
  *
669
673
  * @remarks
670
- * Evaluation serializes the current expression and sends it through
674
+ * Evaluation uses the ordinary serialization path. When scientific display metadata is
675
+ * present, a copy without that metadata is serialized so formatting cannot change the value sent through
671
676
  * {@link Parser.evaluate}. That parser path enables Nerdamer's evaluation mode, so
672
677
  * numeric constants and supported numeric functions are evaluated according to the
673
678
  * parser's current precision and settings. The original expression is not modified.
@@ -1485,7 +1490,7 @@ export declare class Expression implements Base<Expression> {
1485
1490
  */
1486
1491
  sptext(options?: TextOptions, asId?: boolean): string;
1487
1492
  /**
1488
- * Squares this Expression. Shorthand for `this.pow('2')`.
1493
+ * Squares this Expression.
1489
1494
  *
1490
1495
  * @returns A new Expression representing `this²`.
1491
1496
  *
@@ -1547,7 +1552,7 @@ export declare class Expression implements Base<Expression> {
1547
1552
  * @remarks
1548
1553
  * Exact rational text is the default. Use `sort: true` to render terms in Nerdamer's
1549
1554
  * conventional display order without changing the stored expression. Decimal output,
1550
- * precision, and power wrapping can also be selected per call. The `asId` mode is used
1555
+ * precision, scientific notation, and power wrapping can also be selected per call. The `asId` mode is used
1551
1556
  * by internal identity/canonicalization logic and should not be
1552
1557
  * treated as a stable interchange format.
1553
1558
  *
@@ -1561,6 +1566,7 @@ export declare class Expression implements Base<Expression> {
1561
1566
  * Expression.create('x^2 + 2*x + 1').text({ sort: true }); // "x^2+2*x+1"
1562
1567
  * Expression.create('1/3').text(); // "1/3"
1563
1568
  * Expression.create('1/3').text({ decimal: true }); // decimal representation
1569
+ * Expression.create('12345').text({ scientific: 3 }); // "1.23e4"
1564
1570
  * ```
1565
1571
  */
1566
1572
  text(options?: TextOptions, asId?: boolean): string;
@@ -1641,9 +1647,12 @@ export declare class Expression implements Base<Expression> {
1641
1647
  * nodes rebuild it from their current elements. Other node types are left unchanged.
1642
1648
  * This method mutates the receiver and returns the same object for chaining.
1643
1649
  *
1650
+ * @param aggregateElements - Exact aggregate elements already available to a caller
1651
+ * rebuilding a SUM/PRD node. When supplied, the generated value is also the ordinary
1652
+ * lookup key and can seed the key cache without a second formatting pass.
1644
1653
  * @returns This expression after updating its stored value where applicable.
1645
1654
  */
1646
- updateValue(): this;
1655
+ updateValue(aggregateElements?: Expression[]): this;
1647
1656
  /**
1648
1657
  * Provides the primitive value used by JavaScript coercion.
1649
1658
  *
@@ -51,9 +51,20 @@ const { NUM, VAR, EXP, FUN, GRP, PRD, SUM, INF } = constants_1.EXPRESSION_TYPES;
51
51
  * initialize and return internal objects. Use {@link Expression.copy} when an
52
52
  * independently mutable expression tree is required.
53
53
  *
54
- * {@link Expression.create} is the preferred construction API. In particular,
55
- * `Expression.create(existingExpression)` preserves object identity unless its
56
- * `copy` argument is set to `true`.
54
+ * {@link Expression.create} is the preferred construction API for ordinary
55
+ * expression construction and coercion. It centralizes supported input handling and
56
+ * normalization. When the input is already an `Expression`, it preserves object
57
+ * identity unless its `copy` argument is set to `true`.
58
+ *
59
+ * When the source is already known to be an `Expression` and an independent tree is
60
+ * required, use {@link Expression.copy}. When a caller accepts broader input but must
61
+ * guarantee a clone for an existing expression, use
62
+ * `Expression.create(input, undefined, true)`.
63
+ *
64
+ * Direct `new Expression(...)` construction is reserved for representation-level
65
+ * internals that require constructor semantics, such as the `plainConstruct` path and
66
+ * the implementation of {@link Expression.copy}. Ordinary callers should not use the
67
+ * constructor for coercion or cloning.
57
68
  *
58
69
  * The internal expression groups are organizational categories used by Nerdamer's
59
70
  * canonicalization logic. They should not be confused with general mathematical
@@ -152,6 +163,13 @@ class Expression {
152
163
  };
153
164
  /** Internal expression-type constants used by parser and algebra code. */
154
165
  static TYPES = constants_1.EXPRESSION_TYPES;
166
+ /**
167
+ * Cached ordinary lookup key for SUM and PRD nodes.
168
+ *
169
+ * Copies intentionally start without this cache. Aggregate reconstruction clears it
170
+ * through updateValue() before the node is used again.
171
+ */
172
+ _keyValueCache;
155
173
  /**
156
174
  * Arguments stored by a function node.
157
175
  *
@@ -203,6 +221,8 @@ class Expression {
203
221
  * If set, this is the maximum known precision of any of the intermediate operations
204
222
  */
205
223
  precision;
224
+ /** Significant digits requested by the legacy scientific-formatting helper. */
225
+ scientific;
206
226
  /**
207
227
  * The default type is a number for the expression since the default value
208
228
  * for an expression is "1". The assert flag is used because TypeScript
@@ -225,20 +245,12 @@ class Expression {
225
245
  * {@link Expression.create}, and JavaScript constructor return semantics therefore
226
246
  * allow that factory-created expression to become the result of `new Expression(...)`.
227
247
  *
228
- * For ordinary user input, prefer {@link Expression.create}; it makes parsing and
229
- * identity behavior explicit.
248
+ * Ordinary code should use {@link Expression.create} for construction/coercion and
249
+ * {@link Expression.copy} when an independent tree is required. Direct constructor
250
+ * calls are reserved for low-level representation code.
230
251
  *
231
252
  * @param x - The expression or Nerdamer input used to construct the value.
232
253
  * @param plainConstruct - Store a string as a raw internal value instead of parsing it.
233
- *
234
- * @example
235
- * ```ts
236
- * const expression = Expression.create('x + 1');
237
- * const copy = new Expression(expression);
238
- *
239
- * copy === expression; // false
240
- * copy.text(); // "1+x"
241
- * ```
242
254
  */
243
255
  constructor(x, plainConstruct) {
244
256
  // Allow for hooking of the input. The user can override the hook to modify
@@ -342,28 +354,6 @@ class Expression {
342
354
  retval.getMultiplier().asDecimal = x.asDecimal;
343
355
  return retval;
344
356
  }
345
- /**
346
- * Converts a structured entity carrying symbolic bracket access into the scalar
347
- * Expression form used by ordinary algebra and function nodes.
348
- *
349
- * Structured entities without symbolic access are left unchanged by returning
350
- * `undefined`; callers can then apply their normal conversion rules.
351
- */
352
- static fromSymbolicAccess(x) {
353
- let retval;
354
- if (typeof x === 'object' && x !== null) {
355
- const structured = x;
356
- const target = structured.symbolicTarget;
357
- const indices = structured.symbolicAccessor;
358
- if (Expression.isExpression(target) &&
359
- indices &&
360
- indices.length > 0 &&
361
- indices.every(index => Expression.isExpression(index))) {
362
- retval = Expression.toAccessor(target, indices);
363
- }
364
- }
365
- return retval;
366
- }
367
357
  /**
368
358
  * Creates a symbolic function node with the given name.
369
359
  *
@@ -637,7 +627,7 @@ class Expression {
637
627
  .filter((x) => {
638
628
  return x !== undefined;
639
629
  })
640
- .map(x => Expression.fromSymbolicAccess(x) ?? Expression.create(x));
630
+ .map(x => Expression.create(x));
641
631
  // Set the name
642
632
  f.name = name;
643
633
  // TODO: This needs to be generated the same way as in text.
@@ -764,7 +754,7 @@ class Expression {
764
754
  * ```
765
755
  */
766
756
  copy() {
767
- return new Expression(this);
757
+ return (0, utils_1.cloneExpressionTree)(this);
768
758
  }
769
759
  /**
770
760
  * Legacy alias for {@link getDenominator}.
@@ -805,6 +795,7 @@ class Expression {
805
795
  elements[x] = term.distributeMultiplier();
806
796
  }
807
797
  }
798
+ retval.updateValue();
808
799
  }
809
800
  return retval;
810
801
  }
@@ -932,7 +923,8 @@ class Expression {
932
923
  * Re-evaluates this expression numerically, optionally substituting variable values.
933
924
  *
934
925
  * @remarks
935
- * Evaluation serializes the current expression and sends it through
926
+ * Evaluation uses the ordinary serialization path. When scientific display metadata is
927
+ * present, a copy without that metadata is serialized so formatting cannot change the value sent through
936
928
  * {@link Parser.evaluate}. That parser path enables Nerdamer's evaluation mode, so
937
929
  * numeric constants and supported numeric functions are evaluated according to the
938
930
  * parser's current precision and settings. The original expression is not modified.
@@ -947,11 +939,24 @@ class Expression {
947
939
  * ```
948
940
  */
949
941
  evaluate(values) {
950
- const source = this.hasFunction(constants_1.SYMBOLIC_ACCESSOR, true)
951
- ? (0, format_1.toText)(this, { internalAccessor: true }, undefined, Expression.POW_OPR, Expression.sortFunction)
952
- : this.text();
942
+ let source;
943
+ if (this.scientific !== undefined) {
944
+ const sourceExpression = this.copy();
945
+ delete sourceExpression.scientific;
946
+ source = sourceExpression.hasFunction(constants_1.SYMBOLIC_ACCESSOR, true)
947
+ ? (0, format_1.toText)(sourceExpression, { internalAccessor: true }, undefined, Expression.POW_OPR, Expression.sortFunction)
948
+ : sourceExpression.text();
949
+ }
950
+ else {
951
+ source = this.hasFunction(constants_1.SYMBOLIC_ACCESSOR, true)
952
+ ? (0, format_1.toText)(this, { internalAccessor: true }, undefined, Expression.POW_OPR, Expression.sortFunction)
953
+ : this.text();
954
+ }
953
955
  const evaluated = Parser_1.Parser.evaluate(source, values);
954
- const retval = Expression.fromSymbolicAccess(evaluated) ?? Expression.create(evaluated);
956
+ const retval = Expression.create(evaluated);
957
+ if (this.scientific !== undefined) {
958
+ retval.scientific = this.scientific;
959
+ }
955
960
  return retval;
956
961
  }
957
962
  /**
@@ -1352,7 +1357,7 @@ class Expression {
1352
1357
  retval = (0, shortcuts_1.one)().div(this);
1353
1358
  }
1354
1359
  else {
1355
- retval = new Expression(this);
1360
+ retval = this.copy();
1356
1361
  retval.power = retval.getPower().neg();
1357
1362
  retval.multiplier = retval.getMultiplier().invert();
1358
1363
  }
@@ -1783,6 +1788,10 @@ class Expression {
1783
1788
  * Thrown when no key-generation rule exists for the node's internal type.
1784
1789
  */
1785
1790
  keyValue(asSubExpression = false, isGroup = false) {
1791
+ const cacheable = !asSubExpression && !isGroup && (this.type === SUM || this.type === PRD);
1792
+ if (cacheable && this._keyValueCache !== undefined) {
1793
+ return this._keyValueCache;
1794
+ }
1786
1795
  let retval = '';
1787
1796
  // For GRP the key is always the power
1788
1797
  if (isGroup) {
@@ -1814,7 +1823,10 @@ class Expression {
1814
1823
  }
1815
1824
  }
1816
1825
  if (!retval) {
1817
- throw new Error(`The function 'keyValue' not yet implemented for type ${this.type}`);
1826
+ throw new Error((0, errors_1.message)('expressionKeyValueUnsupported', { type: String(this.type) }));
1827
+ }
1828
+ if (cacheable) {
1829
+ this._keyValueCache = retval;
1818
1830
  }
1819
1831
  return retval;
1820
1832
  }
@@ -2051,7 +2063,7 @@ class Expression {
2051
2063
  return txt;
2052
2064
  }
2053
2065
  /**
2054
- * Squares this Expression. Shorthand for `this.pow('2')`.
2066
+ * Squares this Expression.
2055
2067
  *
2056
2068
  * @returns A new Expression representing `this²`.
2057
2069
  *
@@ -2062,7 +2074,7 @@ class Expression {
2062
2074
  * ```
2063
2075
  */
2064
2076
  sq() {
2065
- return this.pow('2');
2077
+ return this.pow((0, shortcuts_1.two)());
2066
2078
  }
2067
2079
  /**
2068
2080
  * Tests Nerdamer equality while also requiring the same top-level internal type.
@@ -2134,7 +2146,7 @@ class Expression {
2134
2146
  * @remarks
2135
2147
  * Exact rational text is the default. Use `sort: true` to render terms in Nerdamer's
2136
2148
  * conventional display order without changing the stored expression. Decimal output,
2137
- * precision, and power wrapping can also be selected per call. The `asId` mode is used
2149
+ * precision, scientific notation, and power wrapping can also be selected per call. The `asId` mode is used
2138
2150
  * by internal identity/canonicalization logic and should not be
2139
2151
  * treated as a stable interchange format.
2140
2152
  *
@@ -2148,9 +2160,16 @@ class Expression {
2148
2160
  * Expression.create('x^2 + 2*x + 1').text({ sort: true }); // "x^2+2*x+1"
2149
2161
  * Expression.create('1/3').text(); // "1/3"
2150
2162
  * Expression.create('1/3').text({ decimal: true }); // decimal representation
2163
+ * Expression.create('12345').text({ scientific: 3 }); // "1.23e4"
2151
2164
  * ```
2152
2165
  */
2153
2166
  text(options, asId) {
2167
+ if (options === undefined &&
2168
+ asId === undefined &&
2169
+ this.precision === undefined &&
2170
+ this.scientific === undefined) {
2171
+ return (0, format_1.toDefaultText)(this, Expression.POW_OPR, Expression.sortFunction);
2172
+ }
2154
2173
  return (0, format_1.toText)(this, options, asId, Expression.POW_OPR, Expression.sortFunction);
2155
2174
  }
2156
2175
  /**
@@ -2277,16 +2296,24 @@ class Expression {
2277
2296
  * nodes rebuild it from their current elements. Other node types are left unchanged.
2278
2297
  * This method mutates the receiver and returns the same object for chaining.
2279
2298
  *
2299
+ * @param aggregateElements - Exact aggregate elements already available to a caller
2300
+ * rebuilding a SUM/PRD node. When supplied, the generated value is also the ordinary
2301
+ * lookup key and can seed the key cache without a second formatting pass.
2280
2302
  * @returns This expression after updating its stored value where applicable.
2281
2303
  */
2282
- updateValue() {
2304
+ updateValue(aggregateElements) {
2305
+ this._keyValueCache = undefined;
2283
2306
  if (this.isFunction()) {
2284
2307
  this.value = `${this.name}(${this.getArguments()
2285
2308
  .map(x => x.text())
2286
2309
  .join(', ')})`;
2287
2310
  }
2288
2311
  else if (this.isProduct() || this.isSum()) {
2289
- this.value = Expression.getValue(this.elementsArray(), 'text', this.type);
2312
+ const elements = aggregateElements ?? this.elementsArray();
2313
+ this.value = Expression.getValue(elements, 'text', this.type);
2314
+ if (aggregateElements && (this.type === SUM || this.type === PRD)) {
2315
+ this._keyValueCache = this.value;
2316
+ }
2290
2317
  }
2291
2318
  return this;
2292
2319
  }
@@ -13,7 +13,7 @@ export declare function separateVar(x: Expression, variables: (string | Expressi
13
13
  *
14
14
  * @param wrt
15
15
  */
16
- export declare function coeffs(x: Expression, variables: string[], coeffsObj?: CoeffObject): CoeffObject;
16
+ export declare function coeffs(x: Expression, variables: string[], coeffsObj?: CoeffObject, expandExpression?: boolean): CoeffObject;
17
17
  export declare function getDenominator(x: Expression): Expression;
18
18
  export declare function getNumerator(x: Expression): Expression; /**
19
19
  * Returns true fo polynomial with coefficients in Z or Q.
@@ -63,15 +63,15 @@ function separateVar(x, variables) {
63
63
  *
64
64
  * @param wrt
65
65
  */
66
- function coeffs(x, variables, coeffsObj) {
66
+ function coeffs(x, variables, coeffsObj, expandExpression = true) {
67
67
  const cObj = coeffsObj || new CoeffObject_1.CoeffObject(variables);
68
68
  // Complex sums are canonically stored as re + i*im. If the requested variables
69
69
  // are inside im, treating i*im as a single coefficient leaves those variables
70
70
  // buried inside the coefficient. Split the two components and collect them
71
71
  // independently, then restore i on the imaginary coefficients.
72
72
  if (x.isComplex() && !variables.includes(Expression_1.Expression.imaginary)) {
73
- const realCoeffs = coeffs(x.realPart(), variables);
74
- const imaginaryCoeffs = coeffs(x.imagPart(), variables);
73
+ const realCoeffs = coeffs(x.realPart(), variables, undefined, expandExpression);
74
+ const imaginaryCoeffs = coeffs(x.imagPart(), variables, undefined, expandExpression);
75
75
  realCoeffs.each((coeff, power) => cObj.add(power, coeff));
76
76
  imaginaryCoeffs.each((coeff, power) => cObj.add(power, coeff.times(Expression_1.Expression.Img())));
77
77
  return cObj;
@@ -95,7 +95,7 @@ function coeffs(x, variables, coeffsObj) {
95
95
  }
96
96
  }
97
97
  if (hasCoefficientFactor) {
98
- const productCoeffs = coeffs(product, variables);
98
+ const productCoeffs = coeffs(product, variables, undefined, expandExpression);
99
99
  productCoeffs.each((value, power) => {
100
100
  cObj.add(power, coefficient.times(value));
101
101
  });
@@ -103,12 +103,12 @@ function coeffs(x, variables, coeffsObj) {
103
103
  }
104
104
  x = product;
105
105
  }
106
- // Expand the expression
107
- const f = (0, expand_1.expand)(x);
106
+ // Expand only when the caller has not already supplied expanded structure.
107
+ const f = expandExpression ? (0, expand_1.expand)(x) : x;
108
108
  if (f.isSum()) {
109
109
  // Loop through the expression and get the coefficient for each
110
110
  f.each(e => {
111
- coeffs(e, variables, cObj);
111
+ coeffs(e, variables, cObj, false);
112
112
  });
113
113
  }
114
114
  else {
@@ -3,6 +3,7 @@ import type { Expression } from './Expression';
3
3
  type ExpressionSortFunction = (a: Expression, b: Expression) => number;
4
4
  type ExpressionTextOptions = TextOptions & {
5
5
  internalAccessor?: boolean;
6
+ exactScientific?: boolean;
6
7
  };
7
8
  /**
8
9
  * Formats the multiplier string for string output.
@@ -23,6 +24,14 @@ export declare function formatMultiplierString(x: Expression, options?: Expressi
23
24
  * @returns
24
25
  */
25
26
  export declare function formatPowerString(x: Expression, options: ExpressionTextOptions | undefined, powerOperator: string): string;
27
+ /**
28
+ * Formats the ordinary no-options text form without creating formatting option objects
29
+ * while descending the expression tree.
30
+ *
31
+ * This routine follows the same default rendering rules as {@link toText}. Calls that
32
+ * request explicit formatting options continue through {@link toText}.
33
+ */
34
+ export declare function toDefaultText(x: Expression, powerOperator: string, sortFunction: ExpressionSortFunction): string;
26
35
  /**
27
36
  * Formats an expression using the current formatting policy supplied by Expression.
28
37
  *