@cortex-js/compute-engine 0.28.0 → 0.29.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.
Files changed (148) hide show
  1. package/dist/{compute-engine.js → compute-engine.cjs} +22673 -23299
  2. package/dist/compute-engine.esm.js +22673 -23299
  3. package/dist/compute-engine.min.cjs +129 -0
  4. package/dist/compute-engine.min.esm.js +48 -64
  5. package/dist/{math-json.js → math-json.cjs} +2 -2
  6. package/dist/math-json.esm.js +2 -2
  7. package/dist/{math-json.min.js → math-json.min.cjs} +2 -2
  8. package/dist/math-json.min.esm.js +2 -2
  9. package/dist/types/common/ansi-codes.d.ts +1 -1
  10. package/dist/types/common/fuzzy-string-match.d.ts +1 -1
  11. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  12. package/dist/types/common/interruptible.d.ts +1 -1
  13. package/dist/types/common/json5.d.ts +1 -1
  14. package/dist/types/common/one-of.d.ts +2 -1
  15. package/dist/types/common/signals.d.ts +1 -2
  16. package/dist/types/common/type/boxed-type.d.ts +2 -1
  17. package/dist/types/common/type/parse.d.ts +1 -1
  18. package/dist/types/common/type/primitive.d.ts +1 -1
  19. package/dist/types/common/type/serialize.d.ts +1 -1
  20. package/dist/types/common/type/subtype.d.ts +1 -1
  21. package/dist/types/common/type/types.d.ts +102 -107
  22. package/dist/types/common/type/utils.d.ts +1 -1
  23. package/dist/types/common/utils.d.ts +1 -1
  24. package/dist/types/compute-engine/assume.d.ts +1 -1
  25. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +11 -14
  26. package/dist/types/compute-engine/boxed-expression/apply.d.ts +2 -2
  27. package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +3 -3
  28. package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +27 -0
  29. package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +2 -2
  30. package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
  31. package/dist/types/compute-engine/boxed-expression/box.d.ts +5 -5
  32. package/dist/types/compute-engine/boxed-expression/boxed-function-definition.d.ts +12 -13
  33. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +4 -7
  34. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +6 -8
  35. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +2 -2
  36. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +2 -3
  37. package/dist/types/compute-engine/boxed-expression/boxed-symbol-definition.d.ts +2 -2
  38. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +6 -7
  39. package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +5 -8
  40. package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
  41. package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
  42. package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
  43. package/dist/types/compute-engine/boxed-expression/expand.d.ts +3 -3
  44. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  45. package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -3
  46. package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
  47. package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
  48. package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
  49. package/dist/types/compute-engine/boxed-expression/negate.d.ts +2 -2
  50. package/dist/types/compute-engine/boxed-expression/numerics.d.ts +3 -3
  51. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  52. package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
  53. package/dist/types/compute-engine/boxed-expression/product.d.ts +5 -5
  54. package/dist/types/compute-engine/boxed-expression/rules.d.ts +2 -2
  55. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +3 -3
  56. package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
  57. package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
  58. package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -2
  59. package/dist/types/compute-engine/boxed-expression/terms.d.ts +2 -2
  60. package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +2 -9
  61. package/dist/types/compute-engine/boxed-expression/utils.d.ts +13 -4
  62. package/dist/types/compute-engine/boxed-expression/validate.d.ts +8 -9
  63. package/dist/types/compute-engine/collection-utils.d.ts +1 -1
  64. package/dist/types/compute-engine/compile.d.ts +2 -4
  65. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  66. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  67. package/dist/types/compute-engine/{boxed-expression/public.d.ts → global-types.d.ts} +835 -807
  68. package/dist/types/compute-engine/{compute-engine.d.ts → index.d.ts} +7 -10
  69. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  70. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  71. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  72. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  73. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  74. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
  75. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  76. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  77. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
  78. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  79. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  80. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  81. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  82. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +2 -2
  83. package/dist/types/compute-engine/latex-syntax/parse-identifier.d.ts +2 -2
  84. package/dist/types/compute-engine/latex-syntax/parse.d.ts +2 -2
  85. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +2 -2
  86. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +2 -2
  87. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +2 -2
  88. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  89. package/dist/types/compute-engine/latex-syntax/{public.d.ts → types.d.ts} +3 -1
  90. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -2
  91. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  92. package/dist/types/compute-engine/library/collections.d.ts +2 -2
  93. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  94. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  95. package/dist/types/compute-engine/library/core.d.ts +1 -1
  96. package/dist/types/compute-engine/library/invisible-operator.d.ts +2 -2
  97. package/dist/types/compute-engine/library/library.d.ts +3 -3
  98. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  99. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  100. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  101. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  102. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  103. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  104. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  105. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  106. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  107. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +3 -4
  108. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +3 -5
  109. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +3 -4
  110. package/dist/types/compute-engine/numeric-value/{public.d.ts → types.d.ts} +9 -5
  111. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  112. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  113. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  114. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  115. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  116. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  117. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  118. package/dist/types/compute-engine/numerics/numeric.d.ts +2 -7
  119. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  120. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -5
  121. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  122. package/dist/types/compute-engine/numerics/special-functions.d.ts +4 -4
  123. package/dist/types/compute-engine/numerics/statistics.d.ts +2 -2
  124. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  125. package/dist/types/compute-engine/numerics/types.d.ts +30 -0
  126. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  127. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  128. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  129. package/dist/types/compute-engine/{boxed-expression → tensor}/tensor-fields.d.ts +19 -18
  130. package/dist/types/compute-engine/tensor/tensors.d.ts +9 -12
  131. package/dist/types/compute-engine/types.d.ts +11 -0
  132. package/dist/types/compute-engine.d.ts +3 -6
  133. package/dist/types/math-json/identifiers.d.ts +1 -1
  134. package/dist/types/math-json/types.d.ts +4 -2
  135. package/dist/types/math-json/utils.d.ts +1 -1
  136. package/dist/types/math-json.d.ts +2 -2
  137. package/package.json +7 -7
  138. package/dist/compute-engine.min.js +0 -145
  139. package/dist/types/common/buffer.d.ts +0 -9
  140. package/dist/types/common/styled-text.d.ts +0 -28
  141. package/dist/types/common/syntax-highlighter.d.ts +0 -40
  142. package/dist/types/common/terminal.d.ts +0 -19
  143. package/dist/types/compute-engine/boxed-expression/arithmetic-divide.d.ts +0 -12
  144. package/dist/types/compute-engine/boxed-expression/arithmetic-multiply.d.ts +0 -16
  145. package/dist/types/compute-engine/debug.d.ts +0 -3
  146. package/dist/types/compute-engine/numerics/bignum.d.ts +0 -12
  147. package/dist/types/compute-engine/private.d.ts +0 -29
  148. package/dist/types/compute-engine/public.d.ts +0 -42
@@ -1,18 +1,61 @@
1
- /* 0.28.0 */
2
- import type { Expression, MathJsonNumber, MathJsonString, MathJsonSymbol, MathJsonFunction, MathJsonIdentifier } from '../../math-json';
3
- import type { SerializeLatexOptions, LatexDictionaryEntry, ParseLatexOptions } from '../latex-syntax/public';
4
- import type { IndexedLatexDictionary } from '../latex-syntax/dictionary/definitions';
5
- import { Rational } from '../numerics/rationals';
6
- import { ExactNumericValueData, NumericValue, NumericValueData } from '../numeric-value/public';
7
- import { BigNum, IBigNum } from '../numerics/bignum';
8
- import { Type, TypeString } from '../../common/type/types';
9
- import { AbstractTensor } from '../tensor/tensors';
10
- import { OneOf } from '../../common/one-of';
11
- import { CompiledType, JSSource } from '../compile';
12
- import { BoxedType } from '../../common/type/boxed-type';
1
+ /* 0.29.1 */
2
+ import type { OneOf } from '../common/one-of';
3
+ import type { Expression, MathJsonNumber, MathJsonString, MathJsonSymbol, MathJsonFunction, MathJsonIdentifier } from '../math-json';
4
+ import { LatexDictionaryEntry, LatexString, ParseLatexOptions, SerializeLatexOptions } from './latex-syntax/types';
5
+ import { ExactNumericValueData, NumericValue, NumericValueData } from './numeric-value/types';
6
+ import { BigNum, IBigNum, Rational } from './numerics/types';
7
+ import { Type, TypeString } from '../common/type/types';
8
+ import { BoxedType } from '../common/type/boxed-type';
9
+ import { IndexedLatexDictionary } from './latex-syntax/dictionary/definitions';
10
+ /** @category Compiling */
11
+ export type CompiledType = boolean | number | string | object;
12
+ /** @category Compiling */
13
+ export type JSSource = string;
14
+ /** @category Compiling */
15
+ export type CompiledExpression = {
16
+ evaluate?: (scope: {
17
+ [symbol: string]: BoxedExpression;
18
+ }) => number | BoxedExpression;
19
+ };
20
+ /** @category Tensors */
21
+ export type DataTypeMap = {
22
+ float64: number;
23
+ float32: number;
24
+ int32: number;
25
+ uint8: number;
26
+ complex128: Complex;
27
+ complex64: Complex;
28
+ bool: boolean;
29
+ string: string;
30
+ expression: BoxedExpression;
31
+ };
32
+ /** @category Tensors */
33
+ export type TensorDataType = keyof DataTypeMap;
34
+ /** @category Tensors */
35
+ export interface TensorData<DT extends keyof DataTypeMap = 'float64'> {
36
+ dtype: DT;
37
+ shape: number[];
38
+ rank: number;
39
+ data: DataTypeMap[DT][];
40
+ }
13
41
  /**
14
42
  * :::info[THEORY OF OPERATIONS]
15
43
  *
44
+ * The `BoxedExpression` interface includes the methods and properties
45
+ * applicable to any kind of expression, for example `expr.symbol` or
46
+ * `expr.ops`.
47
+ *
48
+ * When a member function is not applicable to this `BoxedExpression`,
49
+ * for example `get symbol()` on a `BoxedNumber`, it returns `null`.
50
+ *
51
+ * This convention makes it convenient to manipulate expressions without
52
+ * having to check what kind of instance they are before manipulating them.
53
+ * :::
54
+ *
55
+ * To get a boxed expression from a LaTeX string use `ce.parse()`, and to
56
+ * get a boxed expression from a MathJSON expression use `ce.box()`.
57
+ *
58
+ *
16
59
  * To create a boxed expression:
17
60
  *
18
61
  * ### `ce.box()` and `ce.parse()`
@@ -109,52 +152,6 @@ import { BoxedType } from '../../common/type/boxed-type';
109
152
  * used directly, for example `canonicalAdd(a, b)` instead of
110
153
  * `ce.function('Add', [a, b])`.
111
154
  *
112
- * :::
113
- */
114
- export type Sign =
115
- /** The expression is equal to 0 */
116
- 'zero'
117
- /** The expression is > 0 */
118
- | 'positive'
119
- /** The expression is < 0 */
120
- | 'negative'
121
- /** The expression is >= 0 and isPositive is either false or undefined*/
122
- | 'non-negative'
123
- /** The expression is <= 0 and isNegative is either false or undefined*/
124
- | 'non-positive'
125
- /** The expression is not equal to 0 (possibly with an imaginary part) and isPositive, isNegative, isUnsigned are all false or undefined */
126
- | 'not-zero'
127
- /** The expression has no imaginary part and a non-zero real part and isPositive and isNegative are false or undefined*/
128
- | 'real-not-zero'
129
- /** The expression has no imaginary part and isNotZero,isPositive,isNegative,isNonNegative,isNonPositive,isZero are either false or undefined*/
130
- | 'real'
131
- /** The expression is NaN */
132
- | 'nan'
133
- /** The expression is +∞ */
134
- | 'positive-infinity'
135
- /** The expression is -∞ */
136
- | 'negative-infinity'
137
- /** The expression is ~∞ */
138
- | 'complex-infinity'
139
- /** The expression has an imaginary part or is NaN */
140
- | 'unsigned';
141
- /**
142
- * :::info[THEORY OF OPERATIONS]
143
- *
144
- * The `BoxedExpression` interface includes most of the member functions
145
- * applicable to any kind of expression, for example `get symbol()` or
146
- * `get ops()`.
147
- *
148
- * When a member function is not applicable to this `BoxedExpression`,
149
- * for example `get symbol()` on a `BoxedNumber`, it returns `null`.
150
- *
151
- * This convention makes it convenient to manipulate expressions without
152
- * having to check what kind of instance they are before manipulating them.
153
- * :::
154
- *
155
- * To get a boxed expression from a LaTeX string use `ce.parse()`, or to
156
- * get a boxed expression from a MathJSON expression use `ce.box()`.
157
- *
158
155
  * @category Boxed Expression
159
156
  *
160
157
  */
@@ -164,7 +161,7 @@ export interface BoxedExpression {
164
161
  * and functions.
165
162
  *
166
163
  */
167
- readonly engine: IComputeEngine;
164
+ readonly engine: ComputeEngine;
168
165
  /** From `Object.valueOf()`, return a primitive value for the expression.
169
166
  *
170
167
  * If the expression is a machine number, or bignum or rational that can be
@@ -289,11 +286,6 @@ export interface BoxedExpression {
289
286
  *
290
287
  */
291
288
  readonly symbol: string | null;
292
- /**
293
- * @category Symbol Expression
294
- *
295
- */
296
- readonly tensor: null | AbstractTensor<'expression'>;
297
289
  /** If this expression is a string, return the value of the string.
298
290
  * Otherwise, return `null`.
299
291
  *
@@ -305,6 +297,7 @@ export interface BoxedExpression {
305
297
  *
306
298
  */
307
299
  readonly string: string | null;
300
+ readonly tensor: null | TensorData<'expression'>;
308
301
  /** All the subexpressions matching the named operator, recursively.
309
302
  *
310
303
  * :::info[Note]
@@ -737,13 +730,13 @@ export interface BoxedExpression {
737
730
  *
738
731
  * Attempts to make `rest` a positive value (i.e. pulls out negative sign).
739
732
  *
740
- * For example:
741
- *
733
+ *```json
742
734
  * ['Multiply', 2, 'x', 3, 'a']
743
735
  * -> [NumericValue(6), ['Multiply', 'x', 'a']]
744
736
  *
745
737
  * ['Divide', ['Multiply', 2, 'x'], ['Multiply', 3, 'y', 'a']]
746
738
  * -> [NumericValue({rational: [2, 3]}), ['Divide', 'x', ['Multiply, 'y', 'a']]]
739
+ * ```
747
740
  */
748
741
  toNumericValue(): [NumericValue, BoxedExpression];
749
742
  neg(): BoxedExpression;
@@ -938,7 +931,7 @@ export interface BoxedExpression {
938
931
  * integers) are performed but exact calculations may be performed,
939
932
  * for example:
940
933
  *
941
- * \\( \sin(\frac{\pi}{4}) \longrightarrow \frac{\sqrt{2}}{2} \\).
934
+ * $$ \sin(\frac{\pi}{4}) \longrightarrow \frac{\sqrt{2}}{2} $$.
942
935
  *
943
936
  * The result is canonical.
944
937
  *
@@ -1140,7 +1133,7 @@ export interface BoxedExpression {
1140
1133
  * - `expr.isSame(other)` for a structural comparison
1141
1134
  * - `expr.is(other)` for a comparison of a number literal
1142
1135
  *
1143
- * ## Examples
1136
+ * **Examples**
1144
1137
  *
1145
1138
  * ```js
1146
1139
  * let expr = ce.parse('2 + 2');
@@ -1219,30 +1212,6 @@ export interface BoxedExpression {
1219
1212
  * @category Boxed Expression
1220
1213
  */
1221
1214
  export type SemiBoxedExpression = number | bigint | string | BigNum | MathJsonNumber | MathJsonString | MathJsonSymbol | MathJsonFunction | readonly [MathJsonIdentifier, ...SemiBoxedExpression[]] | BoxedExpression;
1222
- /**
1223
- * @category Definitions
1224
- *
1225
- */
1226
- export interface BoxedBaseDefinition {
1227
- name: string;
1228
- wikidata?: string;
1229
- description?: string | string[];
1230
- url?: string;
1231
- /**
1232
- * The scope this definition belongs to.
1233
- *
1234
- * This field is usually undefined, but its value is set by `getDefinition()`
1235
- */
1236
- scope: RuntimeScope | undefined;
1237
- /** If this is the definition of a collection, the set of primitive operations
1238
- * that can be performed on this collection (counting the number of elements,
1239
- * enumerating it, etc...). */
1240
- collection?: Partial<CollectionHandlers>;
1241
- /** When the environment changes, for example the numerical precision,
1242
- * call `reset()` so that any cached values can be recalculated.
1243
- */
1244
- reset(): void;
1245
- }
1246
1215
  /**
1247
1216
  * These handlers compare two expressions.
1248
1217
  *
@@ -1253,251 +1222,542 @@ export interface BoxedBaseDefinition {
1253
1222
  * @category Definitions
1254
1223
  *
1255
1224
  */
1256
- export type EqHandlers = {
1225
+ export interface EqHandlers {
1257
1226
  eq: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1258
1227
  neq: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1259
- };
1228
+ }
1229
+ /** @category Definitions */
1230
+ export type Hold = 'none' | 'all' | 'first' | 'rest' | 'last' | 'most';
1260
1231
  /**
1261
- * These handlers are the primitive operations that can be performed on
1262
- * collections.
1263
- *
1264
- * There are two types of collections:
1265
- *
1266
- * - finite collections, such as lists, tuples, sets, matrices, etc...
1267
- * The `size()` handler of finite collections returns the number of elements
1268
- *
1269
- * - infinite collections, such as sequences, ranges, etc...
1270
- * The `size()` handler of infinite collections returns `Infinity`
1271
- * Infinite collections are not indexable: they have no `at()` handler.
1232
+ * Options to control the serialization to MathJSON when using `BoxedExpression.toMathJson()`.
1272
1233
  *
1273
- * @category Definitions
1234
+ * @category Serialization
1274
1235
  */
1275
- export type CollectionHandlers = {
1276
- /** Return the number of elements in the collection.
1236
+ export type JsonSerializationOptions = {
1237
+ /** If true, the serialization applies some transformations to make
1238
+ * the JSON more readable. For example, `["Power", "x", 2]` is serialized
1239
+ * as `["Square", "x"]`.
1240
+ */
1241
+ prettify: boolean;
1242
+ /** A list of space separated function names that should be excluded from
1243
+ * the JSON output.
1277
1244
  *
1278
- * An empty collection has a size of 0.
1245
+ * Those functions are replaced with an equivalent, for example, `Square` with
1246
+ * `Power`, etc...
1247
+ *
1248
+ * Possible values include `Sqrt`, `Root`, `Square`, `Exp`, `Subtract`,
1249
+ * `Rational`, `Complex`
1250
+ *
1251
+ * **Default**: `[]` (none)
1279
1252
  */
1280
- size: (collection: BoxedExpression) => number;
1281
- /**
1282
- * Return `true` if the target
1283
- * expression is in the collection, `false` otherwise.
1253
+ exclude: string[];
1254
+ /** A list of space separated keywords indicating which MathJSON expressions
1255
+ * can use a shorthand.
1256
+ *
1257
+ * **Default**: `["all"]`
1284
1258
  */
1285
- contains: (collection: BoxedExpression, target: BoxedExpression) => boolean;
1286
- /** Return an iterator
1287
- * - start is optional and is a 1-based index.
1288
- * - if start is not specified, start from index 1
1289
- * - count is optional and is the number of elements to return
1290
- * - if count is not specified or negative, return all the elements from
1291
- * start to the end
1259
+ shorthands: ('all' | 'number' | 'symbol' | 'function' | 'string')[];
1260
+ /** A list of space separated keywords indicating which metadata should be
1261
+ * included in the MathJSON. If metadata is included, shorthand notation
1262
+ * is not used.
1292
1263
  *
1293
- * If there is a `keys()` handler, there is no `iterator()` handler.
1264
+ * **Default**: `[]` (none)
1265
+ */
1266
+ metadata: ('all' | 'wikidata' | 'latex')[];
1267
+ /** If true, repeating decimals are detected and serialized accordingly
1268
+ * For example:
1269
+ * - `1.3333333333333333` \( \to \) `1.(3)`
1270
+ * - `0.142857142857142857142857142857142857142857142857142` \( \to \) `0.(1428571)`
1294
1271
  *
1295
- * @category Definitions
1272
+ * **Default**: `true`
1296
1273
  */
1297
- iterator: (collection: BoxedExpression, start?: number, count?: number) => Iterator<BoxedExpression, undefined>;
1274
+ repeatingDecimal: boolean;
1298
1275
  /**
1299
- * Return the element at the specified index.
1300
- *
1301
- * The first element is `at(1)`, the last element is `at(-1)`.
1276
+ * The maximum number of significant digits in serialized numbers.
1277
+ * - `"max"`: all availabe digits are serialized.
1278
+ * - `"auto"`: use the same precision as the compute engine.
1302
1279
  *
1303
- * If the index is &lt;0, return the element at index `size() + index + 1`.
1280
+ * **Default**: `"auto"`
1281
+ */
1282
+ fractionalDigits: 'auto' | 'max' | number;
1283
+ };
1284
+ /**
1285
+ * Control how a pattern is matched to an expression.
1286
+ *
1287
+ * - `substitution`: if present, assumes these values for the named wildcards,
1288
+ * and ensure that subsequent occurrence of the same wildcard have the same
1289
+ * value.
1290
+ * - `recursive`: if true, match recursively, otherwise match only the top
1291
+ * level.
1292
+ * - `useVariations`: if false, only match expressions that are structurally identical.
1293
+ * If true, match expressions that are structurally identical or equivalent.
1294
+ *
1295
+ * For example, when true, `["Add", '_a', 2]` matches `2`, with a value of
1296
+ * `_a` of `0`. If false, the expression does not match. **Default**: `false`
1297
+ *
1298
+ * @category Pattern Matching
1299
+ *
1300
+ */
1301
+ export type PatternMatchOptions = {
1302
+ substitution?: BoxedSubstitution;
1303
+ recursive?: boolean;
1304
+ useVariations?: boolean;
1305
+ };
1306
+ /**
1307
+ * @category Boxed Expression
1308
+ *
1309
+ */
1310
+ export type ReplaceOptions = {
1311
+ /**
1312
+ * If `true`, apply replacement rules to all sub-expressions.
1304
1313
  *
1305
- * The index can also be a string for example for maps. The set of valid keys
1306
- * is returned by the `keys()` handler.
1314
+ * If `false`, only consider the top-level expression.
1307
1315
  *
1308
- * If the index is invalid, return `undefined`.
1316
+ * **Default**: `false`
1309
1317
  */
1310
- at: (collection: BoxedExpression, index: number | string) => undefined | BoxedExpression;
1318
+ recursive: boolean;
1311
1319
  /**
1312
- * If the collection can be indexed by strings, return the valid values
1313
- * for the index.
1320
+ * If `true`, stop after the first rule that matches.
1321
+ *
1322
+ * If `false`, apply all the remaining rules even after the first match.
1323
+ *
1324
+ * **Default**: `false`
1314
1325
  */
1315
- keys: (collection: BoxedExpression) => undefined | Iterable<string>;
1326
+ once: boolean;
1316
1327
  /**
1317
- * Return the index of the first element that matches the target expression.
1328
+ * If `true` the rule will use some equivalent variations to match.
1318
1329
  *
1319
- * The comparison is done using the `target.isEqual()` method.
1330
+ * For example when `useVariations` is true:
1331
+ * - `x` matches `a + x` with a = 0
1332
+ * - `x` matches `ax` with a = 1
1333
+ * - etc...
1320
1334
  *
1321
- * If the expression is not found, return `undefined`.
1335
+ * Setting this to `true` can save time by condensing multiple rules
1336
+ * into one. This can be particularly useful when describing equations
1337
+ * solutions. However, it can lead to infinite recursion and should be
1338
+ * used with caution.
1322
1339
  *
1323
- * If the expression is found, return the index, 1-based.
1340
+ */
1341
+ useVariations: boolean;
1342
+ /**
1343
+ * If `iterationLimit` > 1, the rules will be repeatedly applied
1344
+ * until no rules apply, up to `maxIterations` times.
1324
1345
  *
1325
- * Return the index of the first match.
1346
+ * Note that if `once` is true, `iterationLimit` has no effect.
1326
1347
  *
1327
- * `from` is the starting index for the search. If negative, start from
1328
- * the end and search backwards.
1348
+ * **Default**: `1`
1329
1349
  */
1330
- indexOf: (collection: BoxedExpression, target: BoxedExpression, from?: number) => number | undefined;
1350
+ iterationLimit: number;
1331
1351
  /**
1332
- * Return `true` if all the elements of `target` are in `expr`.
1333
- * Both `expr` and `target` are collections.
1334
- * If strict is `true`, the subset must be strict, that is, `expr` must
1335
- * have more elements than `target`.
1352
+ * Indicate if the expression should be canonicalized after the replacement.
1353
+ * If not provided, the expression is canonicalized if the expression
1354
+ * that matched the pattern is canonical.
1336
1355
  */
1337
- subsetOf: (collection: BoxedExpression, target: BoxedExpression, strict: boolean) => boolean;
1338
- /** Return the sign of all the elements of the collection. */
1339
- eltsgn: (collection: BoxedExpression) => Sign | undefined;
1340
- /** Return the widest type of all the elements in the collection */
1341
- elttype: (collection: BoxedExpression) => Type | undefined;
1356
+ canonical: CanonicalOptions;
1342
1357
  };
1343
1358
  /**
1344
- * A function definition can have some flags to indicate specific
1345
- * properties of the function.
1359
+ * A bound symbol (i.e. one with an associated definition) has either a type
1360
+ * (e.g. x ∈ ℝ), a value (x = 5) or both (π: value = 3.14... type = 'real')
1346
1361
  * @category Definitions
1347
1362
  */
1348
- export type FunctionDefinitionFlags = {
1363
+ export type SymbolDefinition = BaseDefinition & Partial<SymbolAttributes> & {
1364
+ type?: Type | TypeString;
1365
+ /** If true, the type is inferred, and could be adjusted later
1366
+ * as more information becomes available or if the symbol is explicitly
1367
+ * declared.
1368
+ */
1369
+ inferred?: boolean;
1370
+ /** `value` can be a JS function since for some constants, such as
1371
+ * `Pi`, the actual value depends on the `precision` setting of the
1372
+ * `ComputeEngine` and possible other environment settings */
1373
+ value?: LatexString | SemiBoxedExpression | ((ce: ComputeEngine) => BoxedExpression | null);
1374
+ flags?: Partial<NumericFlags>;
1375
+ eq?: (a: BoxedExpression) => boolean | undefined;
1376
+ neq?: (a: BoxedExpression) => boolean | undefined;
1377
+ cmp?: (a: BoxedExpression) => '=' | '>' | '<' | undefined;
1378
+ collection?: Partial<CollectionHandlers>;
1379
+ };
1380
+ /**
1381
+ * Definition record for a function.
1382
+ * @category Definitions
1383
+ *
1384
+ */
1385
+ export type FunctionDefinition = BaseDefinition & Partial<FunctionDefinitionFlags> & {
1349
1386
  /**
1350
- * If `true`, the arguments to this function are not automatically
1351
- * evaluated. The default is `false` (the arguments are evaluated).
1387
+ * The function signature.
1352
1388
  *
1353
- * This can be useful for example for functions that take symbolic
1354
- * expressions as arguments, such as `D` or `Integrate`.
1389
+ * If a `type` handler is provided, the return type of the function should
1390
+ * be a subtype of the return type in the signature.
1355
1391
  *
1356
- * This is also useful for functions that take an argument that is
1357
- * potentially an infinite collection.
1392
+ */
1393
+ signature?: Type | TypeString;
1394
+ /**
1395
+ * The actual type of the result based on the arguments.
1358
1396
  *
1359
- * It will be up to the `evaluate()` handler to evaluate the arguments as
1360
- * needed. This is conveninent to pass symbolic expressions as arguments
1361
- * to functions without having to explicitly use a `Hold` expression.
1397
+ * Should be a subtype of the type indicated in the signature.
1362
1398
  *
1363
- * This also applies to the `canonical()` handler.
1399
+ * Do not evaluate the arguments.
1364
1400
  *
1365
- */
1366
- lazy: boolean;
1367
- /** If `true`, the function is applied element by element to lists, matrices
1368
- * (`["List"]` or `["Tuple"]` expressions) and equations (relational
1369
- * operators).
1401
+ * The type of the arguments can be used to determine the type of the
1402
+ * result.
1370
1403
  *
1371
- * **Default**: `false`
1372
1404
  */
1373
- threadable: boolean;
1374
- /** If `true`, `["f", ["f", a], b]` simplifies to `["f", a, b]`
1405
+ type?: (ops: ReadonlyArray<BoxedExpression>, options: {
1406
+ engine: ComputeEngine;
1407
+ }) => Type | TypeString | BoxedType | undefined;
1408
+ /** Return the sign of the function expression.
1375
1409
  *
1376
- * **Default**: `false`
1377
- */
1378
- associative: boolean;
1379
- /** If `true`, `["f", a, b]` equals `["f", b, a]`. The canonical
1380
- * version of the function will order the arguments.
1410
+ * If the sign cannot be determined, return `undefined`.
1411
+ *
1412
+ * When determining the sign, only literal values and the values of
1413
+ * symbols, if they are literals, should be considered.
1414
+ *
1415
+ * Do not evaluate the arguments.
1416
+ *
1417
+ * The type and sign of the arguments can be used to determine the sign.
1381
1418
  *
1382
- * **Default**: `false`
1383
1419
  */
1384
- commutative: boolean;
1420
+ sgn?: (ops: ReadonlyArray<BoxedExpression>, options: {
1421
+ engine: ComputeEngine;
1422
+ }) => Sign | undefined;
1423
+ /** Return true of the function expression is even, false if it is odd and
1424
+ * undefined if it is neither.
1425
+ */
1426
+ even?: (ops: ReadonlyArray<BoxedExpression>, options: {
1427
+ engine: ComputeEngine;
1428
+ }) => boolean | undefined;
1385
1429
  /**
1386
- * If `commutative` is `true`, the order of the arguments is determined by
1387
- * this function.
1430
+ * A number used to order arguments.
1388
1431
  *
1389
- * If the function is not provided, the arguments are ordered by the
1390
- * default order of the arguments.
1432
+ * Argument with higher complexity are placed after arguments with
1433
+ * lower complexity when ordered canonically in commutative functions.
1434
+ *
1435
+ * - Additive functions: 1000-1999
1436
+ * - Multiplicative functions: 2000-2999
1437
+ * - Root and power functions: 3000-3999
1438
+ * - Log functions: 4000-4999
1439
+ * - Trigonometric functions: 5000-5999
1440
+ * - Hypertrigonometric functions: 6000-6999
1441
+ * - Special functions (factorial, Gamma, ...): 7000-7999
1442
+ * - Collections: 8000-8999
1443
+ * - Inert and styling: 9000-9999
1444
+ * - Logic: 10000-10999
1445
+ * - Relational: 11000-11999
1391
1446
  *
1447
+ * **Default**: 100,000
1392
1448
  */
1393
- commutativeOrder: ((a: BoxedExpression, b: BoxedExpression) => number) | undefined;
1394
- /** If `true`, when the function is univariate, `["f", ["Multiply", x, c]]`
1395
- * simplifies to `["Multiply", ["f", x], c]` where `c` is constant
1449
+ complexity?: number;
1450
+ /**
1451
+ * Return the canonical form of the expression with the arguments `args`.
1396
1452
  *
1397
- * When the function is multivariate, multiplicativity is considered only on
1398
- * the first argument: `["f", ["Multiply", x, y], z]` simplifies to
1399
- * `["Multiply", ["f", x, z], ["f", y, z]]`
1453
+ * The arguments (`args`) may not be in canonical form. If necessary, they
1454
+ * can be put in canonical form.
1400
1455
  *
1401
- * Default: `false`
1402
- */
1403
- /** If `true`, `["f", ["f", x]]` simplifies to `["f", x]`.
1456
+ * This handler should validate the type and number of the arguments.
1404
1457
  *
1405
- * **Default**: `false`
1406
- */
1407
- idempotent: boolean;
1408
- /** If `true`, `["f", ["f", x]]` simplifies to `x`.
1458
+ * If a required argument is missing, it should be indicated with a
1459
+ * `["Error", "'missing"]` expression. If more arguments than expected
1460
+ * are present, this should be indicated with an
1461
+ * ["Error", "'unexpected-argument'"]` error expression
1409
1462
  *
1410
- * **Default**: `false`
1411
- */
1412
- involution: boolean;
1413
- /** If `true`, the value of this function is always the same for a given
1414
- * set of arguments and it has no side effects.
1463
+ * If the type of an argument is not compatible, it should be indicated
1464
+ * with an `incompatible-type` error.
1415
1465
  *
1416
- * An expression using this function is pure if the function and all its
1417
- * arguments are pure.
1466
+ * `["Sequence"]` expressions are not folded and need to be handled
1467
+ * explicitly.
1418
1468
  *
1419
- * For example `Sin` is pure, `Random` isn't.
1469
+ * If the function is associative, idempotent or an involution,
1470
+ * this handler should account for it. Notably, if it is commutative, the
1471
+ * arguments should be sorted in canonical order.
1420
1472
  *
1421
- * This information may be used to cache the value of expressions.
1422
1473
  *
1423
- * **Default:** `true`
1424
- */
1425
- pure: boolean;
1426
- };
1427
- /** @category Compiling */
1428
- export type CompiledExpression = {
1429
- evaluate?: (scope: {
1430
- [symbol: string]: BoxedExpression;
1431
- }) => number | BoxedExpression;
1432
- };
1433
- /** @category Definitions */
1434
- export type Hold = 'none' | 'all' | 'first' | 'rest' | 'last' | 'most';
1435
- /**
1436
- * @category Definitions
1437
- *
1438
- */
1439
- export type BoxedFunctionDefinition = BoxedBaseDefinition & FunctionDefinitionFlags & {
1440
- complexity: number;
1441
- /** If true, the signature was inferred from usage and may be modified
1442
- * as more information becomes available.
1443
- */
1444
- inferredSignature: boolean;
1445
- /** The type of the arguments and return value of this function */
1446
- signature: BoxedType;
1447
- /** If present, this handler can be used to more precisely determine the
1448
- * return type based on the type of the arguments. The arguments themselves
1449
- * should *not* be evaluated, only their types should be used.
1450
- */
1451
- type?: (ops: ReadonlyArray<BoxedExpression>, options: {
1452
- engine: IComputeEngine;
1453
- }) => Type | TypeString | BoxedType | undefined;
1454
- /** If present, this handler can be used to determine the sign of the
1455
- * return value of the function, based on the sign and type of its
1456
- * arguments.
1474
+ * Values of symbols should not be substituted, unless they have
1475
+ * a `holdUntil` attribute of `"never"`.
1457
1476
  *
1458
- * The arguments themselves should *not* be evaluated, only their types and
1459
- * sign should be used.
1477
+ * The handler should not consider the value or any assumptions about any
1478
+ * of the arguments that are symbols or functions (i.e. `arg.isZero`,
1479
+ * `arg.isInteger`, etc...) since those may change over time.
1480
+ *
1481
+ * The result of the handler should be a canonical expression.
1482
+ *
1483
+ * If the arguments do not match, they should be replaced with an appropriate
1484
+ * `["Error"]` expression. If the expression cannot be put in canonical form,
1485
+ * the handler should return `null`.
1460
1486
  *
1461
- * This can be used in some case for example to determine when certain
1462
- * simplifications are valid.
1463
1487
  */
1464
- sgn?: (ops: ReadonlyArray<BoxedExpression>, options: {
1465
- engine: IComputeEngine;
1466
- }) => Sign | undefined;
1467
- eq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1468
- neq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1469
1488
  canonical?: (ops: ReadonlyArray<BoxedExpression>, options: {
1470
- engine: IComputeEngine;
1489
+ engine: ComputeEngine;
1471
1490
  }) => BoxedExpression | null;
1472
- evaluate?: (ops: ReadonlyArray<BoxedExpression>, options: Partial<EvaluateOptions> & {
1473
- engine?: IComputeEngine;
1474
- }) => BoxedExpression | undefined;
1475
- evaluateAsync?: (ops: ReadonlyArray<BoxedExpression>, options?: Partial<EvaluateOptions> & {
1476
- engine?: IComputeEngine;
1491
+ /**
1492
+ * Evaluate a function expression.
1493
+ *
1494
+ * The arguments have been evaluated, except the arguments to which a
1495
+ * `hold` applied.
1496
+ *
1497
+ * It is not necessary to further simplify or evaluate the arguments.
1498
+ *
1499
+ * If performing numerical calculations and `options.numericalApproximation`
1500
+ * is `false` return an exact numeric value, for example return a rational
1501
+ * number or a square root, rather than a floating point approximation.
1502
+ * Use `ce.number()` to create the numeric value.
1503
+ *
1504
+ * When `numericalApproximation` is `false`, return a floating point number:
1505
+ * - do not reduce rational numbers to decimal (floating point approximation)
1506
+ * - do not reduce square roots of rational numbers
1507
+ *
1508
+ * If the expression cannot be evaluated, due to the values, types, or
1509
+ * assumptions about its arguments, for example, return `undefined` or
1510
+ * an `["Error"]` expression.
1511
+ */
1512
+ evaluate?: ((ops: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
1513
+ engine: ComputeEngine;
1514
+ }) => BoxedExpression | undefined) | BoxedExpression;
1515
+ /**
1516
+ * An option asynchronous version of `evaluate`.
1517
+ *
1518
+ */
1519
+ evaluateAsync?: (ops: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
1520
+ engine: ComputeEngine;
1477
1521
  }) => Promise<BoxedExpression | undefined>;
1478
- evalDimension?: (ops: ReadonlyArray<BoxedExpression>, options: {
1479
- engine: IComputeEngine;
1522
+ /** Dimensional analysis
1523
+ * @experimental
1524
+ */
1525
+ evalDimension?: (args: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
1526
+ engine: ComputeEngine;
1480
1527
  }) => BoxedExpression;
1528
+ /** Return a compiled (optimized) expression. */
1481
1529
  compile?: (expr: BoxedExpression) => CompiledExpression;
1530
+ eq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1531
+ neq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1532
+ collection?: Partial<CollectionHandlers>;
1482
1533
  };
1483
1534
  /**
1484
1535
  * @category Definitions
1485
1536
  *
1486
1537
  */
1487
- export type SymbolAttributes = {
1538
+ export type BaseDefinition = {
1539
+ /** A short (about 1 line) description. May contain Markdown. */
1540
+ description?: string | string[];
1541
+ /** A URL pointing to more information about this symbol or operator. */
1542
+ url?: string;
1488
1543
  /**
1489
- * If `true` the value of the symbol is constant. The value or type of
1490
- * symbols with this attribute set to `true` cannot be changed.
1491
- *
1492
- * If `false`, the symbol is a variable.
1544
+ * A short string representing an entry in a wikibase.
1493
1545
  *
1494
- * **Default**: `false`
1546
+ * For example `Q167` is the [wikidata entry](https://www.wikidata.org/wiki/Q167)
1547
+ * for the `Pi` constant.
1495
1548
  */
1496
- constant: boolean;
1549
+ wikidata?: string;
1550
+ };
1551
+ /** Options for `BoxedExpression.simplify()`
1552
+ *
1553
+ * @category Boxed Expression
1554
+ */
1555
+ export type SimplifyOptions = {
1497
1556
  /**
1498
- * If the symbol has a value, it is held as indicated in the table below.
1499
- * A green checkmark indicate that the symbol is substituted.
1500
-
1557
+ * The set of rules to apply. If `null`, use no rules. If not provided,
1558
+ * use the default simplification rules.
1559
+ */
1560
+ rules?: null | Rule | ReadonlyArray<BoxedRule | Rule> | BoxedRuleSet;
1561
+ /**
1562
+ * Use this cost function to determine if a simplification is worth it.
1563
+ *
1564
+ * If not provided, `ce.costFunction`, the cost function of the engine is
1565
+ * used.
1566
+ */
1567
+ costFunction?: (expr: BoxedExpression) => number;
1568
+ };
1569
+ /**
1570
+ * A table mapping identifiers to their definition.
1571
+ *
1572
+ * Identifiers should be valid MathJSON identifiers. In addition, the
1573
+ * following rules are recommended:
1574
+ *
1575
+ * - Use only latin letters, digits and `-`: `/[a-zA-Z0-9-]+/`
1576
+ * - The first character should be a letter: `/^[a-zA-Z]/`
1577
+ * - Functions and symbols exported from a library should start with an uppercase letter `/^[A-Z]/`
1578
+ *
1579
+ * @category Definitions
1580
+ *
1581
+ */
1582
+ export type IdentifierDefinition = OneOf<[
1583
+ SymbolDefinition,
1584
+ FunctionDefinition,
1585
+ SemiBoxedExpression
1586
+ ]>;
1587
+ /**
1588
+ * @category Definitions
1589
+ *
1590
+ */
1591
+ export type IdentifierDefinitions = Readonly<{
1592
+ [id: string]: IdentifierDefinition;
1593
+ }>;
1594
+ /** @category Numerics */
1595
+ export type Sign =
1596
+ /** The expression is equal to 0 */
1597
+ 'zero'
1598
+ /** The expression is > 0 */
1599
+ | 'positive'
1600
+ /** The expression is < 0 */
1601
+ | 'negative'
1602
+ /** The expression is >= 0 and isPositive is either false or undefined*/
1603
+ | 'non-negative'
1604
+ /** The expression is <= 0 and isNegative is either false or undefined*/
1605
+ | 'non-positive'
1606
+ /** The expression is not equal to 0 (possibly with an imaginary part) and isPositive, isNegative, isUnsigned are all false or undefined */
1607
+ | 'not-zero'
1608
+ /** The expression has no imaginary part and a non-zero real part and isPositive and isNegative are false or undefined*/
1609
+ | 'real-not-zero'
1610
+ /** The expression has no imaginary part and isNotZero,isPositive,isNegative,isNonNegative,isNonPositive,isZero are either false or undefined*/
1611
+ | 'real'
1612
+ /** The expression is NaN */
1613
+ | 'nan'
1614
+ /** The expression is +∞ */
1615
+ | 'positive-infinity'
1616
+ /** The expression is -∞ */
1617
+ | 'negative-infinity'
1618
+ /** The expression is ~∞ */
1619
+ | 'complex-infinity'
1620
+ /** The expression has an imaginary part or is NaN */
1621
+ | 'unsigned';
1622
+ /**
1623
+ * When used in a `SymbolDefinition` or `Functiondefinition` these flags
1624
+ * provide additional information about the value of the symbol or function.
1625
+ *
1626
+ * If provided, they will override the value derived from
1627
+ * the symbol's value.
1628
+ *
1629
+ * @category Definitions
1630
+ */
1631
+ export type NumericFlags = {
1632
+ sgn: Sign | undefined;
1633
+ even: boolean | undefined;
1634
+ odd: boolean | undefined;
1635
+ };
1636
+ /**
1637
+ * These handlers are the primitive operations that can be performed on
1638
+ * collections.
1639
+ *
1640
+ * There are two types of collections:
1641
+ *
1642
+ * - finite collections, such as lists, tuples, sets, matrices, etc...
1643
+ * The `size()` handler of finite collections returns the number of elements
1644
+ *
1645
+ * - infinite collections, such as sequences, ranges, etc...
1646
+ * The `size()` handler of infinite collections returns `Infinity`
1647
+ * Infinite collections are not indexable: they have no `at()` handler.
1648
+ *
1649
+ * @category Definitions
1650
+ */
1651
+ export type CollectionHandlers = {
1652
+ /** Return the number of elements in the collection.
1653
+ *
1654
+ * An empty collection has a size of 0.
1655
+ */
1656
+ size: (collection: BoxedExpression) => number;
1657
+ /**
1658
+ * Return `true` if the target
1659
+ * expression is in the collection, `false` otherwise.
1660
+ */
1661
+ contains: (collection: BoxedExpression, target: BoxedExpression) => boolean;
1662
+ /** Return an iterator
1663
+ * - start is optional and is a 1-based index.
1664
+ * - if start is not specified, start from index 1
1665
+ * - count is optional and is the number of elements to return
1666
+ * - if count is not specified or negative, return all the elements from
1667
+ * start to the end
1668
+ *
1669
+ * If there is a `keys()` handler, there is no `iterator()` handler.
1670
+ *
1671
+ * @category Definitions
1672
+ */
1673
+ iterator: (collection: BoxedExpression, start?: number, count?: number) => Iterator<BoxedExpression, undefined>;
1674
+ /**
1675
+ * Return the element at the specified index.
1676
+ *
1677
+ * The first element is `at(1)`, the last element is `at(-1)`.
1678
+ *
1679
+ * If the index is &lt;0, return the element at index `size() + index + 1`.
1680
+ *
1681
+ * The index can also be a string for example for maps. The set of valid keys
1682
+ * is returned by the `keys()` handler.
1683
+ *
1684
+ * If the index is invalid, return `undefined`.
1685
+ */
1686
+ at: (collection: BoxedExpression, index: number | string) => undefined | BoxedExpression;
1687
+ /**
1688
+ * If the collection can be indexed by strings, return the valid values
1689
+ * for the index.
1690
+ */
1691
+ keys: (collection: BoxedExpression) => undefined | Iterable<string>;
1692
+ /**
1693
+ * Return the index of the first element that matches the target expression.
1694
+ *
1695
+ * The comparison is done using the `target.isEqual()` method.
1696
+ *
1697
+ * If the expression is not found, return `undefined`.
1698
+ *
1699
+ * If the expression is found, return the index, 1-based.
1700
+ *
1701
+ * Return the index of the first match.
1702
+ *
1703
+ * `from` is the starting index for the search. If negative, start from
1704
+ * the end and search backwards.
1705
+ */
1706
+ indexOf: (collection: BoxedExpression, target: BoxedExpression, from?: number) => number | undefined;
1707
+ /**
1708
+ * Return `true` if all the elements of `target` are in `expr`.
1709
+ * Both `expr` and `target` are collections.
1710
+ * If strict is `true`, the subset must be strict, that is, `expr` must
1711
+ * have more elements than `target`.
1712
+ */
1713
+ subsetOf: (collection: BoxedExpression, target: BoxedExpression, strict: boolean) => boolean;
1714
+ /** Return the sign of all the elements of the collection. */
1715
+ eltsgn: (collection: BoxedExpression) => Sign | undefined;
1716
+ /** Return the widest type of all the elements in the collection */
1717
+ elttype: (collection: BoxedExpression) => Type | undefined;
1718
+ };
1719
+ /**
1720
+ * @category Definitions
1721
+ *
1722
+ */
1723
+ export interface BoxedBaseDefinition {
1724
+ name: string;
1725
+ wikidata?: string;
1726
+ description?: string | string[];
1727
+ url?: string;
1728
+ /**
1729
+ * The scope this definition belongs to.
1730
+ *
1731
+ * This field is usually undefined, but its value is set by `getDefinition()`
1732
+ */
1733
+ scope: RuntimeScope | undefined;
1734
+ /** If this is the definition of a collection, the set of primitive operations
1735
+ * that can be performed on this collection (counting the number of elements,
1736
+ * enumerating it, etc...). */
1737
+ collection?: Partial<CollectionHandlers>;
1738
+ /** When the environment changes, for example the numerical precision,
1739
+ * call `reset()` so that any cached values can be recalculated.
1740
+ */
1741
+ reset(): void;
1742
+ }
1743
+ /**
1744
+ * @category Definitions
1745
+ *
1746
+ */
1747
+ export type SymbolAttributes = {
1748
+ /**
1749
+ * If `true` the value of the symbol is constant. The value or type of
1750
+ * symbols with this attribute set to `true` cannot be changed.
1751
+ *
1752
+ * If `false`, the symbol is a variable.
1753
+ *
1754
+ * **Default**: `false`
1755
+ */
1756
+ constant: boolean;
1757
+ /**
1758
+ * If the symbol has a value, it is held as indicated in the table below.
1759
+ * A green checkmark indicate that the symbol is substituted.
1760
+
1501
1761
  <div className="symbols-table">
1502
1762
 
1503
1763
  | Operation | `"never"` | `"evaluate"` | `"N"` |
@@ -1518,21 +1778,6 @@ export type SymbolAttributes = {
1518
1778
  holdUntil: 'never' | 'evaluate' | 'N';
1519
1779
  };
1520
1780
  /**
1521
- * When used in a `SymbolDefinition` or `Functiondefinition` these flags
1522
- * provide additional information about the value of the symbol or function.
1523
- *
1524
- * If provided, they will override the value derived from
1525
- * the symbol's value.
1526
- *
1527
- * @category Definitions
1528
- */
1529
- export type NumericFlags = {
1530
- sgn: Sign | undefined;
1531
- even: boolean | undefined;
1532
- odd: boolean | undefined;
1533
- };
1534
- /**
1535
- * @noInheritDoc
1536
1781
  * @category Definitions
1537
1782
  */
1538
1783
  export interface BoxedSymbolDefinition extends BoxedBaseDefinition, SymbolAttributes, Partial<NumericFlags> {
@@ -1547,112 +1792,201 @@ export interface BoxedSymbolDefinition extends BoxedBaseDefinition, SymbolAttrib
1547
1792
  type: BoxedType;
1548
1793
  }
1549
1794
  /**
1550
- * Given an expression and set of wildcards, return a new expression.
1551
- *
1552
- * For example:
1553
- *
1554
- * ```ts
1555
- * {
1556
- * match: '_x',
1557
- * replace: (expr, {_x}) => { return ['Add', 1, _x] }
1558
- * }
1559
- * ```
1560
- *
1561
- * @category Rules */
1562
- export type RuleReplaceFunction = (expr: BoxedExpression, wildcards: BoxedSubstitution) => BoxedExpression | undefined;
1563
- /** @category Rules */
1564
- export type RuleConditionFunction = (wildcards: BoxedSubstitution, ce: IComputeEngine) => boolean;
1565
- /** @category Rules */
1566
- export type RuleFunction = (expr: BoxedExpression) => undefined | BoxedExpression | RuleStep;
1567
- export declare function isRuleStep(x: any): x is RuleStep;
1568
- /**
1569
- * A rule describes how to modify an expressions that matches a pattern `match`
1570
- * into a new expression `replace`.
1571
- *
1572
- * - `x-1` \( \to \) `1-x`
1573
- * - `(x+1)(x-1)` \( \to \) `x^2-1
1574
- *
1575
- * The patterns can be expressed as LaTeX strings or a MathJSON expressions.
1576
- *
1577
- * As a shortcut, a rule can be defined as a LaTeX string: `x-1 -> 1-x`.
1578
- * The expression to the left of `->` is the `match` and the expression to the
1579
- * right is the `replace`. When using LaTeX strings, single character variables
1580
- * are assumed to be wildcards.
1795
+ * A scope is a set of names in a dictionary that are bound (defined) in
1796
+ * a MathJSON expression.
1581
1797
  *
1582
- * When using MathJSON expressions, anonymous wildcards (`_`) will match any
1583
- * expression. Named wildcards (`_x`, `_a`, etc...) will match any expression
1584
- * and bind the expression to the wildcard name.
1798
+ * Scopes are arranged in a stack structure. When an expression that defined
1799
+ * a new scope is evaluated, the new scope is added to the scope stack.
1800
+ * Outside of the expression, the scope is removed from the scope stack.
1585
1801
  *
1586
- * In addition the sequence wildcard (`__1`, `__a`, etc...) will match
1587
- * a sequence of one or more expressions, and bind the sequence to the
1588
- * wildcard name.
1802
+ * The scope stack is used to resolve symbols, and it is possible for
1803
+ * a scope to 'mask' definitions from previous scopes.
1589
1804
  *
1590
- * Sequence wildcards are useful when the number of elements in the sequence
1591
- * is not known in advance. For example, in a sum, the number of terms is
1592
- * not known in advance. ["Add", 0, `__a`] will match two or more terms and
1593
- * the `__a` wildcard will be a sequence of the matchign terms.
1805
+ * Scopes are lexical (also called a static scope): they are defined based on
1806
+ * where they are in an expression, they are not determined at runtime.
1594
1807
  *
1595
- * If `exact` is false, the rule will match variants.
1808
+ * @category Compute Engine
1809
+ */
1810
+ export type Scope = Record<string, any>;
1811
+ /** Options for `BoxedExpression.evaluate()`
1596
1812
  *
1597
- * For example 'x' will match 'a + x', 'x' will match 'ax', etc...
1598
- *
1599
- * For simplification rules, you generally want `exact` to be true, but
1600
- * to solve equations, you want it to be false. Default to true.
1601
- *
1602
- * When set to false, infinite recursion is possible.
1603
- *
1604
- * @category Rules
1813
+ * @category Boxed Expression
1605
1814
  */
1606
- export type Rule = string | RuleFunction | {
1607
- match?: LatexString | SemiBoxedExpression | Pattern;
1608
- replace: LatexString | SemiBoxedExpression | RuleReplaceFunction | RuleFunction;
1609
- condition?: LatexString | RuleConditionFunction;
1610
- useVariations?: boolean;
1611
- id?: string;
1815
+ export type EvaluateOptions = {
1816
+ numericApproximation: boolean;
1817
+ signal: AbortSignal;
1612
1818
  };
1613
1819
  /**
1614
- *
1615
- * If the `match` property is `undefined`, all expressions match this rule
1616
- * and `condition` should also be `undefined`. The `replace` property should
1617
- * be a `BoxedExpression` or a `RuleFunction`, and further filtering can be
1618
- * done in the `replace` function.
1619
- *
1620
- * @category Rules */
1621
- export type BoxedRule = {
1622
- /** @internal */
1623
- readonly _tag: 'boxed-rule';
1624
- match: undefined | Pattern;
1625
- replace: BoxedExpression | RuleReplaceFunction | RuleFunction;
1626
- condition: undefined | RuleConditionFunction;
1627
- useVariations?: boolean;
1628
- id?: string;
1629
- };
1630
- export declare function isBoxedRule(x: any): x is BoxedRule;
1631
- export type RuleStep = {
1632
- value: BoxedExpression;
1633
- because: string;
1820
+ * A function definition can have some flags to indicate specific
1821
+ * properties of the function.
1822
+ * @category Definitions
1823
+ */
1824
+ export type FunctionDefinitionFlags = {
1825
+ /**
1826
+ * If `true`, the arguments to this function are not automatically
1827
+ * evaluated. The default is `false` (the arguments are evaluated).
1828
+ *
1829
+ * This can be useful for example for functions that take symbolic
1830
+ * expressions as arguments, such as `D` or `Integrate`.
1831
+ *
1832
+ * This is also useful for functions that take an argument that is
1833
+ * potentially an infinite collection.
1834
+ *
1835
+ * It will be up to the `evaluate()` handler to evaluate the arguments as
1836
+ * needed. This is conveninent to pass symbolic expressions as arguments
1837
+ * to functions without having to explicitly use a `Hold` expression.
1838
+ *
1839
+ * This also applies to the `canonical()` handler.
1840
+ *
1841
+ */
1842
+ lazy: boolean;
1843
+ /** If `true`, the function is applied element by element to lists, matrices
1844
+ * (`["List"]` or `["Tuple"]` expressions) and equations (relational
1845
+ * operators).
1846
+ *
1847
+ * **Default**: `false`
1848
+ */
1849
+ threadable: boolean;
1850
+ /** If `true`, `["f", ["f", a], b]` simplifies to `["f", a, b]`
1851
+ *
1852
+ * **Default**: `false`
1853
+ */
1854
+ associative: boolean;
1855
+ /** If `true`, `["f", a, b]` equals `["f", b, a]`. The canonical
1856
+ * version of the function will order the arguments.
1857
+ *
1858
+ * **Default**: `false`
1859
+ */
1860
+ commutative: boolean;
1861
+ /**
1862
+ * If `commutative` is `true`, the order of the arguments is determined by
1863
+ * this function.
1864
+ *
1865
+ * If the function is not provided, the arguments are ordered by the
1866
+ * default order of the arguments.
1867
+ *
1868
+ */
1869
+ commutativeOrder: ((a: BoxedExpression, b: BoxedExpression) => number) | undefined;
1870
+ /** If `true`, when the function is univariate, `["f", ["Multiply", x, c]]`
1871
+ * simplifies to `["Multiply", ["f", x], c]` where `c` is constant
1872
+ *
1873
+ * When the function is multivariate, multiplicativity is considered only on
1874
+ * the first argument: `["f", ["Multiply", x, y], z]` simplifies to
1875
+ * `["Multiply", ["f", x, z], ["f", y, z]]`
1876
+ *
1877
+ * Default: `false`
1878
+ */
1879
+ /** If `true`, `["f", ["f", x]]` simplifies to `["f", x]`.
1880
+ *
1881
+ * **Default**: `false`
1882
+ */
1883
+ idempotent: boolean;
1884
+ /** If `true`, `["f", ["f", x]]` simplifies to `x`.
1885
+ *
1886
+ * **Default**: `false`
1887
+ */
1888
+ involution: boolean;
1889
+ /** If `true`, the value of this function is always the same for a given
1890
+ * set of arguments and it has no side effects.
1891
+ *
1892
+ * An expression using this function is pure if the function and all its
1893
+ * arguments are pure.
1894
+ *
1895
+ * For example `Sin` is pure, `Random` isn't.
1896
+ *
1897
+ * This information may be used to cache the value of expressions.
1898
+ *
1899
+ * **Default:** `true`
1900
+ */
1901
+ pure: boolean;
1634
1902
  };
1635
- export type RuleSteps = RuleStep[];
1636
1903
  /**
1637
- * To create a BoxedRuleSet use the `ce.rules()` method.
1638
- *
1639
- * Do not create a `BoxedRuleSet` directly.
1904
+ * @category Definitions
1640
1905
  *
1641
- * @category Rules */
1642
- export type BoxedRuleSet = {
1643
- rules: ReadonlyArray<BoxedRule>;
1906
+ */
1907
+ export type BoxedFunctionDefinition = BoxedBaseDefinition & FunctionDefinitionFlags & {
1908
+ complexity: number;
1909
+ /** If true, the signature was inferred from usage and may be modified
1910
+ * as more information becomes available.
1911
+ */
1912
+ inferredSignature: boolean;
1913
+ /** The type of the arguments and return value of this function */
1914
+ signature: BoxedType;
1915
+ /** If present, this handler can be used to more precisely determine the
1916
+ * return type based on the type of the arguments. The arguments themselves
1917
+ * should *not* be evaluated, only their types should be used.
1918
+ */
1919
+ type?: (ops: ReadonlyArray<BoxedExpression>, options: {
1920
+ engine: ComputeEngine;
1921
+ }) => Type | TypeString | BoxedType | undefined;
1922
+ /** If present, this handler can be used to determine the sign of the
1923
+ * return value of the function, based on the sign and type of its
1924
+ * arguments.
1925
+ *
1926
+ * The arguments themselves should *not* be evaluated, only their types and
1927
+ * sign should be used.
1928
+ *
1929
+ * This can be used in some case for example to determine when certain
1930
+ * simplifications are valid.
1931
+ */
1932
+ sgn?: (ops: ReadonlyArray<BoxedExpression>, options: {
1933
+ engine: ComputeEngine;
1934
+ }) => Sign | undefined;
1935
+ eq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1936
+ neq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
1937
+ canonical?: (ops: ReadonlyArray<BoxedExpression>, options: {
1938
+ engine: ComputeEngine;
1939
+ }) => BoxedExpression | null;
1940
+ evaluate?: (ops: ReadonlyArray<BoxedExpression>, options: Partial<EvaluateOptions> & {
1941
+ engine?: ComputeEngine;
1942
+ }) => BoxedExpression | undefined;
1943
+ evaluateAsync?: (ops: ReadonlyArray<BoxedExpression>, options?: Partial<EvaluateOptions> & {
1944
+ engine?: ComputeEngine;
1945
+ }) => Promise<BoxedExpression | undefined>;
1946
+ evalDimension?: (ops: ReadonlyArray<BoxedExpression>, options: {
1947
+ engine: ComputeEngine;
1948
+ }) => BoxedExpression;
1949
+ compile?: (expr: BoxedExpression) => CompiledExpression;
1644
1950
  };
1645
1951
  /**
1646
- * @noInheritDoc
1952
+ * The entries have been validated and optimized for faster evaluation.
1647
1953
  *
1648
- * @category Pattern Matching
1954
+ * When a new scope is created with `pushScope()` or when creating a new
1955
+ * engine instance, new instances of this type are created as needed.
1956
+ *
1957
+ * @category Definitions
1649
1958
  */
1650
- export type Pattern = BoxedExpression;
1959
+ export type RuntimeIdentifierDefinitions = Map<string, OneOf<[BoxedSymbolDefinition, BoxedFunctionDefinition]>>;
1960
+ /** @category Assumptions */
1961
+ export interface ExpressionMapInterface<U> {
1962
+ has(expr: BoxedExpression): boolean;
1963
+ get(expr: BoxedExpression): U | undefined;
1964
+ set(expr: BoxedExpression, value: U): void;
1965
+ delete(expr: BoxedExpression): void;
1966
+ clear(): void;
1967
+ [Symbol.iterator](): IterableIterator<[BoxedExpression, U]>;
1968
+ entries(): IterableIterator<[BoxedExpression, U]>;
1969
+ }
1970
+ /** @category Assumptions */
1971
+ export type AssumeResult = 'internal-error' | 'not-a-predicate' | 'contradiction' | 'tautology' | 'ok';
1651
1972
  /**
1652
- * @category Boxed Expression
1973
+ * When a unitless value is passed to or returned from a trigonometric function,
1974
+ * the angular unit of the value.
1653
1975
  *
1976
+ * - `rad`: radians, 2π radians is a full circle
1977
+ * - `deg`: degrees, 360 degrees is a full circle
1978
+ * - `grad`: gradians, 400 gradians is a full circle
1979
+ * - `turn`: turns, 1 turn is a full circle
1980
+ *
1981
+ * @category Compute Engine
1654
1982
  */
1655
- export type BoxedSubstitution = Substitution<BoxedExpression>;
1983
+ export type AngularUnit = 'rad' | 'deg' | 'grad' | 'turn';
1984
+ /** @category Compute Engine */
1985
+ export type RuntimeScope = Scope & {
1986
+ parentScope?: RuntimeScope;
1987
+ ids?: RuntimeIdentifierDefinitions;
1988
+ assumptions: undefined | ExpressionMapInterface<boolean>;
1989
+ };
1656
1990
  /**
1657
1991
  * When provided, canonical forms are used to put an expression in a
1658
1992
  * "standard" form.
@@ -1679,33 +2013,8 @@ export type BoxedSubstitution = Substitution<BoxedExpression>;
1679
2013
  * @category Boxed Expression
1680
2014
  */
1681
2015
  export type CanonicalForm = 'InvisibleOperator' | 'Number' | 'Multiply' | 'Add' | 'Power' | 'Divide' | 'Flatten' | 'Order';
2016
+ /** @category Boxed Expression */
1682
2017
  export type CanonicalOptions = boolean | CanonicalForm | CanonicalForm[];
1683
- /** Options for `BoxedExpression.simplify()`
1684
- *
1685
- * @category Compute Engine
1686
- */
1687
- export type SimplifyOptions = {
1688
- /**
1689
- * The set of rules to apply. If `null`, use no rules. If not provided,
1690
- * use the default simplification rules.
1691
- */
1692
- rules?: null | Rule | ReadonlyArray<BoxedRule | Rule> | BoxedRuleSet;
1693
- /**
1694
- * Use this cost function to determine if a simplification is worth it.
1695
- *
1696
- * If not provided, `ce.costFunction`, the cost function of the engine is
1697
- * used.
1698
- */
1699
- costFunction?: (expr: BoxedExpression) => number;
1700
- };
1701
- /** Options for `BoxedExpression.evaluate()`
1702
- *
1703
- * @category Boxed Expression
1704
- */
1705
- export type EvaluateOptions = {
1706
- numericApproximation: boolean;
1707
- signal: AbortSignal;
1708
- };
1709
2018
  /**
1710
2019
  * Metadata that can be associated with a `BoxedExpression`
1711
2020
  *
@@ -1716,33 +2025,132 @@ export type Metadata = {
1716
2025
  wikidata?: string | undefined;
1717
2026
  };
1718
2027
  /**
1719
- * When a unitless value is passed to or returned from a trigonometric function,
1720
- * the angular unit of the value.
2028
+ * A substitution describes the values of the wildcards in a pattern so that
2029
+ * the pattern is equal to a target expression.
1721
2030
  *
1722
- * - `rad`: radians, radians is a full circle
1723
- * - `deg`: degrees, 360 degrees is a full circle
1724
- * - `grad`: gradians, 400 gradians is a full circle
1725
- * - `turn`: turns, 1 turn is a full circle
2031
+ * A substitution can also be considered a more constrained version of a
2032
+ * rule whose `match` is always a symbol.
2033
+
2034
+ * @category Pattern Matching
2035
+ */
2036
+ export type Substitution<T = SemiBoxedExpression> = {
2037
+ [symbol: string]: T;
2038
+ };
2039
+ /**
2040
+ * @category Pattern Matching
1726
2041
  *
1727
- * @category Compute Engine
1728
2042
  */
1729
- export type AngularUnit = 'rad' | 'deg' | 'grad' | 'turn';
1730
- /** @category Compute Engine */
1731
- export type ArrayValue = boolean | number | string | BigNum | BoxedExpression | undefined;
1732
- /** @category Assumptions */
1733
- export type AssumeResult = 'internal-error' | 'not-a-predicate' | 'contradiction' | 'tautology' | 'ok';
1734
- /** @category Compute Engine */
1735
- export type AssignValue = boolean | number | SemiBoxedExpression | ((args: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
1736
- engine: IComputeEngine;
1737
- }) => BoxedExpression) | undefined;
1738
- /** @internal */
1739
- export interface IComputeEngine extends IBigNum {
1740
- latexDictionary: readonly LatexDictionaryEntry[];
1741
- /** @private */
1742
- indexedLatexDictionary: IndexedLatexDictionary;
1743
- decimalSeparator: LatexString;
1744
- readonly True: BoxedExpression;
1745
- readonly False: BoxedExpression;
2043
+ export type BoxedSubstitution = Substitution<BoxedExpression>;
2044
+ /**
2045
+ * Given an expression and set of wildcards, return a new expression.
2046
+ *
2047
+ * For example:
2048
+ *
2049
+ * ```ts
2050
+ * {
2051
+ * match: '_x',
2052
+ * replace: (expr, {_x}) => { return ['Add', 1, _x] }
2053
+ * }
2054
+ * ```
2055
+ *
2056
+ * @category Rules */
2057
+ export type RuleReplaceFunction = (expr: BoxedExpression, wildcards: BoxedSubstitution) => BoxedExpression | undefined;
2058
+ /** @category Rules */
2059
+ export type RuleConditionFunction = (wildcards: BoxedSubstitution, ce: ComputeEngine) => boolean;
2060
+ /** @category Rules */
2061
+ export type RuleFunction = (expr: BoxedExpression) => undefined | BoxedExpression | RuleStep;
2062
+ /** @category Rules */
2063
+ export type RuleStep = {
2064
+ value: BoxedExpression;
2065
+ because: string;
2066
+ };
2067
+ /** @category Rules */
2068
+ export type RuleSteps = RuleStep[];
2069
+ /**
2070
+ * A rule describes how to modify an expressions that matches a pattern `match`
2071
+ * into a new expression `replace`.
2072
+ *
2073
+ * - `x-1` \( \to \) `1-x`
2074
+ * - `(x+1)(x-1)` \( \to \) `x^2-1
2075
+ *
2076
+ * The patterns can be expressed as LaTeX strings or a MathJSON expressions.
2077
+ *
2078
+ * As a shortcut, a rule can be defined as a LaTeX string: `x-1 -> 1-x`.
2079
+ * The expression to the left of `->` is the `match` and the expression to the
2080
+ * right is the `replace`. When using LaTeX strings, single character variables
2081
+ * are assumed to be wildcards.
2082
+ *
2083
+ * When using MathJSON expressions, anonymous wildcards (`_`) will match any
2084
+ * expression. Named wildcards (`_x`, `_a`, etc...) will match any expression
2085
+ * and bind the expression to the wildcard name.
2086
+ *
2087
+ * In addition the sequence wildcard (`__1`, `__a`, etc...) will match
2088
+ * a sequence of one or more expressions, and bind the sequence to the
2089
+ * wildcard name.
2090
+ *
2091
+ * Sequence wildcards are useful when the number of elements in the sequence
2092
+ * is not known in advance. For example, in a sum, the number of terms is
2093
+ * not known in advance. ["Add", 0, `__a`] will match two or more terms and
2094
+ * the `__a` wildcard will be a sequence of the matchign terms.
2095
+ *
2096
+ * If `exact` is false, the rule will match variants.
2097
+ *
2098
+ * For example 'x' will match 'a + x', 'x' will match 'ax', etc...
2099
+ *
2100
+ * For simplification rules, you generally want `exact` to be true, but
2101
+ * to solve equations, you want it to be false. Default to true.
2102
+ *
2103
+ * When set to false, infinite recursion is possible.
2104
+ *
2105
+ * @category Rules
2106
+ */
2107
+ export type Rule = string | RuleFunction | {
2108
+ match?: LatexString | SemiBoxedExpression | BoxedExpression;
2109
+ replace: LatexString | SemiBoxedExpression | RuleReplaceFunction | RuleFunction;
2110
+ condition?: LatexString | RuleConditionFunction;
2111
+ useVariations?: boolean;
2112
+ id?: string;
2113
+ };
2114
+ /**
2115
+ *
2116
+ * If the `match` property is `undefined`, all expressions match this rule
2117
+ * and `condition` should also be `undefined`. The `replace` property should
2118
+ * be a `BoxedExpression` or a `RuleFunction`, and further filtering can be
2119
+ * done in the `replace` function.
2120
+ *
2121
+ * @category Rules
2122
+ */
2123
+ export type BoxedRule = {
2124
+ /** @internal */
2125
+ readonly _tag: 'boxed-rule';
2126
+ match: undefined | BoxedExpression;
2127
+ replace: BoxedExpression | RuleReplaceFunction | RuleFunction;
2128
+ condition: undefined | RuleConditionFunction;
2129
+ useVariations?: boolean;
2130
+ id?: string;
2131
+ };
2132
+ /**
2133
+ * To create a BoxedRuleSet use the `ce.rules()` method.
2134
+ *
2135
+ * Do not create a `BoxedRuleSet` directly.
2136
+ *
2137
+ * @category Rules
2138
+ */
2139
+ export type BoxedRuleSet = {
2140
+ rules: ReadonlyArray<BoxedRule>;
2141
+ };
2142
+ /** @category Compute Engine */
2143
+ export type AssignValue = boolean | number | SemiBoxedExpression | ((args: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
2144
+ engine: ComputeEngine;
2145
+ }) => BoxedExpression) | undefined;
2146
+ /** @internal */
2147
+ export interface ComputeEngine extends IBigNum {
2148
+ latexDictionary: readonly LatexDictionaryEntry[];
2149
+ /** @private */
2150
+ indexedLatexDictionary: IndexedLatexDictionary;
2151
+ decimalSeparator: LatexString;
2152
+ readonly True: BoxedExpression;
2153
+ readonly False: BoxedExpression;
1746
2154
  readonly Pi: BoxedExpression;
1747
2155
  readonly E: BoxedExpression;
1748
2156
  readonly Nothing: BoxedExpression;
@@ -1875,8 +2283,8 @@ export interface IComputeEngine extends IBigNum {
1875
2283
  parse(latex: LatexString | null, options?: Partial<ParseLatexOptions> & {
1876
2284
  canonical?: CanonicalOptions;
1877
2285
  }): BoxedExpression | null;
1878
- pushScope(scope?: Partial<Scope>): IComputeEngine;
1879
- popScope(): IComputeEngine;
2286
+ pushScope(scope?: Partial<Scope>): ComputeEngine;
2287
+ popScope(): ComputeEngine;
1880
2288
  swapScope(scope: RuntimeScope | null): RuntimeScope | null;
1881
2289
  resetContext(): void;
1882
2290
  defineSymbol(name: string, def: SymbolDefinition): BoxedSymbolDefinition;
@@ -1885,18 +2293,18 @@ export interface IComputeEngine extends IBigNum {
1885
2293
  lookupFunction(name: string, scope?: RuntimeScope | null): undefined | BoxedFunctionDefinition;
1886
2294
  assign(ids: {
1887
2295
  [id: string]: AssignValue;
1888
- }): IComputeEngine;
1889
- assign(id: string, value: AssignValue): IComputeEngine;
2296
+ }): ComputeEngine;
2297
+ assign(id: string, value: AssignValue): ComputeEngine;
1890
2298
  assign(arg1: string | {
1891
2299
  [id: string]: AssignValue;
1892
- }, arg2?: AssignValue): IComputeEngine;
2300
+ }, arg2?: AssignValue): ComputeEngine;
1893
2301
  declare(identifiers: {
1894
2302
  [id: string]: Type | TypeString | OneOf<[SymbolDefinition | FunctionDefinition]>;
1895
- }): IComputeEngine;
1896
- declare(id: string, def: Type | TypeString | SymbolDefinition | FunctionDefinition): IComputeEngine;
2303
+ }): ComputeEngine;
2304
+ declare(id: string, def: Type | TypeString | SymbolDefinition | FunctionDefinition): ComputeEngine;
1897
2305
  declare(arg1: string | {
1898
2306
  [id: string]: Type | TypeString | OneOf<[SymbolDefinition | FunctionDefinition]>;
1899
- }, arg2?: Type | OneOf<[SymbolDefinition | FunctionDefinition]>): IComputeEngine;
2307
+ }, arg2?: Type | OneOf<[SymbolDefinition | FunctionDefinition]>): ComputeEngine;
1900
2308
  assume(predicate: BoxedExpression): AssumeResult;
1901
2309
  forget(symbol?: string | string[]): void;
1902
2310
  get assumptions(): ExpressionMapInterface<boolean>;
@@ -1923,383 +2331,3 @@ export interface ComputeEngineStats {
1923
2331
  expressions: null | Set<BoxedExpression>;
1924
2332
  highwaterMark: number;
1925
2333
  }
1926
- /**
1927
- * Options to control the serialization to MathJSON when using `BoxedExpression.toMathJson()`.
1928
- *
1929
- * @category Compute Engine
1930
- */
1931
- export type JsonSerializationOptions = {
1932
- /** If true, the serialization applies some transformations to make
1933
- * the JSON more readable. For example, `["Power", "x", 2]` is serialized
1934
- * as `["Square", "x"]`.
1935
- */
1936
- prettify: boolean;
1937
- /** A list of space separated function names that should be excluded from
1938
- * the JSON output.
1939
- *
1940
- * Those functions are replaced with an equivalent, for example, `Square` with
1941
- * `Power`, etc...
1942
- *
1943
- * Possible values include `Sqrt`, `Root`, `Square`, `Exp`, `Subtract`,
1944
- * `Rational`, `Complex`
1945
- *
1946
- * **Default**: `[]` (none)
1947
- */
1948
- exclude: string[];
1949
- /** A list of space separated keywords indicating which MathJSON expressions
1950
- * can use a shorthand.
1951
- *
1952
- * **Default**: `["all"]`
1953
- */
1954
- shorthands: ('all' | 'number' | 'symbol' | 'function' | 'string')[];
1955
- /** A list of space separated keywords indicating which metadata should be
1956
- * included in the MathJSON. If metadata is included, shorthand notation
1957
- * is not used.
1958
- *
1959
- * **Default**: `[]` (none)
1960
- */
1961
- metadata: ('all' | 'wikidata' | 'latex')[];
1962
- /** If true, repeating decimals are detected and serialized accordingly
1963
- * For example:
1964
- * - `1.3333333333333333` \( \to \) `1.(3)`
1965
- * - `0.142857142857142857142857142857142857142857142857142` \( \to \) `0.(1428571)`
1966
- *
1967
- * **Default**: `true`
1968
- */
1969
- repeatingDecimal: boolean;
1970
- /**
1971
- * The maximum number of significant digits in serialized numbers.
1972
- * - `"max"`: all availabe digits are serialized.
1973
- * - `"auto"`: use the same precision as the compute engine.
1974
- *
1975
- * **Default**: `"auto"`
1976
- */
1977
- fractionalDigits: 'auto' | 'max' | number;
1978
- };
1979
- /** A LaTeX string starts and end with `$`, for example
1980
- * `"$\frac{\pi}{2}$"`.
1981
- *
1982
- * @category Latex Parsing and Serialization
1983
- */
1984
- export type LatexString = string;
1985
- /**
1986
- * Control how a pattern is matched to an expression.
1987
- *
1988
- * - `substitution`: if present, assumes these values for the named wildcards,
1989
- * and ensure that subsequent occurrence of the same wildcard have the same
1990
- * value.
1991
- * - `recursive`: if true, match recursively, otherwise match only the top
1992
- * level.
1993
- * - `useVariations`: if false, only match expressions that are structurally identical.
1994
- * If true, match expressions that are structurally identical or equivalent.
1995
- *
1996
- * For example, when true, `["Add", '_a', 2]` matches `2`, with a value of
1997
- * `_a` of `0`. If false, the expression does not match. **Default**: `false`
1998
- *
1999
- * @category Pattern Matching
2000
- *
2001
- */
2002
- export type PatternMatchOptions = {
2003
- substitution?: BoxedSubstitution;
2004
- recursive?: boolean;
2005
- useVariations?: boolean;
2006
- };
2007
- /**
2008
- * @category Boxed Expression
2009
- *
2010
- */
2011
- export type ReplaceOptions = {
2012
- /**
2013
- * If `true`, apply replacement rules to all sub-expressions.
2014
- *
2015
- * If `false`, only consider the top-level expression.
2016
- *
2017
- * **Default**: `false`
2018
- */
2019
- recursive: boolean;
2020
- /**
2021
- * If `true`, stop after the first rule that matches.
2022
- *
2023
- * If `false`, apply all the remaining rules even after the first match.
2024
- *
2025
- * **Default**: `false`
2026
- */
2027
- once: boolean;
2028
- /**
2029
- * If `true` the rule will use some equivalent variations to match.
2030
- *
2031
- * For example when `useVariations` is true:
2032
- * - `x` matches `a + x` with a = 0
2033
- * - `x` matches `ax` with a = 1
2034
- * - etc...
2035
- *
2036
- * Setting this to `true` can save time by condensing multiple rules
2037
- * into one. This can be particularly useful when describing equations
2038
- * solutions. However, it can lead to infinite recursion and should be
2039
- * used with caution.
2040
- *
2041
- */
2042
- useVariations: boolean;
2043
- /**
2044
- * If `iterationLimit` > 1, the rules will be repeatedly applied
2045
- * until no rules apply, up to `maxIterations` times.
2046
- *
2047
- * Note that if `once` is true, `iterationLimit` has no effect.
2048
- *
2049
- * **Default**: `1`
2050
- */
2051
- iterationLimit: number;
2052
- /**
2053
- * Indicate if the expression should be canonicalized after the replacement.
2054
- * If not provided, the expression is canonicalized if the expression
2055
- * that matched the pattern is canonical.
2056
- */
2057
- canonical: CanonicalOptions;
2058
- };
2059
- /**
2060
- * A substitution describes the values of the wildcards in a pattern so that
2061
- * the pattern is equal to a target expression.
2062
- *
2063
- * A substitution can also be considered a more constrained version of a
2064
- * rule whose `match` is always a symbol.
2065
-
2066
- * @category Boxed Expression
2067
- */
2068
- export type Substitution<T = SemiBoxedExpression> = {
2069
- [symbol: string]: T;
2070
- };
2071
- /** @category Assumptions */
2072
- export interface ExpressionMapInterface<U> {
2073
- has(expr: BoxedExpression): boolean;
2074
- get(expr: BoxedExpression): U | undefined;
2075
- set(expr: BoxedExpression, value: U): void;
2076
- delete(expr: BoxedExpression): void;
2077
- clear(): void;
2078
- [Symbol.iterator](): IterableIterator<[BoxedExpression, U]>;
2079
- entries(): IterableIterator<[BoxedExpression, U]>;
2080
- }
2081
- /**
2082
- * The entries have been validated and optimized for faster evaluation.
2083
- *
2084
- * When a new scope is created with `pushScope()` or when creating a new
2085
- * engine instance, new instances of this type are created as needed.
2086
- *
2087
- * @category Definitions
2088
- */
2089
- export type RuntimeIdentifierDefinitions = Map<string, OneOf<[BoxedSymbolDefinition, BoxedFunctionDefinition]>>;
2090
- /**
2091
- * A scope is a set of names in a dictionary that are bound (defined) in
2092
- * a MathJSON expression.
2093
- *
2094
- * Scopes are arranged in a stack structure. When an expression that defined
2095
- * a new scope is evaluated, the new scope is added to the scope stack.
2096
- * Outside of the expression, the scope is removed from the scope stack.
2097
- *
2098
- * The scope stack is used to resolve symbols, and it is possible for
2099
- * a scope to 'mask' definitions from previous scopes.
2100
- *
2101
- * Scopes are lexical (also called a static scope): they are defined based on
2102
- * where they are in an expression, they are not determined at runtime.
2103
- *
2104
- * @category Compute Engine
2105
- */
2106
- export type Scope = {};
2107
- /** @category Compute Engine */
2108
- export type RuntimeScope = Scope & {
2109
- parentScope?: RuntimeScope;
2110
- ids?: RuntimeIdentifierDefinitions;
2111
- assumptions: undefined | ExpressionMapInterface<boolean>;
2112
- };
2113
- /**
2114
- * A bound symbol (i.e. one with an associated definition) has either a type
2115
- * (e.g. ∀ x ∈ ℝ), a value (x = 5) or both (π: value = 3.14... type = 'real')
2116
- * @category Definitions
2117
- */
2118
- export type SymbolDefinition = BaseDefinition & Partial<SymbolAttributes> & {
2119
- type?: Type | TypeString;
2120
- /** If true, the type is inferred, and could be adjusted later
2121
- * as more information becomes available or if the symbol is explicitly
2122
- * declared.
2123
- */
2124
- inferred?: boolean;
2125
- /** `value` can be a JS function since for some constants, such as
2126
- * `Pi`, the actual value depends on the `precision` setting of the
2127
- * `ComputeEngine` and possible other environment settings */
2128
- value?: LatexString | SemiBoxedExpression | ((ce: IComputeEngine) => BoxedExpression | null);
2129
- flags?: Partial<NumericFlags>;
2130
- eq?: (a: BoxedExpression) => boolean | undefined;
2131
- neq?: (a: BoxedExpression) => boolean | undefined;
2132
- cmp?: (a: BoxedExpression) => '=' | '>' | '<' | undefined;
2133
- collection?: Partial<CollectionHandlers>;
2134
- };
2135
- /**
2136
- * Definition record for a function.
2137
- * @category Definitions
2138
- *
2139
- */
2140
- export type FunctionDefinition = BaseDefinition & Partial<FunctionDefinitionFlags> & {
2141
- /**
2142
- * The function signature.
2143
- *
2144
- * If a `type` handler is provided, the return type of the function should
2145
- * be a subtype of the return type in the signature.
2146
- *
2147
- */
2148
- signature?: Type | TypeString;
2149
- /**
2150
- * The actual type of the result based on the arguments.
2151
- *
2152
- * Should be a subtype of the type indicated in the signature.
2153
- *
2154
- * Do not evaluate the arguments.
2155
- *
2156
- * The type of the arguments can be used to determine the type of the
2157
- * result.
2158
- *
2159
- */
2160
- type?: (ops: ReadonlyArray<BoxedExpression>, options: {
2161
- engine: IComputeEngine;
2162
- }) => Type | TypeString | BoxedType | undefined;
2163
- /** Return the sign of the function expression.
2164
- *
2165
- * If the sign cannot be determined, return `undefined`.
2166
- *
2167
- * When determining the sign, only literal values and the values of
2168
- * symbols, if they are literals, should be considered.
2169
- *
2170
- * Do not evaluate the arguments.
2171
- *
2172
- * The type and sign of the arguments can be used to determine the sign.
2173
- *
2174
- */
2175
- sgn?: (ops: ReadonlyArray<BoxedExpression>, options: {
2176
- engine: IComputeEngine;
2177
- }) => Sign | undefined;
2178
- /** Return true of the function expression is even, false if it is odd and
2179
- * undefined if it is neither.
2180
- */
2181
- even?: (ops: ReadonlyArray<BoxedExpression>, options: {
2182
- engine: IComputeEngine;
2183
- }) => boolean | undefined;
2184
- /**
2185
- * A number used to order arguments.
2186
- *
2187
- * Argument with higher complexity are placed after arguments with
2188
- * lower complexity when ordered canonically in commutative functions.
2189
- *
2190
- * - Additive functions: 1000-1999
2191
- * - Multiplicative functions: 2000-2999
2192
- * - Root and power functions: 3000-3999
2193
- * - Log functions: 4000-4999
2194
- * - Trigonometric functions: 5000-5999
2195
- * - Hypertrigonometric functions: 6000-6999
2196
- * - Special functions (factorial, Gamma, ...): 7000-7999
2197
- * - Collections: 8000-8999
2198
- * - Inert and styling: 9000-9999
2199
- * - Logic: 10000-10999
2200
- * - Relational: 11000-11999
2201
- *
2202
- * **Default**: 100,000
2203
- */
2204
- complexity?: number;
2205
- /**
2206
- * Return the canonical form of the expression with the arguments `args`.
2207
- *
2208
- * The arguments (`args`) may not be in canonical form. If necessary, they
2209
- * can be put in canonical form.
2210
- *
2211
- * This handler should validate the type and number of the arguments.
2212
- *
2213
- * If a required argument is missing, it should be indicated with a
2214
- * `["Error", "'missing"]` expression. If more arguments than expected
2215
- * are present, this should be indicated with an
2216
- * ["Error", "'unexpected-argument'"]` error expression
2217
- *
2218
- * If the type of an argument is not compatible, it should be indicated
2219
- * with an `incompatible-type` error.
2220
- *
2221
- * `["Sequence"]` expressions are not folded and need to be handled
2222
- * explicitly.
2223
- *
2224
- * If the function is associative, idempotent or an involution,
2225
- * this handler should account for it. Notably, if it is commutative, the
2226
- * arguments should be sorted in canonical order.
2227
- *
2228
- *
2229
- * Values of symbols should not be substituted, unless they have
2230
- * a `holdUntil` attribute of `"never"`.
2231
- *
2232
- * The handler should not consider the value or any assumptions about any
2233
- * of the arguments that are symbols or functions (i.e. `arg.isZero`,
2234
- * `arg.isInteger`, etc...) since those may change over time.
2235
- *
2236
- * The result of the handler should be a canonical expression.
2237
- *
2238
- * If the arguments do not match, they should be replaced with an appropriate
2239
- * `["Error"]` expression. If the expression cannot be put in canonical form,
2240
- * the handler should return `null`.
2241
- *
2242
- */
2243
- canonical?: (ops: ReadonlyArray<BoxedExpression>, options: {
2244
- engine: IComputeEngine;
2245
- }) => BoxedExpression | null;
2246
- /**
2247
- * Evaluate a function expression.
2248
- *
2249
- * The arguments have been evaluated, except the arguments to which a
2250
- * `hold` applied.
2251
- *
2252
- * It is not necessary to further simplify or evaluate the arguments.
2253
- *
2254
- * If performing numerical calculations and `options.numericalApproximation`
2255
- * is `false` return an exact numeric value, for example return a rational
2256
- * number or a square root, rather than a floating point approximation.
2257
- * Use `ce.number()` to create the numeric value.
2258
- *
2259
- * When `numericalApproximation` is `false`, return a floating point number:
2260
- * - do not reduce rational numbers to decimal (floating point approximation)
2261
- * - do not reduce square roots of rational numbers
2262
- *
2263
- * If the expression cannot be evaluated, due to the values, types, or
2264
- * assumptions about its arguments, for example, return `undefined` or
2265
- * an `["Error"]` expression.
2266
- */
2267
- evaluate?: ((ops: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
2268
- engine: IComputeEngine;
2269
- }) => BoxedExpression | undefined) | BoxedExpression;
2270
- /**
2271
- * An option asynchronous version of `evaluate`.
2272
- *
2273
- */
2274
- evaluateAsync?: (ops: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
2275
- engine: IComputeEngine;
2276
- }) => Promise<BoxedExpression | undefined>;
2277
- /** Dimensional analysis
2278
- * @experimental
2279
- */
2280
- evalDimension?: (args: ReadonlyArray<BoxedExpression>, options: EvaluateOptions & {
2281
- engine: IComputeEngine;
2282
- }) => BoxedExpression;
2283
- /** Return a compiled (optimized) expression. */
2284
- compile?: (expr: BoxedExpression) => CompiledExpression;
2285
- eq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
2286
- neq?: (a: BoxedExpression, b: BoxedExpression) => boolean | undefined;
2287
- collection?: Partial<CollectionHandlers>;
2288
- };
2289
- /**
2290
- * @category Definitions
2291
- *
2292
- */
2293
- export type BaseDefinition = {
2294
- /** A short (about 1 line) description. May contain Markdown. */
2295
- description?: string | string[];
2296
- /** A URL pointing to more information about this symbol or operator. */
2297
- url?: string;
2298
- /**
2299
- * A short string representing an entry in a wikibase.
2300
- *
2301
- * For example `Q167` is the [wikidata entry](https://www.wikidata.org/wiki/Q167)
2302
- * for the `Pi` constant.
2303
- */
2304
- wikidata?: string;
2305
- };