math-expression-compiler 4.3.1 → 4.4.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.
package/dist/index.js DELETED
@@ -1,2246 +0,0 @@
1
- import { exhaustiveGuard } from "@esposter/shared";
2
- import { err, ok } from "neverthrow";
3
- //#region src/models/function/MathExpressionFunctionName.ts
4
- let MathExpressionFunctionName = /* @__PURE__ */ function(MathExpressionFunctionName) {
5
- MathExpressionFunctionName["CTranspose"] = "ctranspose";
6
- MathExpressionFunctionName["Factorial"] = "factorial";
7
- MathExpressionFunctionName["UnaryMinus"] = "unaryMinus";
8
- MathExpressionFunctionName["UnaryPlus"] = "unaryPlus";
9
- return MathExpressionFunctionName;
10
- }({});
11
- //#endregion
12
- //#region src/models/function/MathExpressionParameterType.ts
13
- let MathExpressionParameterType = /* @__PURE__ */ function(MathExpressionParameterType) {
14
- MathExpressionParameterType["Any"] = "any";
15
- MathExpressionParameterType["List"] = "list";
16
- MathExpressionParameterType["Number"] = "number";
17
- return MathExpressionParameterType;
18
- }({});
19
- //#endregion
20
- //#region src/models/parser/MathExpressionGrammarRule.ts
21
- let MathExpressionGrammarRule = /* @__PURE__ */ function(MathExpressionGrammarRule) {
22
- MathExpressionGrammarRule["Assignment"] = "Assignment";
23
- MathExpressionGrammarRule["Binary"] = "Binary";
24
- MathExpressionGrammarRule["Conditional"] = "Conditional";
25
- MathExpressionGrammarRule["DivisionBeforeProduct"] = "DivisionBeforeProduct";
26
- MathExpressionGrammarRule["ImplicitProduct"] = "ImplicitProduct";
27
- MathExpressionGrammarRule["LeftHand"] = "LeftHand";
28
- MathExpressionGrammarRule["Nullish"] = "Nullish";
29
- MathExpressionGrammarRule["Percentage"] = "Percentage";
30
- MathExpressionGrammarRule["Power"] = "Power";
31
- MathExpressionGrammarRule["Symbol"] = "Symbol";
32
- MathExpressionGrammarRule["Unary"] = "Unary";
33
- return MathExpressionGrammarRule;
34
- }({});
35
- //#endregion
36
- //#region src/models/parser/MathExpressionTokenType.ts
37
- let MathExpressionTokenType = /* @__PURE__ */ function(MathExpressionTokenType) {
38
- MathExpressionTokenType["Delimiter"] = "delimiter";
39
- MathExpressionTokenType["Null"] = "null";
40
- MathExpressionTokenType["Number"] = "number";
41
- MathExpressionTokenType["Symbol"] = "symbol";
42
- MathExpressionTokenType["Unknown"] = "unknown";
43
- return MathExpressionTokenType;
44
- }({});
45
- //#endregion
46
- //#region src/models/shared/MathExpressionError.ts
47
- var MathExpressionError = class extends Error {
48
- constructor(message) {
49
- super(message);
50
- this.name = "MathExpressionError";
51
- }
52
- };
53
- //#endregion
54
- //#region src/models/shared/MathExpressionLogicalOperator.ts
55
- let MathExpressionLogicalOperator = /* @__PURE__ */ function(MathExpressionLogicalOperator) {
56
- MathExpressionLogicalOperator["And"] = "and";
57
- MathExpressionLogicalOperator["Nullish"] = "nullish";
58
- MathExpressionLogicalOperator["Or"] = "or";
59
- return MathExpressionLogicalOperator;
60
- }({});
61
- //#endregion
62
- //#region src/models/shared/MathExpressionNodeType.ts
63
- let MathExpressionNodeType = /* @__PURE__ */ function(MathExpressionNodeType) {
64
- MathExpressionNodeType["Assignment"] = "assignment";
65
- MathExpressionNodeType["Binary"] = "binary";
66
- MathExpressionNodeType["Call"] = "call";
67
- MathExpressionNodeType["Comparison"] = "comparison";
68
- MathExpressionNodeType["Conditional"] = "conditional";
69
- MathExpressionNodeType["Group"] = "group";
70
- MathExpressionNodeType["List"] = "list";
71
- MathExpressionNodeType["Logical"] = "logical";
72
- MathExpressionNodeType["Name"] = "name";
73
- MathExpressionNodeType["Number"] = "number";
74
- MathExpressionNodeType["Percentage"] = "percentage";
75
- MathExpressionNodeType["Unary"] = "unary";
76
- return MathExpressionNodeType;
77
- }({});
78
- //#endregion
79
- //#region src/services/compiler/MathExpressionBitwiseAbsorptionMap.ts
80
- const MathExpressionBitwiseAbsorptionMap = {
81
- bitAnd: {
82
- absorbs: 0,
83
- result: 0
84
- },
85
- bitOr: {
86
- absorbs: -1,
87
- result: -1
88
- }
89
- };
90
- //#endregion
91
- //#region src/services/compiler/node/compileAssignment.ts
92
- const compileAssignment = (node, context) => {
93
- const slot = context.assignedSlots.get(node.name) ?? 0;
94
- const compiledValue = context.compile(node.value);
95
- return {
96
- evaluate: (values, locals) => {
97
- const value = compiledValue.evaluate(values, locals);
98
- locals[slot] = value;
99
- return value;
100
- },
101
- isConstant: false
102
- };
103
- };
104
- //#endregion
105
- //#region src/services/compiler/constants.ts
106
- const NO_VALUES = [];
107
- const NO_LOCALS = [];
108
- const ADDITIVE_NAMES = ["add", "subtract"];
109
- //#endregion
110
- //#region src/services/compiler/checkIsPercentageExpression.ts
111
- const checkIsPercentageExpression = (node) => {
112
- if (node.type === "percentage") return true;
113
- if (node.type !== "binary") return false;
114
- if (!ADDITIVE_NAMES.includes(node.name)) return false;
115
- return checkIsPercentageExpression(node.left) && checkIsPercentageExpression(node.right);
116
- };
117
- //#endregion
118
- //#region src/services/function/constants.ts
119
- const MATH_EXPRESSION_RELATIVE_TOLERANCE = 1e-12;
120
- const MATH_EXPRESSION_ABSOLUTE_TOLERANCE = 1e-15;
121
- const SQRT_PI = Math.sqrt(Math.PI);
122
- const BERNOULLI_CLOSED_FORM_INDEX = 54;
123
- const MAXIMUM_DIGITS = 15;
124
- const MAXIMUM_STIRLING_WORK = 4e6;
125
- const MILLER_RABIN_BASES = [
126
- 2n,
127
- 3n,
128
- 5n,
129
- 7n,
130
- 11n,
131
- 13n,
132
- 17n,
133
- 19n,
134
- 23n,
135
- 29n,
136
- 31n,
137
- 37n
138
- ];
139
- const REFINEMENT_STEPS = 4;
140
- const LOW_TAIL_COEFFICIENTS = [
141
- 3.43273939e-7,
142
- -35233877e-13,
143
- -439150654e-14,
144
- .00021858087,
145
- -.00125372503,
146
- -.00417768164,
147
- .246640727,
148
- 1.50140941
149
- ];
150
- const HIGH_TAIL_COEFFICIENTS = [
151
- .000100950558,
152
- .00134934322,
153
- -.00367342844,
154
- .00573950773,
155
- -.0076224613,
156
- .00943887047,
157
- 1.00167406,
158
- 2.83297682
159
- ];
160
- const OVERFLOW_ARGUMENT = 171.35;
161
- const LAST_FACTORIAL_ARGUMENT = 171;
162
- const STIRLING_THRESHOLD = 15;
163
- const STIRLING_TERMS = [
164
- 1 / 12,
165
- -1 / 360,
166
- 1 / 1260,
167
- -1 / 1680,
168
- 1 / 1188,
169
- -691 / 360360,
170
- 1 / 156
171
- ];
172
- const EULER_MACLAURIN_COEFFICIENTS = [
173
- 1 / 12,
174
- -1 / 720,
175
- 1 / 30240,
176
- -1 / 1209600,
177
- 1 / 47900160,
178
- -691 / 1307674368e3,
179
- 1 / 74724249600,
180
- -3617 / 0x25e8dffc150000
181
- ];
182
- const SUMMATION_LIMIT = 10;
183
- //#endregion
184
- //#region src/services/function/checkIsNearlyEqual.ts
185
- const checkIsNearlyEqual = (left, right) => {
186
- if (Number.isNaN(left) || Number.isNaN(right)) return false;
187
- if (!Number.isFinite(left) || !Number.isFinite(right)) return left === right;
188
- if (left === right) return true;
189
- const tolerance = Math.max(MATH_EXPRESSION_RELATIVE_TOLERANCE * Math.max(Math.abs(left), Math.abs(right)), MATH_EXPRESSION_ABSOLUTE_TOLERANCE);
190
- return Math.abs(left - right) <= tolerance;
191
- };
192
- //#endregion
193
- //#region src/services/function/checkIsLarger.ts
194
- const checkIsLarger = (left, right) => left > right && !checkIsNearlyEqual(left, right);
195
- //#endregion
196
- //#region src/services/function/computeModularPower.ts
197
- const computeModularPower = (base, exponent, modulus) => {
198
- let result = 1n;
199
- let square = base % modulus;
200
- let remaining = exponent;
201
- while (remaining > 0n) {
202
- if (remaining % 2n === 1n) result = result * square % modulus;
203
- square = square * square % modulus;
204
- remaining /= 2n;
205
- }
206
- return result;
207
- };
208
- //#endregion
209
- //#region src/services/function/checkIsMillerRabinPassing.ts
210
- const checkIsMillerRabinPassing = (candidate, base, oddPart, twos) => {
211
- const minusOne = candidate - 1n;
212
- let power = computeModularPower(base, oddPart, candidate);
213
- if (power === 1n || power === minusOne) return true;
214
- for (let round = 1; round < twos; round++) {
215
- power = power * power % candidate;
216
- if (power === minusOne) return true;
217
- }
218
- return false;
219
- };
220
- //#endregion
221
- //#region src/services/function/checkIsPrime.ts
222
- const checkIsPrime = (value) => {
223
- if (!Number.isInteger(value) || value < 2 || value > Number.MAX_SAFE_INTEGER) return false;
224
- const candidate = BigInt(value);
225
- for (const base of MILLER_RABIN_BASES) {
226
- if (candidate === base) return true;
227
- if (candidate % base === 0n) return false;
228
- }
229
- let oddPart = candidate - 1n;
230
- let twos = 0;
231
- while (oddPart % 2n === 0n) {
232
- oddPart /= 2n;
233
- twos++;
234
- }
235
- return MILLER_RABIN_BASES.every((base) => checkIsMillerRabinPassing(candidate, base, oddPart, twos));
236
- };
237
- //#endregion
238
- //#region src/services/function/checkIsSmaller.ts
239
- const checkIsSmaller = (left, right) => left < right && !checkIsNearlyEqual(left, right);
240
- //#endregion
241
- //#region src/services/function/computeBellNumber.ts
242
- const computeBellNumber = (index) => {
243
- if (!Number.isInteger(index) || index < 0) return null;
244
- let row = [1];
245
- for (let step = 1; step <= index; step++) {
246
- const next = [row.at(-1) ?? 0];
247
- for (const above of row) next.push((next.at(-1) ?? 0) + above);
248
- if (next[0] === Number.POSITIVE_INFINITY) return Number.POSITIVE_INFINITY;
249
- row = next;
250
- }
251
- return row[0] ?? NaN;
252
- };
253
- //#endregion
254
- //#region src/services/function/computeBernoulliNumber.ts
255
- const computeBernoulliNumber = (index) => {
256
- if (index === 1) return -.5;
257
- if (index > 1 && index % 2 === 1) return 0;
258
- if (index >= 54) {
259
- let product = 1;
260
- for (let factor = 1; factor <= index && Number.isFinite(product); factor++) product *= factor / (2 * Math.PI);
261
- return index / 2 % 2 === 1 ? 2 * product : -2 * product;
262
- }
263
- const numbers = [1];
264
- for (let current = 1; current <= index; current++) {
265
- let sum = 0;
266
- let binomial = 1;
267
- for (let previous = 0; previous < current; previous++) {
268
- sum += binomial * (numbers[previous] ?? 0);
269
- binomial = binomial * (current + 1 - previous) / (previous + 1);
270
- }
271
- numbers.push(-sum / (current + 1));
272
- }
273
- return numbers[index] ?? NaN;
274
- };
275
- //#endregion
276
- //#region src/services/function/computeBitwiseAnd.ts
277
- const computeBitwiseAnd = (left, right) => left & right;
278
- //#endregion
279
- //#region src/services/function/computeBitwiseOr.ts
280
- const computeBitwiseOr = (left, right) => left | right;
281
- //#endregion
282
- //#region src/services/function/computeCombinations.ts
283
- const computeCombinations = (available, chosen) => {
284
- const smaller = Math.min(chosen, available - chosen);
285
- let result = 1;
286
- for (let step = 1; step <= smaller; step++) {
287
- result = result * (available - smaller + step) / step;
288
- if (result > Number.MAX_VALUE) return Number.POSITIVE_INFINITY;
289
- }
290
- return Math.round(result);
291
- };
292
- //#endregion
293
- //#region src/services/function/computeCatalan.ts
294
- const computeCatalan = (index) => {
295
- if (!Number.isInteger(index) || index < 0) return null;
296
- return Math.round(computeCombinations(2 * index, index) / (index + 1));
297
- };
298
- //#endregion
299
- //#region src/services/function/computeComparison.ts
300
- const computeComparison = (left, right) => {
301
- if (checkIsNearlyEqual(left, right)) return 0;
302
- return left > right ? 1 : -1;
303
- };
304
- //#endregion
305
- //#region src/services/function/computeCompositions.ts
306
- const computeCompositions = (total, parts) => {
307
- if (!Number.isInteger(total) || !Number.isInteger(parts) || parts < 1 || parts > total) return null;
308
- return computeCombinations(total - 1, parts - 1);
309
- };
310
- //#endregion
311
- //#region src/services/function/computeDotProduct.ts
312
- const computeDotProduct = (left, right) => {
313
- if (left.length !== right.length) return null;
314
- return left.reduce((total, value, index) => total + value * (right[index] ?? NaN), 0);
315
- };
316
- //#endregion
317
- //#region src/services/function/computeSum.ts
318
- const computeSum = (values) => values.length === 0 ? 0 : values.reduce((total, value) => total + value);
319
- //#endregion
320
- //#region src/services/function/computeCorrelation.ts
321
- const computeCorrelation = (left, right) => {
322
- if (left.length !== right.length) return null;
323
- const count = left.length;
324
- const sumLeft = computeSum(left);
325
- const sumRight = computeSum(right);
326
- const sumProducts = computeDotProduct(left, right) ?? NaN;
327
- const sumLeftSquares = computeSum(left.map((value) => value ** 2));
328
- const sumRightSquares = computeSum(right.map((value) => value ** 2));
329
- return (count * sumProducts - sumLeft * sumRight) / Math.sqrt((count * sumLeftSquares - sumLeft ** 2) * (count * sumRightSquares - sumRight ** 2));
330
- };
331
- //#endregion
332
- //#region src/services/function/computeDeterminant.ts
333
- const computeDeterminant = (values) => {
334
- if (values.length === 0) return 1;
335
- return values.length === 1 ? values[0] ?? null : null;
336
- };
337
- //#endregion
338
- //#region src/services/function/computePointToLine2D.ts
339
- const computePointToLine2D = (point, line) => {
340
- const [x = NaN, y = NaN] = point;
341
- const [a = NaN, b = NaN, c = NaN] = line;
342
- return Math.abs(a * x + b * y + c) / Math.hypot(a, b);
343
- };
344
- //#endregion
345
- //#region src/services/function/computePointToLine3D.ts
346
- const computePointToLine3D = (point, line) => {
347
- const [x = NaN, y = NaN, z = NaN] = point;
348
- const [x0 = NaN, y0 = NaN, z0 = NaN, a = NaN, b = NaN, c = NaN] = line;
349
- const first = (y0 - y) * c - (z0 - z) * b;
350
- const second = (z0 - z) * a - (x0 - x) * c;
351
- const third = (x0 - x) * b - (y0 - y) * a;
352
- return Math.hypot(first, second, third) / Math.hypot(a, b, c);
353
- };
354
- //#endregion
355
- //#region src/services/function/computeDistance.ts
356
- const computeDistance = (point, other) => {
357
- if (point.length === 2 && other.length === 3) return computePointToLine2D(point, other);
358
- if (point.length === 3 && other.length === 6) return computePointToLine3D(point, other);
359
- if (point.length !== other.length || point.length === 0) return null;
360
- let total = 0;
361
- for (const [index, value] of point.entries()) {
362
- const difference = value - (other[index] ?? NaN);
363
- total = difference * difference + total;
364
- }
365
- return Math.sqrt(total);
366
- };
367
- //#endregion
368
- //#region src/services/function/computeErf.ts
369
- const SERIES_LIMIT = 3;
370
- const CONTINUED_FRACTION_DEPTH = 80;
371
- const computeErf = (value) => {
372
- if (Number.isNaN(value)) return NaN;
373
- const magnitude = Math.abs(value);
374
- const sign = value < 0 ? -1 : 1;
375
- if (magnitude < SERIES_LIMIT) {
376
- const squared = magnitude * magnitude;
377
- let term = magnitude;
378
- let total = magnitude;
379
- for (let index = 1; index < 200; index++) {
380
- term *= 2 * squared / (2 * index + 1);
381
- total += term;
382
- if (term < total * 1e-17) break;
383
- }
384
- return sign * 2 * Math.exp(-squared) * total / SQRT_PI;
385
- }
386
- let fraction = magnitude;
387
- for (let index = CONTINUED_FRACTION_DEPTH; index >= 1; index--) fraction = magnitude + index / 2 / fraction;
388
- return sign * (1 - Math.exp(-magnitude * magnitude) / SQRT_PI / fraction);
389
- };
390
- //#endregion
391
- //#region src/services/function/computePolynomial.ts
392
- const computePolynomial = (leading, coefficients, variable) => {
393
- let polynomial = leading;
394
- for (const coefficient of coefficients) polynomial = coefficient + polynomial * variable;
395
- return polynomial;
396
- };
397
- //#endregion
398
- //#region src/services/function/computeInitialGuess.ts
399
- const computeInitialGuess = (value) => {
400
- const weight = -Math.log((1 - value) * (1 + value));
401
- if (weight < 5) return computePolynomial(2.81022636e-8, LOW_TAIL_COEFFICIENTS, weight - 2.5) * value;
402
- return computePolynomial(-.000200214257, HIGH_TAIL_COEFFICIENTS, Math.sqrt(weight) - 3) * value;
403
- };
404
- //#endregion
405
- //#region src/services/function/computeErfInverse.ts
406
- const computeErfInverse = (value) => {
407
- if (Number.isNaN(value) || value < -1 || value > 1) return NaN;
408
- if (value === 1) return Number.POSITIVE_INFINITY;
409
- if (value === -1) return Number.NEGATIVE_INFINITY;
410
- let estimate = computeInitialGuess(value);
411
- for (let step = 0; step < 4; step++) {
412
- const slope = 2 / SQRT_PI * Math.exp(-estimate * estimate);
413
- estimate -= (computeErf(estimate) - value) / slope;
414
- }
415
- return estimate;
416
- };
417
- //#endregion
418
- //#region src/services/function/computeStirlingLogGamma.ts
419
- const computeStirlingLogGamma = (value) => {
420
- const inverse = 1 / value;
421
- const squared = inverse * inverse;
422
- let power = inverse;
423
- let series = 0;
424
- for (const term of STIRLING_TERMS) {
425
- series += term * power;
426
- power *= squared;
427
- }
428
- return (value - .5) * Math.log(value) - value + .5 * Math.log(2 * Math.PI) + series;
429
- };
430
- //#endregion
431
- //#region src/services/function/computeLogGammaOfPositive.ts
432
- const computeLogGammaOfPositive = (value) => {
433
- let shifted = value;
434
- let product = 1;
435
- while (shifted < 15) {
436
- product *= shifted;
437
- shifted += 1;
438
- }
439
- return {
440
- logGamma: computeStirlingLogGamma(shifted),
441
- product
442
- };
443
- };
444
- //#endregion
445
- //#region src/services/function/computeProductOfRange.ts
446
- const computeProductOfRange = (first, last) => {
447
- if (last < first) return 1;
448
- if (last === first) return last;
449
- const middle = Math.floor((first + last) / 2);
450
- return computeProductOfRange(first, middle) * computeProductOfRange(middle + 1, last);
451
- };
452
- //#endregion
453
- //#region src/services/function/computeGamma.ts
454
- const computeGamma = (value) => {
455
- if (Number.isNaN(value)) return NaN;
456
- if (Number.isInteger(value)) {
457
- if (value <= 0 || value > 171) return Number.POSITIVE_INFINITY;
458
- return computeProductOfRange(1, value - 1);
459
- }
460
- if (value < .5) return Math.PI / (Math.sin(Math.PI * value) * computeGamma(1 - value));
461
- if (value >= 171.35) return Number.POSITIVE_INFINITY;
462
- const { logGamma, product } = computeLogGammaOfPositive(value);
463
- return Math.exp(logGamma) / product;
464
- };
465
- //#endregion
466
- //#region src/services/function/computeFactorial.ts
467
- const computeFactorial = (value) => {
468
- if (value < 0) return null;
469
- return computeGamma(value + 1);
470
- };
471
- //#endregion
472
- //#region src/services/function/computeHypotenuse.ts
473
- const computeHypotenuse = (values) => {
474
- let largest = 0;
475
- let total = 0;
476
- for (const value of values) {
477
- const magnitude = Math.abs(value);
478
- if (largest < magnitude) {
479
- const ratio = largest / magnitude;
480
- total = total * (ratio * ratio) + 1;
481
- largest = magnitude;
482
- } else if (magnitude > 0) {
483
- const ratio = magnitude === largest ? 1 : magnitude / largest;
484
- total += ratio * ratio;
485
- } else total += magnitude;
486
- }
487
- return largest * Math.sqrt(total);
488
- };
489
- //#endregion
490
- //#region src/services/function/computeGreatestCommonDivisor.ts
491
- const computeGreatestCommonDivisor = (left, right) => right === 0 ? Math.abs(left) : computeGreatestCommonDivisor(right, left % right);
492
- //#endregion
493
- //#region src/services/function/computeIntegerGreatestCommonDivisor.ts
494
- const computeIntegerGreatestCommonDivisor = (values) => {
495
- if (!values.every((value) => Number.isInteger(value))) return null;
496
- return values.reduce((total, value) => computeGreatestCommonDivisor(total, value), 0);
497
- };
498
- //#endregion
499
- //#region src/services/function/computeInverseCoth.ts
500
- const computeInverseCoth = (value) => {
501
- const magnitude = Math.abs(value);
502
- if (magnitude < 1) return NaN;
503
- if (magnitude === 1) return value * Number.POSITIVE_INFINITY;
504
- return Math.sign(value) * .5 * Math.log1p(2 / (magnitude - 1));
505
- };
506
- //#endregion
507
- //#region src/services/function/computeKullbackLeibler.ts
508
- const computeKullbackLeibler = (distribution, reference) => {
509
- if (distribution.length !== reference.length) return null;
510
- const distributionSum = computeSum(distribution);
511
- const referenceSum = computeSum(reference);
512
- if (distributionSum === 0 || referenceSum === 0) return null;
513
- const normalizedDistribution = distribution.map((value) => value / distributionSum);
514
- const normalizedReference = reference.map((value) => value / referenceSum);
515
- return computeSum(normalizedDistribution.map((value, index) => value * Math.log(value / (normalizedReference[index] ?? NaN))));
516
- };
517
- //#endregion
518
- //#region src/services/function/computeLeastCommonMultiple.ts
519
- const computeLeastCommonMultiple = (left, right) => {
520
- if (!Number.isInteger(left) || !Number.isInteger(right)) return null;
521
- const divisor = computeGreatestCommonDivisor(left, right);
522
- return divisor === 0 ? 0 : Math.abs(left * right / divisor);
523
- };
524
- //#endregion
525
- //#region src/services/function/computeListComparison.ts
526
- const computeListComparison = (left, right) => {
527
- for (const [index, value] of left.entries()) {
528
- const other = right[index];
529
- if (other === void 0) return 1;
530
- const comparison = computeComparison(value, other);
531
- if (comparison !== 0) return comparison;
532
- }
533
- return left.length < right.length ? -1 : 0;
534
- };
535
- //#endregion
536
- //#region src/services/function/computeLogarithm.ts
537
- const computeLogarithm = (value, base) => base === void 0 ? Math.log(value) : Math.log(value) / Math.log(base);
538
- //#endregion
539
- //#region src/services/function/computeLogGamma.ts
540
- const computeLogGamma = (value) => {
541
- if (Number.isNaN(value) || value < 0) return NaN;
542
- if ([0, Number.POSITIVE_INFINITY].includes(value)) return Number.POSITIVE_INFINITY;
543
- if ([1, 2].includes(value)) return 0;
544
- const { logGamma, product } = computeLogGammaOfPositive(value);
545
- return logGamma - Math.log(product);
546
- };
547
- //#endregion
548
- //#region src/services/function/computeMean.ts
549
- const computeMean = (values) => computeSum(values) / values.length;
550
- //#endregion
551
- //#region src/services/function/compareNumbers.ts
552
- const compareNumbers = (left, right) => left - right;
553
- //#endregion
554
- //#region src/services/function/computeMedian.ts
555
- const computeMedian = (values) => {
556
- const sorted = values.toSorted(compareNumbers);
557
- const middle = Math.floor(sorted.length / 2);
558
- if (sorted.length % 2 === 1) return sorted[middle] ?? NaN;
559
- return ((sorted[middle - 1] ?? NaN) + (sorted[middle] ?? NaN)) / 2;
560
- };
561
- //#endregion
562
- //#region src/services/function/computeMedianAbsoluteDeviation.ts
563
- const computeMedianAbsoluteDeviation = (values) => {
564
- const center = computeMedian(values);
565
- return computeMedian(values.map((value) => Math.abs(value - center)));
566
- };
567
- //#endregion
568
- //#region src/services/function/computeModulo.ts
569
- const computeModulo = (dividend, divisor) => {
570
- if (divisor === 0) return dividend;
571
- if (!Number.isFinite(dividend) || !Number.isFinite(divisor)) return NaN;
572
- if (Number.isInteger(dividend) && Number.isInteger(divisor)) {
573
- const remainder = dividend % divisor;
574
- if (remainder === 0) return 0;
575
- return Math.sign(remainder) === Math.sign(divisor) ? remainder : remainder + divisor;
576
- }
577
- const quotient = dividend / divisor;
578
- if (checkIsNearlyEqual(quotient, Math.round(quotient))) return 0;
579
- return dividend - divisor * Math.floor(quotient);
580
- };
581
- //#endregion
582
- //#region src/services/function/computeModularInverse.ts
583
- const computeModularInverse = (value, modulus) => {
584
- if (!Number.isInteger(value) || !Number.isInteger(modulus) || modulus === 0) return null;
585
- let remainder = value;
586
- let nextRemainder = modulus;
587
- let coefficient = 0;
588
- let previousCoefficient = 1;
589
- while (nextRemainder !== 0) {
590
- const quotient = Math.floor(remainder / nextRemainder);
591
- [coefficient, previousCoefficient] = [previousCoefficient - quotient * coefficient, coefficient];
592
- [remainder, nextRemainder] = [nextRemainder, remainder - quotient * nextRemainder];
593
- }
594
- if ((remainder < 0 ? -remainder : remainder) !== 1) return NaN;
595
- const inverse = computeModulo(remainder < 0 ? -previousCoefficient : previousCoefficient, modulus);
596
- return inverse < 0 ? inverse + modulus : inverse;
597
- };
598
- //#endregion
599
- //#region src/services/function/computeMultinomial.ts
600
- const computeMultinomial = (parts) => {
601
- if (!parts.every((part) => Number.isInteger(part) && part > 0)) return null;
602
- let result = 1;
603
- let running = 0;
604
- for (const part of parts) {
605
- running += part;
606
- result *= computeCombinations(running, part);
607
- }
608
- return result;
609
- };
610
- //#endregion
611
- //#region src/services/function/computeNorm.ts
612
- const computeNorm = (values) => {
613
- if (values.length === 0) return 0;
614
- if (values.length === 1) return Math.abs(values[0] ?? NaN);
615
- return Math.sqrt(computeSum(values.map((value) => value * value)));
616
- };
617
- //#endregion
618
- //#region src/services/function/computeNthRoot.ts
619
- const computeNthRoot = (value, root) => {
620
- const isInverse = root < 0;
621
- const degree = Math.abs(root);
622
- if (degree === 0) return null;
623
- if (value < 0 && degree % 2 !== 1) return null;
624
- if (value === 0) return isInverse ? Number.POSITIVE_INFINITY : 0;
625
- if (!Number.isFinite(value)) return isInverse ? 0 : value;
626
- let result = Math.abs(value) ** (1 / degree);
627
- const rounded = Math.round(result);
628
- if (Number.isInteger(degree) && rounded ** degree === Math.abs(value)) result = rounded;
629
- if (value < 0) result = -result;
630
- return isInverse ? 1 / result : result;
631
- };
632
- //#endregion
633
- //#region src/services/function/computePartitionSelect.ts
634
- const computePartitionSelect = (values, index) => {
635
- if (!Number.isInteger(index) || index < 0 || index >= values.length) return null;
636
- return values.toSorted(compareNumbers)[index] ?? null;
637
- };
638
- //#endregion
639
- //#region src/services/function/computePermutations.ts
640
- const computePermutations = (available, chosen) => {
641
- if (!Number.isInteger(available) || !Number.isInteger(chosen) || chosen < 0 || chosen > available) return null;
642
- let result = 1;
643
- for (let factor = available - chosen + 1; factor <= available; factor++) {
644
- result *= factor;
645
- if (result > Number.MAX_VALUE) return Number.POSITIVE_INFINITY;
646
- }
647
- return result;
648
- };
649
- //#endregion
650
- //#region src/services/function/scaleList.ts
651
- const scaleList = (list, scalar) => list.map((element) => element * scalar);
652
- //#endregion
653
- //#region src/services/function/multiplyPair.ts
654
- const multiplyPair = (left, right) => {
655
- if (typeof left === "number" && typeof right === "number") return left * right;
656
- if (typeof left === "number" && Array.isArray(right)) return scaleList(right, left);
657
- if (Array.isArray(left) && typeof right === "number") return scaleList(left, right);
658
- if (Array.isArray(left) && Array.isArray(right)) return computeDotProduct(left, right);
659
- return null;
660
- };
661
- //#endregion
662
- //#region src/services/function/computeProduct.ts
663
- const computeProduct = (values) => {
664
- let total = 1;
665
- for (const value of values) {
666
- if (total === null) return null;
667
- total = multiplyPair(total, value);
668
- }
669
- return typeof total === "number" ? total : null;
670
- };
671
- //#endregion
672
- //#region src/services/function/computeQuantile.ts
673
- const computeQuantile = (values, probability, isSorted) => {
674
- if (values.length === 0 || probability < 0 || probability > 1) return null;
675
- const ordered = isSorted ? values : values.toSorted(compareNumbers);
676
- const index = probability * (ordered.length - 1);
677
- const integerPart = Math.floor(index);
678
- if (Number.isInteger(index)) return ordered[integerPart] ?? NaN;
679
- const fraction = index % 1;
680
- return (ordered[integerPart] ?? NaN) * (1 - fraction) + (ordered[integerPart + 1] ?? NaN) * fraction;
681
- };
682
- //#endregion
683
- //#region src/services/function/computeStirlingColumn.ts
684
- const computeStirlingColumn = (count, parts) => {
685
- const column = Array.from({ length: parts + 1 }, (_element, index) => index === 0 ? 1 : 0);
686
- for (let step = 1; step <= count; step++) {
687
- for (let part = parts; part >= 1; part--) column[part] = part * (column[part] ?? 0) + (column[part - 1] ?? 0);
688
- column[0] = 0;
689
- }
690
- return column[parts] ?? 0;
691
- };
692
- //#endregion
693
- //#region src/services/function/computeStirlingDiagonal.ts
694
- const computeStirlingDiagonal = (count, index) => {
695
- const diagonal = Array.from({ length: index + 1 }, (_element, position) => position === 0 ? 1 : 0);
696
- for (let step = 1; step <= count; step++) for (let position = Math.min(step, index); position >= 1; position--) diagonal[position] = (step - position) * (diagonal[position - 1] ?? 0) + (diagonal[position] ?? 0);
697
- return diagonal[index] ?? 0;
698
- };
699
- //#endregion
700
- //#region src/services/function/computeStirlingSecondKind.ts
701
- const computeStirlingSecondKind = (count, parts) => {
702
- if (!Number.isInteger(count) || !Number.isInteger(parts) || count < 0 || parts < 0 || parts > count) return null;
703
- if (parts === 0) return count === 0 ? 1 : 0;
704
- if (parts === count) return 1;
705
- const band = Math.min(parts, count - parts);
706
- if (count * band > 4e6) return null;
707
- return band === parts ? computeStirlingColumn(count, parts) : computeStirlingDiagonal(count, count - parts);
708
- };
709
- //#endregion
710
- //#region src/services/shared/checkIsTruthy.ts
711
- const checkIsTruthy = (value) => value !== 0 && !Number.isNaN(value);
712
- //#endregion
713
- //#region src/services/function/computeTruthyCount.ts
714
- const computeTruthyCount = (values) => values.filter((value) => checkIsTruthy(value)).length;
715
- //#endregion
716
- //#region src/services/function/computeVariance.ts
717
- const computeVariance = (values) => {
718
- if (values.length === 1) return Number.isFinite(values[0] ?? NaN) ? 0 : NaN;
719
- const average = computeMean(values);
720
- return computeSum(values.map((value) => (value - average) ** 2)) / (values.length - 1);
721
- };
722
- //#endregion
723
- //#region src/services/function/computeExtreme.ts
724
- const computeExtreme = (values, initial, checkIsPreferred) => {
725
- let extreme = initial;
726
- for (const value of values) {
727
- if (Number.isNaN(value)) return NaN;
728
- if (checkIsPreferred(value, extreme)) extreme = value;
729
- }
730
- return extreme;
731
- };
732
- //#endregion
733
- //#region src/services/function/computeVectorNorm.ts
734
- const computeVectorNorm = (values, power) => {
735
- if (Number.isNaN(power)) return null;
736
- const magnitudes = values.map((value) => Math.abs(value));
737
- if (Math.abs(power) === Number.POSITIVE_INFINITY) {
738
- const [first] = magnitudes;
739
- if (first === void 0) return 0;
740
- return computeExtreme(magnitudes, first, power > 0 ? checkIsLarger : checkIsSmaller);
741
- }
742
- if (checkIsNearlyEqual(power, 0)) return Number.POSITIVE_INFINITY;
743
- return computeSum(magnitudes.map((magnitude) => magnitude ** power)) ** (1 / power);
744
- };
745
- //#endregion
746
- //#region src/services/function/computeSummedZeta.ts
747
- const computeSummedZeta = (value) => {
748
- let total = 0;
749
- for (let integer = 1; integer < 10; integer++) total += integer ** -value;
750
- total += 10 ** (1 - value) / (value - 1) + .5 * 10 ** -value;
751
- let rising = value;
752
- for (let index = 1; index <= EULER_MACLAURIN_COEFFICIENTS.length; index++) {
753
- const coefficient = EULER_MACLAURIN_COEFFICIENTS[index - 1] ?? 0;
754
- total += coefficient * rising * 10 ** (-value - 2 * index + 1);
755
- rising *= (value + 2 * index - 1) * (value + 2 * index);
756
- }
757
- return total;
758
- };
759
- //#endregion
760
- //#region src/services/function/computeZeta.ts
761
- const computeZeta = (value) => {
762
- if (value === Number.POSITIVE_INFINITY) return 1;
763
- if (!Number.isFinite(value)) return NaN;
764
- if (value === 1) return NaN;
765
- if (value === 0) return -.5;
766
- if (value > 0) return computeSummedZeta(value);
767
- if (Number.isInteger(value) && value % 2 === 0) return 0;
768
- if (1 - value >= 171.35) {
769
- const sine = Math.sin(Math.PI * value / 2);
770
- const logMagnitude = value * Math.LN2 + (value - 1) * Math.log(Math.PI) + Math.log(Math.abs(sine)) + computeLogGamma(1 - value) + Math.log(computeSummedZeta(1 - value));
771
- return Math.sign(sine) * Math.exp(logMagnitude);
772
- }
773
- return 2 ** value * Math.PI ** (value - 1) * Math.sin(Math.PI * value / 2) * computeGamma(1 - value) * computeSummedZeta(1 - value);
774
- };
775
- //#endregion
776
- //#region src/services/function/signature/createNumericCompute.ts
777
- const createNumericCompute = (compute) => (values) => compute(values.flat());
778
- //#endregion
779
- //#region src/services/function/signature/createSignature.ts
780
- const createSignature = (parameters, minArity, maxArity, compute, scalarCompute = {}) => ({
781
- compute,
782
- maxArity,
783
- minArity,
784
- parameters,
785
- ...scalarCompute
786
- });
787
- //#endregion
788
- //#region src/services/function/signature/createNumberSignature.ts
789
- const createNumberSignature = (minArity, maxArity, compute, scalarCompute) => createSignature(["number"], minArity, maxArity, createNumericCompute(compute), scalarCompute);
790
- //#endregion
791
- //#region src/services/function/signature/createRangedSignatures.ts
792
- const createRangedSignatures = (minArity, maxArity, compute, scalarCompute) => [createNumberSignature(minArity, maxArity, compute, scalarCompute)];
793
- //#endregion
794
- //#region src/services/function/signature/createBinarySignatures.ts
795
- const createBinarySignatures = (compute) => createRangedSignatures(2, 2, (values) => compute(values[0] ?? NaN, values[1] ?? NaN), { computeBinary: compute });
796
- //#endregion
797
- //#region src/services/function/signature/createBitwisePair.ts
798
- const createBitwisePair = (absorbing, compute) => (left, right) => {
799
- if (left === absorbing) return absorbing;
800
- if (!Number.isInteger(left) || !Number.isInteger(right)) return null;
801
- return compute(left, right);
802
- };
803
- //#endregion
804
- //#region src/services/function/signature/createBitwiseFold.ts
805
- const createBitwiseFold = (absorbing, compute) => {
806
- const computePair = createBitwisePair(absorbing, compute);
807
- return (values) => values.slice(1).reduce((result, value) => result === null ? null : computePair(result, value), values[0] ?? NaN);
808
- };
809
- //#endregion
810
- //#region src/services/function/shiftDecimalPlaces.ts
811
- const shiftDecimalPlaces = (value, places) => {
812
- if (!Number.isFinite(value)) return value;
813
- const [mantissa = "", exponent = "0"] = value.toExponential().split("e");
814
- return Number(`${mantissa}e${Number(exponent) + places}`);
815
- };
816
- //#endregion
817
- //#region src/services/function/roundToDigits.ts
818
- const roundToDigits = (rounder, value, digits) => {
819
- if (!Number.isInteger(digits) || digits < 0 || digits > 15) return null;
820
- if (!Number.isFinite(value)) return value;
821
- if (Number.isInteger(value)) return value + 0;
822
- if (digits === 0) return rounder(value) + 0;
823
- return shiftDecimalPlaces(rounder(shiftDecimalPlaces(value, digits)), -digits);
824
- };
825
- //#endregion
826
- //#region src/services/function/signature/createDigitSignatures.ts
827
- const createDigitSignatures = (rounder) => createRangedSignatures(1, 2, (values) => {
828
- const [value = NaN, digits = 0] = values;
829
- return roundToDigits(rounder, value, digits);
830
- }, {
831
- computeBinary: (value, digits) => roundToDigits(rounder, value, digits),
832
- computeUnary: (value) => roundToDigits(rounder, value, 0)
833
- });
834
- //#endregion
835
- //#region src/services/function/signature/createNonEmptyCompute.ts
836
- const createNonEmptyCompute = (compute) => (values) => values.length === 0 ? null : compute(values);
837
- //#endregion
838
- //#region src/services/function/signature/createListSignature.ts
839
- const createListSignature = (compute) => createSignature(["list"], 1, 1, createNumericCompute(compute));
840
- //#endregion
841
- //#region src/services/function/signature/createVariadicSignatures.ts
842
- const createVariadicSignatures = (minArity, compute, computeBinary) => [createNumberSignature(minArity, Number.POSITIVE_INFINITY, compute, { computeBinary })];
843
- //#endregion
844
- //#region src/services/function/signature/createSpreadSignatures.ts
845
- const createSpreadSignatures = (minArity, compute) => [...createVariadicSignatures(minArity, compute), createListSignature(compute)];
846
- //#endregion
847
- //#region src/services/function/signature/createExtremeSignatures.ts
848
- const createExtremeSignatures = (checkIsPreferred) => createSpreadSignatures(1, createNonEmptyCompute((values) => computeExtreme(values, values[0] ?? NaN, checkIsPreferred)));
849
- //#endregion
850
- //#region src/services/function/signature/createSingletonListSignature.ts
851
- const createSingletonListSignature = (compute) => createListSignature((values) => values.length === 1 ? compute(values[0] ?? NaN) : null);
852
- //#endregion
853
- //#region src/services/function/signature/createUnarySignatures.ts
854
- const createUnarySignatures = (compute) => createRangedSignatures(1, 1, (values) => compute(values[0] ?? NaN), { computeUnary: compute });
855
- //#endregion
856
- //#region src/services/function/signature/createIdentitySignatures.ts
857
- const createIdentitySignatures = () => [...createUnarySignatures((value) => value), createSingletonListSignature((value) => value)];
858
- //#endregion
859
- //#region src/services/function/signature/createIntegerBinarySignatures.ts
860
- const createIntegerBinarySignatures = (compute) => createBinarySignatures((left, right) => Number.isInteger(left) && Number.isInteger(right) ? compute(left, right) : null);
861
- //#endregion
862
- //#region src/services/function/signature/createIntegerUnarySignatures.ts
863
- const createIntegerUnarySignatures = (compute) => createUnarySignatures((value) => Number.isInteger(value) ? compute(value) : null);
864
- //#endregion
865
- //#region src/services/function/signature/createListFirstCompute.ts
866
- const createListFirstCompute = (compute) => (values) => compute(values.slice(0, 1).flat(), values.slice(1).flat());
867
- //#endregion
868
- //#region src/services/function/signature/createListPairCompute.ts
869
- const createListPairCompute = (compute) => (values) => compute(values.slice(0, 1).flat(), values.slice(1, 2).flat());
870
- //#endregion
871
- //#region src/services/function/signature/createListPairSignature.ts
872
- const createListPairSignature = (compute) => createSignature(["list", "list"], 2, 2, createListPairCompute(compute));
873
- //#endregion
874
- //#region src/services/function/signature/createOrderedListSignatures.ts
875
- const createOrderedListSignatures = (compute) => {
876
- const computePair = createListPairCompute(compute);
877
- return [
878
- ["number", "list"],
879
- ["list", "number"],
880
- ["list", "list"]
881
- ].map((parameters) => createSignature(parameters, 2, 2, computePair));
882
- };
883
- //#endregion
884
- //#region src/services/shared/toNumber.ts
885
- const toNumber = (flag) => flag ? 1 : 0;
886
- //#endregion
887
- //#region src/services/function/MathExpressionFunctionMap.ts
888
- const MathExpressionFunctionMap = {
889
- abs: createUnarySignatures(Math.abs),
890
- acos: createUnarySignatures(Math.acos),
891
- acosh: createUnarySignatures(Math.acosh),
892
- acot: createUnarySignatures((value) => Math.atan(1 / value)),
893
- acoth: createUnarySignatures(computeInverseCoth),
894
- acsc: createUnarySignatures((value) => Math.asin(1 / value)),
895
- acsch: createUnarySignatures((value) => Math.asinh(1 / value)),
896
- add: createVariadicSignatures(2, computeSum, (left, right) => left + right),
897
- addScalar: createBinarySignatures((left, right) => left + right),
898
- and: createVariadicSignatures(1, (values) => toNumber(values.every((value) => checkIsTruthy(value)))),
899
- arg: createUnarySignatures((value) => Number.isNaN(value) ? NaN : value < 0 ? Math.PI : 0),
900
- asec: createUnarySignatures((value) => Math.acos(1 / value)),
901
- asech: createUnarySignatures((value) => Math.acosh(1 / value)),
902
- asin: createUnarySignatures(Math.asin),
903
- asinh: createUnarySignatures(Math.asinh),
904
- atan: createUnarySignatures(Math.atan),
905
- atan2: createBinarySignatures((left, right) => Math.atan2(left, right)),
906
- atanh: createUnarySignatures(Math.atanh),
907
- bellNumbers: createUnarySignatures(computeBellNumber),
908
- bernoulli: createUnarySignatures((value) => Number.isInteger(value) && value >= 0 ? computeBernoulliNumber(value) : null),
909
- bitAnd: createVariadicSignatures(2, createBitwiseFold(0, computeBitwiseAnd), createBitwisePair(0, computeBitwiseAnd)),
910
- bitNot: createIntegerUnarySignatures((value) => ~value),
911
- bitOr: createVariadicSignatures(2, createBitwiseFold(-1, computeBitwiseOr), createBitwisePair(-1, computeBitwiseOr)),
912
- bitXor: createIntegerBinarySignatures((left, right) => left ^ right),
913
- boolean: createRangedSignatures(0, 1, (values) => values.length === 0 ? 0 : toNumber(checkIsTruthy(values[0] ?? 0))),
914
- catalan: createUnarySignatures(computeCatalan),
915
- cbrt: createUnarySignatures(Math.cbrt),
916
- ceil: createDigitSignatures(Math.ceil),
917
- clone: createUnarySignatures((value) => value),
918
- combinations: createBinarySignatures((available, chosen) => Number.isInteger(available) && Number.isInteger(chosen) && chosen >= 0 && chosen <= available ? computeCombinations(available, chosen) : null),
919
- combinationsWithRep: createBinarySignatures((available, chosen) => Number.isInteger(available) && Number.isInteger(chosen) && available >= 1 && chosen >= 0 ? computeCombinations(available + chosen - 1, chosen) : null),
920
- compare: createBinarySignatures(computeComparison),
921
- compareNatural: [...createBinarySignatures(computeComparison), ...createOrderedListSignatures(computeListComparison)],
922
- composition: createBinarySignatures(computeCompositions),
923
- conj: createUnarySignatures((value) => value),
924
- corr: [createListPairSignature(computeCorrelation)],
925
- cos: createUnarySignatures(Math.cos),
926
- cosh: createUnarySignatures(Math.cosh),
927
- cot: createUnarySignatures((value) => 1 / Math.tan(value)),
928
- coth: createUnarySignatures((value) => 1 / Math.tanh(value)),
929
- count: [createListSignature((values) => values.length)],
930
- csc: createUnarySignatures((value) => 1 / Math.sin(value)),
931
- csch: createUnarySignatures((value) => 1 / Math.sinh(value)),
932
- cube: createUnarySignatures((value) => value * value * value),
933
- deepEqual: [
934
- ...createBinarySignatures((left, right) => toNumber(checkIsNearlyEqual(left, right))),
935
- createListPairSignature((left, right) => toNumber(left.length === right.length && left.every((value, index) => checkIsNearlyEqual(value, right[index] ?? NaN)))),
936
- createSignature(["number", "list"], 2, 2, () => toNumber(false)),
937
- createSignature(["list", "number"], 2, 2, () => toNumber(false))
938
- ],
939
- det: [...createUnarySignatures((value) => value), createListSignature(computeDeterminant)],
940
- distance: [createListPairSignature(computeDistance)],
941
- divide: createBinarySignatures((left, right) => left / right),
942
- divideScalar: createBinarySignatures((left, right) => left / right),
943
- dot: [createListPairSignature(computeDotProduct)],
944
- dotDivide: createBinarySignatures((left, right) => left / right),
945
- dotMultiply: createBinarySignatures((left, right) => left * right),
946
- dotPow: createBinarySignatures((left, right) => left ** right),
947
- equal: createBinarySignatures((left, right) => toNumber(checkIsNearlyEqual(left, right))),
948
- equalScalar: createBinarySignatures((left, right) => toNumber(checkIsNearlyEqual(left, right))),
949
- erf: createUnarySignatures(computeErf),
950
- erfinv: createUnarySignatures(computeErfInverse),
951
- exp: createUnarySignatures(Math.exp),
952
- expm1: createUnarySignatures(Math.expm1),
953
- fix: createDigitSignatures(Math.trunc),
954
- floor: createDigitSignatures(Math.floor),
955
- gamma: createUnarySignatures(computeGamma),
956
- gcd: createSpreadSignatures(2, (values) => values.length < 2 ? null : computeIntegerGreatestCommonDivisor(values)),
957
- hypot: createSpreadSignatures(1, computeHypotenuse),
958
- im: createUnarySignatures(() => 0),
959
- inv: createUnarySignatures((value) => 1 / value),
960
- invmod: createBinarySignatures(computeModularInverse),
961
- isBounded: [...createUnarySignatures((value) => toNumber(Number.isFinite(value))), createListSignature((values) => toNumber(values.every((value) => Number.isFinite(value))))],
962
- isFinite: createUnarySignatures((value) => toNumber(Number.isFinite(value))),
963
- isInteger: createUnarySignatures((value) => toNumber(Number.isInteger(value))),
964
- isNaN: createUnarySignatures((value) => toNumber(Number.isNaN(value))),
965
- isNegative: createUnarySignatures((value) => toNumber(value < 0)),
966
- isPositive: createUnarySignatures((value) => toNumber(value > 0)),
967
- isPrime: createUnarySignatures((value) => toNumber(checkIsPrime(value))),
968
- isZero: createUnarySignatures((value) => toNumber(value === 0)),
969
- kldivergence: [createListPairSignature(computeKullbackLeibler)],
970
- larger: createBinarySignatures((left, right) => toNumber(checkIsLarger(left, right))),
971
- largerEq: createBinarySignatures((left, right) => toNumber(left >= right || checkIsNearlyEqual(left, right))),
972
- lcm: createVariadicSignatures(2, (values) => {
973
- const [first = NaN, ...rest] = values;
974
- return rest.reduce((total, value) => total === null ? null : computeLeastCommonMultiple(total, value), first);
975
- }),
976
- leftShift: createIntegerBinarySignatures((left, right) => left << right),
977
- lgamma: createUnarySignatures(computeLogGamma),
978
- log: createRangedSignatures(1, 2, (values) => computeLogarithm(values[0] ?? NaN, values[1])),
979
- log1p: createRangedSignatures(1, 2, (values) => {
980
- const [value = NaN, base] = values;
981
- return base === void 0 ? Math.log1p(value) : Math.log1p(value) / Math.log(base);
982
- }),
983
- log2: createUnarySignatures(Math.log2),
984
- log10: createUnarySignatures(Math.log10),
985
- mad: createSpreadSignatures(1, createNonEmptyCompute(computeMedianAbsoluteDeviation)),
986
- ["ctranspose"]: createUnarySignatures((value) => value),
987
- ["factorial"]: createUnarySignatures(computeFactorial),
988
- ["unaryMinus"]: createUnarySignatures((value) => -value),
989
- ["unaryPlus"]: createUnarySignatures((value) => value),
990
- max: createExtremeSignatures(checkIsLarger),
991
- mean: createSpreadSignatures(1, createNonEmptyCompute(computeMean)),
992
- median: createSpreadSignatures(1, createNonEmptyCompute(computeMedian)),
993
- min: createExtremeSignatures(checkIsSmaller),
994
- mod: createBinarySignatures(computeModulo),
995
- multinomial: [createListSignature(computeMultinomial)],
996
- multiply: [
997
- ...createVariadicSignatures(2, (values) => values.reduce((total, value) => total * value, 1), (left, right) => left * right),
998
- createListPairSignature(computeDotProduct),
999
- createSignature(["any"], 2, Number.POSITIVE_INFINITY, computeProduct)
1000
- ],
1001
- multiplyScalar: createBinarySignatures((left, right) => left * right),
1002
- norm: [
1003
- ...createRangedSignatures(1, 1, computeNorm),
1004
- createListSignature(computeNorm),
1005
- createSignature(["list", "number"], 2, 2, createListFirstCompute((list, [power = NaN]) => computeVectorNorm(list, power)))
1006
- ],
1007
- not: createUnarySignatures((value) => toNumber(!checkIsTruthy(value))),
1008
- nthRoot: createRangedSignatures(1, 2, (values) => computeNthRoot(values[0] ?? NaN, values[1] ?? 2)),
1009
- nullish: createVariadicSignatures(1, (values) => values[0] ?? NaN),
1010
- number: createRangedSignatures(0, 1, (values) => values.length === 0 ? 0 : values[0] ?? NaN),
1011
- numeric: createUnarySignatures((value) => value),
1012
- or: createVariadicSignatures(1, (values) => toNumber(computeTruthyCount(values) > 0)),
1013
- partitionSelect: [createSignature(["list", "number"], 2, 2, createListFirstCompute((list, [index = NaN]) => computePartitionSelect(list, index)))],
1014
- permutations: createRangedSignatures(1, 2, (values) => {
1015
- const [available = NaN, chosen = available] = values;
1016
- return computePermutations(available, chosen);
1017
- }),
1018
- pinv: createUnarySignatures((value) => value === 0 ? 0 : 1 / value),
1019
- pow: createBinarySignatures((left, right) => left ** right),
1020
- prod: createSpreadSignatures(1, createNonEmptyCompute((values) => values.reduce((total, value) => total * value, 1))),
1021
- quantileSeq: [createSignature(["list", "number"], 2, 3, createListFirstCompute((list, [probability = NaN, sorted = 0]) => computeQuantile(list, probability, checkIsTruthy(sorted))))],
1022
- re: createUnarySignatures((value) => value),
1023
- rightArithShift: createIntegerBinarySignatures((left, right) => left >> right),
1024
- rightLogShift: createIntegerBinarySignatures((left, right) => left >>> right),
1025
- round: createDigitSignatures((value) => Math.sign(value) * Math.round(Math.abs(value))),
1026
- sec: createUnarySignatures((value) => 1 / Math.cos(value)),
1027
- sech: createUnarySignatures((value) => 1 / Math.cosh(value)),
1028
- setIsSubset: [createListPairSignature((left, right) => toNumber(left.every((value) => right.includes(value))))],
1029
- setMultiplicity: [createSignature(["number", "list"], 2, 2, createListFirstCompute(([value = NaN], list) => list.filter((element) => element === value).length))],
1030
- setSize: [createListSignature((values) => values.length)],
1031
- sign: createUnarySignatures(Math.sign),
1032
- sin: createUnarySignatures(Math.sin),
1033
- sinh: createUnarySignatures(Math.sinh),
1034
- smaller: createBinarySignatures((left, right) => toNumber(checkIsSmaller(left, right))),
1035
- smallerEq: createBinarySignatures((left, right) => toNumber(left <= right || checkIsNearlyEqual(left, right))),
1036
- sqrt: createUnarySignatures(Math.sqrt),
1037
- square: createUnarySignatures((value) => value * value),
1038
- squeeze: createIdentitySignatures(),
1039
- std: createSpreadSignatures(1, createNonEmptyCompute((values) => Math.sqrt(computeVariance(values)))),
1040
- stirlingS2: createBinarySignatures(computeStirlingSecondKind),
1041
- subtract: createBinarySignatures((left, right) => left - right),
1042
- subtractScalar: createBinarySignatures((left, right) => left - right),
1043
- sum: createSpreadSignatures(1, computeSum),
1044
- tan: createUnarySignatures(Math.tan),
1045
- tanh: createUnarySignatures(Math.tanh),
1046
- trace: createIdentitySignatures(),
1047
- transpose: createIdentitySignatures(),
1048
- unequal: createBinarySignatures((left, right) => toNumber(!checkIsNearlyEqual(left, right))),
1049
- variance: createSpreadSignatures(1, createNonEmptyCompute(computeVariance)),
1050
- xor: createVariadicSignatures(1, (values) => toNumber(computeTruthyCount(values) % 2 === 1), (left, right) => toNumber(checkIsTruthy(left) !== checkIsTruthy(right))),
1051
- zeta: createUnarySignatures(computeZeta)
1052
- };
1053
- //#endregion
1054
- //#region src/services/shared/getOwnValue.ts
1055
- const getOwnValue = (record, key) => Object.hasOwn(record, key) ? record[key] : void 0;
1056
- //#endregion
1057
- //#region src/services/shared/getMathExpressionSignatures.ts
1058
- const getMathExpressionSignatures = (name) => getOwnValue(MathExpressionFunctionMap, name);
1059
- //#endregion
1060
- //#region src/services/compiler/getMathExpressionScalarCompute.ts
1061
- const getMathExpressionScalarCompute = (name, key) => {
1062
- const signature = getMathExpressionSignatures(name)?.[0];
1063
- if (signature === void 0) return () => null;
1064
- const scalarCompute = signature[key];
1065
- if (scalarCompute !== void 0) return scalarCompute;
1066
- return (...values) => signature.compute(values);
1067
- };
1068
- //#endregion
1069
- //#region src/services/compiler/node/compileBinary.ts
1070
- const compileBinary = (node, context) => {
1071
- const { left, name, right } = node;
1072
- const compiledLeft = context.compile(left);
1073
- if (ADDITIVE_NAMES.includes(name) && right.type === "percentage" && !checkIsPercentageExpression(left)) {
1074
- const compiledPercent = context.compile(right.operand);
1075
- const sign = name === "add" ? 1 : -1;
1076
- const evaluate = (values, locals) => {
1077
- const base = compiledLeft.evaluate(values, locals);
1078
- const percent = compiledPercent.evaluate(values, locals);
1079
- if (base === null || percent === null) return null;
1080
- return base + sign * base * (percent / 100);
1081
- };
1082
- return {
1083
- evaluate,
1084
- isConstant: compiledLeft.isConstant && compiledPercent.isConstant
1085
- };
1086
- }
1087
- const compiledRight = context.compile(right);
1088
- const compute = getMathExpressionScalarCompute(name, "computeBinary");
1089
- const absorption = MathExpressionBitwiseAbsorptionMap[name];
1090
- const evaluate = (values, locals) => {
1091
- const leftValue = compiledLeft.evaluate(values, locals);
1092
- if (leftValue === null) return null;
1093
- if (absorption?.absorbs === leftValue) return absorption.result;
1094
- const rightValue = compiledRight.evaluate(values, locals);
1095
- if (rightValue === null) return null;
1096
- return compute(leftValue, rightValue);
1097
- };
1098
- return {
1099
- evaluate,
1100
- isConstant: compiledLeft.isConstant && compiledRight.isConstant
1101
- };
1102
- };
1103
- //#endregion
1104
- //#region src/services/compiler/compileList.ts
1105
- const compileList = (elements, context) => {
1106
- const compiledElements = elements.map((element) => context.compile(element));
1107
- return {
1108
- evaluate: (values, locals) => {
1109
- const numbers = [];
1110
- for (const element of compiledElements) {
1111
- const elementValue = element.evaluate(values, locals);
1112
- if (elementValue === null) return null;
1113
- numbers.push(elementValue);
1114
- }
1115
- return numbers;
1116
- },
1117
- isConstant: compiledElements.every((element) => element.isConstant)
1118
- };
1119
- };
1120
- //#endregion
1121
- //#region src/services/compiler/compileArgument.ts
1122
- const compileArgument = (node, context) => {
1123
- if (node.type === "list") return compileList(node.elements, context);
1124
- return context.compile(node);
1125
- };
1126
- //#endregion
1127
- //#region src/services/shared/getMathExpressionParameterType.ts
1128
- const getMathExpressionParameterType = (node) => node.type === "list" ? "list" : "number";
1129
- //#endregion
1130
- //#region src/services/shared/checkIsMatchingKind.ts
1131
- const checkIsMatchingKind = (parameterType, argumentType) => parameterType === "any" || parameterType === argumentType;
1132
- //#endregion
1133
- //#region src/services/shared/getParameterType.ts
1134
- const getParameterType = (signature, index) => signature.parameters[Math.min(index, signature.parameters.length - 1)];
1135
- //#endregion
1136
- //#region src/services/shared/checkIsMatching.ts
1137
- const checkIsMatching = (signature, parameterTypes) => parameterTypes.length >= signature.minArity && parameterTypes.length <= signature.maxArity && parameterTypes.every((parameterType, index) => checkIsMatchingKind(getParameterType(signature, index), parameterType));
1138
- //#endregion
1139
- //#region src/services/shared/matchMathExpressionSignature.ts
1140
- const matchMathExpressionSignature = (signatures, parameterTypes) => signatures.find((signature) => checkIsMatching(signature, parameterTypes));
1141
- //#endregion
1142
- //#region src/services/compiler/node/compileCall.ts
1143
- const compileCall = (node, context) => {
1144
- const signatures = getMathExpressionSignatures(node.name);
1145
- const parameterTypes = node.arguments.map((argument) => getMathExpressionParameterType(argument));
1146
- const signature = matchMathExpressionSignature(signatures ?? [], parameterTypes);
1147
- const compute = signature?.compute ?? (() => null);
1148
- const computeUnary = signature?.computeUnary;
1149
- const computeBinary = signature?.computeBinary;
1150
- const compiledArguments = node.arguments.map((argument) => compileArgument(argument, context));
1151
- const isConstant = compiledArguments.every((argument) => argument.isConstant);
1152
- const [first, second] = compiledArguments;
1153
- if (compiledArguments.length === 1 && first !== void 0) return {
1154
- evaluate: (values, locals) => {
1155
- const firstValue = first.evaluate(values, locals);
1156
- if (firstValue === null) return null;
1157
- if (computeUnary !== void 0 && typeof firstValue === "number") return computeUnary(firstValue);
1158
- return compute([firstValue]);
1159
- },
1160
- isConstant
1161
- };
1162
- if (compiledArguments.length === 2 && first !== void 0 && second !== void 0) return {
1163
- evaluate: (values, locals) => {
1164
- const firstValue = first.evaluate(values, locals);
1165
- if (firstValue === null) return null;
1166
- const secondValue = second.evaluate(values, locals);
1167
- if (secondValue === null) return null;
1168
- if (computeBinary !== void 0 && typeof firstValue === "number" && typeof secondValue === "number") return computeBinary(firstValue, secondValue);
1169
- return compute([firstValue, secondValue]);
1170
- },
1171
- isConstant
1172
- };
1173
- return {
1174
- evaluate: (values, locals) => {
1175
- const argumentValues = [];
1176
- for (const argument of compiledArguments) {
1177
- const argumentValue = argument.evaluate(values, locals);
1178
- if (argumentValue === null) return null;
1179
- argumentValues.push(argumentValue);
1180
- }
1181
- return compute(argumentValues);
1182
- },
1183
- isConstant
1184
- };
1185
- };
1186
- //#endregion
1187
- //#region src/services/compiler/node/compileComparison.ts
1188
- const compileComparison = (node, context) => {
1189
- const compiledOperands = node.operands.map((operand) => context.compile(operand));
1190
- const computes = node.names.map((name) => getMathExpressionScalarCompute(name, "computeBinary"));
1191
- const evaluate = (values, locals) => {
1192
- let left = compiledOperands[0]?.evaluate(values, locals) ?? null;
1193
- let result = 1;
1194
- for (const [index, compute] of computes.entries()) {
1195
- const right = compiledOperands[index + 1]?.evaluate(values, locals) ?? null;
1196
- if (left === null || right === null) return null;
1197
- result = compute(left, right);
1198
- if (result !== 1) return result;
1199
- left = right;
1200
- }
1201
- return result;
1202
- };
1203
- return {
1204
- evaluate,
1205
- isConstant: compiledOperands.every((operand) => operand.isConstant)
1206
- };
1207
- };
1208
- //#endregion
1209
- //#region src/services/compiler/node/compileConditional.ts
1210
- const compileConditional = (node, context) => {
1211
- const compiledCondition = context.compile(node.condition);
1212
- const compiledWhenTrue = context.compile(node.whenTrue);
1213
- const compiledWhenFalse = context.compile(node.whenFalse);
1214
- const evaluate = (values, locals) => {
1215
- const test = compiledCondition.evaluate(values, locals);
1216
- if (test === null) return null;
1217
- return checkIsTruthy(test) ? compiledWhenTrue.evaluate(values, locals) : compiledWhenFalse.evaluate(values, locals);
1218
- };
1219
- return {
1220
- evaluate,
1221
- isConstant: compiledCondition.isConstant && compiledWhenTrue.isConstant && compiledWhenFalse.isConstant
1222
- };
1223
- };
1224
- //#endregion
1225
- //#region src/services/compiler/node/compileGroup.ts
1226
- const compileGroup = (node, context) => context.compile(node.operand);
1227
- //#endregion
1228
- //#region src/services/compiler/node/compileListNode.ts
1229
- const compileListNode = () => ({
1230
- evaluate: () => null,
1231
- isConstant: false
1232
- });
1233
- //#endregion
1234
- //#region src/services/compiler/node/compileLogical.ts
1235
- const compileLogical = (node, context) => {
1236
- const compiledLeft = context.compile(node.left);
1237
- if (node.operator === "nullish") return compiledLeft;
1238
- const compiledRight = context.compile(node.right);
1239
- const isConstant = compiledLeft.isConstant && compiledRight.isConstant;
1240
- switch (node.operator) {
1241
- case "and": return {
1242
- evaluate: (values, locals) => {
1243
- const leftValue = compiledLeft.evaluate(values, locals);
1244
- if (leftValue === null) return null;
1245
- if (!checkIsTruthy(leftValue)) return 0;
1246
- const rightValue = compiledRight.evaluate(values, locals);
1247
- return rightValue === null ? null : toNumber(checkIsTruthy(rightValue));
1248
- },
1249
- isConstant
1250
- };
1251
- case "or": return {
1252
- evaluate: (values, locals) => {
1253
- const leftValue = compiledLeft.evaluate(values, locals);
1254
- if (leftValue === null) return null;
1255
- if (checkIsTruthy(leftValue)) return 1;
1256
- const rightValue = compiledRight.evaluate(values, locals);
1257
- return rightValue === null ? null : toNumber(checkIsTruthy(rightValue));
1258
- },
1259
- isConstant
1260
- };
1261
- default: return exhaustiveGuard(node.operator);
1262
- }
1263
- };
1264
- //#endregion
1265
- //#region src/services/shared/MathExpressionConstantMap.ts
1266
- const MathExpressionConstantMap = {
1267
- E: Math.E,
1268
- e: Math.E,
1269
- false: 0,
1270
- Infinity: Number.POSITIVE_INFINITY,
1271
- LN2: Math.LN2,
1272
- LN10: Math.LN10,
1273
- LOG2E: Math.LOG2E,
1274
- LOG10E: Math.LOG10E,
1275
- NaN: NaN,
1276
- phi: (1 + Math.sqrt(5)) / 2,
1277
- PI: Math.PI,
1278
- pi: Math.PI,
1279
- SQRT1_2: Math.SQRT1_2,
1280
- SQRT2: Math.SQRT2,
1281
- tau: 2 * Math.PI,
1282
- true: 1
1283
- };
1284
- //#endregion
1285
- //#region src/services/compiler/getMathExpressionConstant.ts
1286
- const getMathExpressionConstant = (name) => getOwnValue(MathExpressionConstantMap, name);
1287
- //#endregion
1288
- //#region src/services/compiler/node/compileName.ts
1289
- const compileName = (node, context) => {
1290
- const slot = context.assignedSlots.get(node.name);
1291
- if (slot !== void 0) return {
1292
- evaluate: (_values, locals) => locals[slot] ?? null,
1293
- isConstant: false
1294
- };
1295
- const index = context.variableIndices.get(node.name);
1296
- if (index !== void 0) return {
1297
- evaluate: (values) => values[index] ?? NaN,
1298
- isConstant: false
1299
- };
1300
- const constant = getMathExpressionConstant(node.name);
1301
- return {
1302
- evaluate: () => constant ?? null,
1303
- isConstant: true
1304
- };
1305
- };
1306
- //#endregion
1307
- //#region src/services/compiler/node/compileNumber.ts
1308
- const compileNumber = (node) => {
1309
- const { value } = node;
1310
- return {
1311
- evaluate: () => value,
1312
- isConstant: true
1313
- };
1314
- };
1315
- //#endregion
1316
- //#region src/services/compiler/node/compilePercentage.ts
1317
- const compilePercentage = (node, context) => {
1318
- const compiledOperand = context.compile(node.operand);
1319
- return {
1320
- evaluate: (values, locals) => {
1321
- const operandValue = compiledOperand.evaluate(values, locals);
1322
- return operandValue === null ? null : operandValue / 100;
1323
- },
1324
- isConstant: compiledOperand.isConstant
1325
- };
1326
- };
1327
- //#endregion
1328
- //#region src/services/compiler/node/compileUnary.ts
1329
- const compileUnary = (node, context) => {
1330
- const compute = getMathExpressionScalarCompute(node.name, "computeUnary");
1331
- const compiledOperand = context.compile(node.operand);
1332
- return {
1333
- evaluate: (values, locals) => {
1334
- const operandValue = compiledOperand.evaluate(values, locals);
1335
- return operandValue === null ? null : compute(operandValue);
1336
- },
1337
- isConstant: compiledOperand.isConstant
1338
- };
1339
- };
1340
- //#endregion
1341
- //#region src/services/compiler/MathExpressionNodeCompileMap.ts
1342
- const MathExpressionNodeCompileMap = {
1343
- ["assignment"]: compileAssignment,
1344
- ["binary"]: compileBinary,
1345
- ["call"]: compileCall,
1346
- ["comparison"]: compileComparison,
1347
- ["conditional"]: compileConditional,
1348
- ["group"]: compileGroup,
1349
- ["list"]: compileListNode,
1350
- ["logical"]: compileLogical,
1351
- ["name"]: compileName,
1352
- ["number"]: compileNumber,
1353
- ["percentage"]: compilePercentage,
1354
- ["unary"]: compileUnary
1355
- };
1356
- //#endregion
1357
- //#region src/services/shared/getMathExpressionChildren.ts
1358
- const getMathExpressionChildren = (node) => {
1359
- switch (node.type) {
1360
- case "assignment": return [node.value];
1361
- case "binary":
1362
- case "logical": return [node.left, node.right];
1363
- case "call": return node.arguments;
1364
- case "comparison": return node.operands;
1365
- case "conditional": return [
1366
- node.condition,
1367
- node.whenTrue,
1368
- node.whenFalse
1369
- ];
1370
- case "group":
1371
- case "percentage":
1372
- case "unary": return [node.operand];
1373
- case "list": return node.elements;
1374
- case "name":
1375
- case "number": return [];
1376
- default: return exhaustiveGuard(node);
1377
- }
1378
- };
1379
- //#endregion
1380
- //#region src/services/compiler/collectMathExpressionAssignedNames.ts
1381
- const collectMathExpressionAssignedNames = (node, names) => {
1382
- if (node.type === "assignment") names.add(node.name);
1383
- for (const child of getMathExpressionChildren(node)) collectMathExpressionAssignedNames(child, names);
1384
- };
1385
- //#endregion
1386
- //#region src/services/compiler/compileMathExpressionNode.ts
1387
- const compileMathExpressionNode = (node, context) => {
1388
- const compileOfType = MathExpressionNodeCompileMap[node.type];
1389
- const compiled = compileOfType(node, context);
1390
- if (!compiled.isConstant) return compiled;
1391
- const value = compiled.evaluate(NO_VALUES, NO_LOCALS);
1392
- return {
1393
- evaluate: () => value,
1394
- isConstant: true
1395
- };
1396
- };
1397
- //#endregion
1398
- //#region src/services/compiler/getMathExpressionOuterValue.ts
1399
- const getMathExpressionOuterValue = (outer, values) => {
1400
- if (outer.variableIndex !== void 0) return values[outer.variableIndex] ?? NaN;
1401
- return outer.constant ?? null;
1402
- };
1403
- //#endregion
1404
- //#region src/services/compiler/compileMathExpression.ts
1405
- const compileMathExpression = (node, variableNames) => {
1406
- const assignedNames = /* @__PURE__ */ new Set();
1407
- collectMathExpressionAssignedNames(node, assignedNames);
1408
- const assignedSlots = new Map(Array.from(assignedNames, (name, slot) => [name, slot]));
1409
- const variableIndices = new Map(variableNames.map((name, index) => [name, index]));
1410
- const context = {
1411
- assignedSlots,
1412
- compile: (child) => compileMathExpressionNode(child, context),
1413
- variableIndices
1414
- };
1415
- const compiled = context.compile(node);
1416
- const outerBindings = Array.from(assignedNames, (name) => ({
1417
- constant: getMathExpressionConstant(name),
1418
- variableIndex: variableIndices.get(name)
1419
- }));
1420
- return (values) => {
1421
- const locals = outerBindings.length === 0 ? NO_LOCALS : outerBindings.map((outer) => getMathExpressionOuterValue(outer, values));
1422
- return compiled.evaluate(values, locals) ?? NaN;
1423
- };
1424
- };
1425
- //#endregion
1426
- //#region src/services/names/walkNode.ts
1427
- const walkNode = (node, bound, free) => {
1428
- switch (node.type) {
1429
- case "assignment":
1430
- walkNode(node.value, bound, free);
1431
- bound.add(node.name);
1432
- return;
1433
- case "binary": {
1434
- walkNode(node.left, bound, free);
1435
- const rightBound = Object.hasOwn(MathExpressionBitwiseAbsorptionMap, node.name) ? new Set(bound) : bound;
1436
- walkNode(node.right, rightBound, free);
1437
- return;
1438
- }
1439
- case "call":
1440
- case "group":
1441
- case "list":
1442
- case "number":
1443
- case "percentage":
1444
- case "unary":
1445
- for (const child of getMathExpressionChildren(node)) walkNode(child, bound, free);
1446
- return;
1447
- case "comparison": {
1448
- let chainBound = bound;
1449
- for (const [index, operand] of node.operands.entries()) {
1450
- if (index === 2) chainBound = new Set(bound);
1451
- walkNode(operand, chainBound, free);
1452
- }
1453
- return;
1454
- }
1455
- case "conditional": {
1456
- walkNode(node.condition, bound, free);
1457
- const whenTrueBound = new Set(bound);
1458
- const whenFalseBound = new Set(bound);
1459
- walkNode(node.whenTrue, whenTrueBound, free);
1460
- walkNode(node.whenFalse, whenFalseBound, free);
1461
- for (const name of whenTrueBound) if (whenFalseBound.has(name)) bound.add(name);
1462
- return;
1463
- }
1464
- case "logical":
1465
- walkNode(node.left, bound, free);
1466
- if (node.operator !== "nullish") walkNode(node.right, new Set(bound), free);
1467
- return;
1468
- case "name":
1469
- if (!bound.has(node.name)) free.add(node.name);
1470
- return;
1471
- default: return exhaustiveGuard(node);
1472
- }
1473
- };
1474
- //#endregion
1475
- //#region src/services/names/getMathExpressionNames.ts
1476
- const getMathExpressionNames = (node) => {
1477
- const bound = /* @__PURE__ */ new Set();
1478
- const free = /* @__PURE__ */ new Set();
1479
- walkNode(node, bound, free);
1480
- return [...free].filter((name) => getMathExpressionConstant(name) === void 0);
1481
- };
1482
- //#endregion
1483
- //#region src/services/parser/MathExpressionBinaryOperatorMap.ts
1484
- const MathExpressionBinaryOperatorMap = {
1485
- "!=": {
1486
- name: "unequal",
1487
- power: 7,
1488
- type: "comparison"
1489
- },
1490
- "%": {
1491
- name: "mod",
1492
- power: 10,
1493
- type: "binary"
1494
- },
1495
- "&": {
1496
- name: "bitAnd",
1497
- power: 6,
1498
- type: "binary"
1499
- },
1500
- "*": {
1501
- name: "multiply",
1502
- power: 10,
1503
- type: "binary"
1504
- },
1505
- "+": {
1506
- name: "add",
1507
- power: 9,
1508
- type: "binary"
1509
- },
1510
- "-": {
1511
- name: "subtract",
1512
- power: 9,
1513
- type: "binary"
1514
- },
1515
- ".*": {
1516
- name: "dotMultiply",
1517
- power: 10,
1518
- type: "binary"
1519
- },
1520
- "./": {
1521
- name: "dotDivide",
1522
- power: 10,
1523
- type: "binary"
1524
- },
1525
- "/": {
1526
- name: "divide",
1527
- power: 10,
1528
- type: "binary"
1529
- },
1530
- "<": {
1531
- name: "smaller",
1532
- power: 7,
1533
- type: "comparison"
1534
- },
1535
- "<<": {
1536
- name: "leftShift",
1537
- power: 8,
1538
- type: "binary"
1539
- },
1540
- "<=": {
1541
- name: "smallerEq",
1542
- power: 7,
1543
- type: "comparison"
1544
- },
1545
- "==": {
1546
- name: "equal",
1547
- power: 7,
1548
- type: "comparison"
1549
- },
1550
- ">": {
1551
- name: "larger",
1552
- power: 7,
1553
- type: "comparison"
1554
- },
1555
- ">=": {
1556
- name: "largerEq",
1557
- power: 7,
1558
- type: "comparison"
1559
- },
1560
- ">>": {
1561
- name: "rightArithShift",
1562
- power: 8,
1563
- type: "binary"
1564
- },
1565
- ">>>": {
1566
- name: "rightLogShift",
1567
- power: 8,
1568
- type: "binary"
1569
- },
1570
- "^|": {
1571
- name: "bitXor",
1572
- power: 5,
1573
- type: "binary"
1574
- },
1575
- and: {
1576
- operator: "and",
1577
- power: 3,
1578
- type: "logical"
1579
- },
1580
- mod: {
1581
- name: "mod",
1582
- power: 10,
1583
- type: "binary"
1584
- },
1585
- or: {
1586
- operator: "or",
1587
- power: 1,
1588
- type: "logical"
1589
- },
1590
- xor: {
1591
- name: "xor",
1592
- power: 2,
1593
- type: "binary"
1594
- },
1595
- "|": {
1596
- name: "bitOr",
1597
- power: 4,
1598
- type: "binary"
1599
- }
1600
- };
1601
- //#endregion
1602
- //#region src/services/parser/MathExpressionOperatorMap.ts
1603
- const MathExpressionOperatorMap = {
1604
- ["Nullish"]: { "??": "nullish" },
1605
- ["Power"]: {
1606
- ".^": "dotPow",
1607
- "^": "pow"
1608
- },
1609
- ["Unary"]: {
1610
- "+": "unaryPlus",
1611
- "-": "unaryMinus",
1612
- not: "not",
1613
- "~": "bitNot"
1614
- }
1615
- };
1616
- //#endregion
1617
- //#region src/services/parser/constants.ts
1618
- const MAX_MATH_EXPRESSION_DEPTH = 64;
1619
- const PLACEHOLDER = {
1620
- type: "number",
1621
- value: NaN
1622
- };
1623
- //#endregion
1624
- //#region src/services/parser/failMathExpressionAt.ts
1625
- const failMathExpressionAt = (state, message, column) => {
1626
- if (state.error !== null) return;
1627
- state.error = new MathExpressionError(`${message} (char ${column})`);
1628
- };
1629
- //#endregion
1630
- //#region src/services/parser/getMathExpressionColumn.ts
1631
- const getMathExpressionColumn = (state) => state.index - state.token.length + 1;
1632
- //#endregion
1633
- //#region src/services/parser/failMathExpression.ts
1634
- const failMathExpression = (state, message) => failMathExpressionAt(state, message, getMathExpressionColumn(state));
1635
- //#endregion
1636
- //#region src/services/parser/checkCanMathExpressionNest.ts
1637
- const checkCanMathExpressionNest = (state) => {
1638
- if (state.depth < 64) return true;
1639
- failMathExpression(state, `Formula nests deeper than 64 levels`);
1640
- return false;
1641
- };
1642
- //#endregion
1643
- //#region src/services/parser/checkIsToken.ts
1644
- const checkIsToken = (state, token) => state.token === token;
1645
- //#endregion
1646
- //#region src/services/parser/token/checkIsDigitCharacter.ts
1647
- const checkIsDigitCharacter = (character) => character >= "0" && character <= "9";
1648
- //#endregion
1649
- //#region src/services/parser/token/constants.ts
1650
- const DELIMITERS_OF_THREE = /* @__PURE__ */ new Set([">>>"]);
1651
- const DELIMITERS_OF_TWO = /* @__PURE__ */ new Set([
1652
- "!=",
1653
- ".*",
1654
- "./",
1655
- ".^",
1656
- "<<",
1657
- "<=",
1658
- "==",
1659
- ">=",
1660
- ">>",
1661
- "??",
1662
- "^|"
1663
- ]);
1664
- const DELIMITERS_OF_ONE = /* @__PURE__ */ new Set([
1665
- "!",
1666
- "%",
1667
- "&",
1668
- "'",
1669
- "(",
1670
- ")",
1671
- "*",
1672
- "+",
1673
- ",",
1674
- "-",
1675
- "/",
1676
- ":",
1677
- "<",
1678
- "=",
1679
- ">",
1680
- "?",
1681
- "[",
1682
- "]",
1683
- "^",
1684
- "|",
1685
- "~"
1686
- ]);
1687
- const FIRST_CHARACTERS_OF_THREE = new Set(Array.from(DELIMITERS_OF_THREE, (delimiter) => delimiter.charAt(0)));
1688
- const FIRST_CHARACTERS_OF_TWO = new Set(Array.from(DELIMITERS_OF_TWO, (delimiter) => delimiter.charAt(0)));
1689
- const NAMED_DELIMITERS = /* @__PURE__ */ new Set([
1690
- "and",
1691
- "in",
1692
- "mod",
1693
- "not",
1694
- "or",
1695
- "to",
1696
- "xor"
1697
- ]);
1698
- const DECIMAL_MARK_OPERATOR_FOLLOWERS = /* @__PURE__ */ new Set([
1699
- "*",
1700
- "/",
1701
- "^"
1702
- ]);
1703
- const WORD_START_REGEX = /^[\p{L}_$]$/u;
1704
- const WORD_CHARACTER_REGEX = /^[\p{L}\p{Nd}_$]$/u;
1705
- //#endregion
1706
- //#region src/services/parser/token/checkIsWordStartCharacter.ts
1707
- const checkIsWordStartCharacter = (character) => {
1708
- if (character >= "€") return WORD_START_REGEX.test(character);
1709
- return character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$";
1710
- };
1711
- //#endregion
1712
- //#region src/services/parser/token/getMathExpressionCharacter.ts
1713
- const getMathExpressionCharacter = (state, offset) => state.source.charAt(state.index + offset);
1714
- //#endregion
1715
- //#region src/services/parser/token/readMathExpressionDelimiter.ts
1716
- const readMathExpressionDelimiter = (state) => {
1717
- const character = getMathExpressionCharacter(state, 0);
1718
- let length = 0;
1719
- if (FIRST_CHARACTERS_OF_THREE.has(character) && DELIMITERS_OF_THREE.has(state.source.slice(state.index, state.index + 3))) length = 3;
1720
- else if (FIRST_CHARACTERS_OF_TWO.has(character) && DELIMITERS_OF_TWO.has(state.source.slice(state.index, state.index + 2))) length = 2;
1721
- else if (DELIMITERS_OF_ONE.has(character)) length = 1;
1722
- if (length === 0) return 0;
1723
- state.token = state.source.slice(state.index, state.index + length);
1724
- state.index += length;
1725
- state.tokenType = "delimiter";
1726
- if (["(", "["].includes(state.token)) state.nestingLevel++;
1727
- if ([")", "]"].includes(state.token)) state.nestingLevel--;
1728
- return length;
1729
- };
1730
- //#endregion
1731
- //#region src/services/parser/token/MathExpressionRadixMap.ts
1732
- const MathExpressionRadixMap = {
1733
- b: {
1734
- digit: /^[01]$/u,
1735
- radix: 2
1736
- },
1737
- o: {
1738
- digit: /^[0-7]$/u,
1739
- radix: 8
1740
- },
1741
- x: {
1742
- digit: /^[0-9a-fA-F]$/u,
1743
- radix: 16
1744
- }
1745
- };
1746
- //#endregion
1747
- //#region src/services/parser/token/takeMathExpressionMatching.ts
1748
- const takeMathExpressionMatching = (state, checkCharacter) => {
1749
- const start = state.index;
1750
- while (checkCharacter(getMathExpressionCharacter(state, 0))) state.index++;
1751
- return state.source.slice(start, state.index);
1752
- };
1753
- //#endregion
1754
- //#region src/services/parser/token/readRadixNumber.ts
1755
- const readRadixNumber = (state, prefix, baseDigits) => {
1756
- const checkBaseDigit = (character) => baseDigits.test(character);
1757
- state.index += 2;
1758
- let digits = takeMathExpressionMatching(state, checkBaseDigit);
1759
- if (digits === "") {
1760
- state.index--;
1761
- state.token = "0";
1762
- state.tokenType = "number";
1763
- return;
1764
- }
1765
- if (getMathExpressionCharacter(state, 0) === ".") {
1766
- state.index++;
1767
- digits += `.${takeMathExpressionMatching(state, checkBaseDigit)}`;
1768
- }
1769
- let wordSize = "";
1770
- if (getMathExpressionCharacter(state, 0) === "i" && checkIsDigitCharacter(getMathExpressionCharacter(state, 1))) {
1771
- state.index++;
1772
- wordSize = `i${takeMathExpressionMatching(state, checkIsDigitCharacter)}`;
1773
- }
1774
- state.token = `0${prefix}${digits}${wordSize}`;
1775
- state.tokenType = "number";
1776
- };
1777
- //#endregion
1778
- //#region src/services/parser/token/checkIsDecimalMark.ts
1779
- const checkIsDecimalMark = (character, nextCharacter) => character === "." && !DECIMAL_MARK_OPERATOR_FOLLOWERS.has(nextCharacter);
1780
- //#endregion
1781
- //#region src/services/parser/token/failExponent.ts
1782
- const failExponent = (state, text) => {
1783
- state.token = text;
1784
- failMathExpression(state, `Digit expected, got "${getMathExpressionCharacter(state, 0)}"`);
1785
- };
1786
- //#endregion
1787
- //#region src/services/parser/token/takeExponent.ts
1788
- const takeExponent = (state, text) => {
1789
- const exponentMarker = getMathExpressionCharacter(state, 0);
1790
- if (!["e", "E"].includes(exponentMarker)) return text;
1791
- const afterMarker = getMathExpressionCharacter(state, 1);
1792
- if (checkIsDecimalMark(afterMarker, getMathExpressionCharacter(state, 2))) {
1793
- state.index++;
1794
- failExponent(state, text);
1795
- return text;
1796
- }
1797
- if (!checkIsDigitCharacter(afterMarker) && !["+", "-"].includes(afterMarker)) return text;
1798
- state.index++;
1799
- let exponent = "e";
1800
- if (["+", "-"].includes(afterMarker)) {
1801
- exponent += afterMarker;
1802
- state.index++;
1803
- }
1804
- if (!checkIsDigitCharacter(getMathExpressionCharacter(state, 0))) {
1805
- const partial = text + exponent;
1806
- failExponent(state, partial);
1807
- return partial;
1808
- }
1809
- const taken = text + exponent + takeMathExpressionMatching(state, checkIsDigitCharacter);
1810
- if (checkIsDecimalMark(getMathExpressionCharacter(state, 0), getMathExpressionCharacter(state, 1))) failExponent(state, taken);
1811
- return taken;
1812
- };
1813
- //#endregion
1814
- //#region src/services/parser/token/readMathExpressionNumber.ts
1815
- const readMathExpressionNumber = (state) => {
1816
- const prefix = getMathExpressionCharacter(state, 1);
1817
- const radixEntry = MathExpressionRadixMap[prefix];
1818
- if (getMathExpressionCharacter(state, 0) === "0" && radixEntry !== void 0) {
1819
- readRadixNumber(state, prefix, radixEntry.digit);
1820
- return;
1821
- }
1822
- const start = state.index;
1823
- takeMathExpressionMatching(state, checkIsDigitCharacter);
1824
- if (getMathExpressionCharacter(state, 0) === ".") {
1825
- state.index++;
1826
- takeMathExpressionMatching(state, checkIsDigitCharacter);
1827
- }
1828
- state.token = takeExponent(state, state.source.slice(start, state.index));
1829
- state.tokenType = "number";
1830
- };
1831
- //#endregion
1832
- //#region src/services/parser/token/checkIsWordCharacter.ts
1833
- const checkIsWordCharacter = (character) => {
1834
- if (character >= "€") return WORD_CHARACTER_REGEX.test(character);
1835
- return checkIsWordStartCharacter(character) || checkIsDigitCharacter(character);
1836
- };
1837
- //#endregion
1838
- //#region src/services/parser/token/readMathExpressionWord.ts
1839
- const readMathExpressionWord = (state) => {
1840
- state.token = takeMathExpressionMatching(state, checkIsWordCharacter);
1841
- state.tokenType = NAMED_DELIMITERS.has(state.token) ? "delimiter" : "symbol";
1842
- };
1843
- //#endregion
1844
- //#region src/services/parser/token/skipMathExpressionSpaces.ts
1845
- const skipMathExpressionSpaces = (state) => {
1846
- while (state.index < state.source.length) {
1847
- const character = getMathExpressionCharacter(state, 0);
1848
- if ([
1849
- " ",
1850
- " ",
1851
- "\xA0"
1852
- ].includes(character) || character === "\n" && state.nestingLevel > 0) state.index++;
1853
- else if (character === "#") while (state.index < state.source.length && getMathExpressionCharacter(state, 0) !== "\n") state.index++;
1854
- else break;
1855
- }
1856
- };
1857
- //#endregion
1858
- //#region src/services/parser/getMathExpressionToken.ts
1859
- const getMathExpressionToken = (state) => {
1860
- state.token = "";
1861
- state.tokenType = "null";
1862
- skipMathExpressionSpaces(state);
1863
- if (state.index >= state.source.length || state.error !== null) return;
1864
- const character = getMathExpressionCharacter(state, 0);
1865
- const next = getMathExpressionCharacter(state, 1);
1866
- if (checkIsDigitCharacter(character) || character === "." && checkIsDigitCharacter(next)) readMathExpressionNumber(state);
1867
- else if (checkIsWordStartCharacter(character)) readMathExpressionWord(state);
1868
- else if (readMathExpressionDelimiter(state) === 0) {
1869
- state.token = character;
1870
- state.index++;
1871
- state.tokenType = "unknown";
1872
- }
1873
- };
1874
- //#endregion
1875
- //#region src/services/parser/rule/parseAssignment.ts
1876
- const parseAssignment = (state, parse) => {
1877
- if (!checkCanMathExpressionNest(state)) return PLACEHOLDER;
1878
- state.depth++;
1879
- const left = parse(state, "Conditional");
1880
- let node = left;
1881
- if (state.error === null && checkIsToken(state, "=")) if (left.type === "name") {
1882
- getMathExpressionToken(state);
1883
- const value = parse(state, "Assignment");
1884
- node = {
1885
- name: left.name,
1886
- type: "assignment",
1887
- value
1888
- };
1889
- } else failMathExpression(state, "Invalid left hand side of assignment operator =");
1890
- state.depth--;
1891
- return node;
1892
- };
1893
- //#endregion
1894
- //#region src/services/parser/createBinaryNode.ts
1895
- const createBinaryNode = (left, name, right) => ({
1896
- left,
1897
- name,
1898
- right,
1899
- type: "binary"
1900
- });
1901
- //#endregion
1902
- //#region src/services/parser/createLogicalNode.ts
1903
- const createLogicalNode = (left, operator, right) => ({
1904
- left,
1905
- operator,
1906
- right,
1907
- type: "logical"
1908
- });
1909
- //#endregion
1910
- //#region src/services/parser/createBinaryOperation.ts
1911
- const createBinaryOperation = (left, operator, right) => {
1912
- if (operator.type === "logical") return createLogicalNode(left, operator.operator, right);
1913
- if (operator.type === "binary") return createBinaryNode(left, operator.name, right);
1914
- if (left.type === "comparison") {
1915
- left.names.push(operator.name);
1916
- left.operands.push(right);
1917
- return left;
1918
- }
1919
- return {
1920
- names: [operator.name],
1921
- operands: [left, right],
1922
- type: "comparison"
1923
- };
1924
- };
1925
- //#endregion
1926
- //#region src/services/parser/parseBinaryOperators.ts
1927
- const parseBinaryOperators = (state, parse, minimumPower) => {
1928
- let node = parse(state, "ImplicitProduct");
1929
- let operator = getOwnValue(MathExpressionBinaryOperatorMap, state.token);
1930
- while (state.error === null && operator !== void 0 && operator.power >= minimumPower) {
1931
- getMathExpressionToken(state);
1932
- const right = parseBinaryOperators(state, parse, operator.power + 1);
1933
- node = createBinaryOperation(node, operator, right);
1934
- operator = getOwnValue(MathExpressionBinaryOperatorMap, state.token);
1935
- }
1936
- return node;
1937
- };
1938
- //#endregion
1939
- //#region src/services/parser/rule/parseBinary.ts
1940
- const parseBinary = (state, parse) => parseBinaryOperators(state, parse, 0);
1941
- //#endregion
1942
- //#region src/services/parser/rule/parseConditional.ts
1943
- const parseConditional = (state, parse) => {
1944
- const condition = parse(state, "Binary");
1945
- if (state.error !== null || !checkIsToken(state, "?")) return condition;
1946
- getMathExpressionToken(state);
1947
- if (checkIsToken(state, ":")) {
1948
- failMathExpression(state, "The true-expression of a conditional operator may not be empty");
1949
- return PLACEHOLDER;
1950
- }
1951
- const whenTrue = parse(state, "Assignment");
1952
- if (state.error === null && !checkIsToken(state, ":")) failMathExpression(state, "False part of conditional expression expected");
1953
- if (state.error !== null) return PLACEHOLDER;
1954
- getMathExpressionToken(state);
1955
- return {
1956
- condition,
1957
- type: "conditional",
1958
- whenFalse: parse(state, "Conditional"),
1959
- whenTrue
1960
- };
1961
- };
1962
- //#endregion
1963
- //#region src/services/parser/checkIsSignedNumber.ts
1964
- const checkIsSignedNumber = (node) => {
1965
- if (node.type === "number") return true;
1966
- return node.type === "unary" && (node.name === "unaryMinus" || node.name === "unaryPlus") && node.operand.type === "number";
1967
- };
1968
- //#endregion
1969
- //#region src/services/parser/rule/parseDivisionBeforeProduct.ts
1970
- const parseDivisionBeforeProduct = (state, parse) => {
1971
- const dividend = parse(state, "Percentage");
1972
- if (state.error !== null || !checkIsToken(state, "/") || !checkIsSignedNumber(dividend)) return dividend;
1973
- const snapshot = { ...state };
1974
- getMathExpressionToken(state);
1975
- const isNumber = state.tokenType === "number";
1976
- if (isNumber) getMathExpressionToken(state);
1977
- if (isNumber && state.error === null && (state.tokenType === "symbol" || checkIsToken(state, "("))) {
1978
- Object.assign(state, snapshot);
1979
- getMathExpressionToken(state);
1980
- return createBinaryNode(dividend, MathExpressionBinaryOperatorMap["/"].name, parse(state, "Percentage"));
1981
- }
1982
- Object.assign(state, snapshot);
1983
- return dividend;
1984
- };
1985
- //#endregion
1986
- //#region src/services/parser/checkIsOperatorOperand.ts
1987
- const checkIsOperatorOperand = (node) => {
1988
- if (node.type === "unary") return node.name !== "factorial";
1989
- return node.type === "binary" || node.type === "comparison" || node.type === "logical";
1990
- };
1991
- //#endregion
1992
- //#region src/services/parser/rule/parseImplicitProduct.ts
1993
- const parseImplicitProduct = (state, parse) => {
1994
- let node = parse(state, "DivisionBeforeProduct");
1995
- let last = node;
1996
- while (state.error === null) {
1997
- if (!(state.tokenType === "symbol" || checkIsToken(state, "(") || state.tokenType === "number" && last.type !== "number" && !checkIsOperatorOperand(last))) break;
1998
- last = parse(state, "DivisionBeforeProduct");
1999
- node = createBinaryNode(node, MathExpressionBinaryOperatorMap["*"].name, last);
2000
- }
2001
- return node;
2002
- };
2003
- //#endregion
2004
- //#region src/services/parser/rule/parseLeftHand.ts
2005
- const parseLeftHand = (state, parse) => {
2006
- let node = parse(state, "Symbol");
2007
- while (state.error === null && (checkIsToken(state, "!") || checkIsToken(state, "'"))) {
2008
- const name = checkIsToken(state, "!") ? "factorial" : "ctranspose";
2009
- getMathExpressionToken(state);
2010
- node = {
2011
- name,
2012
- operand: node,
2013
- type: "unary"
2014
- };
2015
- }
2016
- return node;
2017
- };
2018
- //#endregion
2019
- //#region src/services/parser/rule/parseNullish.ts
2020
- const parseNullish = (state, parse) => {
2021
- const operators = MathExpressionOperatorMap["Nullish"];
2022
- let node = parse(state, "LeftHand");
2023
- let operator = getOwnValue(operators, state.token);
2024
- while (state.error === null && operator !== void 0) {
2025
- getMathExpressionToken(state);
2026
- const right = parse(state, "LeftHand");
2027
- node = createLogicalNode(node, operator, right);
2028
- operator = getOwnValue(operators, state.token);
2029
- }
2030
- return node;
2031
- };
2032
- //#endregion
2033
- //#region src/services/parser/checkIsNameToken.ts
2034
- const checkIsNameToken = (state) => state.tokenType === "symbol" || state.tokenType === "delimiter" && getMathExpressionSignatures(state.token) !== void 0;
2035
- //#endregion
2036
- //#region src/services/parser/checkIsUnaryStart.ts
2037
- const checkIsUnaryStart = (state) => state.tokenType === "number" || checkIsNameToken(state) || checkIsToken(state, "(") || getOwnValue(MathExpressionOperatorMap["Unary"], state.token) !== void 0;
2038
- //#endregion
2039
- //#region src/services/parser/rule/parsePercentage.ts
2040
- const parsePercentage = (state, parse) => {
2041
- const node = parse(state, "Unary");
2042
- if (state.error !== null || !checkIsToken(state, "%")) return node;
2043
- const snapshot = { ...state };
2044
- getMathExpressionToken(state);
2045
- if (state.error === null && !checkIsToken(state, "+") && !checkIsToken(state, "-") && checkIsUnaryStart(state)) {
2046
- Object.assign(state, snapshot);
2047
- return node;
2048
- }
2049
- return {
2050
- operand: node,
2051
- type: "percentage"
2052
- };
2053
- };
2054
- //#endregion
2055
- //#region src/services/parser/rule/parsePower.ts
2056
- const parsePower = (state, parse) => {
2057
- const base = parse(state, "Nullish");
2058
- const name = getOwnValue(MathExpressionOperatorMap["Power"], state.token);
2059
- if (state.error !== null || name === void 0) return base;
2060
- getMathExpressionToken(state);
2061
- const exponent = parse(state, "Unary");
2062
- return createBinaryNode(base, name, exponent);
2063
- };
2064
- //#endregion
2065
- //#region src/services/parser/computeNumberLiteral.ts
2066
- const computeNumberLiteral = (token) => {
2067
- const radixEntry = MathExpressionRadixMap[token.charAt(1)];
2068
- if (!token.startsWith("0") || radixEntry === void 0) return Number(token);
2069
- const { radix } = radixEntry;
2070
- const [digits = "", wordSize] = token.slice(2).split("i");
2071
- const [integerDigits = "", fractionDigits = ""] = digits.split(".");
2072
- let value = 0;
2073
- for (const digit of integerDigits) value = value * radix + Number.parseInt(digit, radix);
2074
- let scale = 1 / radix;
2075
- for (const digit of fractionDigits) {
2076
- value += Number.parseInt(digit, radix) * scale;
2077
- scale /= radix;
2078
- }
2079
- if (wordSize === void 0) return value;
2080
- const bits = Number(wordSize);
2081
- if (value > 2 ** bits - 1) return null;
2082
- return value >= 2 ** (bits - 1) ? value - 2 ** bits : value;
2083
- };
2084
- //#endregion
2085
- //#region src/services/parser/getArgumentCountText.ts
2086
- const getArgumentCountText = (count) => `${count} ${count === 1 ? "argument" : "arguments"}`;
2087
- //#endregion
2088
- //#region src/services/parser/getMathExpressionArityMessage.ts
2089
- const getMathExpressionArityMessage = (name, minArity, maxArity) => {
2090
- if (maxArity === Number.POSITIVE_INFINITY) return `"${name}" takes at least ${getArgumentCountText(minArity)}`;
2091
- if (minArity === maxArity) return `"${name}" takes ${getArgumentCountText(minArity)}`;
2092
- return `"${name}" takes ${minArity} or ${maxArity} arguments`;
2093
- };
2094
- //#endregion
2095
- //#region src/services/parser/getMathExpressionSignatureError.ts
2096
- const getMathExpressionSignatureError = (name, signatures, parameterTypes) => {
2097
- const count = parameterTypes.length;
2098
- if (signatures.filter((signature) => count >= signature.minArity && count <= signature.maxArity).length === 0) return getMathExpressionArityMessage(name, Math.min(...signatures.map((signature) => signature.minArity)), Math.max(...signatures.map((signature) => signature.maxArity)));
2099
- if (parameterTypes.includes("list")) return `"${name}" does not take a list argument`;
2100
- return `"${name}" takes a list argument`;
2101
- };
2102
- //#endregion
2103
- //#region src/services/parser/parseSequence.ts
2104
- const parseSequence = (state, closing, parseItem) => {
2105
- const nodes = [];
2106
- if (checkIsToken(state, closing)) return nodes;
2107
- while (state.error === null) {
2108
- nodes.push(parseItem(state));
2109
- if (!checkIsToken(state, ",")) break;
2110
- getMathExpressionToken(state);
2111
- }
2112
- if (state.error === null && !checkIsToken(state, closing)) failMathExpression(state, closing === ")" ? "Parenthesis ) expected" : "Parenthesis ] expected");
2113
- return nodes;
2114
- };
2115
- //#endregion
2116
- //#region src/services/parser/parseList.ts
2117
- const parseList = (state, parse) => {
2118
- getMathExpressionToken(state);
2119
- const elements = parseSequence(state, "]", (item) => parse(item, "Assignment"));
2120
- if (state.error !== null) return PLACEHOLDER;
2121
- getMathExpressionToken(state);
2122
- return {
2123
- elements,
2124
- type: "list"
2125
- };
2126
- };
2127
- //#endregion
2128
- //#region src/services/parser/parseArgument.ts
2129
- const parseArgument = (state, parse) => checkIsToken(state, "[") ? parseList(state, parse) : parse(state, "Assignment");
2130
- //#endregion
2131
- //#region src/services/parser/parseCall.ts
2132
- const parseCall = (state, name, column, parse) => {
2133
- const signatures = getMathExpressionSignatures(name);
2134
- if (signatures === void 0) {
2135
- failMathExpressionAt(state, `Unknown function "${name}"`, column);
2136
- return PLACEHOLDER;
2137
- }
2138
- getMathExpressionToken(state);
2139
- const argumentNodes = parseSequence(state, ")", (argument) => parseArgument(argument, parse));
2140
- if (state.error !== null) return PLACEHOLDER;
2141
- getMathExpressionToken(state);
2142
- const parameterTypes = argumentNodes.map((argument) => getMathExpressionParameterType(argument));
2143
- if (matchMathExpressionSignature(signatures, parameterTypes) === void 0) {
2144
- failMathExpressionAt(state, getMathExpressionSignatureError(name, signatures, parameterTypes), column);
2145
- return PLACEHOLDER;
2146
- }
2147
- return {
2148
- arguments: argumentNodes,
2149
- name,
2150
- type: "call"
2151
- };
2152
- };
2153
- //#endregion
2154
- //#region src/services/parser/rule/parseSymbol.ts
2155
- const parseSymbol = (state, parse) => {
2156
- if (state.tokenType === "number") {
2157
- const value = computeNumberLiteral(state.token);
2158
- if (value === null) {
2159
- failMathExpression(state, `String "${state.token.split("i")[0]}" is out of range`);
2160
- getMathExpressionToken(state);
2161
- return PLACEHOLDER;
2162
- }
2163
- getMathExpressionToken(state);
2164
- return {
2165
- type: "number",
2166
- value
2167
- };
2168
- }
2169
- if (checkIsNameToken(state)) {
2170
- const name = state.token;
2171
- const column = getMathExpressionColumn(state);
2172
- const isSymbol = state.tokenType === "symbol";
2173
- getMathExpressionToken(state);
2174
- if (checkIsToken(state, "(")) return parseCall(state, name, column, parse);
2175
- if (isSymbol) return {
2176
- name,
2177
- type: "name"
2178
- };
2179
- }
2180
- if (checkIsToken(state, "(")) {
2181
- getMathExpressionToken(state);
2182
- const operand = parse(state, "Assignment");
2183
- if (state.error === null && !checkIsToken(state, ")")) failMathExpression(state, "Parenthesis ) expected");
2184
- if (state.error !== null) return PLACEHOLDER;
2185
- getMathExpressionToken(state);
2186
- return {
2187
- operand,
2188
- type: "group"
2189
- };
2190
- }
2191
- failMathExpression(state, checkIsToken(state, "") ? "Unexpected end of expression" : "Value expected");
2192
- return PLACEHOLDER;
2193
- };
2194
- //#endregion
2195
- //#region src/services/parser/rule/parseUnary.ts
2196
- const parseUnary = (state, parse) => {
2197
- const name = getOwnValue(MathExpressionOperatorMap["Unary"], state.token);
2198
- if (name === void 0) return parse(state, "Power");
2199
- if (!checkCanMathExpressionNest(state)) return PLACEHOLDER;
2200
- getMathExpressionToken(state);
2201
- state.depth++;
2202
- const operand = parse(state, "Unary");
2203
- state.depth--;
2204
- return {
2205
- name,
2206
- operand,
2207
- type: "unary"
2208
- };
2209
- };
2210
- //#endregion
2211
- //#region src/services/parser/MathExpressionRuleParserMap.ts
2212
- const MathExpressionRuleParserMap = {
2213
- ["Assignment"]: parseAssignment,
2214
- ["Binary"]: parseBinary,
2215
- ["Conditional"]: parseConditional,
2216
- ["DivisionBeforeProduct"]: parseDivisionBeforeProduct,
2217
- ["ImplicitProduct"]: parseImplicitProduct,
2218
- ["LeftHand"]: parseLeftHand,
2219
- ["Nullish"]: parseNullish,
2220
- ["Percentage"]: parsePercentage,
2221
- ["Power"]: parsePower,
2222
- ["Symbol"]: parseSymbol,
2223
- ["Unary"]: parseUnary
2224
- };
2225
- //#endregion
2226
- //#region src/services/parser/parseMathExpressionRule.ts
2227
- const parseMathExpressionRule = (state, rule) => MathExpressionRuleParserMap[rule](state, parseMathExpressionRule);
2228
- //#endregion
2229
- //#region src/services/parser/parseMathExpression.ts
2230
- const parseMathExpression = (formula) => {
2231
- const state = {
2232
- depth: 0,
2233
- error: null,
2234
- index: 0,
2235
- nestingLevel: 0,
2236
- source: formula,
2237
- token: "",
2238
- tokenType: "null"
2239
- };
2240
- getMathExpressionToken(state);
2241
- const node = parseMathExpressionRule(state, "Assignment");
2242
- if (state.error === null && !checkIsToken(state, "")) failMathExpression(state, state.tokenType === "delimiter" ? `Unexpected operator ${state.token}` : `Unexpected part "${state.token}"`);
2243
- return state.error === null ? ok(node) : err(state.error);
2244
- };
2245
- //#endregion
2246
- export { ADDITIVE_NAMES, BERNOULLI_CLOSED_FORM_INDEX, DECIMAL_MARK_OPERATOR_FOLLOWERS, DELIMITERS_OF_ONE, DELIMITERS_OF_THREE, DELIMITERS_OF_TWO, EULER_MACLAURIN_COEFFICIENTS, FIRST_CHARACTERS_OF_THREE, FIRST_CHARACTERS_OF_TWO, HIGH_TAIL_COEFFICIENTS, LAST_FACTORIAL_ARGUMENT, LOW_TAIL_COEFFICIENTS, MATH_EXPRESSION_ABSOLUTE_TOLERANCE, MATH_EXPRESSION_RELATIVE_TOLERANCE, MAXIMUM_DIGITS, MAXIMUM_STIRLING_WORK, MAX_MATH_EXPRESSION_DEPTH, MILLER_RABIN_BASES, MathExpressionBinaryOperatorMap, MathExpressionBitwiseAbsorptionMap, MathExpressionConstantMap, MathExpressionError, MathExpressionFunctionMap, MathExpressionFunctionName, MathExpressionGrammarRule, MathExpressionLogicalOperator, MathExpressionNodeCompileMap, MathExpressionNodeType, MathExpressionOperatorMap, MathExpressionParameterType, MathExpressionRadixMap, MathExpressionRuleParserMap, MathExpressionTokenType, NAMED_DELIMITERS, NO_LOCALS, NO_VALUES, OVERFLOW_ARGUMENT, PLACEHOLDER, REFINEMENT_STEPS, SQRT_PI, STIRLING_TERMS, STIRLING_THRESHOLD, SUMMATION_LIMIT, WORD_CHARACTER_REGEX, WORD_START_REGEX, checkCanMathExpressionNest, checkIsDecimalMark, checkIsDigitCharacter, checkIsLarger, checkIsMatching, checkIsMatchingKind, checkIsMillerRabinPassing, checkIsNameToken, checkIsNearlyEqual, checkIsOperatorOperand, checkIsPercentageExpression, checkIsPrime, checkIsSignedNumber, checkIsSmaller, checkIsToken, checkIsTruthy, checkIsUnaryStart, checkIsWordCharacter, checkIsWordStartCharacter, collectMathExpressionAssignedNames, compareNumbers, compileArgument, compileAssignment, compileBinary, compileCall, compileComparison, compileConditional, compileGroup, compileList, compileListNode, compileLogical, compileMathExpression, compileMathExpressionNode, compileName, compileNumber, compilePercentage, compileUnary, computeBellNumber, computeBernoulliNumber, computeBitwiseAnd, computeBitwiseOr, computeCatalan, computeCombinations, computeComparison, computeCompositions, computeCorrelation, computeDeterminant, computeDistance, computeDotProduct, computeErf, computeErfInverse, computeExtreme, computeFactorial, computeGamma, computeGreatestCommonDivisor, computeHypotenuse, computeInitialGuess, computeIntegerGreatestCommonDivisor, computeInverseCoth, computeKullbackLeibler, computeLeastCommonMultiple, computeListComparison, computeLogGamma, computeLogGammaOfPositive, computeLogarithm, computeMean, computeMedian, computeMedianAbsoluteDeviation, computeModularInverse, computeModularPower, computeModulo, computeMultinomial, computeNorm, computeNthRoot, computeNumberLiteral, computePartitionSelect, computePermutations, computePointToLine2D, computePointToLine3D, computePolynomial, computeProduct, computeProductOfRange, computeQuantile, computeStirlingColumn, computeStirlingDiagonal, computeStirlingLogGamma, computeStirlingSecondKind, computeSum, computeSummedZeta, computeTruthyCount, computeVariance, computeVectorNorm, computeZeta, createBinaryNode, createBinaryOperation, createBinarySignatures, createBitwiseFold, createBitwisePair, createDigitSignatures, createExtremeSignatures, createIdentitySignatures, createIntegerBinarySignatures, createIntegerUnarySignatures, createListFirstCompute, createListPairCompute, createListPairSignature, createListSignature, createLogicalNode, createNonEmptyCompute, createNumberSignature, createNumericCompute, createOrderedListSignatures, createRangedSignatures, createSignature, createSingletonListSignature, createSpreadSignatures, createUnarySignatures, createVariadicSignatures, failExponent, failMathExpression, failMathExpressionAt, getArgumentCountText, getMathExpressionArityMessage, getMathExpressionCharacter, getMathExpressionChildren, getMathExpressionColumn, getMathExpressionConstant, getMathExpressionNames, getMathExpressionOuterValue, getMathExpressionParameterType, getMathExpressionScalarCompute, getMathExpressionSignatureError, getMathExpressionSignatures, getMathExpressionToken, getOwnValue, getParameterType, matchMathExpressionSignature, multiplyPair, parseArgument, parseAssignment, parseBinary, parseBinaryOperators, parseCall, parseConditional, parseDivisionBeforeProduct, parseImplicitProduct, parseLeftHand, parseList, parseMathExpression, parseMathExpressionRule, parseNullish, parsePercentage, parsePower, parseSequence, parseSymbol, parseUnary, readMathExpressionDelimiter, readMathExpressionNumber, readMathExpressionWord, readRadixNumber, roundToDigits, scaleList, shiftDecimalPlaces, skipMathExpressionSpaces, takeExponent, takeMathExpressionMatching, toNumber, walkNode };