@cortex-js/compute-engine 0.57.0 → 0.59.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/README.md +4 -0
- package/dist/compile.esm.js +2376 -501
- package/dist/compile.min.esm.js +316 -68
- package/dist/compile.min.umd.cjs +316 -68
- package/dist/compile.umd.cjs +2376 -501
- package/dist/compute-engine.esm.js +15717 -12444
- package/dist/compute-engine.min.esm.js +331 -83
- package/dist/compute-engine.min.umd.cjs +330 -82
- package/dist/compute-engine.umd.cjs +15717 -12444
- package/dist/core.esm.js +15716 -12443
- package/dist/core.min.esm.js +329 -81
- package/dist/core.min.umd.cjs +329 -81
- package/dist/core.umd.cjs +15716 -12443
- package/dist/identities.esm.js +1921 -0
- package/dist/identities.min.esm.js +2 -0
- package/dist/identities.min.umd.cjs +4 -0
- package/dist/identities.umd.cjs +1946 -0
- package/dist/interval.esm.js +779 -339
- package/dist/interval.min.esm.js +8 -8
- package/dist/interval.min.umd.cjs +8 -8
- package/dist/interval.umd.cjs +779 -339
- package/dist/latex-syntax.esm.js +971 -608
- package/dist/latex-syntax.min.esm.js +7 -7
- package/dist/latex-syntax.min.umd.cjs +7 -7
- package/dist/latex-syntax.umd.cjs +971 -608
- package/dist/math-json.esm.js +8 -12
- package/dist/math-json.min.esm.js +2 -2
- package/dist/math-json.min.umd.cjs +2 -2
- package/dist/math-json.umd.cjs +8 -12
- package/dist/numerics.esm.js +1382 -226
- package/dist/numerics.min.esm.js +16 -5
- package/dist/numerics.min.umd.cjs +16 -5
- package/dist/numerics.umd.cjs +1382 -226
- package/dist/types/big-decimal/big-decimal.d.ts +1 -1
- package/dist/types/big-decimal/index.d.ts +1 -1
- package/dist/types/big-decimal/transcendentals.d.ts +1 -1
- package/dist/types/big-decimal/utils.d.ts +1 -1
- package/dist/types/common/ansi-codes.d.ts +1 -1
- package/dist/types/common/configuration-change.d.ts +1 -1
- package/dist/types/common/fuzzy-string-match.d.ts +1 -1
- package/dist/types/common/grapheme-splitter.d.ts +1 -1
- package/dist/types/common/interruptible.d.ts +1 -1
- package/dist/types/common/one-of.d.ts +1 -1
- package/dist/types/common/signals.d.ts +1 -1
- package/dist/types/common/type/ast-nodes.d.ts +1 -1
- package/dist/types/common/type/boxed-type.d.ts +1 -1
- package/dist/types/common/type/lexer.d.ts +1 -1
- package/dist/types/common/type/parse.d.ts +1 -208
- package/dist/types/common/type/parser.d.ts +124 -2
- package/dist/types/common/type/primitive.d.ts +5 -1
- package/dist/types/common/type/reduce.d.ts +1 -1
- package/dist/types/common/type/serialize.d.ts +1 -1
- package/dist/types/common/type/subtype.d.ts +18 -1
- package/dist/types/common/type/type-builder.d.ts +1 -1
- package/dist/types/common/type/types.d.ts +1 -1
- package/dist/types/common/type/utils.d.ts +1 -1
- package/dist/types/common/utils.d.ts +1 -1
- package/dist/types/compile.d.ts +1 -1
- package/dist/types/compute-engine/assume.d.ts +13 -6
- package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +3 -1
- package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +7 -1
- package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +3 -3
- package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/constraint-subject.d.ts +140 -0
- package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +34 -12
- package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/rule-index.d.ts +112 -0
- package/dist/types/compute-engine/boxed-expression/rules.d.ts +2 -1
- package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
- package/dist/types/compute-engine/collection-utils.d.ts +1 -1
- package/dist/types/compute-engine/compilation/base-compiler.d.ts +8 -1
- package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
- package/dist/types/compute-engine/compilation/constant-folding.d.ts +16 -1
- package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/gpu-target.d.ts +58 -5
- package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +4 -4
- package/dist/types/compute-engine/compilation/javascript-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/types.d.ts +1 -1
- package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
- package/dist/types/compute-engine/cost-function.d.ts +1 -1
- package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
- package/dist/types/compute-engine/engine-cache.d.ts +1 -1
- package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
- package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
- package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
- package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
- package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
- package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
- package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
- package/dist/types/compute-engine/engine-runtime-state.d.ts +4 -1
- package/dist/types/compute-engine/engine-scope.d.ts +1 -1
- package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
- package/dist/types/compute-engine/engine-simplification-rules.d.ts +10 -2
- package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
- package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
- package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/free-functions.d.ts +1 -1
- package/dist/types/compute-engine/function-utils.d.ts +1 -1
- package/dist/types/compute-engine/fungrim/loader.d.ts +13 -0
- package/dist/types/compute-engine/fungrim/types.d.ts +160 -0
- package/dist/types/compute-engine/global-types.d.ts +1 -1
- package/dist/types/compute-engine/index.d.ts +63 -2
- package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
- package/dist/types/compute-engine/interval/elementary.d.ts +10 -2
- package/dist/types/compute-engine/interval/index.d.ts +2 -2
- package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
- package/dist/types/compute-engine/interval/types.d.ts +1 -1
- package/dist/types/compute-engine/interval/util.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +4 -1
- package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse.d.ts +3 -2
- package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -11
- package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/types.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/calculus.d.ts +1 -1
- package/dist/types/compute-engine/library/collections.d.ts +1 -1
- package/dist/types/compute-engine/library/colors.d.ts +1 -1
- package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
- package/dist/types/compute-engine/library/complex.d.ts +13 -1
- package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
- package/dist/types/compute-engine/library/core.d.ts +1 -1
- package/dist/types/compute-engine/library/fractals.d.ts +1 -1
- package/dist/types/compute-engine/library/library.d.ts +1 -1
- package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
- package/dist/types/compute-engine/library/logic.d.ts +1 -1
- package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
- package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
- package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
- package/dist/types/compute-engine/library/sets.d.ts +27 -1
- package/dist/types/compute-engine/library/statistics.d.ts +1 -1
- package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
- package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/library/units.d.ts +1 -1
- package/dist/types/compute-engine/library/utils.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +7 -1
- package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/bernoulli.d.ts +39 -0
- package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
- package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
- package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-complex.d.ts +12 -1
- package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
- package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
- package/dist/types/compute-engine/numerics/random.d.ts +23 -0
- package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
- package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
- package/dist/types/compute-engine/numerics/special-functions.d.ts +78 -10
- package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
- package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
- package/dist/types/compute-engine/numerics/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/oeis.d.ts +1 -1
- package/dist/types/compute-engine/sequence.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensors.d.ts +3 -3
- package/dist/types/compute-engine/types-definitions.d.ts +1 -1
- package/dist/types/compute-engine/types-engine.d.ts +52 -3
- package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-expression.d.ts +85 -14
- package/dist/types/compute-engine/types-kernel-evaluation.d.ts +32 -1
- package/dist/types/compute-engine/types-kernel-serialization.d.ts +45 -3
- package/dist/types/compute-engine/types-serialization.d.ts +1 -1
- package/dist/types/compute-engine/types.d.ts +1 -1
- package/dist/types/compute-engine.d.ts +1 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/identities.d.ts +3 -0
- package/dist/types/interval.d.ts +1 -1
- package/dist/types/latex-syntax.d.ts +2 -2
- package/dist/types/math-json/symbols.d.ts +1 -1
- package/dist/types/math-json/types.d.ts +1 -1
- package/dist/types/math-json/utils.d.ts +1 -1
- package/dist/types/math-json.d.ts +2 -2
- package/dist/types/numerics.d.ts +1 -1
- package/package.json +9 -3
package/dist/compile.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compile 0.
|
|
1
|
+
/** Compile 0.59.0 */
|
|
2
2
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Compile = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var Compile = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -192,6 +192,7 @@ var Compile = (() => {
|
|
|
192
192
|
return sum;
|
|
193
193
|
}
|
|
194
194
|
function fpln(x, scale) {
|
|
195
|
+
if (x <= 0n) throw new RangeError("fpln: input must be positive");
|
|
195
196
|
if (x === scale) return 0n;
|
|
196
197
|
const xNum = Number(x);
|
|
197
198
|
const scaleNum = Number(scale);
|
|
@@ -841,9 +842,11 @@ var Compile = (() => {
|
|
|
841
842
|
if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) {
|
|
842
843
|
if (other.significand === 0n) return _BigDecimal.NAN;
|
|
843
844
|
if (this.significand === 0n) return fromRaw(0n, 0);
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
);
|
|
845
|
+
const ediff = thisExp - otherExp;
|
|
846
|
+
const num = ediff >= 0 ? this.significand * pow10(ediff) : this.significand;
|
|
847
|
+
const den = ediff >= 0 ? other.significand : other.significand * pow10(-ediff);
|
|
848
|
+
const q = num / den;
|
|
849
|
+
return this.sub(fromRaw(q, 0).mul(other));
|
|
847
850
|
}
|
|
848
851
|
if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN;
|
|
849
852
|
if (!Number.isFinite(thisExp)) return _BigDecimal.NAN;
|
|
@@ -888,7 +891,10 @@ var Compile = (() => {
|
|
|
888
891
|
return this.pow(n.neg()).inv();
|
|
889
892
|
}
|
|
890
893
|
const absSig = this.significand < 0n ? -this.significand : this.significand;
|
|
891
|
-
const
|
|
894
|
+
const sigDigits = bigintDigits(absSig);
|
|
895
|
+
const dropped = sigDigits > 15 ? sigDigits - 15 : 0;
|
|
896
|
+
const lead = dropped > 0 ? Number(absSig / 10n ** BigInt(dropped)) : Number(absSig);
|
|
897
|
+
const thisLog10 = Math.log10(lead) + dropped + this.exponent;
|
|
892
898
|
const resultLog10 = Number(expValue) * thisLog10;
|
|
893
899
|
if (resultLog10 > 9e15) {
|
|
894
900
|
return this.significand < 0n && expValue % 2n !== 0n ? _BigDecimal.NEGATIVE_INFINITY : _BigDecimal.POSITIVE_INFINITY;
|
|
@@ -921,7 +927,19 @@ var Compile = (() => {
|
|
|
921
927
|
return _BigDecimal.POSITIVE_INFINITY;
|
|
922
928
|
}
|
|
923
929
|
if (this.significand < 0n) return _BigDecimal.NAN;
|
|
924
|
-
|
|
930
|
+
const baseSig = this.significand;
|
|
931
|
+
const decExpBase = this.exponent + bigintDigits(baseSig) - 1;
|
|
932
|
+
const nSig = n.significand < 0n ? -n.significand : n.significand;
|
|
933
|
+
const decExpN = n.exponent + bigintDigits(nSig) - 1;
|
|
934
|
+
const argMag = decExpN + Math.log10(Math.abs(decExpBase) * 2.303 + 3) + 1;
|
|
935
|
+
const extra = Math.min(20, Math.max(2, Math.ceil(argMag) + 2));
|
|
936
|
+
const savedPrec = _BigDecimal.precision;
|
|
937
|
+
_BigDecimal.precision = savedPrec + extra;
|
|
938
|
+
try {
|
|
939
|
+
return n.mul(this.ln()).exp().toPrecision(savedPrec);
|
|
940
|
+
} finally {
|
|
941
|
+
_BigDecimal.precision = savedPrec;
|
|
942
|
+
}
|
|
925
943
|
}
|
|
926
944
|
// ---------- Conversion methods ----------
|
|
927
945
|
/** Convert to a JavaScript number. May lose precision for large values. */
|
|
@@ -1162,6 +1180,20 @@ var Compile = (() => {
|
|
|
1162
1180
|
const sig = negative ? -absFp : absFp;
|
|
1163
1181
|
return fromRaw(sig, resultExp);
|
|
1164
1182
|
}
|
|
1183
|
+
function decimalExponent(x) {
|
|
1184
|
+
const sig = x.significand < 0n ? -x.significand : x.significand;
|
|
1185
|
+
return x.exponent + bigintDigits(sig) - 1;
|
|
1186
|
+
}
|
|
1187
|
+
var MAX_SAFE_EXPONENT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1188
|
+
var _ln10Fp = null;
|
|
1189
|
+
var _ln10Scale = null;
|
|
1190
|
+
function ln10Fixed(scale) {
|
|
1191
|
+
if (_ln10Scale !== scale) {
|
|
1192
|
+
_ln10Fp = fpln(10n * scale, scale);
|
|
1193
|
+
_ln10Scale = scale;
|
|
1194
|
+
}
|
|
1195
|
+
return _ln10Fp;
|
|
1196
|
+
}
|
|
1165
1197
|
BigDecimal.prototype.sqrt = function() {
|
|
1166
1198
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
1167
1199
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
@@ -1172,9 +1204,13 @@ var Compile = (() => {
|
|
|
1172
1204
|
if (this.significand < 0n) return BigDecimal.NAN;
|
|
1173
1205
|
const targetPrec = BigDecimal.precision;
|
|
1174
1206
|
const workingPrec = targetPrec + 10;
|
|
1175
|
-
const
|
|
1207
|
+
const e = decimalExponent(this);
|
|
1208
|
+
const k = Math.floor(e / 2);
|
|
1209
|
+
const m = fromRaw(this.significand, this.exponent - 2 * k);
|
|
1210
|
+
const [fp, scale] = toFixedPoint(m, workingPrec);
|
|
1176
1211
|
const sqrtFp = fpsqrt(fp, scale);
|
|
1177
|
-
|
|
1212
|
+
const root = fromFixedPoint(sqrtFp, scale, targetPrec);
|
|
1213
|
+
return fromRaw(root.significand, root.exponent + k);
|
|
1178
1214
|
};
|
|
1179
1215
|
BigDecimal.prototype.cbrt = function() {
|
|
1180
1216
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
@@ -1188,10 +1224,13 @@ var Compile = (() => {
|
|
|
1188
1224
|
}
|
|
1189
1225
|
const targetPrec = BigDecimal.precision;
|
|
1190
1226
|
const workingPrec = targetPrec + 10;
|
|
1191
|
-
const
|
|
1227
|
+
const e = decimalExponent(this);
|
|
1228
|
+
const k = Math.floor(e / 3);
|
|
1229
|
+
const m = fromRaw(this.significand, this.exponent - 3 * k);
|
|
1230
|
+
const [fp, scale] = toFixedPoint(m, workingPrec);
|
|
1192
1231
|
const C = fp * scale * scale;
|
|
1193
1232
|
let x;
|
|
1194
|
-
const numVal =
|
|
1233
|
+
const numVal = m.toNumber();
|
|
1195
1234
|
const scaleNum = Number(scale);
|
|
1196
1235
|
if (Number.isFinite(numVal) && numVal > 0 && Number.isFinite(scaleNum)) {
|
|
1197
1236
|
const approx = Math.cbrt(numVal);
|
|
@@ -1220,7 +1259,8 @@ var Compile = (() => {
|
|
|
1220
1259
|
const diffNext = bigintAbs(next * next * next - C);
|
|
1221
1260
|
if (diffNext < diffX) x = next;
|
|
1222
1261
|
}
|
|
1223
|
-
|
|
1262
|
+
const root = fromFixedPoint(x, scale, targetPrec);
|
|
1263
|
+
return fromRaw(root.significand, root.exponent + k);
|
|
1224
1264
|
};
|
|
1225
1265
|
BigDecimal.sqrt = function(x) {
|
|
1226
1266
|
return x.sqrt();
|
|
@@ -1235,11 +1275,27 @@ var Compile = (() => {
|
|
|
1235
1275
|
return BigDecimal.ZERO;
|
|
1236
1276
|
}
|
|
1237
1277
|
if (this.isZero()) return BigDecimal.ONE;
|
|
1278
|
+
if (decimalExponent(this) >= 17)
|
|
1279
|
+
return this.significand > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1238
1280
|
const targetPrec = BigDecimal.precision;
|
|
1239
|
-
const
|
|
1240
|
-
const
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1281
|
+
const absSig = this.significand < 0n ? -this.significand : this.significand;
|
|
1282
|
+
const magnitude = Math.max(0, this.exponent + bigintDigits(absSig));
|
|
1283
|
+
const workingPrec = targetPrec + 20 + magnitude;
|
|
1284
|
+
const [xFp, scale] = toFixedPoint(this, workingPrec);
|
|
1285
|
+
const l10 = ln10Fixed(scale);
|
|
1286
|
+
let k = xFp / l10;
|
|
1287
|
+
let rFp = xFp - k * l10;
|
|
1288
|
+
if (rFp < 0n) {
|
|
1289
|
+
k -= 1n;
|
|
1290
|
+
rFp += l10;
|
|
1291
|
+
}
|
|
1292
|
+
if (k > MAX_SAFE_EXPONENT || k < -MAX_SAFE_EXPONENT)
|
|
1293
|
+
return k > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1294
|
+
const expR = fromFixedPoint(fpexp(rFp, scale), scale, targetPrec);
|
|
1295
|
+
const newExp = expR.exponent + Number(k);
|
|
1296
|
+
if (!Number.isSafeInteger(newExp))
|
|
1297
|
+
return k > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1298
|
+
return fromRaw(expR.significand, newExp);
|
|
1243
1299
|
};
|
|
1244
1300
|
BigDecimal.prototype.ln = function() {
|
|
1245
1301
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
@@ -1251,10 +1307,16 @@ var Compile = (() => {
|
|
|
1251
1307
|
if (this.significand < 0n) return BigDecimal.NAN;
|
|
1252
1308
|
if (this.eq(1)) return BigDecimal.ZERO;
|
|
1253
1309
|
const targetPrec = BigDecimal.precision;
|
|
1254
|
-
const
|
|
1255
|
-
const
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1310
|
+
const sig = this.significand;
|
|
1311
|
+
const digits = bigintDigits(sig);
|
|
1312
|
+
const e = this.exponent + digits - 1;
|
|
1313
|
+
const m = fromRaw(sig, -(digits - 1));
|
|
1314
|
+
const eDigits = Math.abs(e).toString().length;
|
|
1315
|
+
const workingPrec = targetPrec + 20 + eDigits;
|
|
1316
|
+
const [mFp, scale] = toFixedPoint(m, workingPrec);
|
|
1317
|
+
const l10 = ln10Fixed(scale);
|
|
1318
|
+
const resultFp = fpln(mFp, scale) + BigInt(e) * l10;
|
|
1319
|
+
return fromFixedPoint(resultFp, scale, targetPrec);
|
|
1258
1320
|
};
|
|
1259
1321
|
BigDecimal.prototype.log = function(base) {
|
|
1260
1322
|
const b = base instanceof BigDecimal ? base : new BigDecimal(base);
|
|
@@ -1274,7 +1336,10 @@ var Compile = (() => {
|
|
|
1274
1336
|
if (!this.isFinite()) return BigDecimal.NAN;
|
|
1275
1337
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
1276
1338
|
const targetPrec = BigDecimal.precision;
|
|
1277
|
-
const
|
|
1339
|
+
const e = decimalExponent(this);
|
|
1340
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1341
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1342
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1278
1343
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1279
1344
|
const [sinFp] = fpsincos(fp, scale);
|
|
1280
1345
|
return fromFixedPoint(sinFp, scale, targetPrec);
|
|
@@ -1285,6 +1350,8 @@ var Compile = (() => {
|
|
|
1285
1350
|
if (this.isZero()) return BigDecimal.ONE;
|
|
1286
1351
|
const targetPrec = BigDecimal.precision;
|
|
1287
1352
|
const workingPrec = targetPrec + 15;
|
|
1353
|
+
const e = decimalExponent(this);
|
|
1354
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1288
1355
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1289
1356
|
const [, cosFp] = fpsincos(fp, scale);
|
|
1290
1357
|
return fromFixedPoint(cosFp, scale, targetPrec);
|
|
@@ -1294,7 +1361,10 @@ var Compile = (() => {
|
|
|
1294
1361
|
if (!this.isFinite()) return BigDecimal.NAN;
|
|
1295
1362
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
1296
1363
|
const targetPrec = BigDecimal.precision;
|
|
1297
|
-
const
|
|
1364
|
+
const e = decimalExponent(this);
|
|
1365
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1366
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1367
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1298
1368
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1299
1369
|
const [sinFp, cosFp] = fpsincos(fp, scale);
|
|
1300
1370
|
if (cosFp === 0n) {
|
|
@@ -1312,7 +1382,9 @@ var Compile = (() => {
|
|
|
1312
1382
|
return piHalf.neg();
|
|
1313
1383
|
}
|
|
1314
1384
|
const targetPrec = BigDecimal.precision;
|
|
1315
|
-
const
|
|
1385
|
+
const e = decimalExponent(this);
|
|
1386
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1387
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1316
1388
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1317
1389
|
const atanFp = fpatan(fp, scale);
|
|
1318
1390
|
return fromFixedPoint(atanFp, scale, targetPrec);
|
|
@@ -1329,7 +1401,9 @@ var Compile = (() => {
|
|
|
1329
1401
|
return this.significand > 0n ? piHalf : piHalf.neg();
|
|
1330
1402
|
}
|
|
1331
1403
|
const targetPrec = BigDecimal.precision;
|
|
1332
|
-
const
|
|
1404
|
+
const e = decimalExponent(this);
|
|
1405
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1406
|
+
const workingPrec = targetPrec + 20 + (e < 0 ? -e : 0);
|
|
1333
1407
|
const [xFp, scale] = toFixedPoint(this, workingPrec);
|
|
1334
1408
|
const x2 = fpmul(xFp, xFp, scale);
|
|
1335
1409
|
const oneMinusX2 = scale - x2;
|
|
@@ -1392,6 +1466,23 @@ var Compile = (() => {
|
|
|
1392
1466
|
if (this.significand > 0n) return BigDecimal.POSITIVE_INFINITY;
|
|
1393
1467
|
return BigDecimal.NEGATIVE_INFINITY;
|
|
1394
1468
|
}
|
|
1469
|
+
const targetPrec = BigDecimal.precision;
|
|
1470
|
+
const e = decimalExponent(this);
|
|
1471
|
+
if (e < 0) {
|
|
1472
|
+
if (-2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1473
|
+
const saved = BigDecimal.precision;
|
|
1474
|
+
BigDecimal.precision = targetPrec - e + 5;
|
|
1475
|
+
try {
|
|
1476
|
+
const expX2 = this.exp();
|
|
1477
|
+
return expX2.sub(expX2.inv()).div(BigDecimal.TWO).toPrecision(targetPrec);
|
|
1478
|
+
} finally {
|
|
1479
|
+
BigDecimal.precision = saved;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3)) {
|
|
1483
|
+
const h = this.abs().exp().div(BigDecimal.TWO);
|
|
1484
|
+
return this.significand > 0n ? h : h.neg();
|
|
1485
|
+
}
|
|
1395
1486
|
const expX = this.exp();
|
|
1396
1487
|
const expNegX = expX.inv();
|
|
1397
1488
|
return expX.sub(expNegX).div(BigDecimal.TWO);
|
|
@@ -1402,6 +1493,9 @@ var Compile = (() => {
|
|
|
1402
1493
|
if (!this.isFinite()) {
|
|
1403
1494
|
return BigDecimal.POSITIVE_INFINITY;
|
|
1404
1495
|
}
|
|
1496
|
+
const targetPrec = BigDecimal.precision;
|
|
1497
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3))
|
|
1498
|
+
return this.abs().exp().div(BigDecimal.TWO);
|
|
1405
1499
|
const expX = this.exp();
|
|
1406
1500
|
const expNegX = expX.inv();
|
|
1407
1501
|
return expX.add(expNegX).div(BigDecimal.TWO);
|
|
@@ -1413,6 +1507,21 @@ var Compile = (() => {
|
|
|
1413
1507
|
if (this.significand > 0n) return BigDecimal.ONE;
|
|
1414
1508
|
return BigDecimal.NEGATIVE_ONE;
|
|
1415
1509
|
}
|
|
1510
|
+
const targetPrec = BigDecimal.precision;
|
|
1511
|
+
const e = decimalExponent(this);
|
|
1512
|
+
if (e < 0) {
|
|
1513
|
+
if (-2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1514
|
+
const saved = BigDecimal.precision;
|
|
1515
|
+
BigDecimal.precision = targetPrec - e + 5;
|
|
1516
|
+
try {
|
|
1517
|
+
const exp2x2 = this.mul(BigDecimal.TWO).exp();
|
|
1518
|
+
return exp2x2.sub(BigDecimal.ONE).div(exp2x2.add(BigDecimal.ONE)).toPrecision(targetPrec);
|
|
1519
|
+
} finally {
|
|
1520
|
+
BigDecimal.precision = saved;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3))
|
|
1524
|
+
return this.significand > 0n ? BigDecimal.ONE : BigDecimal.NEGATIVE_ONE;
|
|
1416
1525
|
const exp2x = this.mul(BigDecimal.TWO).exp();
|
|
1417
1526
|
return exp2x.sub(BigDecimal.ONE).div(exp2x.add(BigDecimal.ONE));
|
|
1418
1527
|
};
|
|
@@ -1461,6 +1570,7 @@ var Compile = (() => {
|
|
|
1461
1570
|
Math.log10(Math.pow(2, MACHINE_PRECISION_BITS))
|
|
1462
1571
|
);
|
|
1463
1572
|
var DEFAULT_TOLERANCE = 1e-10;
|
|
1573
|
+
var SMALL_INTEGER = 1e6;
|
|
1464
1574
|
var MAX_ITERATION = 1e4;
|
|
1465
1575
|
function gcd(a, b) {
|
|
1466
1576
|
if (a === 0) return b;
|
|
@@ -1472,7 +1582,8 @@ var Compile = (() => {
|
|
|
1472
1582
|
}
|
|
1473
1583
|
function lcm(a, b) {
|
|
1474
1584
|
if (a === 0 || b === 0) return 0;
|
|
1475
|
-
|
|
1585
|
+
let res = BigInt(a) * BigInt(b) / BigInt(gcd(a, b));
|
|
1586
|
+
if (res < 0n) res = -res;
|
|
1476
1587
|
return Number(res);
|
|
1477
1588
|
}
|
|
1478
1589
|
function factorial(n) {
|
|
@@ -1562,216 +1673,27 @@ var Compile = (() => {
|
|
|
1562
1673
|
"error",
|
|
1563
1674
|
...EXPRESSION_TYPES
|
|
1564
1675
|
];
|
|
1676
|
+
var NUMERIC_TYPES_SET = new Set(
|
|
1677
|
+
NUMERIC_TYPES
|
|
1678
|
+
);
|
|
1679
|
+
var COLLECTION_TYPES_SET = new Set(
|
|
1680
|
+
COLLECTION_TYPES
|
|
1681
|
+
);
|
|
1682
|
+
var SCALAR_TYPES_SET = new Set(
|
|
1683
|
+
SCALAR_TYPES
|
|
1684
|
+
);
|
|
1685
|
+
var PRIMITIVE_TYPES_SET = new Set(
|
|
1686
|
+
PRIMITIVE_TYPES
|
|
1687
|
+
);
|
|
1688
|
+
function isValidPrimitiveType(s) {
|
|
1689
|
+
if (typeof s !== "string") return false;
|
|
1690
|
+
return PRIMITIVE_TYPES_SET.has(s);
|
|
1691
|
+
}
|
|
1565
1692
|
function isValidType(t) {
|
|
1566
|
-
if (typeof t === "string")
|
|
1567
|
-
return PRIMITIVE_TYPES.includes(t);
|
|
1693
|
+
if (typeof t === "string") return PRIMITIVE_TYPES_SET.has(t);
|
|
1568
1694
|
if (typeof t !== "object") return false;
|
|
1569
1695
|
if (!("kind" in t)) return false;
|
|
1570
|
-
return t.kind === "signature" || t.kind === "union" || t.kind === "intersection" || t.kind === "negation" || t.kind === "tuple" || t.kind === "list" || t.kind === "record" || t.kind === "dictionary" || t.kind === "set" || t.kind === "
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
// src/common/type/serialize.ts
|
|
1574
|
-
var NEGATION_PRECEDENCE = 3;
|
|
1575
|
-
var UNION_PRECEDENCE = 1;
|
|
1576
|
-
var INTERSECTION_PRECEDENCE = 2;
|
|
1577
|
-
var LIST_PRECEDENCE = 4;
|
|
1578
|
-
var RECORD_PRECEDENCE = 5;
|
|
1579
|
-
var DICTIONARY_PRECEDENCE = 6;
|
|
1580
|
-
var SET_PRECEDENCE = 7;
|
|
1581
|
-
var COLLECTION_PRECEDENCE = 8;
|
|
1582
|
-
var TUPLE_PRECEDENCE = 9;
|
|
1583
|
-
var SIGNATURE_PRECEDENCE = 10;
|
|
1584
|
-
var VALUE_PRECEDENCE = 11;
|
|
1585
|
-
function typeToString(type, precedence = 0) {
|
|
1586
|
-
if (typeof type === "string") return type;
|
|
1587
|
-
let result = "";
|
|
1588
|
-
switch (type.kind) {
|
|
1589
|
-
case "value":
|
|
1590
|
-
if (typeof type.value === "string") result = `"${type.value}"`;
|
|
1591
|
-
else if (typeof type.value === "boolean")
|
|
1592
|
-
result = type.value ? "true" : "false";
|
|
1593
|
-
else result = type.value.toString();
|
|
1594
|
-
break;
|
|
1595
|
-
case "reference":
|
|
1596
|
-
result = type.name;
|
|
1597
|
-
break;
|
|
1598
|
-
case "negation":
|
|
1599
|
-
result = `!${typeToString(type.type, NEGATION_PRECEDENCE)}`;
|
|
1600
|
-
break;
|
|
1601
|
-
case "union":
|
|
1602
|
-
result = type.types.map((t) => typeToString(t, UNION_PRECEDENCE)).join(" | ");
|
|
1603
|
-
break;
|
|
1604
|
-
case "intersection":
|
|
1605
|
-
result = type.types.map((t) => typeToString(t, INTERSECTION_PRECEDENCE)).join(" & ");
|
|
1606
|
-
break;
|
|
1607
|
-
case "expression":
|
|
1608
|
-
result = `expression<${symbolName(type.operator)}>`;
|
|
1609
|
-
break;
|
|
1610
|
-
case "symbol":
|
|
1611
|
-
result = `symbol<${symbolName(type.name)}>`;
|
|
1612
|
-
break;
|
|
1613
|
-
case "numeric":
|
|
1614
|
-
if (Number.isFinite(type.lower) && Number.isFinite(type.upper)) {
|
|
1615
|
-
result = `${type.type}<${type.lower}..${type.upper}>`;
|
|
1616
|
-
} else if (Number.isFinite(type.lower)) {
|
|
1617
|
-
result = `${type.type}<${type.lower}..>`;
|
|
1618
|
-
} else if (Number.isFinite(type.upper)) {
|
|
1619
|
-
result = `${type.type}<..${type.upper}>`;
|
|
1620
|
-
} else {
|
|
1621
|
-
result = `${type.type}`;
|
|
1622
|
-
}
|
|
1623
|
-
break;
|
|
1624
|
-
case "list":
|
|
1625
|
-
if (type.dimensions && typeof type.elements === "string" && NUMERIC_TYPES.includes(type.elements)) {
|
|
1626
|
-
if (type.dimensions === void 0) {
|
|
1627
|
-
if (type.elements === "number") result = "tensor";
|
|
1628
|
-
} else if (type.dimensions.length === 1) {
|
|
1629
|
-
if (type.elements === "number") {
|
|
1630
|
-
if (type.dimensions[0] < 0) result = "vector";
|
|
1631
|
-
else result = `vector<${type.dimensions[0]}>`;
|
|
1632
|
-
} else {
|
|
1633
|
-
if (type.dimensions[0] < 0)
|
|
1634
|
-
result = `vector<${typeToString(type.elements)}>`;
|
|
1635
|
-
else
|
|
1636
|
-
result = `vector<${typeToString(type.elements)}^${type.dimensions[0]}>`;
|
|
1637
|
-
}
|
|
1638
|
-
} else if (type.dimensions.length === 2) {
|
|
1639
|
-
const dims = type.dimensions;
|
|
1640
|
-
if (type.elements === "number") {
|
|
1641
|
-
if (dims[0] < 0 && dims[1] < 0) result = "matrix";
|
|
1642
|
-
else result = `matrix<${dims[0]}x${dims[1]}>`;
|
|
1643
|
-
} else {
|
|
1644
|
-
if (dims[0] < 0 && dims[1] < 0)
|
|
1645
|
-
result = `matrix<${typeToString(type.elements)}>`;
|
|
1646
|
-
else
|
|
1647
|
-
result = `matrix<${typeToString(type.elements)}^(${dims[0]}x${dims[1]})>`;
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
if (!result) {
|
|
1652
|
-
const dimensions = type.dimensions ? type.dimensions.length === 1 ? `^${type.dimensions[0].toString()}` : `^(${type.dimensions.join("x")})` : "";
|
|
1653
|
-
result = `list<${typeToString(type.elements)}${dimensions}>`;
|
|
1654
|
-
}
|
|
1655
|
-
break;
|
|
1656
|
-
case "record":
|
|
1657
|
-
const elements = Object.entries(type.elements).map(([key, value]) => `${key}: ${typeToString(value)}`).join(", ");
|
|
1658
|
-
result = `record<${elements}>`;
|
|
1659
|
-
break;
|
|
1660
|
-
case "dictionary":
|
|
1661
|
-
result = `dictionary<${typeToString(type.values)}>`;
|
|
1662
|
-
break;
|
|
1663
|
-
case "set":
|
|
1664
|
-
result = `set<${typeToString(type.elements)}>`;
|
|
1665
|
-
break;
|
|
1666
|
-
case "collection":
|
|
1667
|
-
result = `collection<${typeToString(type.elements)}>`;
|
|
1668
|
-
break;
|
|
1669
|
-
case "indexed_collection":
|
|
1670
|
-
result = `indexed_collection<${typeToString(type.elements)}>`;
|
|
1671
|
-
break;
|
|
1672
|
-
case "tuple":
|
|
1673
|
-
if (type.elements.length === 0) result = "tuple";
|
|
1674
|
-
else if (type.elements.length === 1) {
|
|
1675
|
-
const [el] = type.elements;
|
|
1676
|
-
result = `tuple<${namedElement(el)}>`;
|
|
1677
|
-
} else {
|
|
1678
|
-
result = "tuple<" + type.elements.map((el) => namedElement(el)).join(", ") + ">";
|
|
1679
|
-
}
|
|
1680
|
-
break;
|
|
1681
|
-
case "signature":
|
|
1682
|
-
const args = type.args ? type.args.map((arg) => namedElement(arg)).join(", ") : "";
|
|
1683
|
-
const optArgs = type.optArgs ? type.optArgs.map((arg) => namedElement(arg) + "?").join(", ") : "";
|
|
1684
|
-
const varArg = type.variadicArg ? type.variadicMin === 0 ? `${namedElement(type.variadicArg)}*` : `${namedElement(type.variadicArg)}+` : "";
|
|
1685
|
-
const argsList = [args, optArgs, varArg].filter((s) => s).join(", ");
|
|
1686
|
-
result = `(${argsList}) -> ${typeToString(type.result)}`;
|
|
1687
|
-
break;
|
|
1688
|
-
default:
|
|
1689
|
-
result = "error";
|
|
1690
|
-
}
|
|
1691
|
-
if (precedence > 0 && precedence > getPrecedence(type.kind))
|
|
1692
|
-
return `(${result})`;
|
|
1693
|
-
return result;
|
|
1694
|
-
}
|
|
1695
|
-
function namedElement(el) {
|
|
1696
|
-
if (el.name) return `${el.name}: ${typeToString(el.type)}`;
|
|
1697
|
-
return typeToString(el.type);
|
|
1698
|
-
}
|
|
1699
|
-
function symbolName(name) {
|
|
1700
|
-
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) return name;
|
|
1701
|
-
return `\`${name}\``;
|
|
1702
|
-
}
|
|
1703
|
-
function getPrecedence(kind) {
|
|
1704
|
-
switch (kind) {
|
|
1705
|
-
case "negation":
|
|
1706
|
-
return NEGATION_PRECEDENCE;
|
|
1707
|
-
case "union":
|
|
1708
|
-
return UNION_PRECEDENCE;
|
|
1709
|
-
case "intersection":
|
|
1710
|
-
return INTERSECTION_PRECEDENCE;
|
|
1711
|
-
case "list":
|
|
1712
|
-
return LIST_PRECEDENCE;
|
|
1713
|
-
case "record":
|
|
1714
|
-
return RECORD_PRECEDENCE;
|
|
1715
|
-
case "dictionary":
|
|
1716
|
-
return DICTIONARY_PRECEDENCE;
|
|
1717
|
-
case "set":
|
|
1718
|
-
return SET_PRECEDENCE;
|
|
1719
|
-
case "collection":
|
|
1720
|
-
case "indexed_collection":
|
|
1721
|
-
return COLLECTION_PRECEDENCE;
|
|
1722
|
-
case "tuple":
|
|
1723
|
-
return TUPLE_PRECEDENCE;
|
|
1724
|
-
case "signature":
|
|
1725
|
-
return SIGNATURE_PRECEDENCE;
|
|
1726
|
-
case "value":
|
|
1727
|
-
return VALUE_PRECEDENCE;
|
|
1728
|
-
default:
|
|
1729
|
-
return 0;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
|
|
1733
|
-
// src/common/fuzzy-string-match.ts
|
|
1734
|
-
function levenshtein(source, target) {
|
|
1735
|
-
if (source === target) return 0;
|
|
1736
|
-
if (source.length === 0) return target.length;
|
|
1737
|
-
if (target.length === 0) return source.length;
|
|
1738
|
-
let prevRow = Array.from(
|
|
1739
|
-
{ length: source.length + 1 },
|
|
1740
|
-
(_, j) => j
|
|
1741
|
-
);
|
|
1742
|
-
let currRow = new Array(source.length + 1);
|
|
1743
|
-
for (let i = 1; i <= target.length; i++) {
|
|
1744
|
-
currRow[0] = i;
|
|
1745
|
-
for (let j = 1; j <= source.length; j++) {
|
|
1746
|
-
const cost = source[j - 1] === target[i - 1] ? 0 : 1;
|
|
1747
|
-
currRow[j] = Math.min(
|
|
1748
|
-
prevRow[j] + 1,
|
|
1749
|
-
// deletion
|
|
1750
|
-
currRow[j - 1] + 1,
|
|
1751
|
-
// insertion
|
|
1752
|
-
prevRow[j - 1] + cost
|
|
1753
|
-
// substitution
|
|
1754
|
-
);
|
|
1755
|
-
}
|
|
1756
|
-
[prevRow, currRow] = [currRow, prevRow];
|
|
1757
|
-
}
|
|
1758
|
-
return prevRow[source.length];
|
|
1759
|
-
}
|
|
1760
|
-
function fuzzyStringMatch(invalidWord, validWords) {
|
|
1761
|
-
const threshold = 7;
|
|
1762
|
-
let bestMatch = null;
|
|
1763
|
-
let minDistance = Infinity;
|
|
1764
|
-
const invalidLength = invalidWord.length;
|
|
1765
|
-
for (const word of validWords) {
|
|
1766
|
-
if (Math.abs(invalidLength - word.length) > threshold) continue;
|
|
1767
|
-
const distance = levenshtein(invalidWord, word);
|
|
1768
|
-
if (distance === 0) return word;
|
|
1769
|
-
if (distance <= threshold && distance < minDistance) {
|
|
1770
|
-
minDistance = distance;
|
|
1771
|
-
bestMatch = word;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
return bestMatch;
|
|
1696
|
+
return t.kind === "signature" || t.kind === "union" || t.kind === "intersection" || t.kind === "negation" || t.kind === "value" || t.kind === "tuple" || t.kind === "list" || t.kind === "record" || t.kind === "dictionary" || t.kind === "set" || t.kind === "symbol" || t.kind === "expression" || t.kind === "numeric" || t.kind === "collection" || t.kind === "indexed_collection" || t.kind === "reference";
|
|
1775
1697
|
}
|
|
1776
1698
|
|
|
1777
1699
|
// src/common/type/lexer.ts
|
|
@@ -2481,19 +2403,13 @@ var Compile = (() => {
|
|
|
2481
2403
|
);
|
|
2482
2404
|
let dimensions;
|
|
2483
2405
|
if (this.match("<")) {
|
|
2484
|
-
dimensions = this.
|
|
2485
|
-
if (!dimensions) {
|
|
2486
|
-
dimensions = this.parseDimensions();
|
|
2487
|
-
}
|
|
2406
|
+
dimensions = this.parseDimensions();
|
|
2488
2407
|
if (!dimensions) {
|
|
2489
2408
|
const type = this.parseUnionType();
|
|
2490
2409
|
if (type) {
|
|
2491
2410
|
elementType = type;
|
|
2492
2411
|
if (this.match("^")) {
|
|
2493
|
-
dimensions = this.
|
|
2494
|
-
if (!dimensions) {
|
|
2495
|
-
dimensions = this.parseDimensions();
|
|
2496
|
-
}
|
|
2412
|
+
dimensions = this.parseCaretDimensions();
|
|
2497
2413
|
}
|
|
2498
2414
|
}
|
|
2499
2415
|
}
|
|
@@ -2534,19 +2450,13 @@ var Compile = (() => {
|
|
|
2534
2450
|
);
|
|
2535
2451
|
let dimensions;
|
|
2536
2452
|
if (this.match("<")) {
|
|
2537
|
-
dimensions = this.
|
|
2538
|
-
if (!dimensions) {
|
|
2539
|
-
dimensions = this.parseDimensions();
|
|
2540
|
-
}
|
|
2453
|
+
dimensions = this.parseDimensions();
|
|
2541
2454
|
if (!dimensions) {
|
|
2542
2455
|
const type = this.parseUnionType();
|
|
2543
2456
|
if (type) {
|
|
2544
2457
|
elementType = type;
|
|
2545
2458
|
if (this.match("^")) {
|
|
2546
|
-
dimensions = this.
|
|
2547
|
-
if (!dimensions) {
|
|
2548
|
-
dimensions = this.parseDimensions();
|
|
2549
|
-
}
|
|
2459
|
+
dimensions = this.parseCaretDimensions();
|
|
2550
2460
|
}
|
|
2551
2461
|
}
|
|
2552
2462
|
}
|
|
@@ -2577,16 +2487,30 @@ var Compile = (() => {
|
|
|
2577
2487
|
return this.createNode("tensor", { elementType });
|
|
2578
2488
|
}
|
|
2579
2489
|
parseDimensions() {
|
|
2580
|
-
const dimensions = [];
|
|
2581
2490
|
const firstDim = this.parseDimension();
|
|
2582
2491
|
if (!firstDim) return void 0;
|
|
2583
|
-
dimensions
|
|
2584
|
-
|
|
2585
|
-
const
|
|
2586
|
-
if (
|
|
2587
|
-
this.
|
|
2492
|
+
const dimensions = [firstDim];
|
|
2493
|
+
for (; ; ) {
|
|
2494
|
+
const tok = this.current;
|
|
2495
|
+
if (tok.type === "IDENTIFIER" && /^(x\d+)+$/.test(tok.value)) {
|
|
2496
|
+
this.advance();
|
|
2497
|
+
for (const m of tok.value.match(/x(\d+)/g))
|
|
2498
|
+
dimensions.push(
|
|
2499
|
+
this.createNode("dimension", {
|
|
2500
|
+
size: parseInt(m.slice(1))
|
|
2501
|
+
})
|
|
2502
|
+
);
|
|
2503
|
+
} else if (tok.type === "IDENTIFIER" && tok.value === "x") {
|
|
2504
|
+
const next = this.lexer.peekToken();
|
|
2505
|
+
if (next.type !== "NUMBER_LITERAL" && next.type !== "?")
|
|
2506
|
+
this.error(
|
|
2507
|
+
"Expected a positive integer literal or `?` after x. For example: `2x3` or `2x?`"
|
|
2508
|
+
);
|
|
2509
|
+
this.advance();
|
|
2510
|
+
dimensions.push(this.parseDimension());
|
|
2511
|
+
} else {
|
|
2512
|
+
break;
|
|
2588
2513
|
}
|
|
2589
|
-
dimensions.push(dim);
|
|
2590
2514
|
}
|
|
2591
2515
|
return dimensions;
|
|
2592
2516
|
}
|
|
@@ -2600,35 +2524,11 @@ var Compile = (() => {
|
|
|
2600
2524
|
}
|
|
2601
2525
|
return void 0;
|
|
2602
2526
|
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
this.createNode("dimension", { size: firstDim })
|
|
2609
|
-
);
|
|
2610
|
-
if (this.current.type === "IDENTIFIER" && this.current.value.startsWith("x")) {
|
|
2611
|
-
const dimString = this.current.value;
|
|
2612
|
-
const matches = dimString.match(/x(\d+)/g);
|
|
2613
|
-
if (matches && matches.join("") === dimString) {
|
|
2614
|
-
this.advance();
|
|
2615
|
-
for (const match of matches) {
|
|
2616
|
-
const dimValue = parseInt(match.substring(1));
|
|
2617
|
-
dimensions.push(
|
|
2618
|
-
this.createNode("dimension", { size: dimValue })
|
|
2619
|
-
);
|
|
2620
|
-
}
|
|
2621
|
-
} else if (dimString === "x" || dimString.startsWith("x")) {
|
|
2622
|
-
this.error(
|
|
2623
|
-
"Expected a positive integer literal or `?` after x. For example: `2x3` or `2x?`"
|
|
2624
|
-
);
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2627
|
-
if (dimensions.length > 1) {
|
|
2628
|
-
return dimensions;
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
|
-
return void 0;
|
|
2527
|
+
parseCaretDimensions() {
|
|
2528
|
+
const paren = this.match("(");
|
|
2529
|
+
const dimensions = this.parseDimensions();
|
|
2530
|
+
if (paren) this.expect(")");
|
|
2531
|
+
return dimensions;
|
|
2632
2532
|
}
|
|
2633
2533
|
parseTupleType() {
|
|
2634
2534
|
if (this.current.type === "IDENTIFIER" && this.current.value === "tuple") {
|
|
@@ -2813,6 +2713,18 @@ var Compile = (() => {
|
|
|
2813
2713
|
this.expect("..");
|
|
2814
2714
|
const upperBound = this.parseValue();
|
|
2815
2715
|
this.expect(">");
|
|
2716
|
+
const lower = lowerBound?.value ?? -Infinity;
|
|
2717
|
+
const upper = upperBound?.value ?? Infinity;
|
|
2718
|
+
if (Number.isNaN(lower) || Number.isNaN(upper))
|
|
2719
|
+
this.error(
|
|
2720
|
+
"Invalid numeric type",
|
|
2721
|
+
"Lower and upper bounds must be valid numbers"
|
|
2722
|
+
);
|
|
2723
|
+
if (lower > upper)
|
|
2724
|
+
this.error(
|
|
2725
|
+
`Invalid range: ${lower}..${upper}`,
|
|
2726
|
+
"The lower bound must be less than the upper bound"
|
|
2727
|
+
);
|
|
2816
2728
|
return this.createNode("numeric", {
|
|
2817
2729
|
baseType,
|
|
2818
2730
|
lowerBound,
|
|
@@ -2827,7 +2739,7 @@ var Compile = (() => {
|
|
|
2827
2739
|
parsePrimitiveType() {
|
|
2828
2740
|
if (this.current.type === "IDENTIFIER") {
|
|
2829
2741
|
const name = this.current.value;
|
|
2830
|
-
if (
|
|
2742
|
+
if (PRIMITIVE_TYPES_SET.has(name)) {
|
|
2831
2743
|
this.advance();
|
|
2832
2744
|
return this.createNode("primitive", { name });
|
|
2833
2745
|
}
|
|
@@ -3161,14 +3073,32 @@ var Compile = (() => {
|
|
|
3161
3073
|
}
|
|
3162
3074
|
|
|
3163
3075
|
// src/common/type/parse.ts
|
|
3076
|
+
var TYPE_CACHE = /* @__PURE__ */ new Map();
|
|
3077
|
+
var TYPE_CACHE_MAX_SIZE = 2048;
|
|
3078
|
+
function deepFreeze(obj) {
|
|
3079
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
3080
|
+
if (Object.isFrozen(obj)) return obj;
|
|
3081
|
+
Object.freeze(obj);
|
|
3082
|
+
for (const value of Object.values(obj)) deepFreeze(value);
|
|
3083
|
+
return obj;
|
|
3084
|
+
}
|
|
3164
3085
|
function parseType(s, typeResolver) {
|
|
3165
3086
|
if (s === void 0) return void 0;
|
|
3166
3087
|
if (isValidType(s)) return s;
|
|
3167
3088
|
if (typeof s !== "string") return void 0;
|
|
3089
|
+
const cacheable = typeResolver === void 0;
|
|
3090
|
+
if (cacheable) {
|
|
3091
|
+
const cached = TYPE_CACHE.get(s);
|
|
3092
|
+
if (cached !== void 0) return cached;
|
|
3093
|
+
}
|
|
3168
3094
|
try {
|
|
3169
3095
|
const parser = new Parser(s, { typeResolver });
|
|
3170
3096
|
const ast = parser.parseType();
|
|
3171
3097
|
const type = buildTypeFromAST(ast, typeResolver);
|
|
3098
|
+
if (cacheable) {
|
|
3099
|
+
if (TYPE_CACHE.size >= TYPE_CACHE_MAX_SIZE) TYPE_CACHE.clear();
|
|
3100
|
+
TYPE_CACHE.set(s, deepFreeze(type));
|
|
3101
|
+
}
|
|
3172
3102
|
return type;
|
|
3173
3103
|
} catch (error) {
|
|
3174
3104
|
throw new Error(
|
|
@@ -3243,19 +3173,54 @@ var Compile = (() => {
|
|
|
3243
3173
|
color: [],
|
|
3244
3174
|
expression: EXPRESSION_TYPES
|
|
3245
3175
|
};
|
|
3176
|
+
var PRIMITIVE_SUBTYPES_CLOSURE = (() => {
|
|
3177
|
+
const closure = {};
|
|
3178
|
+
const closeOver = (t) => {
|
|
3179
|
+
if (closure[t]) return closure[t];
|
|
3180
|
+
const result = /* @__PURE__ */ new Set([t]);
|
|
3181
|
+
closure[t] = result;
|
|
3182
|
+
for (const sub2 of PRIMITIVE_SUBTYPES[t]) {
|
|
3183
|
+
if (sub2 === t) continue;
|
|
3184
|
+
for (const s of closeOver(sub2)) result.add(s);
|
|
3185
|
+
}
|
|
3186
|
+
return result;
|
|
3187
|
+
};
|
|
3188
|
+
for (const t of Object.keys(PRIMITIVE_SUBTYPES))
|
|
3189
|
+
closeOver(t);
|
|
3190
|
+
return closure;
|
|
3191
|
+
})();
|
|
3246
3192
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
3247
3193
|
if (rhs === "any") return true;
|
|
3248
3194
|
if (lhs === "never") return true;
|
|
3249
3195
|
if (lhs === "unknown" || rhs === "unknown") return false;
|
|
3250
3196
|
if (lhs === rhs) return true;
|
|
3251
|
-
return
|
|
3197
|
+
return PRIMITIVE_SUBTYPES_CLOSURE[rhs].has(lhs);
|
|
3198
|
+
}
|
|
3199
|
+
function meetPrimitiveTypes(a, b) {
|
|
3200
|
+
if (a === b) return [a];
|
|
3201
|
+
const sa = PRIMITIVE_SUBTYPES_CLOSURE[a];
|
|
3202
|
+
const sb = PRIMITIVE_SUBTYPES_CLOSURE[b];
|
|
3203
|
+
if (sa.has(b)) return [b];
|
|
3204
|
+
if (sb.has(a)) return [a];
|
|
3205
|
+
const key = a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
3206
|
+
const cached = MEET_CACHE.get(key);
|
|
3207
|
+
if (cached) return cached;
|
|
3208
|
+
const common = [];
|
|
3209
|
+
for (const t of sa) if (sb.has(t)) common.push(t);
|
|
3210
|
+
const maximals = common.filter(
|
|
3211
|
+
(t) => !common.some((u) => u !== t && PRIMITIVE_SUBTYPES_CLOSURE[u].has(t))
|
|
3212
|
+
);
|
|
3213
|
+
MEET_CACHE.set(key, maximals);
|
|
3214
|
+
return maximals;
|
|
3252
3215
|
}
|
|
3216
|
+
var MEET_CACHE = /* @__PURE__ */ new Map();
|
|
3253
3217
|
function isSubtype(lhs, rhs) {
|
|
3254
|
-
if (typeof lhs === "string" && !
|
|
3218
|
+
if (typeof lhs === "string" && !PRIMITIVE_TYPES_SET.has(lhs))
|
|
3255
3219
|
lhs = parseType(lhs);
|
|
3256
|
-
if (typeof rhs === "string" && !
|
|
3220
|
+
if (typeof rhs === "string" && !PRIMITIVE_TYPES_SET.has(rhs))
|
|
3257
3221
|
rhs = parseType(rhs);
|
|
3258
3222
|
if (rhs === "any") return true;
|
|
3223
|
+
if (lhs === "never") return true;
|
|
3259
3224
|
if (rhs === "never") return false;
|
|
3260
3225
|
if (rhs === "error") return lhs === "error";
|
|
3261
3226
|
if (rhs === "nothing") return lhs === "nothing";
|
|
@@ -3270,7 +3235,7 @@ var Compile = (() => {
|
|
|
3270
3235
|
if (typeof lhs.value === "number") {
|
|
3271
3236
|
if (Number.isInteger(lhs.value))
|
|
3272
3237
|
return isPrimitiveSubtype("integer", rhs);
|
|
3273
|
-
return isPrimitiveSubtype("
|
|
3238
|
+
return isPrimitiveSubtype("real", rhs);
|
|
3274
3239
|
}
|
|
3275
3240
|
if (typeof lhs.value === "boolean")
|
|
3276
3241
|
return isPrimitiveSubtype("boolean", rhs);
|
|
@@ -3500,7 +3465,7 @@ var Compile = (() => {
|
|
|
3500
3465
|
}
|
|
3501
3466
|
function isNumeric(type) {
|
|
3502
3467
|
if (typeof type === "string")
|
|
3503
|
-
return
|
|
3468
|
+
return NUMERIC_TYPES_SET.has(type);
|
|
3504
3469
|
if (type.kind === "value") return typeof type.value === "number";
|
|
3505
3470
|
if (type.kind === "numeric") return true;
|
|
3506
3471
|
return false;
|
|
@@ -3508,7 +3473,7 @@ var Compile = (() => {
|
|
|
3508
3473
|
function isScalar(type) {
|
|
3509
3474
|
if (isNumeric(type)) return true;
|
|
3510
3475
|
if (typeof type === "string")
|
|
3511
|
-
return
|
|
3476
|
+
return SCALAR_TYPES_SET.has(type);
|
|
3512
3477
|
if (type.kind === "value")
|
|
3513
3478
|
return ["string", "boolean", "number"].includes(typeof type.value);
|
|
3514
3479
|
return false;
|
|
@@ -3516,7 +3481,7 @@ var Compile = (() => {
|
|
|
3516
3481
|
function isCollection(type) {
|
|
3517
3482
|
if (isIndexedCollection(type)) return true;
|
|
3518
3483
|
if (typeof type === "string")
|
|
3519
|
-
return
|
|
3484
|
+
return COLLECTION_TYPES_SET.has(type);
|
|
3520
3485
|
return ["collection", "set", "record", "dictionary"].includes(type.kind);
|
|
3521
3486
|
}
|
|
3522
3487
|
function isIndexedCollection(type) {
|
|
@@ -3555,7 +3520,7 @@ var Compile = (() => {
|
|
|
3555
3520
|
if (b === "unknown") return a;
|
|
3556
3521
|
if (isSubtype(a, b)) return a;
|
|
3557
3522
|
if (isSubtype(b, a)) return b;
|
|
3558
|
-
return
|
|
3523
|
+
return "never";
|
|
3559
3524
|
}
|
|
3560
3525
|
function widen2(a, b) {
|
|
3561
3526
|
if (a === b) return a;
|
|
@@ -3568,7 +3533,43 @@ var Compile = (() => {
|
|
|
3568
3533
|
if (b === "nothing") return a;
|
|
3569
3534
|
if (isSubtype(a, b)) return b;
|
|
3570
3535
|
if (isSubtype(b, a)) return a;
|
|
3571
|
-
|
|
3536
|
+
const sup = superType(a, b);
|
|
3537
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
3538
|
+
return sup;
|
|
3539
|
+
}
|
|
3540
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
3541
|
+
"scalar",
|
|
3542
|
+
"value",
|
|
3543
|
+
"function",
|
|
3544
|
+
"expression",
|
|
3545
|
+
"collection",
|
|
3546
|
+
"indexed_collection",
|
|
3547
|
+
"list",
|
|
3548
|
+
"set",
|
|
3549
|
+
"tuple",
|
|
3550
|
+
"record",
|
|
3551
|
+
"dictionary",
|
|
3552
|
+
"map",
|
|
3553
|
+
"any"
|
|
3554
|
+
]);
|
|
3555
|
+
function unionTypes(a, b) {
|
|
3556
|
+
const members = [];
|
|
3557
|
+
const keys = /* @__PURE__ */ new Set();
|
|
3558
|
+
const push = (t) => {
|
|
3559
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
3560
|
+
for (const m of t.types) push(m);
|
|
3561
|
+
return;
|
|
3562
|
+
}
|
|
3563
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
3564
|
+
if (!keys.has(key)) {
|
|
3565
|
+
keys.add(key);
|
|
3566
|
+
members.push(t);
|
|
3567
|
+
}
|
|
3568
|
+
};
|
|
3569
|
+
push(a);
|
|
3570
|
+
push(b);
|
|
3571
|
+
if (members.length === 1) return members[0];
|
|
3572
|
+
return { kind: "union", types: members };
|
|
3572
3573
|
}
|
|
3573
3574
|
function narrow(...types) {
|
|
3574
3575
|
if (types.length === 0) return "nothing";
|
|
@@ -3580,6 +3581,32 @@ var Compile = (() => {
|
|
|
3580
3581
|
if (types.length === 1) return types[0];
|
|
3581
3582
|
return types.reduce((a, b) => widen2(a, b));
|
|
3582
3583
|
}
|
|
3584
|
+
var SUPERTYPE_PROBE_ORDER = [
|
|
3585
|
+
"non_finite_number",
|
|
3586
|
+
"finite_integer",
|
|
3587
|
+
"integer",
|
|
3588
|
+
"finite_rational",
|
|
3589
|
+
"rational",
|
|
3590
|
+
"finite_real",
|
|
3591
|
+
"real",
|
|
3592
|
+
"imaginary",
|
|
3593
|
+
"finite_complex",
|
|
3594
|
+
"complex",
|
|
3595
|
+
"finite_number",
|
|
3596
|
+
"number",
|
|
3597
|
+
"list",
|
|
3598
|
+
"record",
|
|
3599
|
+
"dictionary",
|
|
3600
|
+
"set",
|
|
3601
|
+
"tuple",
|
|
3602
|
+
"indexed_collection",
|
|
3603
|
+
"collection",
|
|
3604
|
+
"scalar",
|
|
3605
|
+
"value",
|
|
3606
|
+
"function",
|
|
3607
|
+
"expression"
|
|
3608
|
+
];
|
|
3609
|
+
var PRIMITIVE_SUPERTYPE_CACHE = /* @__PURE__ */ new Map();
|
|
3583
3610
|
function superType(a, b) {
|
|
3584
3611
|
if (a === b) return a;
|
|
3585
3612
|
if (a === "any" || b === "any") return "any";
|
|
@@ -3589,34 +3616,185 @@ var Compile = (() => {
|
|
|
3589
3616
|
if (b === "unknown") return a;
|
|
3590
3617
|
if (a === "nothing") return b;
|
|
3591
3618
|
if (b === "nothing") return a;
|
|
3592
|
-
if (
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
if (commonSupertype(a, b, "collection")) return "collection";
|
|
3611
|
-
if (commonSupertype(a, b, "scalar")) return "scalar";
|
|
3612
|
-
if (commonSupertype(a, b, "value")) return "value";
|
|
3613
|
-
if (commonSupertype(a, b, "function")) return "function";
|
|
3614
|
-
if (commonSupertype(a, b, "expression")) return "expression";
|
|
3619
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
3620
|
+
const key = a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
3621
|
+
let result = PRIMITIVE_SUPERTYPE_CACHE.get(key);
|
|
3622
|
+
if (result === void 0) {
|
|
3623
|
+
result = "any";
|
|
3624
|
+
for (const ancestor of SUPERTYPE_PROBE_ORDER) {
|
|
3625
|
+
const subtypes = PRIMITIVE_SUBTYPES_CLOSURE[ancestor];
|
|
3626
|
+
if (subtypes.has(a) && subtypes.has(b)) {
|
|
3627
|
+
result = ancestor;
|
|
3628
|
+
break;
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
PRIMITIVE_SUPERTYPE_CACHE.set(key, result);
|
|
3632
|
+
}
|
|
3633
|
+
return result;
|
|
3634
|
+
}
|
|
3635
|
+
for (const ancestor of SUPERTYPE_PROBE_ORDER)
|
|
3636
|
+
if (isSubtype(a, ancestor) && isSubtype(b, ancestor)) return ancestor;
|
|
3615
3637
|
return "any";
|
|
3616
3638
|
}
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3639
|
+
|
|
3640
|
+
// src/common/type/serialize.ts
|
|
3641
|
+
var NEGATION_PRECEDENCE = 3;
|
|
3642
|
+
var UNION_PRECEDENCE = 1;
|
|
3643
|
+
var INTERSECTION_PRECEDENCE = 2;
|
|
3644
|
+
var LIST_PRECEDENCE = 4;
|
|
3645
|
+
var RECORD_PRECEDENCE = 5;
|
|
3646
|
+
var DICTIONARY_PRECEDENCE = 6;
|
|
3647
|
+
var SET_PRECEDENCE = 7;
|
|
3648
|
+
var COLLECTION_PRECEDENCE = 8;
|
|
3649
|
+
var TUPLE_PRECEDENCE = 9;
|
|
3650
|
+
var SIGNATURE_PRECEDENCE = 10;
|
|
3651
|
+
var VALUE_PRECEDENCE = 11;
|
|
3652
|
+
function typeToString(type, precedence = 0) {
|
|
3653
|
+
if (typeof type === "string") return type;
|
|
3654
|
+
let result = "";
|
|
3655
|
+
switch (type.kind) {
|
|
3656
|
+
case "value":
|
|
3657
|
+
if (typeof type.value === "string") result = `"${type.value}"`;
|
|
3658
|
+
else if (typeof type.value === "boolean")
|
|
3659
|
+
result = type.value ? "true" : "false";
|
|
3660
|
+
else result = type.value.toString();
|
|
3661
|
+
break;
|
|
3662
|
+
case "reference":
|
|
3663
|
+
result = type.name;
|
|
3664
|
+
break;
|
|
3665
|
+
case "negation":
|
|
3666
|
+
result = `!${typeToString(type.type, NEGATION_PRECEDENCE)}`;
|
|
3667
|
+
break;
|
|
3668
|
+
case "union":
|
|
3669
|
+
result = type.types.map((t) => typeToString(t, UNION_PRECEDENCE)).join(" | ");
|
|
3670
|
+
break;
|
|
3671
|
+
case "intersection":
|
|
3672
|
+
result = type.types.map((t) => typeToString(t, INTERSECTION_PRECEDENCE)).join(" & ");
|
|
3673
|
+
break;
|
|
3674
|
+
case "expression":
|
|
3675
|
+
result = `expression<${symbolName(type.operator)}>`;
|
|
3676
|
+
break;
|
|
3677
|
+
case "symbol":
|
|
3678
|
+
result = `symbol<${symbolName(type.name)}>`;
|
|
3679
|
+
break;
|
|
3680
|
+
case "numeric":
|
|
3681
|
+
if (Number.isFinite(type.lower) && Number.isFinite(type.upper)) {
|
|
3682
|
+
result = `${type.type}<${type.lower}..${type.upper}>`;
|
|
3683
|
+
} else if (Number.isFinite(type.lower)) {
|
|
3684
|
+
result = `${type.type}<${type.lower}..>`;
|
|
3685
|
+
} else if (Number.isFinite(type.upper)) {
|
|
3686
|
+
result = `${type.type}<..${type.upper}>`;
|
|
3687
|
+
} else {
|
|
3688
|
+
result = `${type.type}`;
|
|
3689
|
+
}
|
|
3690
|
+
break;
|
|
3691
|
+
case "list":
|
|
3692
|
+
if (type.dimensions && typeof type.elements === "string" && NUMERIC_TYPES_SET.has(type.elements)) {
|
|
3693
|
+
if (type.dimensions === void 0) {
|
|
3694
|
+
if (type.elements === "number") result = "tensor";
|
|
3695
|
+
} else if (type.dimensions.length === 1) {
|
|
3696
|
+
if (type.elements === "number") {
|
|
3697
|
+
if (type.dimensions[0] < 0) result = "vector";
|
|
3698
|
+
else result = `vector<${type.dimensions[0]}>`;
|
|
3699
|
+
} else {
|
|
3700
|
+
if (type.dimensions[0] < 0)
|
|
3701
|
+
result = `vector<${typeToString(type.elements)}>`;
|
|
3702
|
+
else
|
|
3703
|
+
result = `vector<${typeToString(type.elements)}^${type.dimensions[0]}>`;
|
|
3704
|
+
}
|
|
3705
|
+
} else if (type.dimensions.length === 2) {
|
|
3706
|
+
const dims = type.dimensions;
|
|
3707
|
+
if (type.elements === "number") {
|
|
3708
|
+
if (dims[0] < 0 && dims[1] < 0) result = "matrix";
|
|
3709
|
+
else result = `matrix<${dims[0]}x${dims[1]}>`;
|
|
3710
|
+
} else {
|
|
3711
|
+
if (dims[0] < 0 && dims[1] < 0)
|
|
3712
|
+
result = `matrix<${typeToString(type.elements)}>`;
|
|
3713
|
+
else
|
|
3714
|
+
result = `matrix<${typeToString(type.elements)}^(${dims[0]}x${dims[1]})>`;
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
if (!result) {
|
|
3719
|
+
const dimensions = type.dimensions ? type.dimensions.length === 1 ? `^${type.dimensions[0].toString()}` : `^(${type.dimensions.join("x")})` : "";
|
|
3720
|
+
result = `list<${typeToString(type.elements)}${dimensions}>`;
|
|
3721
|
+
}
|
|
3722
|
+
break;
|
|
3723
|
+
case "record":
|
|
3724
|
+
const elements = Object.entries(type.elements).map(([key, value]) => `${key}: ${typeToString(value)}`).join(", ");
|
|
3725
|
+
result = `record<${elements}>`;
|
|
3726
|
+
break;
|
|
3727
|
+
case "dictionary":
|
|
3728
|
+
result = `dictionary<${typeToString(type.values)}>`;
|
|
3729
|
+
break;
|
|
3730
|
+
case "set":
|
|
3731
|
+
result = `set<${typeToString(type.elements)}>`;
|
|
3732
|
+
break;
|
|
3733
|
+
case "collection":
|
|
3734
|
+
result = `collection<${typeToString(type.elements)}>`;
|
|
3735
|
+
break;
|
|
3736
|
+
case "indexed_collection":
|
|
3737
|
+
result = `indexed_collection<${typeToString(type.elements)}>`;
|
|
3738
|
+
break;
|
|
3739
|
+
case "tuple":
|
|
3740
|
+
if (type.elements.length === 0) result = "tuple";
|
|
3741
|
+
else if (type.elements.length === 1) {
|
|
3742
|
+
const [el] = type.elements;
|
|
3743
|
+
result = `tuple<${namedElement(el)}>`;
|
|
3744
|
+
} else {
|
|
3745
|
+
result = "tuple<" + type.elements.map((el) => namedElement(el)).join(", ") + ">";
|
|
3746
|
+
}
|
|
3747
|
+
break;
|
|
3748
|
+
case "signature":
|
|
3749
|
+
const args = type.args ? type.args.map((arg) => namedElement(arg)).join(", ") : "";
|
|
3750
|
+
const optArgs = type.optArgs ? type.optArgs.map((arg) => namedElement(arg) + "?").join(", ") : "";
|
|
3751
|
+
const varArg = type.variadicArg ? type.variadicMin === 0 ? `${namedElement(type.variadicArg)}*` : `${namedElement(type.variadicArg)}+` : "";
|
|
3752
|
+
const argsList = [args, optArgs, varArg].filter((s) => s).join(", ");
|
|
3753
|
+
result = `(${argsList}) -> ${typeToString(type.result)}`;
|
|
3754
|
+
break;
|
|
3755
|
+
default:
|
|
3756
|
+
result = "error";
|
|
3757
|
+
}
|
|
3758
|
+
if (precedence > 0 && precedence > getPrecedence(type.kind))
|
|
3759
|
+
return `(${result})`;
|
|
3760
|
+
return result;
|
|
3761
|
+
}
|
|
3762
|
+
function namedElement(el) {
|
|
3763
|
+
if (el.name) return `${el.name}: ${typeToString(el.type)}`;
|
|
3764
|
+
return typeToString(el.type);
|
|
3765
|
+
}
|
|
3766
|
+
function symbolName(name) {
|
|
3767
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) return name;
|
|
3768
|
+
return `\`${name}\``;
|
|
3769
|
+
}
|
|
3770
|
+
function getPrecedence(kind) {
|
|
3771
|
+
switch (kind) {
|
|
3772
|
+
case "negation":
|
|
3773
|
+
return NEGATION_PRECEDENCE;
|
|
3774
|
+
case "union":
|
|
3775
|
+
return UNION_PRECEDENCE;
|
|
3776
|
+
case "intersection":
|
|
3777
|
+
return INTERSECTION_PRECEDENCE;
|
|
3778
|
+
case "list":
|
|
3779
|
+
return LIST_PRECEDENCE;
|
|
3780
|
+
case "record":
|
|
3781
|
+
return RECORD_PRECEDENCE;
|
|
3782
|
+
case "dictionary":
|
|
3783
|
+
return DICTIONARY_PRECEDENCE;
|
|
3784
|
+
case "set":
|
|
3785
|
+
return SET_PRECEDENCE;
|
|
3786
|
+
case "collection":
|
|
3787
|
+
case "indexed_collection":
|
|
3788
|
+
return COLLECTION_PRECEDENCE;
|
|
3789
|
+
case "tuple":
|
|
3790
|
+
return TUPLE_PRECEDENCE;
|
|
3791
|
+
case "signature":
|
|
3792
|
+
return SIGNATURE_PRECEDENCE;
|
|
3793
|
+
case "value":
|
|
3794
|
+
return VALUE_PRECEDENCE;
|
|
3795
|
+
default:
|
|
3796
|
+
return 0;
|
|
3797
|
+
}
|
|
3620
3798
|
}
|
|
3621
3799
|
|
|
3622
3800
|
// src/common/type/utils.ts
|
|
@@ -3642,7 +3820,7 @@ var Compile = (() => {
|
|
|
3642
3820
|
if (type.kind === "set") return type.elements;
|
|
3643
3821
|
if (type.kind === "tuple") return widen(...type.elements.map((x) => x.type));
|
|
3644
3822
|
if (type.kind === "dictionary")
|
|
3645
|
-
return parseType(`tuple<string, ${type.values}>`);
|
|
3823
|
+
return parseType(`tuple<string, ${typeToString(type.values)}>`);
|
|
3646
3824
|
if (type.kind === "record") {
|
|
3647
3825
|
return parseType(
|
|
3648
3826
|
`tuple<string, ${typeToString(widen(...Object.values(type.elements)))}>`
|
|
@@ -3725,6 +3903,12 @@ var Compile = (() => {
|
|
|
3725
3903
|
return expr?._kind === "symbol" ? expr.symbol : void 0;
|
|
3726
3904
|
}
|
|
3727
3905
|
|
|
3906
|
+
// src/compute-engine/boxed-expression/constraint-subject.ts
|
|
3907
|
+
var EMPTY_FACT_INDEX = Object.freeze({
|
|
3908
|
+
bySubject: /* @__PURE__ */ new Map(),
|
|
3909
|
+
membership: /* @__PURE__ */ new Map()
|
|
3910
|
+
});
|
|
3911
|
+
|
|
3728
3912
|
// src/compute-engine/boxed-expression/stochastic-equal.ts
|
|
3729
3913
|
var WELL_KNOWN_POINTS = [
|
|
3730
3914
|
0,
|
|
@@ -3973,6 +4157,7 @@ var Compile = (() => {
|
|
|
3973
4157
|
}
|
|
3974
4158
|
|
|
3975
4159
|
// src/compute-engine/collection-utils.ts
|
|
4160
|
+
var MAX_SIZE_EAGER_COLLECTION = 100;
|
|
3976
4161
|
function isFiniteIndexedCollection(col) {
|
|
3977
4162
|
return (col.isFiniteCollection ?? false) && col.isIndexedCollection;
|
|
3978
4163
|
}
|
|
@@ -4601,12 +4786,14 @@ var Compile = (() => {
|
|
|
4601
4786
|
if (expr === null) return null;
|
|
4602
4787
|
if (isDictionaryObject(expr)) return expr;
|
|
4603
4788
|
const kv = keyValuePair(expr);
|
|
4604
|
-
if (kv)
|
|
4789
|
+
if (kv)
|
|
4790
|
+
return {
|
|
4791
|
+
dict: { [kv[0]]: expressionToDictionaryValue(kv[1]) ?? "Nothing" }
|
|
4792
|
+
};
|
|
4605
4793
|
if (operator(expr) === "Dictionary") {
|
|
4606
4794
|
const dict = {};
|
|
4607
|
-
const
|
|
4608
|
-
|
|
4609
|
-
const kv2 = keyValuePair(ops[i]);
|
|
4795
|
+
for (const op of operands(expr)) {
|
|
4796
|
+
const kv2 = keyValuePair(op);
|
|
4610
4797
|
if (kv2) {
|
|
4611
4798
|
dict[kv2[0]] = expressionToDictionaryValue(kv2[1]) ?? "Nothing";
|
|
4612
4799
|
}
|
|
@@ -5544,15 +5731,16 @@ var Compile = (() => {
|
|
|
5544
5731
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
5545
5732
|
parse: parseAssign
|
|
5546
5733
|
},
|
|
5547
|
-
// General colon operator (type annotation, mapping notation)
|
|
5548
|
-
// Precedence below
|
|
5549
|
-
// and below arrows (270) so
|
|
5734
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
5735
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
5736
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
5737
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
5550
5738
|
{
|
|
5551
5739
|
name: "Colon",
|
|
5552
5740
|
latexTrigger: ":",
|
|
5553
5741
|
kind: "infix",
|
|
5554
5742
|
associativity: "right",
|
|
5555
|
-
precedence:
|
|
5743
|
+
precedence: 240,
|
|
5556
5744
|
serialize: (serializer, expr) => joinLatex([
|
|
5557
5745
|
serializer.serialize(operand(expr, 1)),
|
|
5558
5746
|
"\\colon",
|
|
@@ -5563,7 +5751,7 @@ var Compile = (() => {
|
|
|
5563
5751
|
latexTrigger: "\\colon",
|
|
5564
5752
|
kind: "infix",
|
|
5565
5753
|
associativity: "right",
|
|
5566
|
-
precedence:
|
|
5754
|
+
precedence: 240,
|
|
5567
5755
|
parse: "Colon"
|
|
5568
5756
|
},
|
|
5569
5757
|
{
|
|
@@ -6539,6 +6727,7 @@ var Compile = (() => {
|
|
|
6539
6727
|
}
|
|
6540
6728
|
}
|
|
6541
6729
|
if (!variable) return null;
|
|
6730
|
+
if (symbol(variable) === null) return null;
|
|
6542
6731
|
parser.skipSpace();
|
|
6543
6732
|
const fn = parser.parseExpression({ minPrec: 740 });
|
|
6544
6733
|
if (!fn) return null;
|
|
@@ -6725,7 +6914,7 @@ var Compile = (() => {
|
|
|
6725
6914
|
if (runs.length === 1) body = runs[0];
|
|
6726
6915
|
else {
|
|
6727
6916
|
if (runs.every((x) => stringValue(x) !== null))
|
|
6728
|
-
body = "'" + runs.map((x) => stringValue(x)).join() + "'";
|
|
6917
|
+
body = "'" + runs.map((x) => stringValue(x)).join("") + "'";
|
|
6729
6918
|
else body = ["Text", ...runs];
|
|
6730
6919
|
}
|
|
6731
6920
|
return style ? ["Annotated", body, dictionaryFromEntries(style)] : body;
|
|
@@ -7133,7 +7322,10 @@ var Compile = (() => {
|
|
|
7133
7322
|
p.skipVisualSpace();
|
|
7134
7323
|
const isComma = p.peek === ",";
|
|
7135
7324
|
p.index = saved;
|
|
7136
|
-
return
|
|
7325
|
+
if (isComma) return true;
|
|
7326
|
+
if (peekKeyword(p, "where")) return true;
|
|
7327
|
+
if (peekKeyword(p, "with")) return true;
|
|
7328
|
+
return false;
|
|
7137
7329
|
}
|
|
7138
7330
|
};
|
|
7139
7331
|
const elements = [];
|
|
@@ -7174,6 +7366,25 @@ var Compile = (() => {
|
|
|
7174
7366
|
parser.skipVisualSpace();
|
|
7175
7367
|
} while (parser.match(","));
|
|
7176
7368
|
if (bindings.length === 0) return null;
|
|
7369
|
+
const forStart = parser.index;
|
|
7370
|
+
if (matchKeyword(parser, "for")) {
|
|
7371
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
7372
|
+
if (loop) {
|
|
7373
|
+
const block2 = [];
|
|
7374
|
+
for (const b of bindings) {
|
|
7375
|
+
const normalized = normalizeLocalAssign(b);
|
|
7376
|
+
if (operator(normalized) === "Assign") {
|
|
7377
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
7378
|
+
block2.push(normalized);
|
|
7379
|
+
} else {
|
|
7380
|
+
block2.push(normalized);
|
|
7381
|
+
}
|
|
7382
|
+
}
|
|
7383
|
+
block2.push(loop);
|
|
7384
|
+
return ["Block", ...block2];
|
|
7385
|
+
}
|
|
7386
|
+
parser.index = forStart;
|
|
7387
|
+
}
|
|
7177
7388
|
const block = [];
|
|
7178
7389
|
for (const b of bindings) {
|
|
7179
7390
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -7387,6 +7598,17 @@ var Compile = (() => {
|
|
|
7387
7598
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
7388
7599
|
return ["Interval", lowerExpr, upperExpr];
|
|
7389
7600
|
}
|
|
7601
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
7602
|
+
"Less",
|
|
7603
|
+
"LessEqual",
|
|
7604
|
+
"Greater",
|
|
7605
|
+
"GreaterEqual",
|
|
7606
|
+
"Equal",
|
|
7607
|
+
"NotEqual",
|
|
7608
|
+
"And",
|
|
7609
|
+
"Or",
|
|
7610
|
+
"Not"
|
|
7611
|
+
]);
|
|
7390
7612
|
var DEFINITIONS_SETS = [
|
|
7391
7613
|
//
|
|
7392
7614
|
// Constants
|
|
@@ -7645,18 +7867,58 @@ var Compile = (() => {
|
|
|
7645
7867
|
closeTrigger: "}",
|
|
7646
7868
|
parse: (_parser, body) => {
|
|
7647
7869
|
if (isEmptySequence(body)) return "EmptySet";
|
|
7870
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
7871
|
+
body = operand(body, 1);
|
|
7872
|
+
}
|
|
7648
7873
|
const h = operator(body);
|
|
7649
|
-
if (h === "Divides"
|
|
7874
|
+
if (h === "Divides") {
|
|
7650
7875
|
const expr = operand(body, 1);
|
|
7651
7876
|
const condition = operand(body, 2);
|
|
7652
7877
|
if (expr !== null && condition !== null)
|
|
7653
7878
|
return ["Set", expr, ["Condition", condition]];
|
|
7654
7879
|
}
|
|
7655
|
-
if (
|
|
7656
|
-
|
|
7880
|
+
if (h === "Colon") {
|
|
7881
|
+
const lhs = operand(body, 1);
|
|
7882
|
+
const rhs = operand(body, 2);
|
|
7883
|
+
if (lhs !== null && rhs !== null) {
|
|
7884
|
+
const lhsOp = operator(lhs);
|
|
7885
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
7886
|
+
return ["Which", lhs, rhs];
|
|
7887
|
+
}
|
|
7888
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
7889
|
+
}
|
|
7890
|
+
}
|
|
7891
|
+
if (h === "Sequence") {
|
|
7892
|
+
const elements = operands(body);
|
|
7893
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
7894
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
7895
|
+
const lhs = operand(el, 1);
|
|
7896
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
7897
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
7898
|
+
});
|
|
7899
|
+
if (allPiecewise) {
|
|
7900
|
+
const whichOps = [];
|
|
7901
|
+
for (let i = 0; i < elements.length; i++) {
|
|
7902
|
+
const el = elements[i];
|
|
7903
|
+
if (operator(el) === "Colon") {
|
|
7904
|
+
const cond = operand(el, 1);
|
|
7905
|
+
const val = operand(el, 2);
|
|
7906
|
+
if (cond === null || val === null) {
|
|
7907
|
+
return ["Set", ...elements];
|
|
7908
|
+
}
|
|
7909
|
+
whichOps.push(cond, val);
|
|
7910
|
+
} else {
|
|
7911
|
+
if (i !== elements.length - 1) {
|
|
7912
|
+
return ["Set", ...elements];
|
|
7913
|
+
}
|
|
7914
|
+
whichOps.push("True", el);
|
|
7915
|
+
}
|
|
7916
|
+
}
|
|
7917
|
+
return ["Which", ...whichOps];
|
|
7918
|
+
}
|
|
7919
|
+
return ["Set", ...elements];
|
|
7657
7920
|
}
|
|
7658
|
-
|
|
7659
|
-
return ["Set", ...operands(body)];
|
|
7921
|
+
return ["Set", body];
|
|
7660
7922
|
},
|
|
7661
7923
|
serialize: (serializer, expr) => {
|
|
7662
7924
|
if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
|
|
@@ -8185,6 +8447,8 @@ var Compile = (() => {
|
|
|
8185
8447
|
const h = operator(arg);
|
|
8186
8448
|
if (prevWasNumber && (h === "Divide" || h === "Rational")) {
|
|
8187
8449
|
result = latexTemplate(serializer.options.multiply, result, term);
|
|
8450
|
+
} else if (/^\d/.test(term)) {
|
|
8451
|
+
result = latexTemplate(serializer.options.multiply, result, term);
|
|
8188
8452
|
} else if (!serializer.options.invisibleMultiply) {
|
|
8189
8453
|
result = joinLatex([result, term]);
|
|
8190
8454
|
} else {
|
|
@@ -9630,7 +9894,9 @@ var Compile = (() => {
|
|
|
9630
9894
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
9631
9895
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
9632
9896
|
});
|
|
9633
|
-
const
|
|
9897
|
+
const isTwoArgArctan = args?.length === 2 && (fn === "Arctan" || Array.isArray(fn) && fn[0] === "InverseFunction" && fn[1] === "Tan");
|
|
9898
|
+
const head = isTwoArgArctan ? "Arctan2" : fn;
|
|
9899
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
9634
9900
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
9635
9901
|
};
|
|
9636
9902
|
}
|
|
@@ -11753,10 +12019,17 @@ var Compile = (() => {
|
|
|
11753
12019
|
// The capitalized library entries already exist; these are pure parse
|
|
11754
12020
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11755
12021
|
// ---------------------------------------------------------------------------
|
|
12022
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
11756
12023
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11757
12024
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11758
12025
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11759
12026
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
12027
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
12028
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
12029
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
12030
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
12031
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
12032
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
11760
12033
|
// ---------------------------------------------------------------------------
|
|
11761
12034
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11762
12035
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -11909,6 +12182,30 @@ var Compile = (() => {
|
|
|
11909
12182
|
var SOME_EMOJI = new RegExp(`(?:${POSSIBLE_EMOJI})+`, "u");
|
|
11910
12183
|
var EMOJIS = new RegExp(`^(?:${POSSIBLE_EMOJI})+$`, "u");
|
|
11911
12184
|
|
|
12185
|
+
// src/compute-engine/latex-syntax/parse.ts
|
|
12186
|
+
var PARSE_TOKEN_EXCLUDED = /* @__PURE__ */ new Set([
|
|
12187
|
+
...'!"#$%&(),/;:?@[]\\`|~'.split(""),
|
|
12188
|
+
"\\left",
|
|
12189
|
+
"\\bigl",
|
|
12190
|
+
"\\mleft"
|
|
12191
|
+
]);
|
|
12192
|
+
var TEX_UNIT_TOKENS = [
|
|
12193
|
+
"pt",
|
|
12194
|
+
"em",
|
|
12195
|
+
"mu",
|
|
12196
|
+
"ex",
|
|
12197
|
+
"mm",
|
|
12198
|
+
"cm",
|
|
12199
|
+
"in",
|
|
12200
|
+
"bp",
|
|
12201
|
+
"sp",
|
|
12202
|
+
"dd",
|
|
12203
|
+
"cc",
|
|
12204
|
+
"pc",
|
|
12205
|
+
"nc",
|
|
12206
|
+
"nd"
|
|
12207
|
+
].map((unit) => [...unit]);
|
|
12208
|
+
|
|
11912
12209
|
// src/compute-engine/boxed-expression/utils.ts
|
|
11913
12210
|
function isValueDef(def) {
|
|
11914
12211
|
return def !== void 0 && "value" in def;
|
|
@@ -11944,6 +12241,50 @@ var Compile = (() => {
|
|
|
11944
12241
|
return ys;
|
|
11945
12242
|
}
|
|
11946
12243
|
|
|
12244
|
+
// src/common/fuzzy-string-match.ts
|
|
12245
|
+
function levenshtein(source, target) {
|
|
12246
|
+
if (source === target) return 0;
|
|
12247
|
+
if (source.length === 0) return target.length;
|
|
12248
|
+
if (target.length === 0) return source.length;
|
|
12249
|
+
let prevRow = Array.from(
|
|
12250
|
+
{ length: source.length + 1 },
|
|
12251
|
+
(_, j) => j
|
|
12252
|
+
);
|
|
12253
|
+
let currRow = new Array(source.length + 1);
|
|
12254
|
+
for (let i = 1; i <= target.length; i++) {
|
|
12255
|
+
currRow[0] = i;
|
|
12256
|
+
for (let j = 1; j <= source.length; j++) {
|
|
12257
|
+
const cost = source[j - 1] === target[i - 1] ? 0 : 1;
|
|
12258
|
+
currRow[j] = Math.min(
|
|
12259
|
+
prevRow[j] + 1,
|
|
12260
|
+
// deletion
|
|
12261
|
+
currRow[j - 1] + 1,
|
|
12262
|
+
// insertion
|
|
12263
|
+
prevRow[j - 1] + cost
|
|
12264
|
+
// substitution
|
|
12265
|
+
);
|
|
12266
|
+
}
|
|
12267
|
+
[prevRow, currRow] = [currRow, prevRow];
|
|
12268
|
+
}
|
|
12269
|
+
return prevRow[source.length];
|
|
12270
|
+
}
|
|
12271
|
+
function fuzzyStringMatch(invalidWord, validWords) {
|
|
12272
|
+
const threshold = 7;
|
|
12273
|
+
let bestMatch = null;
|
|
12274
|
+
let minDistance = Infinity;
|
|
12275
|
+
const invalidLength = invalidWord.length;
|
|
12276
|
+
for (const word of validWords) {
|
|
12277
|
+
if (Math.abs(invalidLength - word.length) > threshold) continue;
|
|
12278
|
+
const distance = levenshtein(invalidWord, word);
|
|
12279
|
+
if (distance === 0) return word;
|
|
12280
|
+
if (distance <= threshold && distance < minDistance) {
|
|
12281
|
+
minDistance = distance;
|
|
12282
|
+
bestMatch = word;
|
|
12283
|
+
}
|
|
12284
|
+
}
|
|
12285
|
+
return bestMatch;
|
|
12286
|
+
}
|
|
12287
|
+
|
|
11947
12288
|
// src/compute-engine/boxed-expression/validate.ts
|
|
11948
12289
|
function checkArity(ce, ops, count) {
|
|
11949
12290
|
ops = flatten(ops);
|
|
@@ -12886,12 +13227,240 @@ ${lines.join("\n")}`;
|
|
|
12886
13227
|
Complex["EPSILON"] = 1e-15;
|
|
12887
13228
|
|
|
12888
13229
|
// src/compute-engine/boxed-expression/numerics.ts
|
|
13230
|
+
function asSmallInteger(expr) {
|
|
13231
|
+
if (expr === void 0 || expr === null) return null;
|
|
13232
|
+
if (typeof expr === "number") {
|
|
13233
|
+
if (Number.isInteger(expr) && expr >= -SMALL_INTEGER && expr <= SMALL_INTEGER)
|
|
13234
|
+
return expr;
|
|
13235
|
+
return null;
|
|
13236
|
+
}
|
|
13237
|
+
if (!isNumber(expr)) return null;
|
|
13238
|
+
const num = expr.numericValue;
|
|
13239
|
+
if (typeof num === "number") {
|
|
13240
|
+
if (Number.isInteger(num) && num >= -SMALL_INTEGER && num <= SMALL_INTEGER)
|
|
13241
|
+
return num;
|
|
13242
|
+
return null;
|
|
13243
|
+
}
|
|
13244
|
+
if (num.im !== 0) return null;
|
|
13245
|
+
const n = num.re;
|
|
13246
|
+
if (Number.isInteger(n) && n >= -SMALL_INTEGER && n <= SMALL_INTEGER)
|
|
13247
|
+
return Number(n);
|
|
13248
|
+
return null;
|
|
13249
|
+
}
|
|
12889
13250
|
function toInteger(expr) {
|
|
12890
13251
|
if (!isNumber(expr)) return null;
|
|
12891
13252
|
const num = expr.numericValue;
|
|
12892
13253
|
return Math.round(typeof num === "number" ? num : num.re);
|
|
12893
13254
|
}
|
|
12894
13255
|
|
|
13256
|
+
// src/compute-engine/library/logic-analysis.ts
|
|
13257
|
+
function filterValuesWithCondition(values, variable, conditionExpr, _ce) {
|
|
13258
|
+
return values.filter((value) => {
|
|
13259
|
+
const substituted = conditionExpr.subs({ [variable]: value });
|
|
13260
|
+
const result = substituted.evaluate();
|
|
13261
|
+
return sym(result) === "True";
|
|
13262
|
+
});
|
|
13263
|
+
}
|
|
13264
|
+
function extractFiniteDomainWithReason(condition, ce) {
|
|
13265
|
+
if (condition.operator !== "Element") {
|
|
13266
|
+
return { status: "error", reason: "expected-element-expression" };
|
|
13267
|
+
}
|
|
13268
|
+
if (!isFunction2(condition)) {
|
|
13269
|
+
return { status: "error", reason: "expected-element-expression" };
|
|
13270
|
+
}
|
|
13271
|
+
const variable = isSymbol2(condition.op1) ? condition.op1.symbol : void 0;
|
|
13272
|
+
if (!variable) {
|
|
13273
|
+
return { status: "error", reason: "expected-index-variable" };
|
|
13274
|
+
}
|
|
13275
|
+
const domain = condition.op2;
|
|
13276
|
+
if (!domain) {
|
|
13277
|
+
return { status: "error", reason: "expected-domain" };
|
|
13278
|
+
}
|
|
13279
|
+
const maybeCondition = condition.op3;
|
|
13280
|
+
const filterCondition = condition.nops >= 3 && maybeCondition && sym(maybeCondition) !== "Nothing" ? maybeCondition : null;
|
|
13281
|
+
const successResult = (values) => {
|
|
13282
|
+
if (filterCondition) {
|
|
13283
|
+
const filteredValues = filterValuesWithCondition(
|
|
13284
|
+
values,
|
|
13285
|
+
variable,
|
|
13286
|
+
filterCondition,
|
|
13287
|
+
ce
|
|
13288
|
+
);
|
|
13289
|
+
return { status: "success", variable, values: filteredValues };
|
|
13290
|
+
}
|
|
13291
|
+
return { status: "success", variable, values };
|
|
13292
|
+
};
|
|
13293
|
+
if (domain.operator === "Set" || domain.operator === "List") {
|
|
13294
|
+
const values = isFunction2(domain) ? domain.ops : void 0;
|
|
13295
|
+
if (values && values.length <= 1e3) {
|
|
13296
|
+
if (domain.operator === "List" && values.length === 2) {
|
|
13297
|
+
const start = asSmallInteger(values[0]);
|
|
13298
|
+
const end = asSmallInteger(values[1]);
|
|
13299
|
+
if (start !== null && end !== null) {
|
|
13300
|
+
const count = end - start + 1;
|
|
13301
|
+
if (count > 0 && count <= 1e3) {
|
|
13302
|
+
const rangeValues = [];
|
|
13303
|
+
for (let i = start; i <= end; i++) {
|
|
13304
|
+
rangeValues.push(ce.number(i));
|
|
13305
|
+
}
|
|
13306
|
+
return successResult(rangeValues);
|
|
13307
|
+
}
|
|
13308
|
+
if (count > 1e3) {
|
|
13309
|
+
return {
|
|
13310
|
+
status: "non-enumerable",
|
|
13311
|
+
variable,
|
|
13312
|
+
domain,
|
|
13313
|
+
reason: "domain-too-large"
|
|
13314
|
+
};
|
|
13315
|
+
}
|
|
13316
|
+
}
|
|
13317
|
+
}
|
|
13318
|
+
return successResult([...values]);
|
|
13319
|
+
}
|
|
13320
|
+
if (values && values.length > 1e3) {
|
|
13321
|
+
return {
|
|
13322
|
+
status: "non-enumerable",
|
|
13323
|
+
variable,
|
|
13324
|
+
domain,
|
|
13325
|
+
reason: "domain-too-large"
|
|
13326
|
+
};
|
|
13327
|
+
}
|
|
13328
|
+
return { status: "error", reason: "empty-domain" };
|
|
13329
|
+
}
|
|
13330
|
+
if (isFunction2(domain, "Range")) {
|
|
13331
|
+
const start = asSmallInteger(domain.op1);
|
|
13332
|
+
const end = asSmallInteger(domain.op2);
|
|
13333
|
+
const step = domain.ops.length >= 3 ? asSmallInteger(domain.op3) : 1;
|
|
13334
|
+
if (start !== null && end !== null && step !== null && step !== 0) {
|
|
13335
|
+
const count = Math.floor((end - start) / step) + 1;
|
|
13336
|
+
if (count > 0 && count <= 1e3) {
|
|
13337
|
+
const values = [];
|
|
13338
|
+
for (let i = start; step > 0 ? i <= end : i >= end; i += step) {
|
|
13339
|
+
values.push(ce.number(i));
|
|
13340
|
+
}
|
|
13341
|
+
return successResult(values);
|
|
13342
|
+
}
|
|
13343
|
+
if (count > 1e3) {
|
|
13344
|
+
return {
|
|
13345
|
+
status: "non-enumerable",
|
|
13346
|
+
variable,
|
|
13347
|
+
domain,
|
|
13348
|
+
reason: "domain-too-large"
|
|
13349
|
+
};
|
|
13350
|
+
}
|
|
13351
|
+
}
|
|
13352
|
+
return {
|
|
13353
|
+
status: "non-enumerable",
|
|
13354
|
+
variable,
|
|
13355
|
+
domain,
|
|
13356
|
+
reason: "non-integer-bounds"
|
|
13357
|
+
};
|
|
13358
|
+
}
|
|
13359
|
+
if (isFunction2(domain, "Interval")) {
|
|
13360
|
+
let op1 = domain.op1;
|
|
13361
|
+
let op2 = domain.op2;
|
|
13362
|
+
let openStart = false;
|
|
13363
|
+
let openEnd = false;
|
|
13364
|
+
if (isFunction2(op1, "Open")) {
|
|
13365
|
+
openStart = true;
|
|
13366
|
+
op1 = op1.op1;
|
|
13367
|
+
} else if (isFunction2(op1, "Closed")) {
|
|
13368
|
+
op1 = op1.op1;
|
|
13369
|
+
}
|
|
13370
|
+
if (isFunction2(op2, "Open")) {
|
|
13371
|
+
openEnd = true;
|
|
13372
|
+
op2 = op2.op1;
|
|
13373
|
+
} else if (isFunction2(op2, "Closed")) {
|
|
13374
|
+
op2 = op2.op1;
|
|
13375
|
+
}
|
|
13376
|
+
let start = asSmallInteger(op1);
|
|
13377
|
+
let end = asSmallInteger(op2);
|
|
13378
|
+
if (start !== null && end !== null) {
|
|
13379
|
+
if (openStart) start += 1;
|
|
13380
|
+
if (openEnd) end -= 1;
|
|
13381
|
+
const count = end - start + 1;
|
|
13382
|
+
if (count > 0 && count <= 1e3) {
|
|
13383
|
+
const values = [];
|
|
13384
|
+
for (let i = start; i <= end; i++) {
|
|
13385
|
+
values.push(ce.number(i));
|
|
13386
|
+
}
|
|
13387
|
+
return successResult(values);
|
|
13388
|
+
}
|
|
13389
|
+
if (count > 1e3) {
|
|
13390
|
+
return {
|
|
13391
|
+
status: "non-enumerable",
|
|
13392
|
+
variable,
|
|
13393
|
+
domain,
|
|
13394
|
+
reason: "domain-too-large"
|
|
13395
|
+
};
|
|
13396
|
+
}
|
|
13397
|
+
}
|
|
13398
|
+
return {
|
|
13399
|
+
status: "non-enumerable",
|
|
13400
|
+
variable,
|
|
13401
|
+
domain,
|
|
13402
|
+
reason: "non-integer-bounds"
|
|
13403
|
+
};
|
|
13404
|
+
}
|
|
13405
|
+
const domainSymbol = sym(domain);
|
|
13406
|
+
if (domainSymbol) {
|
|
13407
|
+
const knownInfiniteSets = [
|
|
13408
|
+
"Integers",
|
|
13409
|
+
"NonNegativeIntegers",
|
|
13410
|
+
"PositiveIntegers",
|
|
13411
|
+
"NegativeIntegers",
|
|
13412
|
+
"Rationals",
|
|
13413
|
+
"Reals",
|
|
13414
|
+
"PositiveReals",
|
|
13415
|
+
"NonNegativeReals",
|
|
13416
|
+
"NegativeReals",
|
|
13417
|
+
"NonPositiveReals",
|
|
13418
|
+
"ExtendedReals",
|
|
13419
|
+
"Complexes",
|
|
13420
|
+
"ImaginaryNumbers",
|
|
13421
|
+
"Numbers",
|
|
13422
|
+
"ExtendedComplexes",
|
|
13423
|
+
"AlgebraicNumbers",
|
|
13424
|
+
"TranscendentalNumbers"
|
|
13425
|
+
];
|
|
13426
|
+
if (knownInfiniteSets.includes(domainSymbol)) {
|
|
13427
|
+
return {
|
|
13428
|
+
status: "non-enumerable",
|
|
13429
|
+
variable,
|
|
13430
|
+
domain,
|
|
13431
|
+
reason: "infinite-domain"
|
|
13432
|
+
};
|
|
13433
|
+
}
|
|
13434
|
+
const domainValue = domain.value;
|
|
13435
|
+
if (domainValue && domainValue.operator === "Set" && isFunction2(domainValue)) {
|
|
13436
|
+
const values = domainValue.ops;
|
|
13437
|
+
if (values && values.length <= 1e3) {
|
|
13438
|
+
return successResult([...values]);
|
|
13439
|
+
}
|
|
13440
|
+
if (values && values.length > 1e3) {
|
|
13441
|
+
return {
|
|
13442
|
+
status: "non-enumerable",
|
|
13443
|
+
variable,
|
|
13444
|
+
domain,
|
|
13445
|
+
reason: "domain-too-large"
|
|
13446
|
+
};
|
|
13447
|
+
}
|
|
13448
|
+
}
|
|
13449
|
+
return {
|
|
13450
|
+
status: "non-enumerable",
|
|
13451
|
+
variable,
|
|
13452
|
+
domain,
|
|
13453
|
+
reason: "unknown-domain"
|
|
13454
|
+
};
|
|
13455
|
+
}
|
|
13456
|
+
return {
|
|
13457
|
+
status: "non-enumerable",
|
|
13458
|
+
variable,
|
|
13459
|
+
domain,
|
|
13460
|
+
reason: "unrecognized-domain-type"
|
|
13461
|
+
};
|
|
13462
|
+
}
|
|
13463
|
+
|
|
12895
13464
|
// src/compute-engine/numerics/interval.ts
|
|
12896
13465
|
function isNumber2(expr) {
|
|
12897
13466
|
return expr?._kind === "number";
|
|
@@ -12946,6 +13515,20 @@ ${lines.join("\n")}`;
|
|
|
12946
13515
|
}
|
|
12947
13516
|
return void 0;
|
|
12948
13517
|
}
|
|
13518
|
+
function intervalContains(int, val) {
|
|
13519
|
+
if (int.openStart ? val <= int.start : val < int.start) return false;
|
|
13520
|
+
if (int.openEnd ? val >= int.end : val > int.end) return false;
|
|
13521
|
+
return true;
|
|
13522
|
+
}
|
|
13523
|
+
|
|
13524
|
+
// src/compute-engine/numerics/random.ts
|
|
13525
|
+
function deterministicRandom(seed) {
|
|
13526
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
13527
|
+
return v - Math.floor(v);
|
|
13528
|
+
}
|
|
13529
|
+
function nextSeed(seed) {
|
|
13530
|
+
return seed + 0.6180339887498949;
|
|
13531
|
+
}
|
|
12949
13532
|
|
|
12950
13533
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
12951
13534
|
function canonical(ce, xs, scope) {
|
|
@@ -12953,8 +13536,236 @@ ${lines.join("\n")}`;
|
|
|
12953
13536
|
return xs.map((x) => ce.expr(x, { scope }));
|
|
12954
13537
|
}
|
|
12955
13538
|
|
|
13539
|
+
// src/common/type/reduce.ts
|
|
13540
|
+
function reduceType(type) {
|
|
13541
|
+
if (typeof type === "string") {
|
|
13542
|
+
if (!isValidPrimitiveType(type)) return "error";
|
|
13543
|
+
return type;
|
|
13544
|
+
}
|
|
13545
|
+
switch (type.kind) {
|
|
13546
|
+
case "union":
|
|
13547
|
+
return reduceUnionType(type);
|
|
13548
|
+
case "intersection":
|
|
13549
|
+
return reduceIntersectionType(type);
|
|
13550
|
+
case "negation":
|
|
13551
|
+
return reduceNegationType(type);
|
|
13552
|
+
case "collection":
|
|
13553
|
+
case "indexed_collection":
|
|
13554
|
+
return reduceCollectionType(type.kind, type);
|
|
13555
|
+
case "list":
|
|
13556
|
+
return reduceListType(type);
|
|
13557
|
+
case "set":
|
|
13558
|
+
return reduceSetType(type);
|
|
13559
|
+
case "tuple":
|
|
13560
|
+
return reduceTupleType(type);
|
|
13561
|
+
case "record":
|
|
13562
|
+
return reduceRecordType(type);
|
|
13563
|
+
case "dictionary":
|
|
13564
|
+
return reduceDictionaryType(type);
|
|
13565
|
+
case "signature":
|
|
13566
|
+
return reduceSignatureType(type);
|
|
13567
|
+
case "value":
|
|
13568
|
+
return type;
|
|
13569
|
+
case "reference":
|
|
13570
|
+
return type;
|
|
13571
|
+
default:
|
|
13572
|
+
throw new Error(`Unknown type kind: ${type}`);
|
|
13573
|
+
}
|
|
13574
|
+
}
|
|
13575
|
+
function decorate(t) {
|
|
13576
|
+
if (typeof t !== "object") return t;
|
|
13577
|
+
if (Object.isFrozen(t) || Object.prototype.hasOwnProperty.call(t, "toString"))
|
|
13578
|
+
return t;
|
|
13579
|
+
Object.defineProperty(t, "toString", { value: () => typeToString(t) });
|
|
13580
|
+
return t;
|
|
13581
|
+
}
|
|
13582
|
+
function reduceMembers(types) {
|
|
13583
|
+
const result = [];
|
|
13584
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13585
|
+
for (const t of types) {
|
|
13586
|
+
const reduced = reduceType(t);
|
|
13587
|
+
const key = typeof reduced === "string" ? reduced : typeToString(reduced);
|
|
13588
|
+
if (!seen.has(key)) {
|
|
13589
|
+
seen.add(key);
|
|
13590
|
+
result.push(reduced);
|
|
13591
|
+
}
|
|
13592
|
+
}
|
|
13593
|
+
return result;
|
|
13594
|
+
}
|
|
13595
|
+
function reduceNegationType(type) {
|
|
13596
|
+
const reducedType = reduceType(type.type);
|
|
13597
|
+
if (reducedType === "nothing") return "any";
|
|
13598
|
+
if (reducedType === "any") return "nothing";
|
|
13599
|
+
return decorate({ kind: "negation", type: reducedType });
|
|
13600
|
+
}
|
|
13601
|
+
function reduceUnionType(type) {
|
|
13602
|
+
const reducedTypes = reduceMembers(type.types);
|
|
13603
|
+
if (reducedTypes.length === 0) return "never";
|
|
13604
|
+
if (reducedTypes.some((type2) => type2 === "error")) return "error";
|
|
13605
|
+
if (reducedTypes.length === 1) return decorate(reducedTypes[0]);
|
|
13606
|
+
const acc = [];
|
|
13607
|
+
for (const current of reducedTypes) {
|
|
13608
|
+
if (acc.some((t) => isSubtype(current, t))) continue;
|
|
13609
|
+
for (let i = acc.length - 1; i >= 0; i--)
|
|
13610
|
+
if (isSubtype(acc[i], current)) acc.splice(i, 1);
|
|
13611
|
+
acc.push(current);
|
|
13612
|
+
}
|
|
13613
|
+
if (acc.length === 1) return decorate(acc[0]);
|
|
13614
|
+
return decorate({ kind: "union", types: acc });
|
|
13615
|
+
}
|
|
13616
|
+
function meet2(a, b) {
|
|
13617
|
+
if (isSubtype(a, b)) return a;
|
|
13618
|
+
if (isSubtype(b, a)) return b;
|
|
13619
|
+
if (typeof a === "object" && a.kind === "union") return meetUnion(a.types, b);
|
|
13620
|
+
if (typeof b === "object" && b.kind === "union") return meetUnion(b.types, a);
|
|
13621
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
13622
|
+
const maximals = meetPrimitiveTypes(a, b);
|
|
13623
|
+
if (maximals.length === 0) return "nothing";
|
|
13624
|
+
if (maximals.length === 1) return maximals[0];
|
|
13625
|
+
return { kind: "union", types: maximals };
|
|
13626
|
+
}
|
|
13627
|
+
return "nothing";
|
|
13628
|
+
}
|
|
13629
|
+
function meetUnion(types, b) {
|
|
13630
|
+
const members = types.map((t) => meet2(t, b)).filter((t) => t !== "nothing");
|
|
13631
|
+
if (members.length === 0) return "nothing";
|
|
13632
|
+
if (members.length === 1) return members[0];
|
|
13633
|
+
return reduceUnionType({ kind: "union", types: members });
|
|
13634
|
+
}
|
|
13635
|
+
function reduceIntersectionType(type) {
|
|
13636
|
+
const reducedTypes = reduceMembers(type.types);
|
|
13637
|
+
if (reducedTypes.length === 0) return "nothing";
|
|
13638
|
+
if (reducedTypes.some((type2) => type2 === "error")) return "error";
|
|
13639
|
+
let result = reducedTypes[0];
|
|
13640
|
+
for (let i = 1; i < reducedTypes.length; i++) {
|
|
13641
|
+
result = meet2(result, reducedTypes[i]);
|
|
13642
|
+
if (result === "nothing") return "nothing";
|
|
13643
|
+
}
|
|
13644
|
+
return decorate(result);
|
|
13645
|
+
}
|
|
13646
|
+
function reduceCollectionType(kind, type) {
|
|
13647
|
+
const reducedType = reduceType(type.elements);
|
|
13648
|
+
if (reducedType === "error") return "error";
|
|
13649
|
+
if (reducedType === "nothing") return decorate({ kind, elements: "nothing" });
|
|
13650
|
+
if (reducedType === "any") return kind;
|
|
13651
|
+
return decorate({
|
|
13652
|
+
...type,
|
|
13653
|
+
elements: reducedType
|
|
13654
|
+
});
|
|
13655
|
+
}
|
|
13656
|
+
function reduceListType(type) {
|
|
13657
|
+
const reducedType = reduceType(type.elements);
|
|
13658
|
+
if (reducedType === "error") return "error";
|
|
13659
|
+
if (reducedType === "nothing")
|
|
13660
|
+
return decorate({ kind: "list", elements: "nothing" });
|
|
13661
|
+
if (reducedType === "any") return "list";
|
|
13662
|
+
let dimensions = type.dimensions;
|
|
13663
|
+
if (dimensions) {
|
|
13664
|
+
dimensions = dimensions.filter((dim) => dim >= 1 || dim === -1);
|
|
13665
|
+
if (dimensions.length === 0) return "nothing";
|
|
13666
|
+
}
|
|
13667
|
+
return decorate({
|
|
13668
|
+
...type,
|
|
13669
|
+
dimensions,
|
|
13670
|
+
elements: reducedType
|
|
13671
|
+
});
|
|
13672
|
+
}
|
|
13673
|
+
function reduceSetType(type) {
|
|
13674
|
+
const reducedType = reduceType(type.elements);
|
|
13675
|
+
if (reducedType === "error") return "error";
|
|
13676
|
+
if (reducedType === "nothing")
|
|
13677
|
+
return decorate({ kind: "set", elements: "nothing" });
|
|
13678
|
+
if (reducedType === "any") return "set";
|
|
13679
|
+
return decorate({
|
|
13680
|
+
...type,
|
|
13681
|
+
elements: reducedType
|
|
13682
|
+
});
|
|
13683
|
+
}
|
|
13684
|
+
function reduceTupleType(type) {
|
|
13685
|
+
let reducedElements = type.elements.map((element) => ({
|
|
13686
|
+
...element,
|
|
13687
|
+
type: reduceType(element.type)
|
|
13688
|
+
}));
|
|
13689
|
+
if (reducedElements.length === 0) return "nothing";
|
|
13690
|
+
if (reducedElements.some((element) => element.type === "error"))
|
|
13691
|
+
return "error";
|
|
13692
|
+
reducedElements = reducedElements.filter(
|
|
13693
|
+
(element) => element.type !== "nothing"
|
|
13694
|
+
);
|
|
13695
|
+
return decorate({
|
|
13696
|
+
...type,
|
|
13697
|
+
elements: reducedElements
|
|
13698
|
+
});
|
|
13699
|
+
}
|
|
13700
|
+
function reduceRecordType(type) {
|
|
13701
|
+
let reducedElements = {};
|
|
13702
|
+
for (const [key, value] of Object.entries(type.elements))
|
|
13703
|
+
reducedElements[key] = reduceType(value);
|
|
13704
|
+
if (Object.values(reducedElements).some((type2) => type2 === "error"))
|
|
13705
|
+
return "error";
|
|
13706
|
+
reducedElements = Object.fromEntries(
|
|
13707
|
+
Object.entries(reducedElements).filter(([_, value]) => value !== "nothing")
|
|
13708
|
+
);
|
|
13709
|
+
if (Object.keys(reducedElements).length === 0) return "record";
|
|
13710
|
+
return decorate({
|
|
13711
|
+
...type,
|
|
13712
|
+
elements: reducedElements
|
|
13713
|
+
});
|
|
13714
|
+
}
|
|
13715
|
+
function reduceDictionaryType(type) {
|
|
13716
|
+
const reducedValues = reduceType(type.values);
|
|
13717
|
+
if (reducedValues === "error") return "error";
|
|
13718
|
+
if (reducedValues === "nothing") return "error";
|
|
13719
|
+
if (reducedValues === "any" || reducedValues === "unknown") return "any";
|
|
13720
|
+
return decorate({ kind: "dictionary", values: reducedValues });
|
|
13721
|
+
}
|
|
13722
|
+
function reduceSignatureType(type) {
|
|
13723
|
+
const reducedArgs = type.args?.map((arg) => ({
|
|
13724
|
+
...arg,
|
|
13725
|
+
type: reduceType(arg.type)
|
|
13726
|
+
}));
|
|
13727
|
+
let reducedOptArgs = type.optArgs?.map((arg) => ({
|
|
13728
|
+
...arg,
|
|
13729
|
+
type: reduceType(arg.type)
|
|
13730
|
+
}));
|
|
13731
|
+
let reducedVarArg = type.variadicArg ? {
|
|
13732
|
+
...type.variadicArg,
|
|
13733
|
+
type: reduceType(type.variadicArg.type)
|
|
13734
|
+
} : void 0;
|
|
13735
|
+
const reducedResult = reduceType(type.result);
|
|
13736
|
+
if (reducedArgs?.some((arg) => arg.type === "error")) return "error";
|
|
13737
|
+
if (reducedOptArgs?.some((arg) => arg.type === "error")) return "error";
|
|
13738
|
+
if (reducedVarArg?.type === "error") return "error";
|
|
13739
|
+
if (reducedResult === "error") return "error";
|
|
13740
|
+
reducedOptArgs = reducedOptArgs?.filter((arg) => arg.type !== "nothing");
|
|
13741
|
+
if (reducedArgs?.length === 0) reducedOptArgs = void 0;
|
|
13742
|
+
if (reducedOptArgs?.length === 0) reducedOptArgs = void 0;
|
|
13743
|
+
if (reducedVarArg?.type === "nothing") reducedVarArg = void 0;
|
|
13744
|
+
return decorate({
|
|
13745
|
+
...type,
|
|
13746
|
+
args: reducedArgs,
|
|
13747
|
+
optArgs: reducedOptArgs,
|
|
13748
|
+
variadicArg: reducedVarArg,
|
|
13749
|
+
variadicMin: reducedVarArg ? type.variadicMin : void 0,
|
|
13750
|
+
result: reducedResult
|
|
13751
|
+
});
|
|
13752
|
+
}
|
|
13753
|
+
|
|
13754
|
+
// src/compute-engine/library/sets.ts
|
|
13755
|
+
function typeIntersection(a, b) {
|
|
13756
|
+
return reduceType({ kind: "intersection", types: [a, b] });
|
|
13757
|
+
}
|
|
13758
|
+
function typeMembership(x, t) {
|
|
13759
|
+
const vt = x.type;
|
|
13760
|
+
if (vt.matches(t)) return true;
|
|
13761
|
+
if (typeIntersection(vt.type, t) === "nothing") return false;
|
|
13762
|
+
if (isNumber(x)) return false;
|
|
13763
|
+
return void 0;
|
|
13764
|
+
}
|
|
13765
|
+
|
|
12956
13766
|
// src/compute-engine/library/collections.ts
|
|
12957
13767
|
var DEFAULT_LINSPACE_COUNT = 50;
|
|
13768
|
+
var SET_BASE_HANDLERS = basicIndexedCollectionHandlers();
|
|
12958
13769
|
var COLLECTIONS_LIBRARY = {
|
|
12959
13770
|
//
|
|
12960
13771
|
// Data Structures
|
|
@@ -12977,11 +13788,38 @@ ${lines.join("\n")}`;
|
|
|
12977
13788
|
},
|
|
12978
13789
|
// Extensional set. Elements do not repeat. The order of the elements is not significant.
|
|
12979
13790
|
// For intensional set, use `Filter` with a condition, e.g. `Filter(RealNumbers, _ > 0)`
|
|
13791
|
+
//
|
|
13792
|
+
// A `Set` expression can also be a set-builder (comprehension), e.g.
|
|
13793
|
+
// `["Set", body, ["Element", k, domain, cond?]]` or
|
|
13794
|
+
// `["Set", body, ["Condition", ...]]` (see `parseSetComprehension()`).
|
|
13795
|
+
// Comprehensions are not literal 2-element sets: their elements are the
|
|
13796
|
+
// substituted bodies over the (filtered) domain.
|
|
12980
13797
|
Set: {
|
|
12981
13798
|
complexity: 8200,
|
|
12982
13799
|
signature: "(any*) -> set",
|
|
12983
|
-
type: (ops, { engine: _ce }) =>
|
|
13800
|
+
type: (ops, { engine: _ce }) => {
|
|
13801
|
+
if (parseSetComprehension(ops) !== null) return parseType("set");
|
|
13802
|
+
return parseType(`set<${BoxedType.widen(...ops.map((op) => op.type))}>`);
|
|
13803
|
+
},
|
|
12984
13804
|
canonical: canonicalSet,
|
|
13805
|
+
// The `lazy` flag suppresses the default operand evaluation: evaluating
|
|
13806
|
+
// the operands of a comprehension would mangle its indexing set (e.g.
|
|
13807
|
+
// the condition `gcd(n,k) = 1` with a free `k` evaluates to `False`).
|
|
13808
|
+
// Literal elements are evaluated explicitly in the `evaluate` handler.
|
|
13809
|
+
lazy: true,
|
|
13810
|
+
evaluate: (ops, { engine: ce, numericApproximation, materialization }) => {
|
|
13811
|
+
const comp = parseSetComprehension(ops);
|
|
13812
|
+
if (comp !== null) {
|
|
13813
|
+
const elements = enumerateSetComprehension(comp);
|
|
13814
|
+
if (elements === void 0 || elements.length > MAX_SIZE_EAGER_COLLECTION)
|
|
13815
|
+
return void 0;
|
|
13816
|
+
return ce.function("Set", elements);
|
|
13817
|
+
}
|
|
13818
|
+
return ce.function(
|
|
13819
|
+
"Set",
|
|
13820
|
+
ops.map((op) => op.evaluate({ numericApproximation, materialization }))
|
|
13821
|
+
);
|
|
13822
|
+
},
|
|
12985
13823
|
eq: (a, b) => {
|
|
12986
13824
|
if (a.operator !== b.operator) return false;
|
|
12987
13825
|
if (!isFunction2(a) || !isFunction2(b)) return false;
|
|
@@ -12990,10 +13828,75 @@ ${lines.join("\n")}`;
|
|
|
12990
13828
|
return a.ops.every(has);
|
|
12991
13829
|
},
|
|
12992
13830
|
collection: {
|
|
12993
|
-
...
|
|
13831
|
+
...SET_BASE_HANDLERS,
|
|
12994
13832
|
// A set is not indexable
|
|
12995
13833
|
at: void 0,
|
|
12996
|
-
indexWhere: void 0
|
|
13834
|
+
indexWhere: void 0,
|
|
13835
|
+
// A comprehension computes its elements on demand
|
|
13836
|
+
isLazy: (expr) => isFunction2(expr) && parseSetComprehension(expr.ops) !== null,
|
|
13837
|
+
count: (expr) => {
|
|
13838
|
+
if (!isFunction2(expr)) return 0;
|
|
13839
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13840
|
+
if (comp === null) return expr.nops;
|
|
13841
|
+
return enumerateSetComprehension(comp)?.length;
|
|
13842
|
+
},
|
|
13843
|
+
isEmpty: (expr) => {
|
|
13844
|
+
if (!isFunction2(expr)) return true;
|
|
13845
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13846
|
+
if (comp === null) return expr.nops === 0;
|
|
13847
|
+
const elements = enumerateSetComprehension(comp);
|
|
13848
|
+
return elements === void 0 ? void 0 : elements.length === 0;
|
|
13849
|
+
},
|
|
13850
|
+
isFinite: (expr) => {
|
|
13851
|
+
if (!isFunction2(expr)) return true;
|
|
13852
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13853
|
+
if (comp === null) return true;
|
|
13854
|
+
if (enumerateSetComprehension(comp) !== void 0) return true;
|
|
13855
|
+
if (comp.domain?.isFiniteCollection === true) return true;
|
|
13856
|
+
return void 0;
|
|
13857
|
+
},
|
|
13858
|
+
iterator: (expr) => {
|
|
13859
|
+
if (!isFunction2(expr)) return SET_BASE_HANDLERS.iterator(expr);
|
|
13860
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13861
|
+
if (comp === null) return SET_BASE_HANDLERS.iterator(expr);
|
|
13862
|
+
const elements = enumerateSetComprehension(comp);
|
|
13863
|
+
if (elements === void 0) return void 0;
|
|
13864
|
+
let i = 0;
|
|
13865
|
+
return {
|
|
13866
|
+
next: () => i >= elements.length ? { value: void 0, done: true } : { value: elements[i++], done: false }
|
|
13867
|
+
};
|
|
13868
|
+
},
|
|
13869
|
+
// Three-valued membership: `true` when an element matches, `false`
|
|
13870
|
+
// only when every element is definitively different from `target`
|
|
13871
|
+
// (concrete values), `undefined` otherwise — e.g. a symbolic target
|
|
13872
|
+
// (`Element(ω, {-1, 1})`) is indeterminate, not refuted.
|
|
13873
|
+
contains: (expr, target) => {
|
|
13874
|
+
if (!isFunction2(expr)) return void 0;
|
|
13875
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13876
|
+
if (comp !== null) return setComprehensionContains(comp, target);
|
|
13877
|
+
return literalSetContains(expr.ops, target);
|
|
13878
|
+
},
|
|
13879
|
+
elttype: (expr) => {
|
|
13880
|
+
if (!isFunction2(expr)) return SET_BASE_HANDLERS.elttype(expr);
|
|
13881
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13882
|
+
if (comp === null) return SET_BASE_HANDLERS.elttype(expr);
|
|
13883
|
+
const elements = enumerateSetComprehension(comp);
|
|
13884
|
+
if (elements === void 0 || elements.length === 0) return "unknown";
|
|
13885
|
+
return widen(...elements.map((op) => op.type.type));
|
|
13886
|
+
}
|
|
13887
|
+
}
|
|
13888
|
+
},
|
|
13889
|
+
Length: {
|
|
13890
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
13891
|
+
complexity: 4e3,
|
|
13892
|
+
signature: "(any) -> integer",
|
|
13893
|
+
type: () => "integer",
|
|
13894
|
+
evaluate: ([xs], { engine }) => {
|
|
13895
|
+
if (!xs.isCollection) return void 0;
|
|
13896
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
13897
|
+
const n = xs.count;
|
|
13898
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
13899
|
+
return engine.number(n);
|
|
12997
13900
|
}
|
|
12998
13901
|
},
|
|
12999
13902
|
Tuple: {
|
|
@@ -13080,7 +13983,12 @@ ${lines.join("\n")}`;
|
|
|
13080
13983
|
},
|
|
13081
13984
|
contains: (expr, target) => {
|
|
13082
13985
|
const t = target.re;
|
|
13986
|
+
if (Number.isNaN(t))
|
|
13987
|
+
return typeMembership(target, "number") === false ? false : void 0;
|
|
13988
|
+
if (target.im !== 0) return false;
|
|
13083
13989
|
if (!isFinite(t)) return false;
|
|
13990
|
+
if (isFunction2(expr) && expr.ops.some((op) => Number.isNaN(op.re)))
|
|
13991
|
+
return void 0;
|
|
13084
13992
|
const [lower, upper, step] = range(expr);
|
|
13085
13993
|
if (step === 0) return false;
|
|
13086
13994
|
if (step > 0) {
|
|
@@ -13156,13 +14064,23 @@ ${lines.join("\n")}`;
|
|
|
13156
14064
|
signature: "(number, number) -> set<real>",
|
|
13157
14065
|
canonical: ([lo, hi], { engine }) => {
|
|
13158
14066
|
if (!lo || !hi) return null;
|
|
14067
|
+
const unwrap2 = (op) => {
|
|
14068
|
+
if (isFunction2(op, "Open")) return [op.op1, true];
|
|
14069
|
+
if (isFunction2(op, "Closed")) return [op.op1, false];
|
|
14070
|
+
return [op, false];
|
|
14071
|
+
};
|
|
14072
|
+
const [loVal, loOpen] = unwrap2(lo);
|
|
14073
|
+
const [hiVal, hiOpen] = unwrap2(hi);
|
|
13159
14074
|
const [lower, upper] = checkTypes(
|
|
13160
14075
|
engine,
|
|
13161
|
-
[
|
|
14076
|
+
[loVal.canonical, hiVal.canonical],
|
|
13162
14077
|
["number", "number"]
|
|
13163
14078
|
);
|
|
13164
14079
|
if (!lower.isValid || !upper.isValid) return null;
|
|
13165
|
-
return engine._fn("Interval", [
|
|
14080
|
+
return engine._fn("Interval", [
|
|
14081
|
+
loOpen ? engine._fn("Open", [lower]) : lower,
|
|
14082
|
+
hiOpen ? engine._fn("Open", [upper]) : upper
|
|
14083
|
+
]);
|
|
13166
14084
|
},
|
|
13167
14085
|
eq: (a, b) => {
|
|
13168
14086
|
const intervalA = interval(a);
|
|
@@ -13197,19 +14115,32 @@ ${lines.join("\n")}`;
|
|
|
13197
14115
|
},
|
|
13198
14116
|
isEmpty: (_expr) => {
|
|
13199
14117
|
const int = interval(_expr);
|
|
13200
|
-
if (!int) return
|
|
14118
|
+
if (!int) return void 0;
|
|
13201
14119
|
if (int.openStart && int.start === int.end) return true;
|
|
13202
14120
|
if (int.openEnd && int.start === int.end) return true;
|
|
13203
14121
|
if (int.openStart && int.openEnd) return false;
|
|
13204
14122
|
return int.start >= int.end;
|
|
13205
14123
|
},
|
|
13206
14124
|
isFinite: (_expr) => false,
|
|
14125
|
+
// Three-valued membership: `true` only when both bound checks are
|
|
14126
|
+
// entailed, `false` when a bound check (or the type of the target)
|
|
14127
|
+
// refutes membership, `undefined` otherwise (e.g. symbolic target
|
|
14128
|
+
// with unknown bounds). Endpoints may be ±Infinity.
|
|
13207
14129
|
contains: (expr, target) => {
|
|
13208
14130
|
const int = interval(expr);
|
|
13209
|
-
if (!int) return
|
|
13210
|
-
if (
|
|
13211
|
-
|
|
13212
|
-
|
|
14131
|
+
if (!int) return void 0;
|
|
14132
|
+
if (typeMembership(target, "number") === false) return false;
|
|
14133
|
+
const t = target.re;
|
|
14134
|
+
if (!Number.isNaN(t)) {
|
|
14135
|
+
if (target.im !== 0) return false;
|
|
14136
|
+
return intervalContains(int, t);
|
|
14137
|
+
}
|
|
14138
|
+
const aboveLower = int.openStart ? target.isGreater(int.start) : target.isGreaterEqual(int.start);
|
|
14139
|
+
if (aboveLower === false) return false;
|
|
14140
|
+
const belowUpper = int.openEnd ? target.isLess(int.end) : target.isLessEqual(int.end);
|
|
14141
|
+
if (belowUpper === false) return false;
|
|
14142
|
+
if (aboveLower === true && belowUpper === true) return true;
|
|
14143
|
+
return void 0;
|
|
13213
14144
|
},
|
|
13214
14145
|
eltsgn: (expr) => {
|
|
13215
14146
|
const i = interval(expr);
|
|
@@ -13249,10 +14180,12 @@ ${lines.join("\n")}`;
|
|
|
13249
14180
|
const upper = expr.op2.re;
|
|
13250
14181
|
let count = expr.op3.re;
|
|
13251
14182
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
14183
|
+
count = Math.floor(count);
|
|
13252
14184
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
13253
14185
|
if (index < 1 || index > count) return void 0;
|
|
14186
|
+
if (count === 1) return expr.engine.number(lower);
|
|
13254
14187
|
return expr.engine.number(
|
|
13255
|
-
lower + (upper - lower) * (index - 1) / count
|
|
14188
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
13256
14189
|
);
|
|
13257
14190
|
},
|
|
13258
14191
|
iterator: (expr) => {
|
|
@@ -13271,6 +14204,8 @@ ${lines.join("\n")}`;
|
|
|
13271
14204
|
!isFinite(expr.op3.re) ? DEFAULT_LINSPACE_COUNT : expr.op3.re
|
|
13272
14205
|
);
|
|
13273
14206
|
}
|
|
14207
|
+
totalCount = Math.floor(totalCount);
|
|
14208
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
13274
14209
|
let index = 1;
|
|
13275
14210
|
return {
|
|
13276
14211
|
next: () => {
|
|
@@ -13279,7 +14214,7 @@ ${lines.join("\n")}`;
|
|
|
13279
14214
|
index += 1;
|
|
13280
14215
|
return {
|
|
13281
14216
|
value: expr.engine.number(
|
|
13282
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
14217
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
13283
14218
|
),
|
|
13284
14219
|
done: false
|
|
13285
14220
|
};
|
|
@@ -13287,17 +14222,26 @@ ${lines.join("\n")}`;
|
|
|
13287
14222
|
};
|
|
13288
14223
|
},
|
|
13289
14224
|
contains: (expr, target) => {
|
|
13290
|
-
if (!target.type.matches("finite_real")) return false;
|
|
13291
|
-
if (!isFunction2(expr)) return false;
|
|
13292
14225
|
const t = target.re;
|
|
14226
|
+
if (Number.isNaN(t))
|
|
14227
|
+
return typeMembership(target, "number") === false ? false : void 0;
|
|
14228
|
+
if (target.im !== 0) return false;
|
|
14229
|
+
if (!isFinite(t)) return false;
|
|
14230
|
+
if (!isFunction2(expr)) return void 0;
|
|
13293
14231
|
const lower = expr.op1.re;
|
|
13294
14232
|
const upper = expr.op2.re;
|
|
14233
|
+
if (Number.isNaN(lower) || Number.isNaN(upper)) return void 0;
|
|
13295
14234
|
if (t < lower || t > upper) return false;
|
|
13296
14235
|
let count = expr.op3.re;
|
|
13297
14236
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
14237
|
+
count = Math.floor(count);
|
|
13298
14238
|
if (count === 0) return false;
|
|
13299
|
-
|
|
13300
|
-
|
|
14239
|
+
if (count === 1) return t === lower;
|
|
14240
|
+
const step = (upper - lower) / (count - 1);
|
|
14241
|
+
const k = (t - lower) / step;
|
|
14242
|
+
const tol = expr.engine.tolerance;
|
|
14243
|
+
const kRounded = Math.round(k);
|
|
14244
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
13301
14245
|
}
|
|
13302
14246
|
}
|
|
13303
14247
|
},
|
|
@@ -13316,8 +14260,18 @@ ${lines.join("\n")}`;
|
|
|
13316
14260
|
description: ["Return the number of elements in the collection."],
|
|
13317
14261
|
complexity: 8200,
|
|
13318
14262
|
signature: "(collection) -> integer",
|
|
13319
|
-
evaluate: ([xs], { engine }) =>
|
|
13320
|
-
|
|
14263
|
+
evaluate: ([xs], { engine }) => {
|
|
14264
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
14265
|
+
const n = xs.count;
|
|
14266
|
+
if (n === void 0) return void 0;
|
|
14267
|
+
return engine.number(n);
|
|
14268
|
+
},
|
|
14269
|
+
sgn: ([xs]) => {
|
|
14270
|
+
const empty = xs.isEmptyCollection;
|
|
14271
|
+
if (empty === true) return "zero";
|
|
14272
|
+
if (empty === false) return "positive";
|
|
14273
|
+
return void 0;
|
|
14274
|
+
}
|
|
13321
14275
|
},
|
|
13322
14276
|
IsEmpty: {
|
|
13323
14277
|
description: ["Return True if the collection is empty, False otherwise."],
|
|
@@ -13433,7 +14387,13 @@ ${lines.join("\n")}`;
|
|
|
13433
14387
|
},
|
|
13434
14388
|
collection: {
|
|
13435
14389
|
isLazy: (_expr) => true,
|
|
13436
|
-
count: (
|
|
14390
|
+
count: (expr) => {
|
|
14391
|
+
if (!isFunction2(expr)) return void 0;
|
|
14392
|
+
if (!expr.op1.isFiniteCollection) return Infinity;
|
|
14393
|
+
let n = 0;
|
|
14394
|
+
for (const _ of expr.each()) n++;
|
|
14395
|
+
return n;
|
|
14396
|
+
},
|
|
13437
14397
|
contains: (expr, target) => {
|
|
13438
14398
|
if (!isFunction2(expr)) return false;
|
|
13439
14399
|
if (!expr.contains(target)) return false;
|
|
@@ -13542,24 +14502,26 @@ ${lines.join("\n")}`;
|
|
|
13542
14502
|
type: (ops) => parseType(functionResult(ops[1].type.type) ?? "unknown"),
|
|
13543
14503
|
evaluate: ([collection, fn, initial], { engine: ce }) => {
|
|
13544
14504
|
if (!collection.isFiniteCollection) return void 0;
|
|
14505
|
+
const hasInitial = initial !== void 0;
|
|
13545
14506
|
initial ??= ce.Nothing;
|
|
13546
14507
|
if (initial.type.matches("real") && collection.type.matches(ce.type("collection<real>"))) {
|
|
13547
14508
|
const compiled = ce._compile(fn);
|
|
13548
|
-
if (compiled.calling
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
14509
|
+
if (compiled.calling === "lambda" && compiled.run) {
|
|
14510
|
+
return run(
|
|
14511
|
+
(function* () {
|
|
14512
|
+
let accumulator = hasInitial ? initial.re : NaN;
|
|
14513
|
+
let first = true;
|
|
14514
|
+
for (const item of collection.each()) {
|
|
14515
|
+
if (first && !hasInitial) accumulator = item.re;
|
|
14516
|
+
else accumulator = compiled.run(accumulator, item.re);
|
|
14517
|
+
first = false;
|
|
14518
|
+
yield;
|
|
14519
|
+
}
|
|
14520
|
+
return ce.expr(accumulator);
|
|
14521
|
+
})(),
|
|
14522
|
+
ce._timeRemaining
|
|
14523
|
+
);
|
|
14524
|
+
}
|
|
13563
14525
|
}
|
|
13564
14526
|
const f = applicable(fn);
|
|
13565
14527
|
return run(
|
|
@@ -13622,10 +14584,12 @@ ${lines.join("\n")}`;
|
|
|
13622
14584
|
description: [
|
|
13623
14585
|
"Access an element of an indexed collection.",
|
|
13624
14586
|
"If the index is negative, it is counted from the end.",
|
|
13625
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
14587
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
14588
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
14589
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
13626
14590
|
],
|
|
13627
14591
|
complexity: 8200,
|
|
13628
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
14592
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
13629
14593
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
13630
14594
|
evaluate: (ops, { engine: ce }) => {
|
|
13631
14595
|
let expr = ops[0];
|
|
@@ -13636,12 +14600,39 @@ ${lines.join("\n")}`;
|
|
|
13636
14600
|
if (!at) return void 0;
|
|
13637
14601
|
const opAtIndex = ops[index];
|
|
13638
14602
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
13639
|
-
if (s !== void 0)
|
|
13640
|
-
|
|
13641
|
-
|
|
13642
|
-
|
|
13643
|
-
|
|
14603
|
+
if (s !== void 0) {
|
|
14604
|
+
expr = at(expr, s) ?? ce.Nothing;
|
|
14605
|
+
index += 1;
|
|
14606
|
+
continue;
|
|
14607
|
+
}
|
|
14608
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
14609
|
+
const indices = Array.from(opAtIndex.each());
|
|
14610
|
+
const isMask = indices.every((m) => {
|
|
14611
|
+
const name = sym(m);
|
|
14612
|
+
return name === "True" || name === "False";
|
|
14613
|
+
});
|
|
14614
|
+
const picked = [];
|
|
14615
|
+
if (isMask) {
|
|
14616
|
+
indices.forEach((m, i2) => {
|
|
14617
|
+
if (sym(m) !== "True") return;
|
|
14618
|
+
const v = at(expr, i2 + 1);
|
|
14619
|
+
if (v !== void 0) picked.push(v);
|
|
14620
|
+
});
|
|
14621
|
+
} else {
|
|
14622
|
+
for (const m of indices) {
|
|
14623
|
+
const k = m.re;
|
|
14624
|
+
if (!Number.isInteger(k)) return void 0;
|
|
14625
|
+
const v = at(expr, k);
|
|
14626
|
+
if (v !== void 0) picked.push(v);
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
expr = ce._fn("List", picked);
|
|
14630
|
+
index += 1;
|
|
14631
|
+
continue;
|
|
13644
14632
|
}
|
|
14633
|
+
const i = opAtIndex.re;
|
|
14634
|
+
if (!Number.isInteger(i)) return void 0;
|
|
14635
|
+
expr = at(expr, i) ?? ce.Nothing;
|
|
13645
14636
|
index += 1;
|
|
13646
14637
|
}
|
|
13647
14638
|
return expr;
|
|
@@ -13652,7 +14643,7 @@ ${lines.join("\n")}`;
|
|
|
13652
14643
|
description: ["Return `n` elements from a collection."],
|
|
13653
14644
|
complexity: 8200,
|
|
13654
14645
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13655
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14646
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13656
14647
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
13657
14648
|
if (!eager) return void 0;
|
|
13658
14649
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -13699,7 +14690,7 @@ ${lines.join("\n")}`;
|
|
|
13699
14690
|
description: ["Return the collection without the first n elements."],
|
|
13700
14691
|
complexity: 8200,
|
|
13701
14692
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13702
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14693
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13703
14694
|
collection: {
|
|
13704
14695
|
isLazy: (_expr) => true,
|
|
13705
14696
|
count: (expr) => {
|
|
@@ -13723,10 +14714,13 @@ ${lines.join("\n")}`;
|
|
|
13723
14714
|
const [xs, nExpr] = expr.ops;
|
|
13724
14715
|
const n = toInteger(nExpr) ?? 0;
|
|
13725
14716
|
if (n <= 0) return xs.each();
|
|
14717
|
+
const count = xs.count;
|
|
13726
14718
|
let index = n + 1;
|
|
13727
14719
|
return {
|
|
13728
14720
|
next: () => {
|
|
13729
|
-
|
|
14721
|
+
if (count !== void 0 && index > count)
|
|
14722
|
+
return { value: void 0, done: true };
|
|
14723
|
+
const value = xs.at(index++);
|
|
13730
14724
|
if (value === void 0) return { value: void 0, done: true };
|
|
13731
14725
|
return { value, done: false };
|
|
13732
14726
|
}
|
|
@@ -13737,7 +14731,13 @@ ${lines.join("\n")}`;
|
|
|
13737
14731
|
if (!isFunction2(expr)) return void 0;
|
|
13738
14732
|
const [xs, nExpr] = expr.ops;
|
|
13739
14733
|
const n = toInteger(nExpr) ?? 0;
|
|
13740
|
-
if (n <= 0) return
|
|
14734
|
+
if (n <= 0) return xs.at(index);
|
|
14735
|
+
if (index < 0) {
|
|
14736
|
+
const count = xs.count;
|
|
14737
|
+
if (count !== void 0 && -index > count - n) return void 0;
|
|
14738
|
+
return xs.at(index);
|
|
14739
|
+
}
|
|
14740
|
+
if (index < 1) return void 0;
|
|
13741
14741
|
return xs.at(index + n);
|
|
13742
14742
|
}
|
|
13743
14743
|
}
|
|
@@ -13819,11 +14819,15 @@ ${lines.join("\n")}`;
|
|
|
13819
14819
|
iterator: (expr) => {
|
|
13820
14820
|
if (!isFunction2(expr))
|
|
13821
14821
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14822
|
+
const op1 = expr.op1;
|
|
14823
|
+
const count = op1.count;
|
|
14824
|
+
let index = 2;
|
|
13822
14825
|
return {
|
|
13823
14826
|
next: () => {
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
14827
|
+
if (count !== void 0 && index > count)
|
|
14828
|
+
return { value: void 0, done: true };
|
|
14829
|
+
const value = op1.at(index);
|
|
14830
|
+
if (value === void 0) return { value: void 0, done: true };
|
|
13827
14831
|
index += 1;
|
|
13828
14832
|
return { value, done: false };
|
|
13829
14833
|
}
|
|
@@ -13895,17 +14899,24 @@ ${lines.join("\n")}`;
|
|
|
13895
14899
|
],
|
|
13896
14900
|
complexity: 8200,
|
|
13897
14901
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
13898
|
-
type: ([xs]) => parseType(
|
|
14902
|
+
type: ([xs]) => parseType(
|
|
14903
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
14904
|
+
),
|
|
13899
14905
|
collection: {
|
|
13900
14906
|
isLazy: (_expr) => true,
|
|
13901
14907
|
count: (expr) => {
|
|
13902
14908
|
if (!isFunction2(expr)) return void 0;
|
|
13903
|
-
const start = toInteger(expr.op2) ?? 1;
|
|
13904
14909
|
const count = expr.op1.count;
|
|
13905
14910
|
if (count === void 0) return void 0;
|
|
13906
|
-
|
|
13907
|
-
if (start < 1)
|
|
13908
|
-
|
|
14911
|
+
let start = toInteger(expr.op2) ?? 1;
|
|
14912
|
+
if (start < 1) start = count + 1 + start;
|
|
14913
|
+
if (start < 1) start = 1;
|
|
14914
|
+
if (start > count) return 0;
|
|
14915
|
+
let end = toInteger(expr.op3) ?? count;
|
|
14916
|
+
if (end < 1) end = count + 1 + end;
|
|
14917
|
+
if (end < 1) end = 1;
|
|
14918
|
+
if (end > count) end = count;
|
|
14919
|
+
return Math.max(0, end - start + 1);
|
|
13909
14920
|
},
|
|
13910
14921
|
isFinite: (_expr) => true,
|
|
13911
14922
|
at: (expr, index) => {
|
|
@@ -13921,6 +14932,11 @@ ${lines.join("\n")}`;
|
|
|
13921
14932
|
if (end < 1) end = count + 1 + end;
|
|
13922
14933
|
if (end < 1) end = 1;
|
|
13923
14934
|
if (end > count) end = count;
|
|
14935
|
+
const length = end - start + 1;
|
|
14936
|
+
if (length <= 0) return void 0;
|
|
14937
|
+
if (index < 0) index = length + 1 + index;
|
|
14938
|
+
if (index < 1 || index > length) return void 0;
|
|
14939
|
+
return expr.op1.at(start + index - 1);
|
|
13924
14940
|
},
|
|
13925
14941
|
iterator: (expr) => {
|
|
13926
14942
|
if (!isFunction2(expr))
|
|
@@ -14184,7 +15200,7 @@ ${lines.join("\n")}`;
|
|
|
14184
15200
|
for (const item of xs.each()) {
|
|
14185
15201
|
const pred = sym(f([item]));
|
|
14186
15202
|
if (pred === "True") indices.push(ce.number(index));
|
|
14187
|
-
if (pred !== "False")
|
|
15203
|
+
else if (pred !== "False")
|
|
14188
15204
|
throw new Error(
|
|
14189
15205
|
`Filter predicate must return "True" or "False". ${spellCheckMessage(
|
|
14190
15206
|
fn
|
|
@@ -14227,16 +15243,26 @@ ${lines.join("\n")}`;
|
|
|
14227
15243
|
},
|
|
14228
15244
|
// Randomize the order of the elements in the collection.
|
|
14229
15245
|
Shuffle: {
|
|
14230
|
-
description: "Randomize the order of the elements in the collection.",
|
|
15246
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
14231
15247
|
complexity: 8200,
|
|
14232
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
15248
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
14233
15249
|
type: (ops) => ops[0].type,
|
|
14234
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
15250
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
14235
15251
|
if (!xs.isFiniteCollection) return void 0;
|
|
14236
15252
|
const data = Array.from(xs.each());
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
15253
|
+
const seed = seedOp?.re;
|
|
15254
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
15255
|
+
let s = seed;
|
|
15256
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
15257
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
15258
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
15259
|
+
s = nextSeed(s);
|
|
15260
|
+
}
|
|
15261
|
+
} else {
|
|
15262
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
15263
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
15264
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
15265
|
+
}
|
|
14240
15266
|
}
|
|
14241
15267
|
return ce.function(xs.operator, data);
|
|
14242
15268
|
}
|
|
@@ -14303,7 +15329,9 @@ ${lines.join("\n")}`;
|
|
|
14303
15329
|
if (t === "string")
|
|
14304
15330
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
14305
15331
|
return parseType(
|
|
14306
|
-
`tuple<list<${
|
|
15332
|
+
`tuple<list<${typeToString(
|
|
15333
|
+
collectionElementType(t) ?? "any"
|
|
15334
|
+
)}>, list<integer>>`
|
|
14307
15335
|
);
|
|
14308
15336
|
},
|
|
14309
15337
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -14319,7 +15347,7 @@ ${lines.join("\n")}`;
|
|
|
14319
15347
|
description: "Return a list of the unique elements of the collection.",
|
|
14320
15348
|
complexity: 8200,
|
|
14321
15349
|
signature: "(collection) -> list",
|
|
14322
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
15350
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14323
15351
|
evaluate: (ops, { engine: ce }) => {
|
|
14324
15352
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
14325
15353
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -14331,7 +15359,7 @@ ${lines.join("\n")}`;
|
|
|
14331
15359
|
wikidata: "Q381060",
|
|
14332
15360
|
complexity: 8200,
|
|
14333
15361
|
signature: "(collection, integer | function) -> list",
|
|
14334
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
15362
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14335
15363
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
14336
15364
|
if (!xs.isFiniteCollection) return void 0;
|
|
14337
15365
|
const k = toInteger(arg);
|
|
@@ -14421,11 +15449,25 @@ ${lines.join("\n")}`;
|
|
|
14421
15449
|
count: zipCount,
|
|
14422
15450
|
isFinite: (expr) => {
|
|
14423
15451
|
if (!isFunction2(expr)) return void 0;
|
|
14424
|
-
|
|
15452
|
+
if (expr.nops === 0) return true;
|
|
15453
|
+
let anyUnknown = false;
|
|
15454
|
+
for (const x of expr.ops) {
|
|
15455
|
+
const f = x.isFiniteCollection;
|
|
15456
|
+
if (f === true) return true;
|
|
15457
|
+
if (f === void 0) anyUnknown = true;
|
|
15458
|
+
}
|
|
15459
|
+
return anyUnknown ? void 0 : false;
|
|
14425
15460
|
},
|
|
14426
15461
|
isEmpty: (expr) => {
|
|
14427
15462
|
if (!isFunction2(expr)) return void 0;
|
|
14428
|
-
|
|
15463
|
+
if (expr.nops === 0) return true;
|
|
15464
|
+
let anyUnknown = false;
|
|
15465
|
+
for (const x of expr.ops) {
|
|
15466
|
+
const e = x.isEmptyCollection;
|
|
15467
|
+
if (e === true) return true;
|
|
15468
|
+
if (e === void 0) anyUnknown = true;
|
|
15469
|
+
}
|
|
15470
|
+
return anyUnknown ? void 0 : false;
|
|
14429
15471
|
},
|
|
14430
15472
|
iterator: (expr) => {
|
|
14431
15473
|
if (!isFunction2(expr))
|
|
@@ -14505,32 +15547,74 @@ ${lines.join("\n")}`;
|
|
|
14505
15547
|
}
|
|
14506
15548
|
}
|
|
14507
15549
|
},
|
|
14508
|
-
// Repeat(x) -> [x, x, ...]
|
|
14509
|
-
//
|
|
14510
|
-
// x is evaluated once. Although could use Hold()?
|
|
14511
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
15550
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
15551
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
14512
15552
|
Repeat: {
|
|
14513
|
-
description: "Produce
|
|
15553
|
+
description: "Produce a sequence by repeating a single value. With 1 argument, returns an infinite sequence; with 2 arguments (value, count), returns a finite list of `count` copies.",
|
|
14514
15554
|
complexity: 8200,
|
|
14515
|
-
signature: "(value: any) -> list",
|
|
15555
|
+
signature: "(value: any, count: integer?) -> list",
|
|
15556
|
+
evaluate: (ops, { engine }) => {
|
|
15557
|
+
if (ops.length !== 2) return void 0;
|
|
15558
|
+
const raw = toInteger(ops[1]);
|
|
15559
|
+
if (raw === null) return void 0;
|
|
15560
|
+
const n = Math.max(0, raw);
|
|
15561
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
15562
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
15563
|
+
},
|
|
14516
15564
|
collection: {
|
|
14517
|
-
isLazy: (
|
|
14518
|
-
count: () =>
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14522
|
-
|
|
15565
|
+
isLazy: (expr) => isFunction2(expr) && expr.ops?.length === 1,
|
|
15566
|
+
count: (expr) => {
|
|
15567
|
+
if (!isFunction2(expr)) return void 0;
|
|
15568
|
+
if (expr.ops?.length === 2) {
|
|
15569
|
+
const n = toInteger(expr.op2);
|
|
15570
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
15571
|
+
}
|
|
15572
|
+
return Infinity;
|
|
15573
|
+
},
|
|
15574
|
+
isEmpty: (expr) => {
|
|
15575
|
+
if (!isFunction2(expr)) return void 0;
|
|
15576
|
+
if (expr.ops?.length === 2) {
|
|
15577
|
+
const n = toInteger(expr.op2);
|
|
15578
|
+
return n !== null ? n <= 0 : void 0;
|
|
15579
|
+
}
|
|
15580
|
+
return false;
|
|
15581
|
+
},
|
|
15582
|
+
isFinite: (expr) => isFunction2(expr) && expr.ops?.length === 2,
|
|
14523
15583
|
contains: (expr, target) => {
|
|
14524
15584
|
if (!isFunction2(expr)) return false;
|
|
15585
|
+
if (expr.ops?.length === 2) {
|
|
15586
|
+
const n = toInteger(expr.op2);
|
|
15587
|
+
if (n !== null && n <= 0) return false;
|
|
15588
|
+
}
|
|
14525
15589
|
return expr.op1.isSame(target);
|
|
14526
15590
|
},
|
|
14527
15591
|
iterator: (expr) => {
|
|
14528
15592
|
if (!isFunction2(expr))
|
|
14529
15593
|
return { next: () => ({ value: void 0, done: true }) };
|
|
15594
|
+
if (expr.ops?.length === 2) {
|
|
15595
|
+
const n = toInteger(expr.op2);
|
|
15596
|
+
if (n === null) {
|
|
15597
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
15598
|
+
}
|
|
15599
|
+
const count = Math.max(0, n);
|
|
15600
|
+
let i = 0;
|
|
15601
|
+
return {
|
|
15602
|
+
next: () => i++ < count ? { value: expr.op1, done: false } : { value: void 0, done: true }
|
|
15603
|
+
};
|
|
15604
|
+
}
|
|
14530
15605
|
return { next: () => ({ value: expr.op1, done: false }) };
|
|
14531
15606
|
},
|
|
14532
|
-
at
|
|
15607
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
15608
|
+
at: (expr, index) => {
|
|
14533
15609
|
if (!isFunction2(expr)) return void 0;
|
|
15610
|
+
if (typeof index !== "number") return void 0;
|
|
15611
|
+
if (expr.ops?.length === 2) {
|
|
15612
|
+
const n = toInteger(expr.op2);
|
|
15613
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
15614
|
+
if (index < 1 || index > count) return void 0;
|
|
15615
|
+
} else {
|
|
15616
|
+
if (index < 1) return void 0;
|
|
15617
|
+
}
|
|
14534
15618
|
return expr.op1;
|
|
14535
15619
|
}
|
|
14536
15620
|
}
|
|
@@ -14543,9 +15627,22 @@ ${lines.join("\n")}`;
|
|
|
14543
15627
|
signature: "(list) -> list",
|
|
14544
15628
|
collection: {
|
|
14545
15629
|
isLazy: (_expr) => true,
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
15630
|
+
// Cycling a non-empty collection is infinite; cycling an empty one is
|
|
15631
|
+
// empty. Inspect the *underlying* collection (`op1`) — reading
|
|
15632
|
+
// `expr.isEmptyCollection`/`expr.isFiniteCollection` here would re-enter
|
|
15633
|
+
// these same handlers and recurse infinitely.
|
|
15634
|
+
count: (expr) => {
|
|
15635
|
+
if (!isFunction2(expr)) return void 0;
|
|
15636
|
+
return expr.op1.isEmptyCollection ? 0 : Infinity;
|
|
15637
|
+
},
|
|
15638
|
+
isEmpty: (expr) => {
|
|
15639
|
+
if (!isFunction2(expr)) return void 0;
|
|
15640
|
+
return expr.op1.isEmptyCollection;
|
|
15641
|
+
},
|
|
15642
|
+
isFinite: (expr) => {
|
|
15643
|
+
if (!isFunction2(expr)) return void 0;
|
|
15644
|
+
return expr.op1.isEmptyCollection;
|
|
15645
|
+
},
|
|
14549
15646
|
contains: (expr, target) => {
|
|
14550
15647
|
if (!isFunction2(expr)) return false;
|
|
14551
15648
|
return expr.op1.contains(target) ?? false;
|
|
@@ -14559,7 +15656,7 @@ ${lines.join("\n")}`;
|
|
|
14559
15656
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14560
15657
|
return {
|
|
14561
15658
|
next: () => {
|
|
14562
|
-
const i = (index - 1
|
|
15659
|
+
const i = (index - 1) % l + 1;
|
|
14563
15660
|
const value = expr.op1.at(i);
|
|
14564
15661
|
if (value === void 0) return { value: void 0, done: true };
|
|
14565
15662
|
index += 1;
|
|
@@ -14681,7 +15778,7 @@ ${lines.join("\n")}`;
|
|
|
14681
15778
|
evaluate: (ops, { engine: ce }) => {
|
|
14682
15779
|
const elements = [];
|
|
14683
15780
|
for (const xs of ops) {
|
|
14684
|
-
if (xs.isCollection) elements.push(xs);
|
|
15781
|
+
if (!xs.isCollection) elements.push(xs);
|
|
14685
15782
|
else {
|
|
14686
15783
|
if (!xs.isFiniteCollection) return void 0;
|
|
14687
15784
|
elements.push(...Array.from(xs.each()));
|
|
@@ -14697,7 +15794,7 @@ ${lines.join("\n")}`;
|
|
|
14697
15794
|
evaluate: (ops, { engine: ce }) => {
|
|
14698
15795
|
const elements = [];
|
|
14699
15796
|
for (const xs of ops) {
|
|
14700
|
-
if (xs.isCollection) elements.push(xs);
|
|
15797
|
+
if (!xs.isCollection) elements.push(xs);
|
|
14701
15798
|
else {
|
|
14702
15799
|
if (!xs.isFiniteCollection) return void 0;
|
|
14703
15800
|
elements.push(...Array.from(xs.each()));
|
|
@@ -14790,11 +15887,129 @@ ${lines.join("\n")}`;
|
|
|
14790
15887
|
return ce._fn("List", ops);
|
|
14791
15888
|
}
|
|
14792
15889
|
function canonicalSet(ops, { engine }) {
|
|
15890
|
+
ops = ops.map((op) => op.canonical);
|
|
15891
|
+
if (parseSetComprehension(ops) !== null) return engine._fn("Set", [...ops]);
|
|
14793
15892
|
const set = [];
|
|
14794
15893
|
const has = (x) => set.some((y) => y.isSame(x));
|
|
14795
15894
|
for (const op of ops) if (!has(op)) set.push(op);
|
|
14796
15895
|
return engine._fn("Set", set);
|
|
14797
15896
|
}
|
|
15897
|
+
function parseSetComprehension(ops) {
|
|
15898
|
+
if (ops.length !== 2) return null;
|
|
15899
|
+
const [body, spec] = ops;
|
|
15900
|
+
const canon = (x) => x.isCanonical ? x : x.canonical;
|
|
15901
|
+
if (isFunction2(spec, "Element") && spec.nops >= 2) {
|
|
15902
|
+
if (!isSymbol2(spec.op1)) return null;
|
|
15903
|
+
const v = spec.op1.symbol;
|
|
15904
|
+
if (!body.has(v)) return null;
|
|
15905
|
+
const cond = spec.nops >= 3 && sym(spec.op3) !== "Nothing" ? spec.op3 : void 0;
|
|
15906
|
+
return { body, variable: v, domain: spec.op2, condition: cond };
|
|
15907
|
+
}
|
|
15908
|
+
if (isFunction2(spec, "Condition") && spec.nops >= 1) {
|
|
15909
|
+
const pred = spec.op1;
|
|
15910
|
+
if (isFunction2(body, "Element") && body.nops === 2 && isSymbol2(body.op1)) {
|
|
15911
|
+
return {
|
|
15912
|
+
body: body.op1,
|
|
15913
|
+
variable: body.op1.symbol,
|
|
15914
|
+
domain: canon(body.op2),
|
|
15915
|
+
condition: canon(pred)
|
|
15916
|
+
};
|
|
15917
|
+
}
|
|
15918
|
+
if (isFunction2(pred, "Element") && pred.nops === 2 && isSymbol2(pred.op1)) {
|
|
15919
|
+
const v = pred.op1.symbol;
|
|
15920
|
+
if (body.has(v))
|
|
15921
|
+
return {
|
|
15922
|
+
body,
|
|
15923
|
+
variable: v,
|
|
15924
|
+
domain: canon(pred.op2),
|
|
15925
|
+
condition: void 0
|
|
15926
|
+
};
|
|
15927
|
+
}
|
|
15928
|
+
if (isFunction2(pred, "And")) {
|
|
15929
|
+
const memberships = pred.ops.filter(
|
|
15930
|
+
(x) => isFunction2(x, "Element") && x.nops === 2 && isSymbol2(x.op1) && body.has(x.op1.symbol)
|
|
15931
|
+
);
|
|
15932
|
+
const membership = memberships.length === 1 ? memberships[0] : void 0;
|
|
15933
|
+
if (membership && isFunction2(membership, "Element") && isSymbol2(membership.op1)) {
|
|
15934
|
+
const rest = pred.ops.filter((x) => x !== membership).map(canon);
|
|
15935
|
+
const ce = body.engine;
|
|
15936
|
+
const cond = rest.length === 0 ? void 0 : rest.length === 1 ? rest[0] : ce._fn("And", rest);
|
|
15937
|
+
return {
|
|
15938
|
+
body,
|
|
15939
|
+
variable: membership.op1.symbol,
|
|
15940
|
+
domain: canon(membership.op2),
|
|
15941
|
+
condition: cond
|
|
15942
|
+
};
|
|
15943
|
+
}
|
|
15944
|
+
}
|
|
15945
|
+
return {
|
|
15946
|
+
body,
|
|
15947
|
+
variable: isSymbol2(body) ? body.symbol : void 0,
|
|
15948
|
+
domain: void 0,
|
|
15949
|
+
condition: pred
|
|
15950
|
+
};
|
|
15951
|
+
}
|
|
15952
|
+
return null;
|
|
15953
|
+
}
|
|
15954
|
+
function enumerateSetComprehension(comp) {
|
|
15955
|
+
const { body, variable, domain, condition } = comp;
|
|
15956
|
+
if (variable === void 0 || domain === void 0) return void 0;
|
|
15957
|
+
const ce = body.engine;
|
|
15958
|
+
const extract = (dom) => extractFiniteDomainWithReason(
|
|
15959
|
+
ce._fn("Element", [
|
|
15960
|
+
ce.symbol(variable),
|
|
15961
|
+
dom,
|
|
15962
|
+
...condition ? [condition] : []
|
|
15963
|
+
]),
|
|
15964
|
+
ce
|
|
15965
|
+
);
|
|
15966
|
+
let result = extract(domain);
|
|
15967
|
+
if (result.status !== "success") {
|
|
15968
|
+
const evaluatedDomain = domain.evaluate();
|
|
15969
|
+
if (!evaluatedDomain.isSame(domain)) result = extract(evaluatedDomain);
|
|
15970
|
+
}
|
|
15971
|
+
if (result.status !== "success") return void 0;
|
|
15972
|
+
const isIdentity = isSymbol2(body) && body.symbol === variable;
|
|
15973
|
+
const elements = [];
|
|
15974
|
+
for (const value of result.values) {
|
|
15975
|
+
const x = isIdentity ? value : body.subs({ [variable]: value }).evaluate();
|
|
15976
|
+
if (!elements.some((y) => y.isSame(x))) elements.push(x);
|
|
15977
|
+
}
|
|
15978
|
+
return elements;
|
|
15979
|
+
}
|
|
15980
|
+
function literalSetContains(ops, target) {
|
|
15981
|
+
let indeterminate = false;
|
|
15982
|
+
for (const op of ops) {
|
|
15983
|
+
if (target.isSame(op)) return true;
|
|
15984
|
+
if (isNumber(target) && isNumber(op)) {
|
|
15985
|
+
const eq2 = target.isEqual(op);
|
|
15986
|
+
if (eq2 === true) return true;
|
|
15987
|
+
if (eq2 !== false) indeterminate = true;
|
|
15988
|
+
} else if (isString(target) && isString(op)) {
|
|
15989
|
+
} else {
|
|
15990
|
+
indeterminate = true;
|
|
15991
|
+
}
|
|
15992
|
+
}
|
|
15993
|
+
return indeterminate ? void 0 : false;
|
|
15994
|
+
}
|
|
15995
|
+
function setComprehensionContains(comp, target) {
|
|
15996
|
+
const elements = enumerateSetComprehension(comp);
|
|
15997
|
+
if (elements !== void 0) return literalSetContains(elements, target);
|
|
15998
|
+
if (comp.domain !== void 0 && comp.variable !== void 0 && isSymbol2(comp.body) && comp.body.symbol === comp.variable) {
|
|
15999
|
+
const inDomain = comp.domain.contains(target);
|
|
16000
|
+
if (inDomain === false) return false;
|
|
16001
|
+
let condition = true;
|
|
16002
|
+
if (comp.condition !== void 0) {
|
|
16003
|
+
if (isNumber(target) || isString(target)) {
|
|
16004
|
+
const result = comp.condition.subs({ [comp.variable]: target }).evaluate();
|
|
16005
|
+
condition = sym(result) === "True" ? true : sym(result) === "False" ? false : void 0;
|
|
16006
|
+
} else condition = void 0;
|
|
16007
|
+
}
|
|
16008
|
+
if (condition === false) return false;
|
|
16009
|
+
if (inDomain === true && condition === true) return true;
|
|
16010
|
+
}
|
|
16011
|
+
return void 0;
|
|
16012
|
+
}
|
|
14798
16013
|
function tally(collection) {
|
|
14799
16014
|
const values = [];
|
|
14800
16015
|
const counts = [];
|
|
@@ -15034,7 +16249,11 @@ ${lines.join("\n")}`;
|
|
|
15034
16249
|
op[1]
|
|
15035
16250
|
)}`;
|
|
15036
16251
|
} else {
|
|
15037
|
-
|
|
16252
|
+
const rightAssoc = h === "Power";
|
|
16253
|
+
resultStr = args.map((arg, i) => {
|
|
16254
|
+
const operandPrec = rightAssoc && i < args.length - 1 ? op[1] + 1 : op[1];
|
|
16255
|
+
return _BaseCompiler.compile(arg, target, operandPrec);
|
|
16256
|
+
}).join(` ${op[0]} `);
|
|
15038
16257
|
}
|
|
15039
16258
|
return op[1] < prec ? `(${resultStr})` : resultStr;
|
|
15040
16259
|
}
|
|
@@ -15239,6 +16458,13 @@ ${lines.join("\n")}`;
|
|
|
15239
16458
|
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15240
16459
|
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15241
16460
|
* array or by unrolling when bounds are known at compile time.
|
|
16461
|
+
*
|
|
16462
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
16463
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
16464
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
16465
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
16466
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
16467
|
+
* current behavior.
|
|
15242
16468
|
*/
|
|
15243
16469
|
static compileForLoop(args, target) {
|
|
15244
16470
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -15720,6 +16946,17 @@ ${lines.join("\n")}`;
|
|
|
15720
16946
|
`Compilation fallback for "${expr.operator}" (target: ${options?.to ?? "javascript"}): ${e.message}`
|
|
15721
16947
|
);
|
|
15722
16948
|
const ce = expr.engine;
|
|
16949
|
+
const target = options?.to ?? "javascript";
|
|
16950
|
+
if (isFunction2(expr, "Function")) {
|
|
16951
|
+
const lambdaRun = ((...args) => ce.function("Apply", [expr, ...args.map((a) => ce.box(a))]).evaluate().re);
|
|
16952
|
+
return {
|
|
16953
|
+
target,
|
|
16954
|
+
success: false,
|
|
16955
|
+
code: "",
|
|
16956
|
+
calling: "lambda",
|
|
16957
|
+
run: lambdaRun
|
|
16958
|
+
};
|
|
16959
|
+
}
|
|
15723
16960
|
const fallbackRun = ((vars) => {
|
|
15724
16961
|
ce.pushScope();
|
|
15725
16962
|
try {
|
|
@@ -15732,7 +16969,7 @@ ${lines.join("\n")}`;
|
|
|
15732
16969
|
}
|
|
15733
16970
|
});
|
|
15734
16971
|
return {
|
|
15735
|
-
target
|
|
16972
|
+
target,
|
|
15736
16973
|
success: false,
|
|
15737
16974
|
code: "",
|
|
15738
16975
|
calling: "expression",
|
|
@@ -15786,6 +17023,11 @@ ${lines.join("\n")}`;
|
|
|
15786
17023
|
if (symbolic.length === 1) return symbolic[0];
|
|
15787
17024
|
return symbolic.join(op === "+" ? " + " : " * ");
|
|
15788
17025
|
}
|
|
17026
|
+
function parenthesizeFactor(expr, code) {
|
|
17027
|
+
if (isFunction2(expr, "Add") || isFunction2(expr, "Subtract"))
|
|
17028
|
+
return `(${code})`;
|
|
17029
|
+
return code;
|
|
17030
|
+
}
|
|
15789
17031
|
function tryGetComplexParts(expr, compile2) {
|
|
15790
17032
|
if (isSymbol2(expr, "ImaginaryUnit")) {
|
|
15791
17033
|
return { re: null, im: "1.0" };
|
|
@@ -15810,7 +17052,9 @@ ${lines.join("\n")}`;
|
|
|
15810
17052
|
if (remaining.length === 0) {
|
|
15811
17053
|
return { re: null, im: formatFloat(iScale) };
|
|
15812
17054
|
}
|
|
15813
|
-
const compiledFactors = remaining.map(
|
|
17055
|
+
const compiledFactors = remaining.map(
|
|
17056
|
+
(r) => parenthesizeFactor(r, compile2(r))
|
|
17057
|
+
);
|
|
15814
17058
|
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
15815
17059
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
15816
17060
|
return { re: null, im: imCode };
|
|
@@ -19327,9 +20571,14 @@ ${lines.join("\n")}`;
|
|
|
19327
20571
|
];
|
|
19328
20572
|
function gammaln(z) {
|
|
19329
20573
|
if (z < 0) return NaN;
|
|
20574
|
+
let shift = 0;
|
|
20575
|
+
while (z < 10) {
|
|
20576
|
+
shift += Math.log(z);
|
|
20577
|
+
z += 1;
|
|
20578
|
+
}
|
|
19330
20579
|
const pi = Math.PI;
|
|
19331
20580
|
const z3 = z * z * z;
|
|
19332
|
-
return z * Math.log(z) - z - 0.5 * Math.log(z) + 0.5 * Math.log(2 * pi) + 1 / (12 * z) - 1 / (360 * z3) + 1 / (1260 * z3 * z * z);
|
|
20581
|
+
return z * Math.log(z) - z - 0.5 * Math.log(z) + 0.5 * Math.log(2 * pi) + 1 / (12 * z) - 1 / (360 * z3) + 1 / (1260 * z3 * z * z) - shift;
|
|
19333
20582
|
}
|
|
19334
20583
|
function gamma(z) {
|
|
19335
20584
|
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
|
|
@@ -19340,31 +20589,62 @@ ${lines.join("\n")}`;
|
|
|
19340
20589
|
const t = z + gammaG + 0.5;
|
|
19341
20590
|
return Math.sqrt(2 * Math.PI) * Math.pow(t, z + 0.5) * Math.exp(-t) * x;
|
|
19342
20591
|
}
|
|
20592
|
+
function erfInvApprox(x) {
|
|
20593
|
+
const a = 0.147;
|
|
20594
|
+
const ln1mx2 = Math.log(1 - x * x);
|
|
20595
|
+
const b = 2 / (Math.PI * a) + ln1mx2 / 2;
|
|
20596
|
+
return Math.sign(x) * Math.sqrt(Math.sqrt(b * b - ln1mx2 / a) - b);
|
|
20597
|
+
}
|
|
19343
20598
|
function erfInv(x) {
|
|
19344
|
-
|
|
19345
|
-
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
const
|
|
19349
|
-
const
|
|
19350
|
-
|
|
19351
|
-
|
|
20599
|
+
if (Number.isNaN(x) || x < -1 || x > 1) return NaN;
|
|
20600
|
+
if (x === 0) return 0;
|
|
20601
|
+
if (x === 1) return Infinity;
|
|
20602
|
+
if (x === -1) return -Infinity;
|
|
20603
|
+
const sign2 = x < 0 ? -1 : 1;
|
|
20604
|
+
const ax = Math.abs(x);
|
|
20605
|
+
let y = erfInvApprox(ax);
|
|
20606
|
+
const c = Math.sqrt(Math.PI) / 2;
|
|
20607
|
+
for (let i = 0; i < 4; i++) y -= (erf(y) - ax) * c * Math.exp(y * y);
|
|
20608
|
+
return sign2 * y;
|
|
19352
20609
|
}
|
|
19353
20610
|
function erfc(x) {
|
|
19354
|
-
|
|
20611
|
+
if (Number.isNaN(x)) return NaN;
|
|
20612
|
+
if (!Number.isFinite(x)) return x > 0 ? 0 : 2;
|
|
20613
|
+
if (x < 0) return 2 - erfc(-x);
|
|
20614
|
+
if (x < 2) return 1 - erf(x);
|
|
20615
|
+
const tiny = 1e-300;
|
|
20616
|
+
let f = x === 0 ? tiny : x;
|
|
20617
|
+
let c = f;
|
|
20618
|
+
let d = 0;
|
|
20619
|
+
for (let k = 1; k <= 500; k++) {
|
|
20620
|
+
const a = k / 2;
|
|
20621
|
+
d = x + a * d;
|
|
20622
|
+
if (d === 0) d = tiny;
|
|
20623
|
+
d = 1 / d;
|
|
20624
|
+
c = x + a / c;
|
|
20625
|
+
if (c === 0) c = tiny;
|
|
20626
|
+
const delta = c * d;
|
|
20627
|
+
f *= delta;
|
|
20628
|
+
if (Math.abs(delta - 1) < 1e-17) break;
|
|
20629
|
+
}
|
|
20630
|
+
return Math.exp(-x * x) / (Math.sqrt(Math.PI) * f);
|
|
19355
20631
|
}
|
|
19356
20632
|
function erf(x) {
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
const a4 = -1.453152027;
|
|
19361
|
-
const a5 = 1.061405429;
|
|
19362
|
-
const p = 0.3275911;
|
|
20633
|
+
if (Number.isNaN(x)) return NaN;
|
|
20634
|
+
if (x === 0) return 0;
|
|
20635
|
+
if (!Number.isFinite(x)) return x > 0 ? 1 : -1;
|
|
19363
20636
|
const sign2 = x < 0 ? -1 : 1;
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
const
|
|
19367
|
-
|
|
20637
|
+
const ax = Math.abs(x);
|
|
20638
|
+
if (ax >= 6) return sign2;
|
|
20639
|
+
const x2 = ax * ax;
|
|
20640
|
+
let term = ax;
|
|
20641
|
+
let sum = ax;
|
|
20642
|
+
for (let n = 1; n < 200; n++) {
|
|
20643
|
+
term *= 2 * x2 / (2 * n + 1);
|
|
20644
|
+
sum += term;
|
|
20645
|
+
if (term < sum * 1e-18) break;
|
|
20646
|
+
}
|
|
20647
|
+
return sign2 * (2 / Math.sqrt(Math.PI)) * Math.exp(-x2) * sum;
|
|
19368
20648
|
}
|
|
19369
20649
|
var EULER_MASCHERONI = 0.5772156649015329;
|
|
19370
20650
|
var BERNOULLI_2K = [
|
|
@@ -19950,7 +21230,7 @@ ${lines.join("\n")}`;
|
|
|
19950
21230
|
const t = x2 * x2;
|
|
19951
21231
|
return sign2 * x * x2 * polevl(t, SN) / polevl(t, SD);
|
|
19952
21232
|
}
|
|
19953
|
-
if (x <
|
|
21233
|
+
if (x < 36974) {
|
|
19954
21234
|
const x2 = x * x;
|
|
19955
21235
|
const t = Math.PI * x2;
|
|
19956
21236
|
const u = 1 / (t * t);
|
|
@@ -19975,7 +21255,7 @@ ${lines.join("\n")}`;
|
|
|
19975
21255
|
const t = x2 * x2;
|
|
19976
21256
|
return sign2 * x * polevl(t, CN) / polevl(t, CD);
|
|
19977
21257
|
}
|
|
19978
|
-
if (x <
|
|
21258
|
+
if (x < 36974) {
|
|
19979
21259
|
const x2 = x * x;
|
|
19980
21260
|
const t = Math.PI * x2;
|
|
19981
21261
|
const u = 1 / (t * t);
|
|
@@ -20066,6 +21346,7 @@ ${lines.join("\n")}`;
|
|
|
20066
21346
|
function kurtosis(values) {
|
|
20067
21347
|
let sum = 0;
|
|
20068
21348
|
let sum2 = 0;
|
|
21349
|
+
let sum3 = 0;
|
|
20069
21350
|
let sum4 = 0;
|
|
20070
21351
|
let count = 0;
|
|
20071
21352
|
for (const op of values) {
|
|
@@ -20073,12 +21354,16 @@ ${lines.join("\n")}`;
|
|
|
20073
21354
|
if (!Number.isFinite(v)) return NaN;
|
|
20074
21355
|
sum += v;
|
|
20075
21356
|
sum2 += v * v;
|
|
21357
|
+
sum3 += v * v * v;
|
|
20076
21358
|
sum4 += v * v * v * v;
|
|
20077
21359
|
count++;
|
|
20078
21360
|
}
|
|
20079
21361
|
if (count === 0) return NaN;
|
|
20080
|
-
const
|
|
20081
|
-
|
|
21362
|
+
const n = count;
|
|
21363
|
+
const m = sum / n;
|
|
21364
|
+
const m2 = (sum2 - sum * sum / n) / n;
|
|
21365
|
+
const m4 = (sum4 - 4 * m * sum3 + 6 * m * m * sum2 - 4 * m * m * m * sum + n * m * m * m * m) / n;
|
|
21366
|
+
return m4 / (m2 * m2);
|
|
20082
21367
|
}
|
|
20083
21368
|
function skewness(values) {
|
|
20084
21369
|
let sum = 0;
|
|
@@ -20094,9 +21379,11 @@ ${lines.join("\n")}`;
|
|
|
20094
21379
|
count++;
|
|
20095
21380
|
}
|
|
20096
21381
|
if (count === 0) return NaN;
|
|
20097
|
-
const
|
|
20098
|
-
const
|
|
20099
|
-
|
|
21382
|
+
const n = count;
|
|
21383
|
+
const m = sum / n;
|
|
21384
|
+
const m2 = (sum2 - sum * sum / n) / n;
|
|
21385
|
+
const m3 = (sum3 - 3 * m * sum2 + 3 * m * m * sum - n * m * m * m) / n;
|
|
21386
|
+
return m3 / Math.pow(m2, 3 / 2);
|
|
20100
21387
|
}
|
|
20101
21388
|
function mode(values) {
|
|
20102
21389
|
const counts = {};
|
|
@@ -20123,11 +21410,8 @@ ${lines.join("\n")}`;
|
|
|
20123
21410
|
return [q1, q2, q3];
|
|
20124
21411
|
}
|
|
20125
21412
|
function interquartileRange(values) {
|
|
20126
|
-
const
|
|
20127
|
-
|
|
20128
|
-
const lower = sorted.slice(0, mid);
|
|
20129
|
-
const upper = sorted.slice(mid + 1);
|
|
20130
|
-
return median(upper) - median(lower);
|
|
21413
|
+
const [q1, , q3] = quartiles(values);
|
|
21414
|
+
return q3 - q1;
|
|
20131
21415
|
}
|
|
20132
21416
|
|
|
20133
21417
|
// src/compute-engine/numerics/monte-carlo.ts
|
|
@@ -20326,6 +21610,7 @@ ${lines.join("\n")}`;
|
|
|
20326
21610
|
return `_SYS.cexp(${compile2(args[0])})`;
|
|
20327
21611
|
return `Math.exp(${compile2(args[0])})`;
|
|
20328
21612
|
},
|
|
21613
|
+
First: (args, compile2) => `${compile2(args[0])}[0]`,
|
|
20329
21614
|
Floor: (args, compile2) => {
|
|
20330
21615
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20331
21616
|
return `Math.floor(${compile2(args[0])})`;
|
|
@@ -20457,7 +21742,7 @@ ${lines.join("\n")}`;
|
|
|
20457
21742
|
if (parseFloat(step) === 1) {
|
|
20458
21743
|
const fStop = parseFloat(stop);
|
|
20459
21744
|
const fStart = parseFloat(start);
|
|
20460
|
-
if (fStop
|
|
21745
|
+
if (!isNaN(fStop) && !isNaN(fStart)) {
|
|
20461
21746
|
if (fStop - fStart < 50) {
|
|
20462
21747
|
return `[${Array.from(
|
|
20463
21748
|
{ length: fStop - fStart + 1 },
|
|
@@ -20468,9 +21753,9 @@ ${lines.join("\n")}`;
|
|
|
20468
21753
|
}, (_, i) => ${start} + i)`;
|
|
20469
21754
|
}
|
|
20470
21755
|
return `Array.from({length: ${stop} - ${start} + 1
|
|
20471
|
-
}, (
|
|
21756
|
+
}, (_e, i) => ${start} + i)`;
|
|
20472
21757
|
}
|
|
20473
|
-
return `Array.from({length: Math.floor((${stop} - ${start}) / ${step}) + 1}, (
|
|
21758
|
+
return `Array.from({length: Math.floor((${stop} - ${start}) / ${step}) + 1}, (_e, i) => ${start} + i * ${step})`;
|
|
20474
21759
|
},
|
|
20475
21760
|
Root: ([arg, exp3], compile2) => {
|
|
20476
21761
|
if (arg === null) throw new Error("Root: no argument");
|
|
@@ -20484,7 +21769,20 @@ ${lines.join("\n")}`;
|
|
|
20484
21769
|
if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
|
|
20485
21770
|
return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
|
|
20486
21771
|
},
|
|
20487
|
-
Random:
|
|
21772
|
+
Random: (args, compile2) => {
|
|
21773
|
+
if (args.length === 0) return "Math.random()";
|
|
21774
|
+
if (args.length === 2) {
|
|
21775
|
+
const m = compile2(args[0]);
|
|
21776
|
+
const n = compile2(args[1]);
|
|
21777
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
21778
|
+
}
|
|
21779
|
+
const arg = args[0];
|
|
21780
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
21781
|
+
return `Math.floor(Math.random() * (${compile2(arg)}))`;
|
|
21782
|
+
}
|
|
21783
|
+
const a = compile2(arg);
|
|
21784
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
21785
|
+
},
|
|
20488
21786
|
Round: (args, compile2) => {
|
|
20489
21787
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20490
21788
|
return `Math.round(${compile2(args[0])})`;
|
|
@@ -20512,6 +21810,7 @@ ${lines.join("\n")}`;
|
|
|
20512
21810
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile2(arg)})`;
|
|
20513
21811
|
return `1 / Math.cosh(${compile2(arg)})`;
|
|
20514
21812
|
},
|
|
21813
|
+
Second: (args, compile2) => `${compile2(args[0])}[1]`,
|
|
20515
21814
|
Heaviside: "_SYS.heaviside",
|
|
20516
21815
|
Sign: "Math.sign",
|
|
20517
21816
|
Sinc: "_SYS.sinc",
|
|
@@ -20544,6 +21843,7 @@ ${lines.join("\n")}`;
|
|
|
20544
21843
|
return `_SYS.ctanh(${compile2(args[0])})`;
|
|
20545
21844
|
return `Math.tanh(${compile2(args[0])})`;
|
|
20546
21845
|
},
|
|
21846
|
+
Third: (args, compile2) => `${compile2(args[0])}[2]`,
|
|
20547
21847
|
Mod: ([a, b], compile2) => {
|
|
20548
21848
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
20549
21849
|
const ca = compile2(a);
|
|
@@ -21612,6 +22912,14 @@ ${lines.join("\n")}`;
|
|
|
21612
22912
|
function gpuVec3(target) {
|
|
21613
22913
|
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
21614
22914
|
}
|
|
22915
|
+
function gpuNaN(target) {
|
|
22916
|
+
return target?.language === "wgsl" ? "bitcast<f32>(0x7fc00000u)" : "(0.0 / 0.0)";
|
|
22917
|
+
}
|
|
22918
|
+
function gpuConditional(cond, whenTrue, whenFalse, target) {
|
|
22919
|
+
if (target?.language === "wgsl")
|
|
22920
|
+
return `select(${whenFalse}, ${whenTrue}, ${cond})`;
|
|
22921
|
+
return `((${cond}) ? (${whenTrue}) : (${whenFalse}))`;
|
|
22922
|
+
}
|
|
21615
22923
|
function readStringLiteral(expr) {
|
|
21616
22924
|
if (!isString(expr)) return null;
|
|
21617
22925
|
return expr.string?.toLowerCase() ?? null;
|
|
@@ -21729,7 +23037,7 @@ ${lines.join("\n")}`;
|
|
|
21729
23037
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
21730
23038
|
const v2 = gpuVec2(target);
|
|
21731
23039
|
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
21732
|
-
const factors = realFactors.map((f) => compile2(f));
|
|
23040
|
+
const factors = realFactors.map((f) => parenthesizeFactor(f, compile2(f)));
|
|
21733
23041
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
21734
23042
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
21735
23043
|
return `${v2}(0.0, ${imCode})`;
|
|
@@ -21738,7 +23046,7 @@ ${lines.join("\n")}`;
|
|
|
21738
23046
|
const complexCodes = [];
|
|
21739
23047
|
for (const a of args) {
|
|
21740
23048
|
if (BaseCompiler.isComplexValued(a)) complexCodes.push(compile2(a));
|
|
21741
|
-
else realCodes.push(compile2(a));
|
|
23049
|
+
else realCodes.push(parenthesizeFactor(a, compile2(a)));
|
|
21742
23050
|
}
|
|
21743
23051
|
const scalarCode = foldTerms(realCodes, "1.0", "*");
|
|
21744
23052
|
let result = complexCodes[0];
|
|
@@ -21816,13 +23124,23 @@ ${lines.join("\n")}`;
|
|
|
21816
23124
|
return `_gpu_ccos(${compile2(args[0])})`;
|
|
21817
23125
|
return `cos(${compile2(args[0])})`;
|
|
21818
23126
|
},
|
|
21819
|
-
Degrees
|
|
23127
|
+
// CE's `Degrees` converts degrees→radians (Degrees(180) = π), which is
|
|
23128
|
+
// GLSL's `radians()`. GLSL's `degrees()` is the inverse (rad→deg).
|
|
23129
|
+
Degrees: "radians",
|
|
21820
23130
|
Exp: (args, compile2) => {
|
|
21821
23131
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
21822
23132
|
return `_gpu_cexp(${compile2(args[0])})`;
|
|
21823
23133
|
return `exp(${compile2(args[0])})`;
|
|
21824
23134
|
},
|
|
21825
23135
|
Exp2: "exp2",
|
|
23136
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
23137
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
23138
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
23139
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
23140
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
23141
|
+
First: (args, compile2) => `${compile2(args[0])}.x`,
|
|
23142
|
+
Second: (args, compile2) => `${compile2(args[0])}.y`,
|
|
23143
|
+
Third: (args, compile2) => `${compile2(args[0])}.z`,
|
|
21826
23144
|
Floor: (args, compile2) => {
|
|
21827
23145
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21828
23146
|
return `floor(${compile2(args[0])})`;
|
|
@@ -21837,6 +23155,43 @@ ${lines.join("\n")}`;
|
|
|
21837
23155
|
Max: "max",
|
|
21838
23156
|
Min: "min",
|
|
21839
23157
|
Mix: "mix",
|
|
23158
|
+
// Control-flow forms — the base compiler's default emits a JS ternary and a
|
|
23159
|
+
// bare `NaN`, neither of which is valid GPU code (WGSL has no `?:`, and no
|
|
23160
|
+
// shader language has a `NaN` identifier). Emit `select(...)` for WGSL and a
|
|
23161
|
+
// language-appropriate NaN.
|
|
23162
|
+
If: (args, compile2, target) => {
|
|
23163
|
+
if (args.length !== 3) throw new Error("If: wrong number of arguments");
|
|
23164
|
+
return gpuConditional(
|
|
23165
|
+
compile2(args[0]),
|
|
23166
|
+
compile2(args[1]),
|
|
23167
|
+
compile2(args[2]),
|
|
23168
|
+
target
|
|
23169
|
+
);
|
|
23170
|
+
},
|
|
23171
|
+
When: (args, compile2, target) => {
|
|
23172
|
+
if (args.length !== 2)
|
|
23173
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
23174
|
+
if (isSymbol2(args[1], "True")) return `(${compile2(args[0])})`;
|
|
23175
|
+
if (isSymbol2(args[1], "False")) return gpuNaN(target);
|
|
23176
|
+
return gpuConditional(
|
|
23177
|
+
compile2(args[1]),
|
|
23178
|
+
compile2(args[0]),
|
|
23179
|
+
gpuNaN(target),
|
|
23180
|
+
target
|
|
23181
|
+
);
|
|
23182
|
+
},
|
|
23183
|
+
Which: (args, compile2, target) => {
|
|
23184
|
+
if (args.length < 2 || args.length % 2 !== 0)
|
|
23185
|
+
throw new Error("Which: expected condition/value pairs");
|
|
23186
|
+
const build = (i) => {
|
|
23187
|
+
if (i >= args.length) return gpuNaN(target);
|
|
23188
|
+
const cond = args[i];
|
|
23189
|
+
const val = args[i + 1];
|
|
23190
|
+
if (isSymbol2(cond, "True")) return `(${compile2(val)})`;
|
|
23191
|
+
return gpuConditional(compile2(cond), compile2(val), build(i + 2), target);
|
|
23192
|
+
};
|
|
23193
|
+
return build(0);
|
|
23194
|
+
},
|
|
21840
23195
|
Power: (args, compile2, target) => {
|
|
21841
23196
|
const base = args[0];
|
|
21842
23197
|
const exp3 = args[1];
|
|
@@ -22300,6 +23655,39 @@ ${lines.join("\n")}`;
|
|
|
22300
23655
|
// Sum/Product — unrolled or for-loop
|
|
22301
23656
|
Sum: (args, compile2, target) => compileGPUSumProduct("Sum", args, compile2, target),
|
|
22302
23657
|
Product: (args, compile2, target) => compileGPUSumProduct("Product", args, compile2, target),
|
|
23658
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
23659
|
+
Range: (args, _compile, target) => {
|
|
23660
|
+
if (args.length < 2 || args.length > 3) {
|
|
23661
|
+
throw new Error(
|
|
23662
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
23663
|
+
);
|
|
23664
|
+
}
|
|
23665
|
+
const lo = args[0].re;
|
|
23666
|
+
const hi = args[1].re;
|
|
23667
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
23668
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
23669
|
+
throw new Error(
|
|
23670
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
23671
|
+
);
|
|
23672
|
+
}
|
|
23673
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
23674
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
23675
|
+
if (count === 0) {
|
|
23676
|
+
throw new Error(
|
|
23677
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
23678
|
+
);
|
|
23679
|
+
}
|
|
23680
|
+
if (count > 256) {
|
|
23681
|
+
throw new Error(
|
|
23682
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
23683
|
+
);
|
|
23684
|
+
}
|
|
23685
|
+
const values = [];
|
|
23686
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
23687
|
+
const isWGSL = target.language === "wgsl";
|
|
23688
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
23689
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
23690
|
+
},
|
|
22303
23691
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
22304
23692
|
Loop: (args, _compile, target) => {
|
|
22305
23693
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -22328,6 +23716,134 @@ ${lines.join("\n")}`;
|
|
|
22328
23716
|
${bodyCode};
|
|
22329
23717
|
}`;
|
|
22330
23718
|
},
|
|
23719
|
+
// Statistical functions
|
|
23720
|
+
/**
|
|
23721
|
+
* GCD of two scalar arguments.
|
|
23722
|
+
*
|
|
23723
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
23724
|
+
* Only two-argument form is supported in GPU targets.
|
|
23725
|
+
*/
|
|
23726
|
+
GCD: (args, compile2) => {
|
|
23727
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
23728
|
+
if (args.length > 2)
|
|
23729
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
23730
|
+
const a = args[0];
|
|
23731
|
+
const b = args[1];
|
|
23732
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
23733
|
+
return `_gpu_gcd(${compile2(a)}, ${compile2(b)})`;
|
|
23734
|
+
},
|
|
23735
|
+
/**
|
|
23736
|
+
* Variance of a compile-time-known list.
|
|
23737
|
+
*
|
|
23738
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
23739
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
23740
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
23741
|
+
*/
|
|
23742
|
+
Variance: (args, compile2) => {
|
|
23743
|
+
let elems;
|
|
23744
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
23745
|
+
elems = args[0].ops;
|
|
23746
|
+
} else if (args.length >= 2) {
|
|
23747
|
+
elems = args;
|
|
23748
|
+
} else {
|
|
23749
|
+
throw new Error(
|
|
23750
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
23751
|
+
);
|
|
23752
|
+
}
|
|
23753
|
+
const n = elems.length;
|
|
23754
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
23755
|
+
const compiled = elems.map((e) => compile2(e));
|
|
23756
|
+
const sum = compiled.join(" + ");
|
|
23757
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
23758
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
23759
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
23760
|
+
},
|
|
23761
|
+
/**
|
|
23762
|
+
* Median of a compile-time-known list.
|
|
23763
|
+
*
|
|
23764
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
23765
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
23766
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
23767
|
+
*
|
|
23768
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
23769
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
23770
|
+
*/
|
|
23771
|
+
Median: (args, compile2) => {
|
|
23772
|
+
let elems;
|
|
23773
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
23774
|
+
elems = args[0].ops;
|
|
23775
|
+
} else if (args.length >= 1) {
|
|
23776
|
+
elems = args;
|
|
23777
|
+
} else {
|
|
23778
|
+
throw new Error(
|
|
23779
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
23780
|
+
);
|
|
23781
|
+
}
|
|
23782
|
+
const n = elems.length;
|
|
23783
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
23784
|
+
if (n > 8) {
|
|
23785
|
+
throw new Error(
|
|
23786
|
+
`Median: GPU target supports up to 8 elements via inline sorting network (got ${n}). For larger lists, compute on the CPU and pass the result as a uniform.`
|
|
23787
|
+
);
|
|
23788
|
+
}
|
|
23789
|
+
const compiled = elems.map((e) => compile2(e));
|
|
23790
|
+
if (n === 1) return compiled[0];
|
|
23791
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
23792
|
+
},
|
|
23793
|
+
/**
|
|
23794
|
+
* Deterministic pseudorandom for GPU.
|
|
23795
|
+
*
|
|
23796
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
23797
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
23798
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
23799
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
23800
|
+
* integer-returning operators in this target.
|
|
23801
|
+
*
|
|
23802
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
23803
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
23804
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
23805
|
+
* caller must provide an explicit seed.
|
|
23806
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
23807
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
23808
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
23809
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
23810
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
23811
|
+
*
|
|
23812
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
23813
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
23814
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
23815
|
+
* `sin` differences.
|
|
23816
|
+
*/
|
|
23817
|
+
Random: (args, compile2, target) => {
|
|
23818
|
+
if (args.length === 0) {
|
|
23819
|
+
if (target.language === "wgsl") {
|
|
23820
|
+
throw new Error(
|
|
23821
|
+
"Random(): WGSL compile requires an explicit seed argument. WGSL has no gl_FragCoord built-in outside fragment entry points, so the no-arg fallback used in GLSL is unavailable. Use Random(seed) where seed is a deterministic per-invocation value."
|
|
23822
|
+
);
|
|
23823
|
+
}
|
|
23824
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
23825
|
+
}
|
|
23826
|
+
if (args.length === 1) {
|
|
23827
|
+
const arg = args[0];
|
|
23828
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
23829
|
+
const compiled = compile2(arg);
|
|
23830
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
23831
|
+
}
|
|
23832
|
+
return `_gpu_random(${compile2(arg)})`;
|
|
23833
|
+
}
|
|
23834
|
+
if (args.length === 2) {
|
|
23835
|
+
if (target.language === "wgsl") {
|
|
23836
|
+
throw new Error(
|
|
23837
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
23838
|
+
);
|
|
23839
|
+
}
|
|
23840
|
+
const m = compile2(args[0]);
|
|
23841
|
+
const n = compile2(args[1]);
|
|
23842
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
23843
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
23844
|
+
}
|
|
23845
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
23846
|
+
},
|
|
22331
23847
|
// Function (lambda) — not supported in GPU
|
|
22332
23848
|
Function: () => {
|
|
22333
23849
|
throw new Error(
|
|
@@ -22363,7 +23879,7 @@ ${lines.join("\n")}`;
|
|
|
22363
23879
|
}
|
|
22364
23880
|
return compile2(body);
|
|
22365
23881
|
}
|
|
22366
|
-
var
|
|
23882
|
+
var GPU_GAMMA_PREAMBLE_GLSL = `
|
|
22367
23883
|
float _gpu_gamma(float z) {
|
|
22368
23884
|
const float PI = 3.14159265358979;
|
|
22369
23885
|
// For z < 0.5, use reflection formula with inlined Lanczos (non-recursive)
|
|
@@ -22395,7 +23911,37 @@ float _gpu_gammaln(float z) {
|
|
|
22395
23911
|
+ 1.0 / (1260.0 * z3 * z * z);
|
|
22396
23912
|
}
|
|
22397
23913
|
`;
|
|
22398
|
-
var
|
|
23914
|
+
var GPU_GAMMA_PREAMBLE_WGSL = `
|
|
23915
|
+
fn _gpu_gamma(z: f32) -> f32 {
|
|
23916
|
+
let PI = 3.14159265358979;
|
|
23917
|
+
var w = z;
|
|
23918
|
+
if (z < 0.5) { w = 1.0 - z; }
|
|
23919
|
+
w = w - 1.0;
|
|
23920
|
+
var x = 0.99999999999980993;
|
|
23921
|
+
x = x + 676.5203681218851 / (w + 1.0);
|
|
23922
|
+
x = x + -1259.1392167224028 / (w + 2.0);
|
|
23923
|
+
x = x + 771.32342877765313 / (w + 3.0);
|
|
23924
|
+
x = x + -176.61502916214059 / (w + 4.0);
|
|
23925
|
+
x = x + 12.507343278686905 / (w + 5.0);
|
|
23926
|
+
x = x + -0.13857109526572012 / (w + 6.0);
|
|
23927
|
+
x = x + 9.9843695780195716e-6 / (w + 7.0);
|
|
23928
|
+
x = x + 1.5056327351493116e-7 / (w + 8.0);
|
|
23929
|
+
let t = w + 7.5;
|
|
23930
|
+
let g = sqrt(2.0 * PI) * pow(t, w + 0.5) * exp(-t) * x;
|
|
23931
|
+
if (z < 0.5) { return PI / (sin(PI * z) * g); }
|
|
23932
|
+
return g;
|
|
23933
|
+
}
|
|
23934
|
+
|
|
23935
|
+
fn _gpu_gammaln(z: f32) -> f32 {
|
|
23936
|
+
let z3 = z * z * z;
|
|
23937
|
+
return z * log(z) - z - 0.5 * log(z)
|
|
23938
|
+
+ 0.5 * log(2.0 * 3.14159265358979)
|
|
23939
|
+
+ 1.0 / (12.0 * z)
|
|
23940
|
+
- 1.0 / (360.0 * z3)
|
|
23941
|
+
+ 1.0 / (1260.0 * z3 * z * z);
|
|
23942
|
+
}
|
|
23943
|
+
`;
|
|
23944
|
+
var GPU_ERF_PREAMBLE_GLSL = `
|
|
22399
23945
|
float _gpu_erf(float x) {
|
|
22400
23946
|
float ax = abs(x);
|
|
22401
23947
|
float t = 1.0 / (1.0 + 0.3275911 * ax);
|
|
@@ -22413,6 +23959,26 @@ float _gpu_erfinv(float x) {
|
|
|
22413
23959
|
float x9 = x7 * x2;
|
|
22414
23960
|
return sqrt(pi) * 0.5 * (x + (pi / 12.0) * x3 + (7.0 * pi * pi / 480.0) * x5 + (127.0 * pi * pi * pi / 40320.0) * x7 + (4369.0 * pi * pi * pi * pi / 5806080.0) * x9);
|
|
22415
23961
|
}
|
|
23962
|
+
`;
|
|
23963
|
+
var GPU_ERF_PREAMBLE_WGSL = `
|
|
23964
|
+
fn _gpu_erf(x: f32) -> f32 {
|
|
23965
|
+
let ax = abs(x);
|
|
23966
|
+
let t = 1.0 / (1.0 + 0.3275911 * ax);
|
|
23967
|
+
let y = ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t;
|
|
23968
|
+
let result = 1.0 - y * exp(-ax * ax);
|
|
23969
|
+
if (x < 0.0) { return -result; }
|
|
23970
|
+
return result;
|
|
23971
|
+
}
|
|
23972
|
+
|
|
23973
|
+
fn _gpu_erfinv(x: f32) -> f32 {
|
|
23974
|
+
let pi = 3.14159265358979;
|
|
23975
|
+
let x2 = x * x;
|
|
23976
|
+
let x3 = x * x2;
|
|
23977
|
+
let x5 = x3 * x2;
|
|
23978
|
+
let x7 = x5 * x2;
|
|
23979
|
+
let x9 = x7 * x2;
|
|
23980
|
+
return sqrt(pi) * 0.5 * (x + (pi / 12.0) * x3 + (7.0 * pi * pi / 480.0) * x5 + (127.0 * pi * pi * pi / 40320.0) * x7 + (4369.0 * pi * pi * pi * pi / 5806080.0) * x9);
|
|
23981
|
+
}
|
|
22416
23982
|
`;
|
|
22417
23983
|
var GPU_HEAVISIDE_PREAMBLE_GLSL = `
|
|
22418
23984
|
float _gpu_heaviside(float x) {
|
|
@@ -22926,6 +24492,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
22926
24492
|
}
|
|
22927
24493
|
return 1.0;
|
|
22928
24494
|
}
|
|
24495
|
+
`;
|
|
24496
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
24497
|
+
float _gpu_gcd(float a, float b) {
|
|
24498
|
+
a = abs(a); b = abs(b);
|
|
24499
|
+
for (int i = 0; i < 32; i++) {
|
|
24500
|
+
if (b < 0.5) break;
|
|
24501
|
+
float t = mod(a, b);
|
|
24502
|
+
a = b;
|
|
24503
|
+
b = t;
|
|
24504
|
+
}
|
|
24505
|
+
return a;
|
|
24506
|
+
}
|
|
24507
|
+
`;
|
|
24508
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
24509
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
24510
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
24511
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
24512
|
+
if (b < 0.5) { break; }
|
|
24513
|
+
let t = a % b;
|
|
24514
|
+
a = b;
|
|
24515
|
+
b = t;
|
|
24516
|
+
}
|
|
24517
|
+
return a;
|
|
24518
|
+
}
|
|
24519
|
+
`;
|
|
24520
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
24521
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
24522
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
24523
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
24524
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
24525
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
24526
|
+
float _gpu_random(float seed) {
|
|
24527
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
24528
|
+
}
|
|
24529
|
+
`;
|
|
24530
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
24531
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
24532
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
24533
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
24534
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
24535
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
24536
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
24537
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
24538
|
+
}
|
|
24539
|
+
`;
|
|
24540
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
24541
|
+
float _gpu_median_2(float a, float b) {
|
|
24542
|
+
return (a + b) * 0.5;
|
|
24543
|
+
}
|
|
24544
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
24545
|
+
return max(min(a, b), min(max(a, b), c));
|
|
24546
|
+
}
|
|
24547
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
24548
|
+
float lo = max(min(a, b), min(c, d));
|
|
24549
|
+
float hi = min(max(a, b), max(c, d));
|
|
24550
|
+
return (lo + hi) * 0.5;
|
|
24551
|
+
}
|
|
24552
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
24553
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
24554
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
24555
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24556
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24557
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24558
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24559
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
24560
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24561
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
24562
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24563
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24564
|
+
return v2;
|
|
24565
|
+
}
|
|
24566
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
24567
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
24568
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24569
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24570
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24571
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24572
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24573
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24574
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24575
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24576
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24577
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24578
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24579
|
+
return (v2 + v3) * 0.5;
|
|
24580
|
+
}
|
|
24581
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
24582
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
24583
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24584
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24585
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24586
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24587
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24588
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24589
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24590
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24591
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24592
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24593
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24594
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24595
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24596
|
+
return v3;
|
|
24597
|
+
}
|
|
24598
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
24599
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
24600
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24601
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24602
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24603
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
24604
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24605
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24606
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24607
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
24608
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24609
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24610
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24611
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
24612
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24613
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24614
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
24615
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24616
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24617
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24618
|
+
return (v3 + v4) * 0.5;
|
|
24619
|
+
}
|
|
24620
|
+
`;
|
|
24621
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
24622
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
24623
|
+
return (a + b) * 0.5;
|
|
24624
|
+
}
|
|
24625
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
24626
|
+
return max(min(a, b), min(max(a, b), c));
|
|
24627
|
+
}
|
|
24628
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
24629
|
+
let lo = max(min(a, b), min(c, d));
|
|
24630
|
+
let hi = min(max(a, b), max(c, d));
|
|
24631
|
+
return (lo + hi) * 0.5;
|
|
24632
|
+
}
|
|
24633
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
24634
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
24635
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
24636
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24637
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24638
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24639
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24640
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
24641
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24642
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
24643
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24644
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24645
|
+
return v2;
|
|
24646
|
+
}
|
|
24647
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
24648
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
24649
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24650
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24651
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24652
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24653
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24654
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24655
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24656
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24657
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24658
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24659
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24660
|
+
return (v2 + v3) * 0.5;
|
|
24661
|
+
}
|
|
24662
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
24663
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
24664
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24665
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24666
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24667
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24668
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24669
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24670
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24671
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24672
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24673
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24674
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24675
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24676
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24677
|
+
return v3;
|
|
24678
|
+
}
|
|
24679
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
24680
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var v7=h; var t: f32;
|
|
24681
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24682
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24683
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24684
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
24685
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24686
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24687
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24688
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
24689
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24690
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24691
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24692
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
24693
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24694
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24695
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
24696
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24697
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24698
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24699
|
+
return (v3 + v4) * 0.5;
|
|
24700
|
+
}
|
|
22929
24701
|
`;
|
|
22930
24702
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
22931
24703
|
float _gpu_srgb_to_linear(float c) {
|
|
@@ -23587,8 +25359,10 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
|
23587
25359
|
};
|
|
23588
25360
|
let preamble = "";
|
|
23589
25361
|
preamble += buildComplexPreamble(code, this.languageId);
|
|
23590
|
-
if (code.includes("_gpu_gamma"))
|
|
23591
|
-
|
|
25362
|
+
if (code.includes("_gpu_gamma"))
|
|
25363
|
+
preamble += this.languageId === "wgsl" ? GPU_GAMMA_PREAMBLE_WGSL : GPU_GAMMA_PREAMBLE_GLSL;
|
|
25364
|
+
if (code.includes("_gpu_erf"))
|
|
25365
|
+
preamble += this.languageId === "wgsl" ? GPU_ERF_PREAMBLE_WGSL : GPU_ERF_PREAMBLE_GLSL;
|
|
23592
25366
|
if (code.includes("_gpu_heaviside"))
|
|
23593
25367
|
preamble += this.languageId === "wgsl" ? GPU_HEAVISIDE_PREAMBLE_WGSL : GPU_HEAVISIDE_PREAMBLE_GLSL;
|
|
23594
25368
|
if (code.includes("_gpu_sinc"))
|
|
@@ -23604,6 +25378,12 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
|
23604
25378
|
if (code.includes("_fractal_")) {
|
|
23605
25379
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
23606
25380
|
}
|
|
25381
|
+
if (code.includes("_gpu_random"))
|
|
25382
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
25383
|
+
if (code.includes("_gpu_gcd"))
|
|
25384
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
25385
|
+
if (code.includes("_gpu_median_"))
|
|
25386
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
23607
25387
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
23608
25388
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
23609
25389
|
}
|
|
@@ -24368,9 +26148,18 @@ ${code}`;
|
|
|
24368
26148
|
return ok({ lo: -xVal.hi, hi: -xVal.lo });
|
|
24369
26149
|
}
|
|
24370
26150
|
function _mul(a, b) {
|
|
24371
|
-
const products = [
|
|
26151
|
+
const products = [
|
|
26152
|
+
_prod(a.lo, b.lo),
|
|
26153
|
+
_prod(a.lo, b.hi),
|
|
26154
|
+
_prod(a.hi, b.lo),
|
|
26155
|
+
_prod(a.hi, b.hi)
|
|
26156
|
+
];
|
|
24372
26157
|
return { lo: Math.min(...products), hi: Math.max(...products) };
|
|
24373
26158
|
}
|
|
26159
|
+
function _prod(x, y) {
|
|
26160
|
+
if (x === 0 || y === 0) return 0;
|
|
26161
|
+
return x * y;
|
|
26162
|
+
}
|
|
24374
26163
|
function mul3(a, b) {
|
|
24375
26164
|
const unwrapped = unwrapOrPropagate(a, b);
|
|
24376
26165
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -24704,6 +26493,7 @@ ${code}`;
|
|
|
24704
26493
|
const period = Math.abs(
|
|
24705
26494
|
bVal.lo === bVal.hi ? bVal.lo : Math.max(Math.abs(bVal.lo), Math.abs(bVal.hi))
|
|
24706
26495
|
);
|
|
26496
|
+
const divisorNegative = bVal.hi < 0;
|
|
24707
26497
|
const flo = Math.floor(aVal.lo / period);
|
|
24708
26498
|
const fhi = Math.floor(aVal.hi / period);
|
|
24709
26499
|
if (flo !== fhi) {
|
|
@@ -24711,6 +26501,11 @@ ${code}`;
|
|
|
24711
26501
|
}
|
|
24712
26502
|
const modLo = aVal.lo - period * flo;
|
|
24713
26503
|
const modHi = aVal.hi - period * flo;
|
|
26504
|
+
if (divisorNegative) {
|
|
26505
|
+
if (modLo === 0)
|
|
26506
|
+
return { kind: "singular", at: aVal.lo, continuity: "right" };
|
|
26507
|
+
return ok({ lo: modLo - period, hi: modHi - period });
|
|
26508
|
+
}
|
|
24714
26509
|
return ok({ lo: Math.min(modLo, modHi), hi: Math.max(modLo, modHi) });
|
|
24715
26510
|
}
|
|
24716
26511
|
function remainder(a, b) {
|
|
@@ -24742,6 +26537,23 @@ ${code}`;
|
|
|
24742
26537
|
const [xVal] = unwrapped;
|
|
24743
26538
|
return _gamma(xVal);
|
|
24744
26539
|
}
|
|
26540
|
+
var GAMMA_NEG_EXTREMA_X = [
|
|
26541
|
+
-0.504083008264455,
|
|
26542
|
+
-1.573498473162391,
|
|
26543
|
+
-2.610720868444145,
|
|
26544
|
+
-3.635293366436901,
|
|
26545
|
+
-4.653163765628266,
|
|
26546
|
+
-5.667162441556885,
|
|
26547
|
+
-6.678418213073426,
|
|
26548
|
+
-7.687788325031709,
|
|
26549
|
+
-8.695764163640956,
|
|
26550
|
+
-9.702672540001863
|
|
26551
|
+
];
|
|
26552
|
+
function gammaNegStripExtremum(lo) {
|
|
26553
|
+
const n = Math.floor(lo);
|
|
26554
|
+
const idx = -n - 1;
|
|
26555
|
+
return idx >= 0 && idx < GAMMA_NEG_EXTREMA_X.length ? GAMMA_NEG_EXTREMA_X[idx] : null;
|
|
26556
|
+
}
|
|
24745
26557
|
function _gamma(x) {
|
|
24746
26558
|
if (x.hi >= 0 && x.lo <= 0) {
|
|
24747
26559
|
return { kind: "singular", at: 0 };
|
|
@@ -24754,7 +26566,21 @@ ${code}`;
|
|
|
24754
26566
|
}
|
|
24755
26567
|
const gLo = gamma(x.lo);
|
|
24756
26568
|
const gHi = gamma(x.hi);
|
|
24757
|
-
|
|
26569
|
+
let lo = Math.min(gLo, gHi);
|
|
26570
|
+
let hi = Math.max(gLo, gHi);
|
|
26571
|
+
const xStar = gammaNegStripExtremum(x.lo);
|
|
26572
|
+
if (xStar !== null) {
|
|
26573
|
+
if (xStar >= x.lo && xStar <= x.hi) {
|
|
26574
|
+
const g = gamma(xStar);
|
|
26575
|
+
lo = Math.min(lo, g);
|
|
26576
|
+
hi = Math.max(hi, g);
|
|
26577
|
+
}
|
|
26578
|
+
} else {
|
|
26579
|
+
const stripEven = Math.floor(x.lo) % 2 === 0;
|
|
26580
|
+
if (stripEven) lo = Math.min(lo, 0);
|
|
26581
|
+
else hi = Math.max(hi, 0);
|
|
26582
|
+
}
|
|
26583
|
+
return ok({ lo, hi });
|
|
24758
26584
|
}
|
|
24759
26585
|
if (x.lo >= GAMMA_MIN_X) {
|
|
24760
26586
|
return ok({ lo: gamma(x.lo), hi: gamma(x.hi) });
|
|
@@ -24785,7 +26611,15 @@ ${code}`;
|
|
|
24785
26611
|
}
|
|
24786
26612
|
const gLo = gammaln(x.lo);
|
|
24787
26613
|
const gHi = gammaln(x.hi);
|
|
24788
|
-
|
|
26614
|
+
let lo = Math.min(gLo, gHi);
|
|
26615
|
+
const hi = Math.max(gLo, gHi);
|
|
26616
|
+
const xStar = gammaNegStripExtremum(x.lo);
|
|
26617
|
+
if (xStar !== null) {
|
|
26618
|
+
if (xStar >= x.lo && xStar <= x.hi) lo = Math.min(lo, gammaln(xStar));
|
|
26619
|
+
} else {
|
|
26620
|
+
lo = -Infinity;
|
|
26621
|
+
}
|
|
26622
|
+
return ok({ lo, hi });
|
|
24789
26623
|
}
|
|
24790
26624
|
return ok({ lo: gammaln(x.lo), hi: gammaln(x.hi) });
|
|
24791
26625
|
}
|
|
@@ -24811,6 +26645,33 @@ ${code}`;
|
|
|
24811
26645
|
return ok({ lo: Math.min(fLo, fHi), hi: Math.max(fLo, fHi) });
|
|
24812
26646
|
return ok({ lo: fLo, hi: fHi });
|
|
24813
26647
|
}
|
|
26648
|
+
var MAX_INT_ENUM_POINTS = 4096;
|
|
26649
|
+
function integerPoints(lo, hi, cap) {
|
|
26650
|
+
const a = Math.round(lo);
|
|
26651
|
+
const b = Math.round(hi);
|
|
26652
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return null;
|
|
26653
|
+
if (b - a + 1 > cap) return null;
|
|
26654
|
+
const out = [];
|
|
26655
|
+
for (let i = a; i <= b; i++) out.push(i);
|
|
26656
|
+
return out;
|
|
26657
|
+
}
|
|
26658
|
+
function enumerateInteger2(a, b, f) {
|
|
26659
|
+
const xs = integerPoints(a.lo, a.hi, MAX_INT_ENUM_POINTS);
|
|
26660
|
+
const ys = integerPoints(b.lo, b.hi, MAX_INT_ENUM_POINTS);
|
|
26661
|
+
if (!xs || !ys || xs.length * ys.length > MAX_INT_ENUM_POINTS) return null;
|
|
26662
|
+
let lo = Infinity;
|
|
26663
|
+
let hi = -Infinity;
|
|
26664
|
+
for (const x of xs)
|
|
26665
|
+
for (const y of ys) {
|
|
26666
|
+
const v = f(x, y);
|
|
26667
|
+
if (Number.isFinite(v)) {
|
|
26668
|
+
if (v < lo) lo = v;
|
|
26669
|
+
if (v > hi) hi = v;
|
|
26670
|
+
}
|
|
26671
|
+
}
|
|
26672
|
+
if (lo === Infinity) return null;
|
|
26673
|
+
return ok({ lo, hi });
|
|
26674
|
+
}
|
|
24814
26675
|
function binomial(n, k) {
|
|
24815
26676
|
const uN = unwrapOrPropagate(n);
|
|
24816
26677
|
if (!Array.isArray(uN)) return uN;
|
|
@@ -24818,13 +26679,10 @@ ${code}`;
|
|
|
24818
26679
|
if (!Array.isArray(uK)) return uK;
|
|
24819
26680
|
const [nVal] = uN;
|
|
24820
26681
|
const [kVal] = uK;
|
|
24821
|
-
const
|
|
24822
|
-
|
|
24823
|
-
|
|
24824
|
-
|
|
24825
|
-
choose(Math.round(nVal.hi), Math.round(kVal.hi))
|
|
24826
|
-
];
|
|
24827
|
-
return ok({ lo: Math.min(...vals), hi: Math.max(...vals) });
|
|
26682
|
+
const enumerated = enumerateInteger2(nVal, kVal, choose);
|
|
26683
|
+
if (enumerated) return enumerated;
|
|
26684
|
+
const nMax = Math.round(nVal.hi);
|
|
26685
|
+
return ok({ lo: 0, hi: choose(nMax, Math.floor(nMax / 2)) });
|
|
24828
26686
|
}
|
|
24829
26687
|
function gcd3(a, b) {
|
|
24830
26688
|
const uA = unwrapOrPropagate(a);
|
|
@@ -24833,13 +26691,15 @@ ${code}`;
|
|
|
24833
26691
|
if (!Array.isArray(uB)) return uB;
|
|
24834
26692
|
const [aVal] = uA;
|
|
24835
26693
|
const [bVal] = uB;
|
|
24836
|
-
const
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
26694
|
+
const enumerated = enumerateInteger2(aVal, bVal, gcd);
|
|
26695
|
+
if (enumerated) return enumerated;
|
|
26696
|
+
const m = Math.max(
|
|
26697
|
+
Math.abs(Math.round(aVal.lo)),
|
|
26698
|
+
Math.abs(Math.round(aVal.hi)),
|
|
26699
|
+
Math.abs(Math.round(bVal.lo)),
|
|
26700
|
+
Math.abs(Math.round(bVal.hi))
|
|
26701
|
+
);
|
|
26702
|
+
return ok({ lo: 0, hi: m });
|
|
24843
26703
|
}
|
|
24844
26704
|
function lcm3(a, b) {
|
|
24845
26705
|
const uA = unwrapOrPropagate(a);
|
|
@@ -24848,13 +26708,11 @@ ${code}`;
|
|
|
24848
26708
|
if (!Array.isArray(uB)) return uB;
|
|
24849
26709
|
const [aVal] = uA;
|
|
24850
26710
|
const [bVal] = uB;
|
|
24851
|
-
const
|
|
24852
|
-
|
|
24853
|
-
|
|
24854
|
-
|
|
24855
|
-
|
|
24856
|
-
];
|
|
24857
|
-
return ok({ lo: Math.min(...vals), hi: Math.max(...vals) });
|
|
26711
|
+
const enumerated = enumerateInteger2(aVal, bVal, lcm);
|
|
26712
|
+
if (enumerated) return enumerated;
|
|
26713
|
+
const ma = Math.max(Math.abs(Math.round(aVal.lo)), Math.abs(Math.round(aVal.hi)));
|
|
26714
|
+
const mb = Math.max(Math.abs(Math.round(bVal.lo)), Math.abs(Math.round(bVal.hi)));
|
|
26715
|
+
return ok({ lo: 0, hi: ma * mb });
|
|
24858
26716
|
}
|
|
24859
26717
|
function chop2(x) {
|
|
24860
26718
|
const unwrapped = unwrapOrPropagate(x);
|
|
@@ -25246,7 +27104,6 @@ ${code}`;
|
|
|
25246
27104
|
29.8116,
|
|
25247
27105
|
32.95639
|
|
25248
27106
|
];
|
|
25249
|
-
var SINC_GLOBAL_LO = -0.21724;
|
|
25250
27107
|
function sinc2(x) {
|
|
25251
27108
|
const unwrapped = unwrapOrPropagate(x);
|
|
25252
27109
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -25267,8 +27124,14 @@ ${code}`;
|
|
|
25267
27124
|
if (e >= xVal.lo && e <= xVal.hi) update(sincVal(e));
|
|
25268
27125
|
if (-e >= xVal.lo && -e <= xVal.hi) update(sincVal(-e));
|
|
25269
27126
|
}
|
|
25270
|
-
|
|
25271
|
-
|
|
27127
|
+
let minBeyondAbs = Infinity;
|
|
27128
|
+
if (xVal.hi > lastExtremum)
|
|
27129
|
+
minBeyondAbs = Math.min(minBeyondAbs, Math.max(xVal.lo, lastExtremum));
|
|
27130
|
+
if (xVal.lo < -lastExtremum)
|
|
27131
|
+
minBeyondAbs = Math.min(minBeyondAbs, -Math.min(xVal.hi, -lastExtremum));
|
|
27132
|
+
if (Number.isFinite(minBeyondAbs) && minBeyondAbs > 0) {
|
|
27133
|
+
update(1 / minBeyondAbs);
|
|
27134
|
+
update(-1 / minBeyondAbs);
|
|
25272
27135
|
}
|
|
25273
27136
|
return ok({ lo, hi });
|
|
25274
27137
|
}
|
|
@@ -25294,8 +27157,21 @@ ${code}`;
|
|
|
25294
27157
|
if (e >= xVal.lo && e <= xVal.hi) update(fresnelS(e));
|
|
25295
27158
|
if (-e >= xVal.lo && -e <= xVal.hi) update(fresnelS(-e));
|
|
25296
27159
|
}
|
|
27160
|
+
fresnelConvergenceBound(xVal, FRESNEL_S_EXTREMA, fresnelS, update);
|
|
25297
27161
|
return ok({ lo, hi });
|
|
25298
27162
|
}
|
|
27163
|
+
function fresnelConvergenceBound(xVal, extrema, scalar, update) {
|
|
27164
|
+
const lastE = extrema[extrema.length - 1];
|
|
27165
|
+
const amp = Math.abs(scalar(lastE) - 0.5);
|
|
27166
|
+
if (xVal.hi > lastE) {
|
|
27167
|
+
update(0.5 + amp);
|
|
27168
|
+
update(0.5 - amp);
|
|
27169
|
+
}
|
|
27170
|
+
if (xVal.lo < -lastE) {
|
|
27171
|
+
update(-0.5 - amp);
|
|
27172
|
+
update(-0.5 + amp);
|
|
27173
|
+
}
|
|
27174
|
+
}
|
|
25299
27175
|
function fresnelC2(x) {
|
|
25300
27176
|
const unwrapped = unwrapOrPropagate(x);
|
|
25301
27177
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -25312,6 +27188,7 @@ ${code}`;
|
|
|
25312
27188
|
if (e >= xVal.lo && e <= xVal.hi) update(fresnelC(e));
|
|
25313
27189
|
if (-e >= xVal.lo && -e <= xVal.hi) update(fresnelC(-e));
|
|
25314
27190
|
}
|
|
27191
|
+
fresnelConvergenceBound(xVal, FRESNEL_C_EXTREMA, fresnelC, update);
|
|
25315
27192
|
return ok({ lo, hi });
|
|
25316
27193
|
}
|
|
25317
27194
|
|
|
@@ -25419,11 +27296,9 @@ ${code}`;
|
|
|
25419
27296
|
const unwrapped = unwrapOrPropagate(x, lo, hi);
|
|
25420
27297
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
25421
27298
|
const [xVal, loVal, hiVal] = unwrapped;
|
|
25422
|
-
const
|
|
25423
|
-
const
|
|
25424
|
-
|
|
25425
|
-
return { kind: "empty" };
|
|
25426
|
-
}
|
|
27299
|
+
const lowered = { lo: Math.max(xVal.lo, loVal.lo), hi: Math.max(xVal.hi, loVal.hi) };
|
|
27300
|
+
const resultLo = Math.min(lowered.lo, hiVal.lo);
|
|
27301
|
+
const resultHi = Math.min(lowered.hi, hiVal.hi);
|
|
25427
27302
|
return { kind: "interval", value: { lo: resultLo, hi: resultHi } };
|
|
25428
27303
|
}
|
|
25429
27304
|
|
|
@@ -25756,7 +27631,7 @@ ${code}`;
|
|
|
25756
27631
|
function compileIntervalBound(expr, numVal, target) {
|
|
25757
27632
|
if (numVal !== void 0) return String(numVal);
|
|
25758
27633
|
const compiled = BaseCompiler.compile(expr, target);
|
|
25759
|
-
return `Math.floor((${compiled})
|
|
27634
|
+
return `Math.floor(((_b) => (_b && _b.value ? _b.value.hi : _b.hi))(${compiled}))`;
|
|
25760
27635
|
}
|
|
25761
27636
|
function compileIntervalSumProduct(kind, args, _compile, target) {
|
|
25762
27637
|
if (!args[0]) throw new Error(`${kind}: no body`);
|
|
@@ -25942,7 +27817,7 @@ ${code}`;
|
|
|
25942
27817
|
}
|
|
25943
27818
|
|
|
25944
27819
|
// src/compile.ts
|
|
25945
|
-
var version = "0.
|
|
27820
|
+
var version = "0.59.0";
|
|
25946
27821
|
return __toCommonJS(compile_exports);
|
|
25947
27822
|
})();
|
|
25948
27823
|
/*! Bundled license information:
|