@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.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 0.59.0 */
|
|
2
2
|
|
|
3
3
|
// src/compute-engine/numerics/richardson.ts
|
|
4
4
|
function extrapolate(f, x0, options = {}) {
|
|
@@ -159,6 +159,7 @@ function fpexp(x, scale) {
|
|
|
159
159
|
return sum;
|
|
160
160
|
}
|
|
161
161
|
function fpln(x, scale) {
|
|
162
|
+
if (x <= 0n) throw new RangeError("fpln: input must be positive");
|
|
162
163
|
if (x === scale) return 0n;
|
|
163
164
|
const xNum = Number(x);
|
|
164
165
|
const scaleNum = Number(scale);
|
|
@@ -808,9 +809,11 @@ var BigDecimal = class _BigDecimal {
|
|
|
808
809
|
if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) {
|
|
809
810
|
if (other.significand === 0n) return _BigDecimal.NAN;
|
|
810
811
|
if (this.significand === 0n) return fromRaw(0n, 0);
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
);
|
|
812
|
+
const ediff = thisExp - otherExp;
|
|
813
|
+
const num = ediff >= 0 ? this.significand * pow10(ediff) : this.significand;
|
|
814
|
+
const den = ediff >= 0 ? other.significand : other.significand * pow10(-ediff);
|
|
815
|
+
const q = num / den;
|
|
816
|
+
return this.sub(fromRaw(q, 0).mul(other));
|
|
814
817
|
}
|
|
815
818
|
if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN;
|
|
816
819
|
if (!Number.isFinite(thisExp)) return _BigDecimal.NAN;
|
|
@@ -855,7 +858,10 @@ var BigDecimal = class _BigDecimal {
|
|
|
855
858
|
return this.pow(n.neg()).inv();
|
|
856
859
|
}
|
|
857
860
|
const absSig = this.significand < 0n ? -this.significand : this.significand;
|
|
858
|
-
const
|
|
861
|
+
const sigDigits = bigintDigits(absSig);
|
|
862
|
+
const dropped = sigDigits > 15 ? sigDigits - 15 : 0;
|
|
863
|
+
const lead = dropped > 0 ? Number(absSig / 10n ** BigInt(dropped)) : Number(absSig);
|
|
864
|
+
const thisLog10 = Math.log10(lead) + dropped + this.exponent;
|
|
859
865
|
const resultLog10 = Number(expValue) * thisLog10;
|
|
860
866
|
if (resultLog10 > 9e15) {
|
|
861
867
|
return this.significand < 0n && expValue % 2n !== 0n ? _BigDecimal.NEGATIVE_INFINITY : _BigDecimal.POSITIVE_INFINITY;
|
|
@@ -888,7 +894,19 @@ var BigDecimal = class _BigDecimal {
|
|
|
888
894
|
return _BigDecimal.POSITIVE_INFINITY;
|
|
889
895
|
}
|
|
890
896
|
if (this.significand < 0n) return _BigDecimal.NAN;
|
|
891
|
-
|
|
897
|
+
const baseSig = this.significand;
|
|
898
|
+
const decExpBase = this.exponent + bigintDigits(baseSig) - 1;
|
|
899
|
+
const nSig = n.significand < 0n ? -n.significand : n.significand;
|
|
900
|
+
const decExpN = n.exponent + bigintDigits(nSig) - 1;
|
|
901
|
+
const argMag = decExpN + Math.log10(Math.abs(decExpBase) * 2.303 + 3) + 1;
|
|
902
|
+
const extra = Math.min(20, Math.max(2, Math.ceil(argMag) + 2));
|
|
903
|
+
const savedPrec = _BigDecimal.precision;
|
|
904
|
+
_BigDecimal.precision = savedPrec + extra;
|
|
905
|
+
try {
|
|
906
|
+
return n.mul(this.ln()).exp().toPrecision(savedPrec);
|
|
907
|
+
} finally {
|
|
908
|
+
_BigDecimal.precision = savedPrec;
|
|
909
|
+
}
|
|
892
910
|
}
|
|
893
911
|
// ---------- Conversion methods ----------
|
|
894
912
|
/** Convert to a JavaScript number. May lose precision for large values. */
|
|
@@ -1129,6 +1147,20 @@ function fromFixedPoint(fp, scale, targetPrecision) {
|
|
|
1129
1147
|
const sig = negative ? -absFp : absFp;
|
|
1130
1148
|
return fromRaw(sig, resultExp);
|
|
1131
1149
|
}
|
|
1150
|
+
function decimalExponent(x) {
|
|
1151
|
+
const sig = x.significand < 0n ? -x.significand : x.significand;
|
|
1152
|
+
return x.exponent + bigintDigits(sig) - 1;
|
|
1153
|
+
}
|
|
1154
|
+
var MAX_SAFE_EXPONENT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1155
|
+
var _ln10Fp = null;
|
|
1156
|
+
var _ln10Scale = null;
|
|
1157
|
+
function ln10Fixed(scale) {
|
|
1158
|
+
if (_ln10Scale !== scale) {
|
|
1159
|
+
_ln10Fp = fpln(10n * scale, scale);
|
|
1160
|
+
_ln10Scale = scale;
|
|
1161
|
+
}
|
|
1162
|
+
return _ln10Fp;
|
|
1163
|
+
}
|
|
1132
1164
|
BigDecimal.prototype.sqrt = function() {
|
|
1133
1165
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
1134
1166
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
@@ -1139,9 +1171,13 @@ BigDecimal.prototype.sqrt = function() {
|
|
|
1139
1171
|
if (this.significand < 0n) return BigDecimal.NAN;
|
|
1140
1172
|
const targetPrec = BigDecimal.precision;
|
|
1141
1173
|
const workingPrec = targetPrec + 10;
|
|
1142
|
-
const
|
|
1174
|
+
const e = decimalExponent(this);
|
|
1175
|
+
const k = Math.floor(e / 2);
|
|
1176
|
+
const m = fromRaw(this.significand, this.exponent - 2 * k);
|
|
1177
|
+
const [fp, scale] = toFixedPoint(m, workingPrec);
|
|
1143
1178
|
const sqrtFp = fpsqrt(fp, scale);
|
|
1144
|
-
|
|
1179
|
+
const root = fromFixedPoint(sqrtFp, scale, targetPrec);
|
|
1180
|
+
return fromRaw(root.significand, root.exponent + k);
|
|
1145
1181
|
};
|
|
1146
1182
|
BigDecimal.prototype.cbrt = function() {
|
|
1147
1183
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
@@ -1155,10 +1191,13 @@ BigDecimal.prototype.cbrt = function() {
|
|
|
1155
1191
|
}
|
|
1156
1192
|
const targetPrec = BigDecimal.precision;
|
|
1157
1193
|
const workingPrec = targetPrec + 10;
|
|
1158
|
-
const
|
|
1194
|
+
const e = decimalExponent(this);
|
|
1195
|
+
const k = Math.floor(e / 3);
|
|
1196
|
+
const m = fromRaw(this.significand, this.exponent - 3 * k);
|
|
1197
|
+
const [fp, scale] = toFixedPoint(m, workingPrec);
|
|
1159
1198
|
const C = fp * scale * scale;
|
|
1160
1199
|
let x;
|
|
1161
|
-
const numVal =
|
|
1200
|
+
const numVal = m.toNumber();
|
|
1162
1201
|
const scaleNum = Number(scale);
|
|
1163
1202
|
if (Number.isFinite(numVal) && numVal > 0 && Number.isFinite(scaleNum)) {
|
|
1164
1203
|
const approx = Math.cbrt(numVal);
|
|
@@ -1187,7 +1226,8 @@ BigDecimal.prototype.cbrt = function() {
|
|
|
1187
1226
|
const diffNext = bigintAbs(next * next * next - C);
|
|
1188
1227
|
if (diffNext < diffX) x = next;
|
|
1189
1228
|
}
|
|
1190
|
-
|
|
1229
|
+
const root = fromFixedPoint(x, scale, targetPrec);
|
|
1230
|
+
return fromRaw(root.significand, root.exponent + k);
|
|
1191
1231
|
};
|
|
1192
1232
|
BigDecimal.sqrt = function(x) {
|
|
1193
1233
|
return x.sqrt();
|
|
@@ -1202,11 +1242,27 @@ BigDecimal.prototype.exp = function() {
|
|
|
1202
1242
|
return BigDecimal.ZERO;
|
|
1203
1243
|
}
|
|
1204
1244
|
if (this.isZero()) return BigDecimal.ONE;
|
|
1245
|
+
if (decimalExponent(this) >= 17)
|
|
1246
|
+
return this.significand > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1205
1247
|
const targetPrec = BigDecimal.precision;
|
|
1206
|
-
const
|
|
1207
|
-
const
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1248
|
+
const absSig = this.significand < 0n ? -this.significand : this.significand;
|
|
1249
|
+
const magnitude = Math.max(0, this.exponent + bigintDigits(absSig));
|
|
1250
|
+
const workingPrec = targetPrec + 20 + magnitude;
|
|
1251
|
+
const [xFp, scale] = toFixedPoint(this, workingPrec);
|
|
1252
|
+
const l10 = ln10Fixed(scale);
|
|
1253
|
+
let k = xFp / l10;
|
|
1254
|
+
let rFp = xFp - k * l10;
|
|
1255
|
+
if (rFp < 0n) {
|
|
1256
|
+
k -= 1n;
|
|
1257
|
+
rFp += l10;
|
|
1258
|
+
}
|
|
1259
|
+
if (k > MAX_SAFE_EXPONENT || k < -MAX_SAFE_EXPONENT)
|
|
1260
|
+
return k > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1261
|
+
const expR = fromFixedPoint(fpexp(rFp, scale), scale, targetPrec);
|
|
1262
|
+
const newExp = expR.exponent + Number(k);
|
|
1263
|
+
if (!Number.isSafeInteger(newExp))
|
|
1264
|
+
return k > 0n ? BigDecimal.POSITIVE_INFINITY : BigDecimal.ZERO;
|
|
1265
|
+
return fromRaw(expR.significand, newExp);
|
|
1210
1266
|
};
|
|
1211
1267
|
BigDecimal.prototype.ln = function() {
|
|
1212
1268
|
if (this.isNaN()) return BigDecimal.NAN;
|
|
@@ -1218,10 +1274,16 @@ BigDecimal.prototype.ln = function() {
|
|
|
1218
1274
|
if (this.significand < 0n) return BigDecimal.NAN;
|
|
1219
1275
|
if (this.eq(1)) return BigDecimal.ZERO;
|
|
1220
1276
|
const targetPrec = BigDecimal.precision;
|
|
1221
|
-
const
|
|
1222
|
-
const
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1277
|
+
const sig = this.significand;
|
|
1278
|
+
const digits = bigintDigits(sig);
|
|
1279
|
+
const e = this.exponent + digits - 1;
|
|
1280
|
+
const m = fromRaw(sig, -(digits - 1));
|
|
1281
|
+
const eDigits = Math.abs(e).toString().length;
|
|
1282
|
+
const workingPrec = targetPrec + 20 + eDigits;
|
|
1283
|
+
const [mFp, scale] = toFixedPoint(m, workingPrec);
|
|
1284
|
+
const l10 = ln10Fixed(scale);
|
|
1285
|
+
const resultFp = fpln(mFp, scale) + BigInt(e) * l10;
|
|
1286
|
+
return fromFixedPoint(resultFp, scale, targetPrec);
|
|
1225
1287
|
};
|
|
1226
1288
|
BigDecimal.prototype.log = function(base) {
|
|
1227
1289
|
const b = base instanceof BigDecimal ? base : new BigDecimal(base);
|
|
@@ -1241,7 +1303,10 @@ BigDecimal.prototype.sin = function() {
|
|
|
1241
1303
|
if (!this.isFinite()) return BigDecimal.NAN;
|
|
1242
1304
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
1243
1305
|
const targetPrec = BigDecimal.precision;
|
|
1244
|
-
const
|
|
1306
|
+
const e = decimalExponent(this);
|
|
1307
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1308
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1309
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1245
1310
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1246
1311
|
const [sinFp] = fpsincos(fp, scale);
|
|
1247
1312
|
return fromFixedPoint(sinFp, scale, targetPrec);
|
|
@@ -1252,6 +1317,8 @@ BigDecimal.prototype.cos = function() {
|
|
|
1252
1317
|
if (this.isZero()) return BigDecimal.ONE;
|
|
1253
1318
|
const targetPrec = BigDecimal.precision;
|
|
1254
1319
|
const workingPrec = targetPrec + 15;
|
|
1320
|
+
const e = decimalExponent(this);
|
|
1321
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1255
1322
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1256
1323
|
const [, cosFp] = fpsincos(fp, scale);
|
|
1257
1324
|
return fromFixedPoint(cosFp, scale, targetPrec);
|
|
@@ -1261,7 +1328,10 @@ BigDecimal.prototype.tan = function() {
|
|
|
1261
1328
|
if (!this.isFinite()) return BigDecimal.NAN;
|
|
1262
1329
|
if (this.isZero()) return BigDecimal.ZERO;
|
|
1263
1330
|
const targetPrec = BigDecimal.precision;
|
|
1264
|
-
const
|
|
1331
|
+
const e = decimalExponent(this);
|
|
1332
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1333
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1334
|
+
if (e > PI_DIGITS.length - workingPrec - 30) return BigDecimal.NAN;
|
|
1265
1335
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1266
1336
|
const [sinFp, cosFp] = fpsincos(fp, scale);
|
|
1267
1337
|
if (cosFp === 0n) {
|
|
@@ -1279,7 +1349,9 @@ BigDecimal.prototype.atan = function() {
|
|
|
1279
1349
|
return piHalf.neg();
|
|
1280
1350
|
}
|
|
1281
1351
|
const targetPrec = BigDecimal.precision;
|
|
1282
|
-
const
|
|
1352
|
+
const e = decimalExponent(this);
|
|
1353
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1354
|
+
const workingPrec = targetPrec + 15 + (e < 0 ? -e : 0);
|
|
1283
1355
|
const [fp, scale] = toFixedPoint(this, workingPrec);
|
|
1284
1356
|
const atanFp = fpatan(fp, scale);
|
|
1285
1357
|
return fromFixedPoint(atanFp, scale, targetPrec);
|
|
@@ -1296,7 +1368,9 @@ BigDecimal.prototype.asin = function() {
|
|
|
1296
1368
|
return this.significand > 0n ? piHalf : piHalf.neg();
|
|
1297
1369
|
}
|
|
1298
1370
|
const targetPrec = BigDecimal.precision;
|
|
1299
|
-
const
|
|
1371
|
+
const e = decimalExponent(this);
|
|
1372
|
+
if (e < 0 && -2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1373
|
+
const workingPrec = targetPrec + 20 + (e < 0 ? -e : 0);
|
|
1300
1374
|
const [xFp, scale] = toFixedPoint(this, workingPrec);
|
|
1301
1375
|
const x2 = fpmul(xFp, xFp, scale);
|
|
1302
1376
|
const oneMinusX2 = scale - x2;
|
|
@@ -1359,6 +1433,23 @@ BigDecimal.prototype.sinh = function() {
|
|
|
1359
1433
|
if (this.significand > 0n) return BigDecimal.POSITIVE_INFINITY;
|
|
1360
1434
|
return BigDecimal.NEGATIVE_INFINITY;
|
|
1361
1435
|
}
|
|
1436
|
+
const targetPrec = BigDecimal.precision;
|
|
1437
|
+
const e = decimalExponent(this);
|
|
1438
|
+
if (e < 0) {
|
|
1439
|
+
if (-2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1440
|
+
const saved = BigDecimal.precision;
|
|
1441
|
+
BigDecimal.precision = targetPrec - e + 5;
|
|
1442
|
+
try {
|
|
1443
|
+
const expX2 = this.exp();
|
|
1444
|
+
return expX2.sub(expX2.inv()).div(BigDecimal.TWO).toPrecision(targetPrec);
|
|
1445
|
+
} finally {
|
|
1446
|
+
BigDecimal.precision = saved;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3)) {
|
|
1450
|
+
const h = this.abs().exp().div(BigDecimal.TWO);
|
|
1451
|
+
return this.significand > 0n ? h : h.neg();
|
|
1452
|
+
}
|
|
1362
1453
|
const expX = this.exp();
|
|
1363
1454
|
const expNegX = expX.inv();
|
|
1364
1455
|
return expX.sub(expNegX).div(BigDecimal.TWO);
|
|
@@ -1369,6 +1460,9 @@ BigDecimal.prototype.cosh = function() {
|
|
|
1369
1460
|
if (!this.isFinite()) {
|
|
1370
1461
|
return BigDecimal.POSITIVE_INFINITY;
|
|
1371
1462
|
}
|
|
1463
|
+
const targetPrec = BigDecimal.precision;
|
|
1464
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3))
|
|
1465
|
+
return this.abs().exp().div(BigDecimal.TWO);
|
|
1372
1466
|
const expX = this.exp();
|
|
1373
1467
|
const expNegX = expX.inv();
|
|
1374
1468
|
return expX.add(expNegX).div(BigDecimal.TWO);
|
|
@@ -1380,6 +1474,21 @@ BigDecimal.prototype.tanh = function() {
|
|
|
1380
1474
|
if (this.significand > 0n) return BigDecimal.ONE;
|
|
1381
1475
|
return BigDecimal.NEGATIVE_ONE;
|
|
1382
1476
|
}
|
|
1477
|
+
const targetPrec = BigDecimal.precision;
|
|
1478
|
+
const e = decimalExponent(this);
|
|
1479
|
+
if (e < 0) {
|
|
1480
|
+
if (-2 * e >= targetPrec + 4) return this.toPrecision(targetPrec);
|
|
1481
|
+
const saved = BigDecimal.precision;
|
|
1482
|
+
BigDecimal.precision = targetPrec - e + 5;
|
|
1483
|
+
try {
|
|
1484
|
+
const exp2x2 = this.mul(BigDecimal.TWO).exp();
|
|
1485
|
+
return exp2x2.sub(BigDecimal.ONE).div(exp2x2.add(BigDecimal.ONE)).toPrecision(targetPrec);
|
|
1486
|
+
} finally {
|
|
1487
|
+
BigDecimal.precision = saved;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
if (Math.abs(this.toNumber()) > 1.16 * (targetPrec + 3))
|
|
1491
|
+
return this.significand > 0n ? BigDecimal.ONE : BigDecimal.NEGATIVE_ONE;
|
|
1383
1492
|
const exp2x = this.mul(BigDecimal.TWO).exp();
|
|
1384
1493
|
return exp2x.sub(BigDecimal.ONE).div(exp2x.add(BigDecimal.ONE));
|
|
1385
1494
|
};
|
|
@@ -1428,6 +1537,7 @@ var MACHINE_PRECISION = Math.floor(
|
|
|
1428
1537
|
Math.log10(Math.pow(2, MACHINE_PRECISION_BITS))
|
|
1429
1538
|
);
|
|
1430
1539
|
var DEFAULT_TOLERANCE = 1e-10;
|
|
1540
|
+
var SMALL_INTEGER = 1e6;
|
|
1431
1541
|
var MAX_ITERATION = 1e4;
|
|
1432
1542
|
function gcd(a, b) {
|
|
1433
1543
|
if (a === 0) return b;
|
|
@@ -1439,7 +1549,8 @@ function gcd(a, b) {
|
|
|
1439
1549
|
}
|
|
1440
1550
|
function lcm(a, b) {
|
|
1441
1551
|
if (a === 0 || b === 0) return 0;
|
|
1442
|
-
|
|
1552
|
+
let res = BigInt(a) * BigInt(b) / BigInt(gcd(a, b));
|
|
1553
|
+
if (res < 0n) res = -res;
|
|
1443
1554
|
return Number(res);
|
|
1444
1555
|
}
|
|
1445
1556
|
function factorial(n) {
|
|
@@ -1529,216 +1640,27 @@ var PRIMITIVE_TYPES = [
|
|
|
1529
1640
|
"error",
|
|
1530
1641
|
...EXPRESSION_TYPES
|
|
1531
1642
|
];
|
|
1643
|
+
var NUMERIC_TYPES_SET = new Set(
|
|
1644
|
+
NUMERIC_TYPES
|
|
1645
|
+
);
|
|
1646
|
+
var COLLECTION_TYPES_SET = new Set(
|
|
1647
|
+
COLLECTION_TYPES
|
|
1648
|
+
);
|
|
1649
|
+
var SCALAR_TYPES_SET = new Set(
|
|
1650
|
+
SCALAR_TYPES
|
|
1651
|
+
);
|
|
1652
|
+
var PRIMITIVE_TYPES_SET = new Set(
|
|
1653
|
+
PRIMITIVE_TYPES
|
|
1654
|
+
);
|
|
1655
|
+
function isValidPrimitiveType(s) {
|
|
1656
|
+
if (typeof s !== "string") return false;
|
|
1657
|
+
return PRIMITIVE_TYPES_SET.has(s);
|
|
1658
|
+
}
|
|
1532
1659
|
function isValidType(t) {
|
|
1533
|
-
if (typeof t === "string")
|
|
1534
|
-
return PRIMITIVE_TYPES.includes(t);
|
|
1660
|
+
if (typeof t === "string") return PRIMITIVE_TYPES_SET.has(t);
|
|
1535
1661
|
if (typeof t !== "object") return false;
|
|
1536
1662
|
if (!("kind" in t)) return false;
|
|
1537
|
-
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 === "
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
// src/common/type/serialize.ts
|
|
1541
|
-
var NEGATION_PRECEDENCE = 3;
|
|
1542
|
-
var UNION_PRECEDENCE = 1;
|
|
1543
|
-
var INTERSECTION_PRECEDENCE = 2;
|
|
1544
|
-
var LIST_PRECEDENCE = 4;
|
|
1545
|
-
var RECORD_PRECEDENCE = 5;
|
|
1546
|
-
var DICTIONARY_PRECEDENCE = 6;
|
|
1547
|
-
var SET_PRECEDENCE = 7;
|
|
1548
|
-
var COLLECTION_PRECEDENCE = 8;
|
|
1549
|
-
var TUPLE_PRECEDENCE = 9;
|
|
1550
|
-
var SIGNATURE_PRECEDENCE = 10;
|
|
1551
|
-
var VALUE_PRECEDENCE = 11;
|
|
1552
|
-
function typeToString(type, precedence = 0) {
|
|
1553
|
-
if (typeof type === "string") return type;
|
|
1554
|
-
let result = "";
|
|
1555
|
-
switch (type.kind) {
|
|
1556
|
-
case "value":
|
|
1557
|
-
if (typeof type.value === "string") result = `"${type.value}"`;
|
|
1558
|
-
else if (typeof type.value === "boolean")
|
|
1559
|
-
result = type.value ? "true" : "false";
|
|
1560
|
-
else result = type.value.toString();
|
|
1561
|
-
break;
|
|
1562
|
-
case "reference":
|
|
1563
|
-
result = type.name;
|
|
1564
|
-
break;
|
|
1565
|
-
case "negation":
|
|
1566
|
-
result = `!${typeToString(type.type, NEGATION_PRECEDENCE)}`;
|
|
1567
|
-
break;
|
|
1568
|
-
case "union":
|
|
1569
|
-
result = type.types.map((t) => typeToString(t, UNION_PRECEDENCE)).join(" | ");
|
|
1570
|
-
break;
|
|
1571
|
-
case "intersection":
|
|
1572
|
-
result = type.types.map((t) => typeToString(t, INTERSECTION_PRECEDENCE)).join(" & ");
|
|
1573
|
-
break;
|
|
1574
|
-
case "expression":
|
|
1575
|
-
result = `expression<${symbolName(type.operator)}>`;
|
|
1576
|
-
break;
|
|
1577
|
-
case "symbol":
|
|
1578
|
-
result = `symbol<${symbolName(type.name)}>`;
|
|
1579
|
-
break;
|
|
1580
|
-
case "numeric":
|
|
1581
|
-
if (Number.isFinite(type.lower) && Number.isFinite(type.upper)) {
|
|
1582
|
-
result = `${type.type}<${type.lower}..${type.upper}>`;
|
|
1583
|
-
} else if (Number.isFinite(type.lower)) {
|
|
1584
|
-
result = `${type.type}<${type.lower}..>`;
|
|
1585
|
-
} else if (Number.isFinite(type.upper)) {
|
|
1586
|
-
result = `${type.type}<..${type.upper}>`;
|
|
1587
|
-
} else {
|
|
1588
|
-
result = `${type.type}`;
|
|
1589
|
-
}
|
|
1590
|
-
break;
|
|
1591
|
-
case "list":
|
|
1592
|
-
if (type.dimensions && typeof type.elements === "string" && NUMERIC_TYPES.includes(type.elements)) {
|
|
1593
|
-
if (type.dimensions === void 0) {
|
|
1594
|
-
if (type.elements === "number") result = "tensor";
|
|
1595
|
-
} else if (type.dimensions.length === 1) {
|
|
1596
|
-
if (type.elements === "number") {
|
|
1597
|
-
if (type.dimensions[0] < 0) result = "vector";
|
|
1598
|
-
else result = `vector<${type.dimensions[0]}>`;
|
|
1599
|
-
} else {
|
|
1600
|
-
if (type.dimensions[0] < 0)
|
|
1601
|
-
result = `vector<${typeToString(type.elements)}>`;
|
|
1602
|
-
else
|
|
1603
|
-
result = `vector<${typeToString(type.elements)}^${type.dimensions[0]}>`;
|
|
1604
|
-
}
|
|
1605
|
-
} else if (type.dimensions.length === 2) {
|
|
1606
|
-
const dims = type.dimensions;
|
|
1607
|
-
if (type.elements === "number") {
|
|
1608
|
-
if (dims[0] < 0 && dims[1] < 0) result = "matrix";
|
|
1609
|
-
else result = `matrix<${dims[0]}x${dims[1]}>`;
|
|
1610
|
-
} else {
|
|
1611
|
-
if (dims[0] < 0 && dims[1] < 0)
|
|
1612
|
-
result = `matrix<${typeToString(type.elements)}>`;
|
|
1613
|
-
else
|
|
1614
|
-
result = `matrix<${typeToString(type.elements)}^(${dims[0]}x${dims[1]})>`;
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
if (!result) {
|
|
1619
|
-
const dimensions = type.dimensions ? type.dimensions.length === 1 ? `^${type.dimensions[0].toString()}` : `^(${type.dimensions.join("x")})` : "";
|
|
1620
|
-
result = `list<${typeToString(type.elements)}${dimensions}>`;
|
|
1621
|
-
}
|
|
1622
|
-
break;
|
|
1623
|
-
case "record":
|
|
1624
|
-
const elements = Object.entries(type.elements).map(([key, value]) => `${key}: ${typeToString(value)}`).join(", ");
|
|
1625
|
-
result = `record<${elements}>`;
|
|
1626
|
-
break;
|
|
1627
|
-
case "dictionary":
|
|
1628
|
-
result = `dictionary<${typeToString(type.values)}>`;
|
|
1629
|
-
break;
|
|
1630
|
-
case "set":
|
|
1631
|
-
result = `set<${typeToString(type.elements)}>`;
|
|
1632
|
-
break;
|
|
1633
|
-
case "collection":
|
|
1634
|
-
result = `collection<${typeToString(type.elements)}>`;
|
|
1635
|
-
break;
|
|
1636
|
-
case "indexed_collection":
|
|
1637
|
-
result = `indexed_collection<${typeToString(type.elements)}>`;
|
|
1638
|
-
break;
|
|
1639
|
-
case "tuple":
|
|
1640
|
-
if (type.elements.length === 0) result = "tuple";
|
|
1641
|
-
else if (type.elements.length === 1) {
|
|
1642
|
-
const [el] = type.elements;
|
|
1643
|
-
result = `tuple<${namedElement(el)}>`;
|
|
1644
|
-
} else {
|
|
1645
|
-
result = "tuple<" + type.elements.map((el) => namedElement(el)).join(", ") + ">";
|
|
1646
|
-
}
|
|
1647
|
-
break;
|
|
1648
|
-
case "signature":
|
|
1649
|
-
const args = type.args ? type.args.map((arg) => namedElement(arg)).join(", ") : "";
|
|
1650
|
-
const optArgs = type.optArgs ? type.optArgs.map((arg) => namedElement(arg) + "?").join(", ") : "";
|
|
1651
|
-
const varArg = type.variadicArg ? type.variadicMin === 0 ? `${namedElement(type.variadicArg)}*` : `${namedElement(type.variadicArg)}+` : "";
|
|
1652
|
-
const argsList = [args, optArgs, varArg].filter((s) => s).join(", ");
|
|
1653
|
-
result = `(${argsList}) -> ${typeToString(type.result)}`;
|
|
1654
|
-
break;
|
|
1655
|
-
default:
|
|
1656
|
-
result = "error";
|
|
1657
|
-
}
|
|
1658
|
-
if (precedence > 0 && precedence > getPrecedence(type.kind))
|
|
1659
|
-
return `(${result})`;
|
|
1660
|
-
return result;
|
|
1661
|
-
}
|
|
1662
|
-
function namedElement(el) {
|
|
1663
|
-
if (el.name) return `${el.name}: ${typeToString(el.type)}`;
|
|
1664
|
-
return typeToString(el.type);
|
|
1665
|
-
}
|
|
1666
|
-
function symbolName(name) {
|
|
1667
|
-
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) return name;
|
|
1668
|
-
return `\`${name}\``;
|
|
1669
|
-
}
|
|
1670
|
-
function getPrecedence(kind) {
|
|
1671
|
-
switch (kind) {
|
|
1672
|
-
case "negation":
|
|
1673
|
-
return NEGATION_PRECEDENCE;
|
|
1674
|
-
case "union":
|
|
1675
|
-
return UNION_PRECEDENCE;
|
|
1676
|
-
case "intersection":
|
|
1677
|
-
return INTERSECTION_PRECEDENCE;
|
|
1678
|
-
case "list":
|
|
1679
|
-
return LIST_PRECEDENCE;
|
|
1680
|
-
case "record":
|
|
1681
|
-
return RECORD_PRECEDENCE;
|
|
1682
|
-
case "dictionary":
|
|
1683
|
-
return DICTIONARY_PRECEDENCE;
|
|
1684
|
-
case "set":
|
|
1685
|
-
return SET_PRECEDENCE;
|
|
1686
|
-
case "collection":
|
|
1687
|
-
case "indexed_collection":
|
|
1688
|
-
return COLLECTION_PRECEDENCE;
|
|
1689
|
-
case "tuple":
|
|
1690
|
-
return TUPLE_PRECEDENCE;
|
|
1691
|
-
case "signature":
|
|
1692
|
-
return SIGNATURE_PRECEDENCE;
|
|
1693
|
-
case "value":
|
|
1694
|
-
return VALUE_PRECEDENCE;
|
|
1695
|
-
default:
|
|
1696
|
-
return 0;
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
// src/common/fuzzy-string-match.ts
|
|
1701
|
-
function levenshtein(source, target) {
|
|
1702
|
-
if (source === target) return 0;
|
|
1703
|
-
if (source.length === 0) return target.length;
|
|
1704
|
-
if (target.length === 0) return source.length;
|
|
1705
|
-
let prevRow = Array.from(
|
|
1706
|
-
{ length: source.length + 1 },
|
|
1707
|
-
(_, j) => j
|
|
1708
|
-
);
|
|
1709
|
-
let currRow = new Array(source.length + 1);
|
|
1710
|
-
for (let i = 1; i <= target.length; i++) {
|
|
1711
|
-
currRow[0] = i;
|
|
1712
|
-
for (let j = 1; j <= source.length; j++) {
|
|
1713
|
-
const cost = source[j - 1] === target[i - 1] ? 0 : 1;
|
|
1714
|
-
currRow[j] = Math.min(
|
|
1715
|
-
prevRow[j] + 1,
|
|
1716
|
-
// deletion
|
|
1717
|
-
currRow[j - 1] + 1,
|
|
1718
|
-
// insertion
|
|
1719
|
-
prevRow[j - 1] + cost
|
|
1720
|
-
// substitution
|
|
1721
|
-
);
|
|
1722
|
-
}
|
|
1723
|
-
[prevRow, currRow] = [currRow, prevRow];
|
|
1724
|
-
}
|
|
1725
|
-
return prevRow[source.length];
|
|
1726
|
-
}
|
|
1727
|
-
function fuzzyStringMatch(invalidWord, validWords) {
|
|
1728
|
-
const threshold = 7;
|
|
1729
|
-
let bestMatch = null;
|
|
1730
|
-
let minDistance = Infinity;
|
|
1731
|
-
const invalidLength = invalidWord.length;
|
|
1732
|
-
for (const word of validWords) {
|
|
1733
|
-
if (Math.abs(invalidLength - word.length) > threshold) continue;
|
|
1734
|
-
const distance = levenshtein(invalidWord, word);
|
|
1735
|
-
if (distance === 0) return word;
|
|
1736
|
-
if (distance <= threshold && distance < minDistance) {
|
|
1737
|
-
minDistance = distance;
|
|
1738
|
-
bestMatch = word;
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
return bestMatch;
|
|
1663
|
+
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";
|
|
1742
1664
|
}
|
|
1743
1665
|
|
|
1744
1666
|
// src/common/type/lexer.ts
|
|
@@ -2448,19 +2370,13 @@ var Parser = class {
|
|
|
2448
2370
|
);
|
|
2449
2371
|
let dimensions;
|
|
2450
2372
|
if (this.match("<")) {
|
|
2451
|
-
dimensions = this.
|
|
2452
|
-
if (!dimensions) {
|
|
2453
|
-
dimensions = this.parseDimensions();
|
|
2454
|
-
}
|
|
2373
|
+
dimensions = this.parseDimensions();
|
|
2455
2374
|
if (!dimensions) {
|
|
2456
2375
|
const type = this.parseUnionType();
|
|
2457
2376
|
if (type) {
|
|
2458
2377
|
elementType = type;
|
|
2459
2378
|
if (this.match("^")) {
|
|
2460
|
-
dimensions = this.
|
|
2461
|
-
if (!dimensions) {
|
|
2462
|
-
dimensions = this.parseDimensions();
|
|
2463
|
-
}
|
|
2379
|
+
dimensions = this.parseCaretDimensions();
|
|
2464
2380
|
}
|
|
2465
2381
|
}
|
|
2466
2382
|
}
|
|
@@ -2501,19 +2417,13 @@ var Parser = class {
|
|
|
2501
2417
|
);
|
|
2502
2418
|
let dimensions;
|
|
2503
2419
|
if (this.match("<")) {
|
|
2504
|
-
dimensions = this.
|
|
2505
|
-
if (!dimensions) {
|
|
2506
|
-
dimensions = this.parseDimensions();
|
|
2507
|
-
}
|
|
2420
|
+
dimensions = this.parseDimensions();
|
|
2508
2421
|
if (!dimensions) {
|
|
2509
2422
|
const type = this.parseUnionType();
|
|
2510
2423
|
if (type) {
|
|
2511
2424
|
elementType = type;
|
|
2512
2425
|
if (this.match("^")) {
|
|
2513
|
-
dimensions = this.
|
|
2514
|
-
if (!dimensions) {
|
|
2515
|
-
dimensions = this.parseDimensions();
|
|
2516
|
-
}
|
|
2426
|
+
dimensions = this.parseCaretDimensions();
|
|
2517
2427
|
}
|
|
2518
2428
|
}
|
|
2519
2429
|
}
|
|
@@ -2544,16 +2454,30 @@ var Parser = class {
|
|
|
2544
2454
|
return this.createNode("tensor", { elementType });
|
|
2545
2455
|
}
|
|
2546
2456
|
parseDimensions() {
|
|
2547
|
-
const dimensions = [];
|
|
2548
2457
|
const firstDim = this.parseDimension();
|
|
2549
2458
|
if (!firstDim) return void 0;
|
|
2550
|
-
dimensions
|
|
2551
|
-
|
|
2552
|
-
const
|
|
2553
|
-
if (
|
|
2554
|
-
this.
|
|
2459
|
+
const dimensions = [firstDim];
|
|
2460
|
+
for (; ; ) {
|
|
2461
|
+
const tok = this.current;
|
|
2462
|
+
if (tok.type === "IDENTIFIER" && /^(x\d+)+$/.test(tok.value)) {
|
|
2463
|
+
this.advance();
|
|
2464
|
+
for (const m of tok.value.match(/x(\d+)/g))
|
|
2465
|
+
dimensions.push(
|
|
2466
|
+
this.createNode("dimension", {
|
|
2467
|
+
size: parseInt(m.slice(1))
|
|
2468
|
+
})
|
|
2469
|
+
);
|
|
2470
|
+
} else if (tok.type === "IDENTIFIER" && tok.value === "x") {
|
|
2471
|
+
const next = this.lexer.peekToken();
|
|
2472
|
+
if (next.type !== "NUMBER_LITERAL" && next.type !== "?")
|
|
2473
|
+
this.error(
|
|
2474
|
+
"Expected a positive integer literal or `?` after x. For example: `2x3` or `2x?`"
|
|
2475
|
+
);
|
|
2476
|
+
this.advance();
|
|
2477
|
+
dimensions.push(this.parseDimension());
|
|
2478
|
+
} else {
|
|
2479
|
+
break;
|
|
2555
2480
|
}
|
|
2556
|
-
dimensions.push(dim);
|
|
2557
2481
|
}
|
|
2558
2482
|
return dimensions;
|
|
2559
2483
|
}
|
|
@@ -2567,35 +2491,11 @@ var Parser = class {
|
|
|
2567
2491
|
}
|
|
2568
2492
|
return void 0;
|
|
2569
2493
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
this.createNode("dimension", { size: firstDim })
|
|
2576
|
-
);
|
|
2577
|
-
if (this.current.type === "IDENTIFIER" && this.current.value.startsWith("x")) {
|
|
2578
|
-
const dimString = this.current.value;
|
|
2579
|
-
const matches = dimString.match(/x(\d+)/g);
|
|
2580
|
-
if (matches && matches.join("") === dimString) {
|
|
2581
|
-
this.advance();
|
|
2582
|
-
for (const match of matches) {
|
|
2583
|
-
const dimValue = parseInt(match.substring(1));
|
|
2584
|
-
dimensions.push(
|
|
2585
|
-
this.createNode("dimension", { size: dimValue })
|
|
2586
|
-
);
|
|
2587
|
-
}
|
|
2588
|
-
} else if (dimString === "x" || dimString.startsWith("x")) {
|
|
2589
|
-
this.error(
|
|
2590
|
-
"Expected a positive integer literal or `?` after x. For example: `2x3` or `2x?`"
|
|
2591
|
-
);
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
if (dimensions.length > 1) {
|
|
2595
|
-
return dimensions;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
return void 0;
|
|
2494
|
+
parseCaretDimensions() {
|
|
2495
|
+
const paren = this.match("(");
|
|
2496
|
+
const dimensions = this.parseDimensions();
|
|
2497
|
+
if (paren) this.expect(")");
|
|
2498
|
+
return dimensions;
|
|
2599
2499
|
}
|
|
2600
2500
|
parseTupleType() {
|
|
2601
2501
|
if (this.current.type === "IDENTIFIER" && this.current.value === "tuple") {
|
|
@@ -2780,6 +2680,18 @@ var Parser = class {
|
|
|
2780
2680
|
this.expect("..");
|
|
2781
2681
|
const upperBound = this.parseValue();
|
|
2782
2682
|
this.expect(">");
|
|
2683
|
+
const lower = lowerBound?.value ?? -Infinity;
|
|
2684
|
+
const upper = upperBound?.value ?? Infinity;
|
|
2685
|
+
if (Number.isNaN(lower) || Number.isNaN(upper))
|
|
2686
|
+
this.error(
|
|
2687
|
+
"Invalid numeric type",
|
|
2688
|
+
"Lower and upper bounds must be valid numbers"
|
|
2689
|
+
);
|
|
2690
|
+
if (lower > upper)
|
|
2691
|
+
this.error(
|
|
2692
|
+
`Invalid range: ${lower}..${upper}`,
|
|
2693
|
+
"The lower bound must be less than the upper bound"
|
|
2694
|
+
);
|
|
2783
2695
|
return this.createNode("numeric", {
|
|
2784
2696
|
baseType,
|
|
2785
2697
|
lowerBound,
|
|
@@ -2794,7 +2706,7 @@ var Parser = class {
|
|
|
2794
2706
|
parsePrimitiveType() {
|
|
2795
2707
|
if (this.current.type === "IDENTIFIER") {
|
|
2796
2708
|
const name = this.current.value;
|
|
2797
|
-
if (
|
|
2709
|
+
if (PRIMITIVE_TYPES_SET.has(name)) {
|
|
2798
2710
|
this.advance();
|
|
2799
2711
|
return this.createNode("primitive", { name });
|
|
2800
2712
|
}
|
|
@@ -3128,14 +3040,32 @@ function buildTypeFromAST(node, typeResolver) {
|
|
|
3128
3040
|
}
|
|
3129
3041
|
|
|
3130
3042
|
// src/common/type/parse.ts
|
|
3043
|
+
var TYPE_CACHE = /* @__PURE__ */ new Map();
|
|
3044
|
+
var TYPE_CACHE_MAX_SIZE = 2048;
|
|
3045
|
+
function deepFreeze(obj) {
|
|
3046
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
3047
|
+
if (Object.isFrozen(obj)) return obj;
|
|
3048
|
+
Object.freeze(obj);
|
|
3049
|
+
for (const value of Object.values(obj)) deepFreeze(value);
|
|
3050
|
+
return obj;
|
|
3051
|
+
}
|
|
3131
3052
|
function parseType(s, typeResolver) {
|
|
3132
3053
|
if (s === void 0) return void 0;
|
|
3133
3054
|
if (isValidType(s)) return s;
|
|
3134
3055
|
if (typeof s !== "string") return void 0;
|
|
3056
|
+
const cacheable = typeResolver === void 0;
|
|
3057
|
+
if (cacheable) {
|
|
3058
|
+
const cached = TYPE_CACHE.get(s);
|
|
3059
|
+
if (cached !== void 0) return cached;
|
|
3060
|
+
}
|
|
3135
3061
|
try {
|
|
3136
3062
|
const parser = new Parser(s, { typeResolver });
|
|
3137
3063
|
const ast = parser.parseType();
|
|
3138
3064
|
const type = buildTypeFromAST(ast, typeResolver);
|
|
3065
|
+
if (cacheable) {
|
|
3066
|
+
if (TYPE_CACHE.size >= TYPE_CACHE_MAX_SIZE) TYPE_CACHE.clear();
|
|
3067
|
+
TYPE_CACHE.set(s, deepFreeze(type));
|
|
3068
|
+
}
|
|
3139
3069
|
return type;
|
|
3140
3070
|
} catch (error) {
|
|
3141
3071
|
throw new Error(
|
|
@@ -3210,19 +3140,54 @@ var PRIMITIVE_SUBTYPES = {
|
|
|
3210
3140
|
color: [],
|
|
3211
3141
|
expression: EXPRESSION_TYPES
|
|
3212
3142
|
};
|
|
3143
|
+
var PRIMITIVE_SUBTYPES_CLOSURE = (() => {
|
|
3144
|
+
const closure = {};
|
|
3145
|
+
const closeOver = (t) => {
|
|
3146
|
+
if (closure[t]) return closure[t];
|
|
3147
|
+
const result = /* @__PURE__ */ new Set([t]);
|
|
3148
|
+
closure[t] = result;
|
|
3149
|
+
for (const sub2 of PRIMITIVE_SUBTYPES[t]) {
|
|
3150
|
+
if (sub2 === t) continue;
|
|
3151
|
+
for (const s of closeOver(sub2)) result.add(s);
|
|
3152
|
+
}
|
|
3153
|
+
return result;
|
|
3154
|
+
};
|
|
3155
|
+
for (const t of Object.keys(PRIMITIVE_SUBTYPES))
|
|
3156
|
+
closeOver(t);
|
|
3157
|
+
return closure;
|
|
3158
|
+
})();
|
|
3213
3159
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
3214
3160
|
if (rhs === "any") return true;
|
|
3215
3161
|
if (lhs === "never") return true;
|
|
3216
3162
|
if (lhs === "unknown" || rhs === "unknown") return false;
|
|
3217
3163
|
if (lhs === rhs) return true;
|
|
3218
|
-
return
|
|
3164
|
+
return PRIMITIVE_SUBTYPES_CLOSURE[rhs].has(lhs);
|
|
3165
|
+
}
|
|
3166
|
+
function meetPrimitiveTypes(a, b) {
|
|
3167
|
+
if (a === b) return [a];
|
|
3168
|
+
const sa = PRIMITIVE_SUBTYPES_CLOSURE[a];
|
|
3169
|
+
const sb = PRIMITIVE_SUBTYPES_CLOSURE[b];
|
|
3170
|
+
if (sa.has(b)) return [b];
|
|
3171
|
+
if (sb.has(a)) return [a];
|
|
3172
|
+
const key = a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
3173
|
+
const cached = MEET_CACHE.get(key);
|
|
3174
|
+
if (cached) return cached;
|
|
3175
|
+
const common = [];
|
|
3176
|
+
for (const t of sa) if (sb.has(t)) common.push(t);
|
|
3177
|
+
const maximals = common.filter(
|
|
3178
|
+
(t) => !common.some((u) => u !== t && PRIMITIVE_SUBTYPES_CLOSURE[u].has(t))
|
|
3179
|
+
);
|
|
3180
|
+
MEET_CACHE.set(key, maximals);
|
|
3181
|
+
return maximals;
|
|
3219
3182
|
}
|
|
3183
|
+
var MEET_CACHE = /* @__PURE__ */ new Map();
|
|
3220
3184
|
function isSubtype(lhs, rhs) {
|
|
3221
|
-
if (typeof lhs === "string" && !
|
|
3185
|
+
if (typeof lhs === "string" && !PRIMITIVE_TYPES_SET.has(lhs))
|
|
3222
3186
|
lhs = parseType(lhs);
|
|
3223
|
-
if (typeof rhs === "string" && !
|
|
3187
|
+
if (typeof rhs === "string" && !PRIMITIVE_TYPES_SET.has(rhs))
|
|
3224
3188
|
rhs = parseType(rhs);
|
|
3225
3189
|
if (rhs === "any") return true;
|
|
3190
|
+
if (lhs === "never") return true;
|
|
3226
3191
|
if (rhs === "never") return false;
|
|
3227
3192
|
if (rhs === "error") return lhs === "error";
|
|
3228
3193
|
if (rhs === "nothing") return lhs === "nothing";
|
|
@@ -3237,7 +3202,7 @@ function isSubtype(lhs, rhs) {
|
|
|
3237
3202
|
if (typeof lhs.value === "number") {
|
|
3238
3203
|
if (Number.isInteger(lhs.value))
|
|
3239
3204
|
return isPrimitiveSubtype("integer", rhs);
|
|
3240
|
-
return isPrimitiveSubtype("
|
|
3205
|
+
return isPrimitiveSubtype("real", rhs);
|
|
3241
3206
|
}
|
|
3242
3207
|
if (typeof lhs.value === "boolean")
|
|
3243
3208
|
return isPrimitiveSubtype("boolean", rhs);
|
|
@@ -3467,7 +3432,7 @@ function isSubtype(lhs, rhs) {
|
|
|
3467
3432
|
}
|
|
3468
3433
|
function isNumeric(type) {
|
|
3469
3434
|
if (typeof type === "string")
|
|
3470
|
-
return
|
|
3435
|
+
return NUMERIC_TYPES_SET.has(type);
|
|
3471
3436
|
if (type.kind === "value") return typeof type.value === "number";
|
|
3472
3437
|
if (type.kind === "numeric") return true;
|
|
3473
3438
|
return false;
|
|
@@ -3475,7 +3440,7 @@ function isNumeric(type) {
|
|
|
3475
3440
|
function isScalar(type) {
|
|
3476
3441
|
if (isNumeric(type)) return true;
|
|
3477
3442
|
if (typeof type === "string")
|
|
3478
|
-
return
|
|
3443
|
+
return SCALAR_TYPES_SET.has(type);
|
|
3479
3444
|
if (type.kind === "value")
|
|
3480
3445
|
return ["string", "boolean", "number"].includes(typeof type.value);
|
|
3481
3446
|
return false;
|
|
@@ -3483,7 +3448,7 @@ function isScalar(type) {
|
|
|
3483
3448
|
function isCollection(type) {
|
|
3484
3449
|
if (isIndexedCollection(type)) return true;
|
|
3485
3450
|
if (typeof type === "string")
|
|
3486
|
-
return
|
|
3451
|
+
return COLLECTION_TYPES_SET.has(type);
|
|
3487
3452
|
return ["collection", "set", "record", "dictionary"].includes(type.kind);
|
|
3488
3453
|
}
|
|
3489
3454
|
function isIndexedCollection(type) {
|
|
@@ -3522,7 +3487,7 @@ function narrow2(a, b) {
|
|
|
3522
3487
|
if (b === "unknown") return a;
|
|
3523
3488
|
if (isSubtype(a, b)) return a;
|
|
3524
3489
|
if (isSubtype(b, a)) return b;
|
|
3525
|
-
return
|
|
3490
|
+
return "never";
|
|
3526
3491
|
}
|
|
3527
3492
|
function widen2(a, b) {
|
|
3528
3493
|
if (a === b) return a;
|
|
@@ -3535,7 +3500,43 @@ function widen2(a, b) {
|
|
|
3535
3500
|
if (b === "nothing") return a;
|
|
3536
3501
|
if (isSubtype(a, b)) return b;
|
|
3537
3502
|
if (isSubtype(b, a)) return a;
|
|
3538
|
-
|
|
3503
|
+
const sup = superType(a, b);
|
|
3504
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
3505
|
+
return sup;
|
|
3506
|
+
}
|
|
3507
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
3508
|
+
"scalar",
|
|
3509
|
+
"value",
|
|
3510
|
+
"function",
|
|
3511
|
+
"expression",
|
|
3512
|
+
"collection",
|
|
3513
|
+
"indexed_collection",
|
|
3514
|
+
"list",
|
|
3515
|
+
"set",
|
|
3516
|
+
"tuple",
|
|
3517
|
+
"record",
|
|
3518
|
+
"dictionary",
|
|
3519
|
+
"map",
|
|
3520
|
+
"any"
|
|
3521
|
+
]);
|
|
3522
|
+
function unionTypes(a, b) {
|
|
3523
|
+
const members = [];
|
|
3524
|
+
const keys = /* @__PURE__ */ new Set();
|
|
3525
|
+
const push = (t) => {
|
|
3526
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
3527
|
+
for (const m of t.types) push(m);
|
|
3528
|
+
return;
|
|
3529
|
+
}
|
|
3530
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
3531
|
+
if (!keys.has(key)) {
|
|
3532
|
+
keys.add(key);
|
|
3533
|
+
members.push(t);
|
|
3534
|
+
}
|
|
3535
|
+
};
|
|
3536
|
+
push(a);
|
|
3537
|
+
push(b);
|
|
3538
|
+
if (members.length === 1) return members[0];
|
|
3539
|
+
return { kind: "union", types: members };
|
|
3539
3540
|
}
|
|
3540
3541
|
function narrow(...types) {
|
|
3541
3542
|
if (types.length === 0) return "nothing";
|
|
@@ -3547,6 +3548,32 @@ function widen(...types) {
|
|
|
3547
3548
|
if (types.length === 1) return types[0];
|
|
3548
3549
|
return types.reduce((a, b) => widen2(a, b));
|
|
3549
3550
|
}
|
|
3551
|
+
var SUPERTYPE_PROBE_ORDER = [
|
|
3552
|
+
"non_finite_number",
|
|
3553
|
+
"finite_integer",
|
|
3554
|
+
"integer",
|
|
3555
|
+
"finite_rational",
|
|
3556
|
+
"rational",
|
|
3557
|
+
"finite_real",
|
|
3558
|
+
"real",
|
|
3559
|
+
"imaginary",
|
|
3560
|
+
"finite_complex",
|
|
3561
|
+
"complex",
|
|
3562
|
+
"finite_number",
|
|
3563
|
+
"number",
|
|
3564
|
+
"list",
|
|
3565
|
+
"record",
|
|
3566
|
+
"dictionary",
|
|
3567
|
+
"set",
|
|
3568
|
+
"tuple",
|
|
3569
|
+
"indexed_collection",
|
|
3570
|
+
"collection",
|
|
3571
|
+
"scalar",
|
|
3572
|
+
"value",
|
|
3573
|
+
"function",
|
|
3574
|
+
"expression"
|
|
3575
|
+
];
|
|
3576
|
+
var PRIMITIVE_SUPERTYPE_CACHE = /* @__PURE__ */ new Map();
|
|
3550
3577
|
function superType(a, b) {
|
|
3551
3578
|
if (a === b) return a;
|
|
3552
3579
|
if (a === "any" || b === "any") return "any";
|
|
@@ -3556,34 +3583,185 @@ function superType(a, b) {
|
|
|
3556
3583
|
if (b === "unknown") return a;
|
|
3557
3584
|
if (a === "nothing") return b;
|
|
3558
3585
|
if (b === "nothing") return a;
|
|
3559
|
-
if (
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
if (commonSupertype(a, b, "collection")) return "collection";
|
|
3578
|
-
if (commonSupertype(a, b, "scalar")) return "scalar";
|
|
3579
|
-
if (commonSupertype(a, b, "value")) return "value";
|
|
3580
|
-
if (commonSupertype(a, b, "function")) return "function";
|
|
3581
|
-
if (commonSupertype(a, b, "expression")) return "expression";
|
|
3586
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
3587
|
+
const key = a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
3588
|
+
let result = PRIMITIVE_SUPERTYPE_CACHE.get(key);
|
|
3589
|
+
if (result === void 0) {
|
|
3590
|
+
result = "any";
|
|
3591
|
+
for (const ancestor of SUPERTYPE_PROBE_ORDER) {
|
|
3592
|
+
const subtypes = PRIMITIVE_SUBTYPES_CLOSURE[ancestor];
|
|
3593
|
+
if (subtypes.has(a) && subtypes.has(b)) {
|
|
3594
|
+
result = ancestor;
|
|
3595
|
+
break;
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
PRIMITIVE_SUPERTYPE_CACHE.set(key, result);
|
|
3599
|
+
}
|
|
3600
|
+
return result;
|
|
3601
|
+
}
|
|
3602
|
+
for (const ancestor of SUPERTYPE_PROBE_ORDER)
|
|
3603
|
+
if (isSubtype(a, ancestor) && isSubtype(b, ancestor)) return ancestor;
|
|
3582
3604
|
return "any";
|
|
3583
3605
|
}
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3606
|
+
|
|
3607
|
+
// src/common/type/serialize.ts
|
|
3608
|
+
var NEGATION_PRECEDENCE = 3;
|
|
3609
|
+
var UNION_PRECEDENCE = 1;
|
|
3610
|
+
var INTERSECTION_PRECEDENCE = 2;
|
|
3611
|
+
var LIST_PRECEDENCE = 4;
|
|
3612
|
+
var RECORD_PRECEDENCE = 5;
|
|
3613
|
+
var DICTIONARY_PRECEDENCE = 6;
|
|
3614
|
+
var SET_PRECEDENCE = 7;
|
|
3615
|
+
var COLLECTION_PRECEDENCE = 8;
|
|
3616
|
+
var TUPLE_PRECEDENCE = 9;
|
|
3617
|
+
var SIGNATURE_PRECEDENCE = 10;
|
|
3618
|
+
var VALUE_PRECEDENCE = 11;
|
|
3619
|
+
function typeToString(type, precedence = 0) {
|
|
3620
|
+
if (typeof type === "string") return type;
|
|
3621
|
+
let result = "";
|
|
3622
|
+
switch (type.kind) {
|
|
3623
|
+
case "value":
|
|
3624
|
+
if (typeof type.value === "string") result = `"${type.value}"`;
|
|
3625
|
+
else if (typeof type.value === "boolean")
|
|
3626
|
+
result = type.value ? "true" : "false";
|
|
3627
|
+
else result = type.value.toString();
|
|
3628
|
+
break;
|
|
3629
|
+
case "reference":
|
|
3630
|
+
result = type.name;
|
|
3631
|
+
break;
|
|
3632
|
+
case "negation":
|
|
3633
|
+
result = `!${typeToString(type.type, NEGATION_PRECEDENCE)}`;
|
|
3634
|
+
break;
|
|
3635
|
+
case "union":
|
|
3636
|
+
result = type.types.map((t) => typeToString(t, UNION_PRECEDENCE)).join(" | ");
|
|
3637
|
+
break;
|
|
3638
|
+
case "intersection":
|
|
3639
|
+
result = type.types.map((t) => typeToString(t, INTERSECTION_PRECEDENCE)).join(" & ");
|
|
3640
|
+
break;
|
|
3641
|
+
case "expression":
|
|
3642
|
+
result = `expression<${symbolName(type.operator)}>`;
|
|
3643
|
+
break;
|
|
3644
|
+
case "symbol":
|
|
3645
|
+
result = `symbol<${symbolName(type.name)}>`;
|
|
3646
|
+
break;
|
|
3647
|
+
case "numeric":
|
|
3648
|
+
if (Number.isFinite(type.lower) && Number.isFinite(type.upper)) {
|
|
3649
|
+
result = `${type.type}<${type.lower}..${type.upper}>`;
|
|
3650
|
+
} else if (Number.isFinite(type.lower)) {
|
|
3651
|
+
result = `${type.type}<${type.lower}..>`;
|
|
3652
|
+
} else if (Number.isFinite(type.upper)) {
|
|
3653
|
+
result = `${type.type}<..${type.upper}>`;
|
|
3654
|
+
} else {
|
|
3655
|
+
result = `${type.type}`;
|
|
3656
|
+
}
|
|
3657
|
+
break;
|
|
3658
|
+
case "list":
|
|
3659
|
+
if (type.dimensions && typeof type.elements === "string" && NUMERIC_TYPES_SET.has(type.elements)) {
|
|
3660
|
+
if (type.dimensions === void 0) {
|
|
3661
|
+
if (type.elements === "number") result = "tensor";
|
|
3662
|
+
} else if (type.dimensions.length === 1) {
|
|
3663
|
+
if (type.elements === "number") {
|
|
3664
|
+
if (type.dimensions[0] < 0) result = "vector";
|
|
3665
|
+
else result = `vector<${type.dimensions[0]}>`;
|
|
3666
|
+
} else {
|
|
3667
|
+
if (type.dimensions[0] < 0)
|
|
3668
|
+
result = `vector<${typeToString(type.elements)}>`;
|
|
3669
|
+
else
|
|
3670
|
+
result = `vector<${typeToString(type.elements)}^${type.dimensions[0]}>`;
|
|
3671
|
+
}
|
|
3672
|
+
} else if (type.dimensions.length === 2) {
|
|
3673
|
+
const dims = type.dimensions;
|
|
3674
|
+
if (type.elements === "number") {
|
|
3675
|
+
if (dims[0] < 0 && dims[1] < 0) result = "matrix";
|
|
3676
|
+
else result = `matrix<${dims[0]}x${dims[1]}>`;
|
|
3677
|
+
} else {
|
|
3678
|
+
if (dims[0] < 0 && dims[1] < 0)
|
|
3679
|
+
result = `matrix<${typeToString(type.elements)}>`;
|
|
3680
|
+
else
|
|
3681
|
+
result = `matrix<${typeToString(type.elements)}^(${dims[0]}x${dims[1]})>`;
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
if (!result) {
|
|
3686
|
+
const dimensions = type.dimensions ? type.dimensions.length === 1 ? `^${type.dimensions[0].toString()}` : `^(${type.dimensions.join("x")})` : "";
|
|
3687
|
+
result = `list<${typeToString(type.elements)}${dimensions}>`;
|
|
3688
|
+
}
|
|
3689
|
+
break;
|
|
3690
|
+
case "record":
|
|
3691
|
+
const elements = Object.entries(type.elements).map(([key, value]) => `${key}: ${typeToString(value)}`).join(", ");
|
|
3692
|
+
result = `record<${elements}>`;
|
|
3693
|
+
break;
|
|
3694
|
+
case "dictionary":
|
|
3695
|
+
result = `dictionary<${typeToString(type.values)}>`;
|
|
3696
|
+
break;
|
|
3697
|
+
case "set":
|
|
3698
|
+
result = `set<${typeToString(type.elements)}>`;
|
|
3699
|
+
break;
|
|
3700
|
+
case "collection":
|
|
3701
|
+
result = `collection<${typeToString(type.elements)}>`;
|
|
3702
|
+
break;
|
|
3703
|
+
case "indexed_collection":
|
|
3704
|
+
result = `indexed_collection<${typeToString(type.elements)}>`;
|
|
3705
|
+
break;
|
|
3706
|
+
case "tuple":
|
|
3707
|
+
if (type.elements.length === 0) result = "tuple";
|
|
3708
|
+
else if (type.elements.length === 1) {
|
|
3709
|
+
const [el] = type.elements;
|
|
3710
|
+
result = `tuple<${namedElement(el)}>`;
|
|
3711
|
+
} else {
|
|
3712
|
+
result = "tuple<" + type.elements.map((el) => namedElement(el)).join(", ") + ">";
|
|
3713
|
+
}
|
|
3714
|
+
break;
|
|
3715
|
+
case "signature":
|
|
3716
|
+
const args = type.args ? type.args.map((arg) => namedElement(arg)).join(", ") : "";
|
|
3717
|
+
const optArgs = type.optArgs ? type.optArgs.map((arg) => namedElement(arg) + "?").join(", ") : "";
|
|
3718
|
+
const varArg = type.variadicArg ? type.variadicMin === 0 ? `${namedElement(type.variadicArg)}*` : `${namedElement(type.variadicArg)}+` : "";
|
|
3719
|
+
const argsList = [args, optArgs, varArg].filter((s) => s).join(", ");
|
|
3720
|
+
result = `(${argsList}) -> ${typeToString(type.result)}`;
|
|
3721
|
+
break;
|
|
3722
|
+
default:
|
|
3723
|
+
result = "error";
|
|
3724
|
+
}
|
|
3725
|
+
if (precedence > 0 && precedence > getPrecedence(type.kind))
|
|
3726
|
+
return `(${result})`;
|
|
3727
|
+
return result;
|
|
3728
|
+
}
|
|
3729
|
+
function namedElement(el) {
|
|
3730
|
+
if (el.name) return `${el.name}: ${typeToString(el.type)}`;
|
|
3731
|
+
return typeToString(el.type);
|
|
3732
|
+
}
|
|
3733
|
+
function symbolName(name) {
|
|
3734
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) return name;
|
|
3735
|
+
return `\`${name}\``;
|
|
3736
|
+
}
|
|
3737
|
+
function getPrecedence(kind) {
|
|
3738
|
+
switch (kind) {
|
|
3739
|
+
case "negation":
|
|
3740
|
+
return NEGATION_PRECEDENCE;
|
|
3741
|
+
case "union":
|
|
3742
|
+
return UNION_PRECEDENCE;
|
|
3743
|
+
case "intersection":
|
|
3744
|
+
return INTERSECTION_PRECEDENCE;
|
|
3745
|
+
case "list":
|
|
3746
|
+
return LIST_PRECEDENCE;
|
|
3747
|
+
case "record":
|
|
3748
|
+
return RECORD_PRECEDENCE;
|
|
3749
|
+
case "dictionary":
|
|
3750
|
+
return DICTIONARY_PRECEDENCE;
|
|
3751
|
+
case "set":
|
|
3752
|
+
return SET_PRECEDENCE;
|
|
3753
|
+
case "collection":
|
|
3754
|
+
case "indexed_collection":
|
|
3755
|
+
return COLLECTION_PRECEDENCE;
|
|
3756
|
+
case "tuple":
|
|
3757
|
+
return TUPLE_PRECEDENCE;
|
|
3758
|
+
case "signature":
|
|
3759
|
+
return SIGNATURE_PRECEDENCE;
|
|
3760
|
+
case "value":
|
|
3761
|
+
return VALUE_PRECEDENCE;
|
|
3762
|
+
default:
|
|
3763
|
+
return 0;
|
|
3764
|
+
}
|
|
3587
3765
|
}
|
|
3588
3766
|
|
|
3589
3767
|
// src/common/type/utils.ts
|
|
@@ -3609,7 +3787,7 @@ function collectionElementType(type) {
|
|
|
3609
3787
|
if (type.kind === "set") return type.elements;
|
|
3610
3788
|
if (type.kind === "tuple") return widen(...type.elements.map((x) => x.type));
|
|
3611
3789
|
if (type.kind === "dictionary")
|
|
3612
|
-
return parseType(`tuple<string, ${type.values}>`);
|
|
3790
|
+
return parseType(`tuple<string, ${typeToString(type.values)}>`);
|
|
3613
3791
|
if (type.kind === "record") {
|
|
3614
3792
|
return parseType(
|
|
3615
3793
|
`tuple<string, ${typeToString(widen(...Object.values(type.elements)))}>`
|
|
@@ -3692,6 +3870,12 @@ function sym(expr) {
|
|
|
3692
3870
|
return expr?._kind === "symbol" ? expr.symbol : void 0;
|
|
3693
3871
|
}
|
|
3694
3872
|
|
|
3873
|
+
// src/compute-engine/boxed-expression/constraint-subject.ts
|
|
3874
|
+
var EMPTY_FACT_INDEX = Object.freeze({
|
|
3875
|
+
bySubject: /* @__PURE__ */ new Map(),
|
|
3876
|
+
membership: /* @__PURE__ */ new Map()
|
|
3877
|
+
});
|
|
3878
|
+
|
|
3695
3879
|
// src/compute-engine/boxed-expression/stochastic-equal.ts
|
|
3696
3880
|
var WELL_KNOWN_POINTS = [
|
|
3697
3881
|
0,
|
|
@@ -3940,6 +4124,7 @@ function applicable(fn) {
|
|
|
3940
4124
|
}
|
|
3941
4125
|
|
|
3942
4126
|
// src/compute-engine/collection-utils.ts
|
|
4127
|
+
var MAX_SIZE_EAGER_COLLECTION = 100;
|
|
3943
4128
|
function isFiniteIndexedCollection(col) {
|
|
3944
4129
|
return (col.isFiniteCollection ?? false) && col.isIndexedCollection;
|
|
3945
4130
|
}
|
|
@@ -4568,12 +4753,14 @@ function dictionaryFromExpression(expr) {
|
|
|
4568
4753
|
if (expr === null) return null;
|
|
4569
4754
|
if (isDictionaryObject(expr)) return expr;
|
|
4570
4755
|
const kv = keyValuePair(expr);
|
|
4571
|
-
if (kv)
|
|
4756
|
+
if (kv)
|
|
4757
|
+
return {
|
|
4758
|
+
dict: { [kv[0]]: expressionToDictionaryValue(kv[1]) ?? "Nothing" }
|
|
4759
|
+
};
|
|
4572
4760
|
if (operator(expr) === "Dictionary") {
|
|
4573
4761
|
const dict = {};
|
|
4574
|
-
const
|
|
4575
|
-
|
|
4576
|
-
const kv2 = keyValuePair(ops[i]);
|
|
4762
|
+
for (const op of operands(expr)) {
|
|
4763
|
+
const kv2 = keyValuePair(op);
|
|
4577
4764
|
if (kv2) {
|
|
4578
4765
|
dict[kv2[0]] = expressionToDictionaryValue(kv2[1]) ?? "Nothing";
|
|
4579
4766
|
}
|
|
@@ -5511,15 +5698,16 @@ var DEFINITIONS_CORE = [
|
|
|
5511
5698
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
5512
5699
|
parse: parseAssign
|
|
5513
5700
|
},
|
|
5514
|
-
// General colon operator (type annotation, mapping notation)
|
|
5515
|
-
// Precedence below
|
|
5516
|
-
// and below arrows (270) so
|
|
5701
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
5702
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
5703
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
5704
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
5517
5705
|
{
|
|
5518
5706
|
name: "Colon",
|
|
5519
5707
|
latexTrigger: ":",
|
|
5520
5708
|
kind: "infix",
|
|
5521
5709
|
associativity: "right",
|
|
5522
|
-
precedence:
|
|
5710
|
+
precedence: 240,
|
|
5523
5711
|
serialize: (serializer, expr) => joinLatex([
|
|
5524
5712
|
serializer.serialize(operand(expr, 1)),
|
|
5525
5713
|
"\\colon",
|
|
@@ -5530,7 +5718,7 @@ var DEFINITIONS_CORE = [
|
|
|
5530
5718
|
latexTrigger: "\\colon",
|
|
5531
5719
|
kind: "infix",
|
|
5532
5720
|
associativity: "right",
|
|
5533
|
-
precedence:
|
|
5721
|
+
precedence: 240,
|
|
5534
5722
|
parse: "Colon"
|
|
5535
5723
|
},
|
|
5536
5724
|
{
|
|
@@ -6506,6 +6694,7 @@ var DEFINITIONS_CORE = [
|
|
|
6506
6694
|
}
|
|
6507
6695
|
}
|
|
6508
6696
|
if (!variable) return null;
|
|
6697
|
+
if (symbol(variable) === null) return null;
|
|
6509
6698
|
parser.skipSpace();
|
|
6510
6699
|
const fn = parser.parseExpression({ minPrec: 740 });
|
|
6511
6700
|
if (!fn) return null;
|
|
@@ -6692,7 +6881,7 @@ function parseTextRun(parser, style) {
|
|
|
6692
6881
|
if (runs.length === 1) body = runs[0];
|
|
6693
6882
|
else {
|
|
6694
6883
|
if (runs.every((x) => stringValue(x) !== null))
|
|
6695
|
-
body = "'" + runs.map((x) => stringValue(x)).join() + "'";
|
|
6884
|
+
body = "'" + runs.map((x) => stringValue(x)).join("") + "'";
|
|
6696
6885
|
else body = ["Text", ...runs];
|
|
6697
6886
|
}
|
|
6698
6887
|
return style ? ["Annotated", body, dictionaryFromEntries(style)] : body;
|
|
@@ -7100,7 +7289,10 @@ function parseForComprehension(parser, lhs, until) {
|
|
|
7100
7289
|
p.skipVisualSpace();
|
|
7101
7290
|
const isComma = p.peek === ",";
|
|
7102
7291
|
p.index = saved;
|
|
7103
|
-
return
|
|
7292
|
+
if (isComma) return true;
|
|
7293
|
+
if (peekKeyword(p, "where")) return true;
|
|
7294
|
+
if (peekKeyword(p, "with")) return true;
|
|
7295
|
+
return false;
|
|
7104
7296
|
}
|
|
7105
7297
|
};
|
|
7106
7298
|
const elements = [];
|
|
@@ -7141,6 +7333,25 @@ function parseWhereExpression(parser, lhs, until) {
|
|
|
7141
7333
|
parser.skipVisualSpace();
|
|
7142
7334
|
} while (parser.match(","));
|
|
7143
7335
|
if (bindings.length === 0) return null;
|
|
7336
|
+
const forStart = parser.index;
|
|
7337
|
+
if (matchKeyword(parser, "for")) {
|
|
7338
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
7339
|
+
if (loop) {
|
|
7340
|
+
const block2 = [];
|
|
7341
|
+
for (const b of bindings) {
|
|
7342
|
+
const normalized = normalizeLocalAssign(b);
|
|
7343
|
+
if (operator(normalized) === "Assign") {
|
|
7344
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
7345
|
+
block2.push(normalized);
|
|
7346
|
+
} else {
|
|
7347
|
+
block2.push(normalized);
|
|
7348
|
+
}
|
|
7349
|
+
}
|
|
7350
|
+
block2.push(loop);
|
|
7351
|
+
return ["Block", ...block2];
|
|
7352
|
+
}
|
|
7353
|
+
parser.index = forStart;
|
|
7354
|
+
}
|
|
7144
7355
|
const block = [];
|
|
7145
7356
|
for (const b of bindings) {
|
|
7146
7357
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -7354,6 +7565,17 @@ function parseIntervalBody(body, openLeft, openRight) {
|
|
|
7354
7565
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
7355
7566
|
return ["Interval", lowerExpr, upperExpr];
|
|
7356
7567
|
}
|
|
7568
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
7569
|
+
"Less",
|
|
7570
|
+
"LessEqual",
|
|
7571
|
+
"Greater",
|
|
7572
|
+
"GreaterEqual",
|
|
7573
|
+
"Equal",
|
|
7574
|
+
"NotEqual",
|
|
7575
|
+
"And",
|
|
7576
|
+
"Or",
|
|
7577
|
+
"Not"
|
|
7578
|
+
]);
|
|
7357
7579
|
var DEFINITIONS_SETS = [
|
|
7358
7580
|
//
|
|
7359
7581
|
// Constants
|
|
@@ -7612,18 +7834,58 @@ var DEFINITIONS_SETS = [
|
|
|
7612
7834
|
closeTrigger: "}",
|
|
7613
7835
|
parse: (_parser, body) => {
|
|
7614
7836
|
if (isEmptySequence(body)) return "EmptySet";
|
|
7837
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
7838
|
+
body = operand(body, 1);
|
|
7839
|
+
}
|
|
7615
7840
|
const h = operator(body);
|
|
7616
|
-
if (h === "Divides"
|
|
7841
|
+
if (h === "Divides") {
|
|
7617
7842
|
const expr = operand(body, 1);
|
|
7618
7843
|
const condition = operand(body, 2);
|
|
7619
7844
|
if (expr !== null && condition !== null)
|
|
7620
7845
|
return ["Set", expr, ["Condition", condition]];
|
|
7621
7846
|
}
|
|
7622
|
-
if (
|
|
7623
|
-
|
|
7847
|
+
if (h === "Colon") {
|
|
7848
|
+
const lhs = operand(body, 1);
|
|
7849
|
+
const rhs = operand(body, 2);
|
|
7850
|
+
if (lhs !== null && rhs !== null) {
|
|
7851
|
+
const lhsOp = operator(lhs);
|
|
7852
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
7853
|
+
return ["Which", lhs, rhs];
|
|
7854
|
+
}
|
|
7855
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
7856
|
+
}
|
|
7857
|
+
}
|
|
7858
|
+
if (h === "Sequence") {
|
|
7859
|
+
const elements = operands(body);
|
|
7860
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
7861
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
7862
|
+
const lhs = operand(el, 1);
|
|
7863
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
7864
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
7865
|
+
});
|
|
7866
|
+
if (allPiecewise) {
|
|
7867
|
+
const whichOps = [];
|
|
7868
|
+
for (let i = 0; i < elements.length; i++) {
|
|
7869
|
+
const el = elements[i];
|
|
7870
|
+
if (operator(el) === "Colon") {
|
|
7871
|
+
const cond = operand(el, 1);
|
|
7872
|
+
const val = operand(el, 2);
|
|
7873
|
+
if (cond === null || val === null) {
|
|
7874
|
+
return ["Set", ...elements];
|
|
7875
|
+
}
|
|
7876
|
+
whichOps.push(cond, val);
|
|
7877
|
+
} else {
|
|
7878
|
+
if (i !== elements.length - 1) {
|
|
7879
|
+
return ["Set", ...elements];
|
|
7880
|
+
}
|
|
7881
|
+
whichOps.push("True", el);
|
|
7882
|
+
}
|
|
7883
|
+
}
|
|
7884
|
+
return ["Which", ...whichOps];
|
|
7885
|
+
}
|
|
7886
|
+
return ["Set", ...elements];
|
|
7624
7887
|
}
|
|
7625
|
-
|
|
7626
|
-
return ["Set", ...operands(body)];
|
|
7888
|
+
return ["Set", body];
|
|
7627
7889
|
},
|
|
7628
7890
|
serialize: (serializer, expr) => {
|
|
7629
7891
|
if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
|
|
@@ -8152,6 +8414,8 @@ function serializeMultiply(serializer, expr) {
|
|
|
8152
8414
|
const h = operator(arg);
|
|
8153
8415
|
if (prevWasNumber && (h === "Divide" || h === "Rational")) {
|
|
8154
8416
|
result = latexTemplate(serializer.options.multiply, result, term);
|
|
8417
|
+
} else if (/^\d/.test(term)) {
|
|
8418
|
+
result = latexTemplate(serializer.options.multiply, result, term);
|
|
8155
8419
|
} else if (!serializer.options.invisibleMultiply) {
|
|
8156
8420
|
result = joinLatex([result, term]);
|
|
8157
8421
|
} else {
|
|
@@ -9597,7 +9861,9 @@ function parseTrig(op) {
|
|
|
9597
9861
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
9598
9862
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
9599
9863
|
});
|
|
9600
|
-
const
|
|
9864
|
+
const isTwoArgArctan = args?.length === 2 && (fn === "Arctan" || Array.isArray(fn) && fn[0] === "InverseFunction" && fn[1] === "Tan");
|
|
9865
|
+
const head = isTwoArgArctan ? "Arctan2" : fn;
|
|
9866
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
9601
9867
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
9602
9868
|
};
|
|
9603
9869
|
}
|
|
@@ -11720,10 +11986,17 @@ var DEFINITIONS_OTHERS = [
|
|
|
11720
11986
|
// The capitalized library entries already exist; these are pure parse
|
|
11721
11987
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11722
11988
|
// ---------------------------------------------------------------------------
|
|
11989
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
11723
11990
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11724
11991
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11725
11992
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11726
11993
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
11994
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
11995
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
11996
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
11997
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
11998
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
11999
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
11727
12000
|
// ---------------------------------------------------------------------------
|
|
11728
12001
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11729
12002
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -11876,6 +12149,30 @@ var POSSIBLE_EMOJI = `(?:${ZWJ_ELEMENT})(${ZWJ}${ZWJ_ELEMENT})*`;
|
|
|
11876
12149
|
var SOME_EMOJI = new RegExp(`(?:${POSSIBLE_EMOJI})+`, "u");
|
|
11877
12150
|
var EMOJIS = new RegExp(`^(?:${POSSIBLE_EMOJI})+$`, "u");
|
|
11878
12151
|
|
|
12152
|
+
// src/compute-engine/latex-syntax/parse.ts
|
|
12153
|
+
var PARSE_TOKEN_EXCLUDED = /* @__PURE__ */ new Set([
|
|
12154
|
+
...'!"#$%&(),/;:?@[]\\`|~'.split(""),
|
|
12155
|
+
"\\left",
|
|
12156
|
+
"\\bigl",
|
|
12157
|
+
"\\mleft"
|
|
12158
|
+
]);
|
|
12159
|
+
var TEX_UNIT_TOKENS = [
|
|
12160
|
+
"pt",
|
|
12161
|
+
"em",
|
|
12162
|
+
"mu",
|
|
12163
|
+
"ex",
|
|
12164
|
+
"mm",
|
|
12165
|
+
"cm",
|
|
12166
|
+
"in",
|
|
12167
|
+
"bp",
|
|
12168
|
+
"sp",
|
|
12169
|
+
"dd",
|
|
12170
|
+
"cc",
|
|
12171
|
+
"pc",
|
|
12172
|
+
"nc",
|
|
12173
|
+
"nd"
|
|
12174
|
+
].map((unit) => [...unit]);
|
|
12175
|
+
|
|
11879
12176
|
// src/compute-engine/boxed-expression/utils.ts
|
|
11880
12177
|
function isValueDef(def) {
|
|
11881
12178
|
return def !== void 0 && "value" in def;
|
|
@@ -11911,6 +12208,50 @@ function flatten(ops, operator2, canonicalize = true) {
|
|
|
11911
12208
|
return ys;
|
|
11912
12209
|
}
|
|
11913
12210
|
|
|
12211
|
+
// src/common/fuzzy-string-match.ts
|
|
12212
|
+
function levenshtein(source, target) {
|
|
12213
|
+
if (source === target) return 0;
|
|
12214
|
+
if (source.length === 0) return target.length;
|
|
12215
|
+
if (target.length === 0) return source.length;
|
|
12216
|
+
let prevRow = Array.from(
|
|
12217
|
+
{ length: source.length + 1 },
|
|
12218
|
+
(_, j) => j
|
|
12219
|
+
);
|
|
12220
|
+
let currRow = new Array(source.length + 1);
|
|
12221
|
+
for (let i = 1; i <= target.length; i++) {
|
|
12222
|
+
currRow[0] = i;
|
|
12223
|
+
for (let j = 1; j <= source.length; j++) {
|
|
12224
|
+
const cost = source[j - 1] === target[i - 1] ? 0 : 1;
|
|
12225
|
+
currRow[j] = Math.min(
|
|
12226
|
+
prevRow[j] + 1,
|
|
12227
|
+
// deletion
|
|
12228
|
+
currRow[j - 1] + 1,
|
|
12229
|
+
// insertion
|
|
12230
|
+
prevRow[j - 1] + cost
|
|
12231
|
+
// substitution
|
|
12232
|
+
);
|
|
12233
|
+
}
|
|
12234
|
+
[prevRow, currRow] = [currRow, prevRow];
|
|
12235
|
+
}
|
|
12236
|
+
return prevRow[source.length];
|
|
12237
|
+
}
|
|
12238
|
+
function fuzzyStringMatch(invalidWord, validWords) {
|
|
12239
|
+
const threshold = 7;
|
|
12240
|
+
let bestMatch = null;
|
|
12241
|
+
let minDistance = Infinity;
|
|
12242
|
+
const invalidLength = invalidWord.length;
|
|
12243
|
+
for (const word of validWords) {
|
|
12244
|
+
if (Math.abs(invalidLength - word.length) > threshold) continue;
|
|
12245
|
+
const distance = levenshtein(invalidWord, word);
|
|
12246
|
+
if (distance === 0) return word;
|
|
12247
|
+
if (distance <= threshold && distance < minDistance) {
|
|
12248
|
+
minDistance = distance;
|
|
12249
|
+
bestMatch = word;
|
|
12250
|
+
}
|
|
12251
|
+
}
|
|
12252
|
+
return bestMatch;
|
|
12253
|
+
}
|
|
12254
|
+
|
|
11914
12255
|
// src/compute-engine/boxed-expression/validate.ts
|
|
11915
12256
|
function checkArity(ce, ops, count) {
|
|
11916
12257
|
ops = flatten(ops);
|
|
@@ -12853,12 +13194,240 @@ Complex["NAN"] = new Complex(NaN, NaN);
|
|
|
12853
13194
|
Complex["EPSILON"] = 1e-15;
|
|
12854
13195
|
|
|
12855
13196
|
// src/compute-engine/boxed-expression/numerics.ts
|
|
13197
|
+
function asSmallInteger(expr) {
|
|
13198
|
+
if (expr === void 0 || expr === null) return null;
|
|
13199
|
+
if (typeof expr === "number") {
|
|
13200
|
+
if (Number.isInteger(expr) && expr >= -SMALL_INTEGER && expr <= SMALL_INTEGER)
|
|
13201
|
+
return expr;
|
|
13202
|
+
return null;
|
|
13203
|
+
}
|
|
13204
|
+
if (!isNumber(expr)) return null;
|
|
13205
|
+
const num = expr.numericValue;
|
|
13206
|
+
if (typeof num === "number") {
|
|
13207
|
+
if (Number.isInteger(num) && num >= -SMALL_INTEGER && num <= SMALL_INTEGER)
|
|
13208
|
+
return num;
|
|
13209
|
+
return null;
|
|
13210
|
+
}
|
|
13211
|
+
if (num.im !== 0) return null;
|
|
13212
|
+
const n = num.re;
|
|
13213
|
+
if (Number.isInteger(n) && n >= -SMALL_INTEGER && n <= SMALL_INTEGER)
|
|
13214
|
+
return Number(n);
|
|
13215
|
+
return null;
|
|
13216
|
+
}
|
|
12856
13217
|
function toInteger(expr) {
|
|
12857
13218
|
if (!isNumber(expr)) return null;
|
|
12858
13219
|
const num = expr.numericValue;
|
|
12859
13220
|
return Math.round(typeof num === "number" ? num : num.re);
|
|
12860
13221
|
}
|
|
12861
13222
|
|
|
13223
|
+
// src/compute-engine/library/logic-analysis.ts
|
|
13224
|
+
function filterValuesWithCondition(values, variable, conditionExpr, _ce) {
|
|
13225
|
+
return values.filter((value) => {
|
|
13226
|
+
const substituted = conditionExpr.subs({ [variable]: value });
|
|
13227
|
+
const result = substituted.evaluate();
|
|
13228
|
+
return sym(result) === "True";
|
|
13229
|
+
});
|
|
13230
|
+
}
|
|
13231
|
+
function extractFiniteDomainWithReason(condition, ce) {
|
|
13232
|
+
if (condition.operator !== "Element") {
|
|
13233
|
+
return { status: "error", reason: "expected-element-expression" };
|
|
13234
|
+
}
|
|
13235
|
+
if (!isFunction2(condition)) {
|
|
13236
|
+
return { status: "error", reason: "expected-element-expression" };
|
|
13237
|
+
}
|
|
13238
|
+
const variable = isSymbol2(condition.op1) ? condition.op1.symbol : void 0;
|
|
13239
|
+
if (!variable) {
|
|
13240
|
+
return { status: "error", reason: "expected-index-variable" };
|
|
13241
|
+
}
|
|
13242
|
+
const domain = condition.op2;
|
|
13243
|
+
if (!domain) {
|
|
13244
|
+
return { status: "error", reason: "expected-domain" };
|
|
13245
|
+
}
|
|
13246
|
+
const maybeCondition = condition.op3;
|
|
13247
|
+
const filterCondition = condition.nops >= 3 && maybeCondition && sym(maybeCondition) !== "Nothing" ? maybeCondition : null;
|
|
13248
|
+
const successResult = (values) => {
|
|
13249
|
+
if (filterCondition) {
|
|
13250
|
+
const filteredValues = filterValuesWithCondition(
|
|
13251
|
+
values,
|
|
13252
|
+
variable,
|
|
13253
|
+
filterCondition,
|
|
13254
|
+
ce
|
|
13255
|
+
);
|
|
13256
|
+
return { status: "success", variable, values: filteredValues };
|
|
13257
|
+
}
|
|
13258
|
+
return { status: "success", variable, values };
|
|
13259
|
+
};
|
|
13260
|
+
if (domain.operator === "Set" || domain.operator === "List") {
|
|
13261
|
+
const values = isFunction2(domain) ? domain.ops : void 0;
|
|
13262
|
+
if (values && values.length <= 1e3) {
|
|
13263
|
+
if (domain.operator === "List" && values.length === 2) {
|
|
13264
|
+
const start = asSmallInteger(values[0]);
|
|
13265
|
+
const end = asSmallInteger(values[1]);
|
|
13266
|
+
if (start !== null && end !== null) {
|
|
13267
|
+
const count = end - start + 1;
|
|
13268
|
+
if (count > 0 && count <= 1e3) {
|
|
13269
|
+
const rangeValues = [];
|
|
13270
|
+
for (let i = start; i <= end; i++) {
|
|
13271
|
+
rangeValues.push(ce.number(i));
|
|
13272
|
+
}
|
|
13273
|
+
return successResult(rangeValues);
|
|
13274
|
+
}
|
|
13275
|
+
if (count > 1e3) {
|
|
13276
|
+
return {
|
|
13277
|
+
status: "non-enumerable",
|
|
13278
|
+
variable,
|
|
13279
|
+
domain,
|
|
13280
|
+
reason: "domain-too-large"
|
|
13281
|
+
};
|
|
13282
|
+
}
|
|
13283
|
+
}
|
|
13284
|
+
}
|
|
13285
|
+
return successResult([...values]);
|
|
13286
|
+
}
|
|
13287
|
+
if (values && values.length > 1e3) {
|
|
13288
|
+
return {
|
|
13289
|
+
status: "non-enumerable",
|
|
13290
|
+
variable,
|
|
13291
|
+
domain,
|
|
13292
|
+
reason: "domain-too-large"
|
|
13293
|
+
};
|
|
13294
|
+
}
|
|
13295
|
+
return { status: "error", reason: "empty-domain" };
|
|
13296
|
+
}
|
|
13297
|
+
if (isFunction2(domain, "Range")) {
|
|
13298
|
+
const start = asSmallInteger(domain.op1);
|
|
13299
|
+
const end = asSmallInteger(domain.op2);
|
|
13300
|
+
const step = domain.ops.length >= 3 ? asSmallInteger(domain.op3) : 1;
|
|
13301
|
+
if (start !== null && end !== null && step !== null && step !== 0) {
|
|
13302
|
+
const count = Math.floor((end - start) / step) + 1;
|
|
13303
|
+
if (count > 0 && count <= 1e3) {
|
|
13304
|
+
const values = [];
|
|
13305
|
+
for (let i = start; step > 0 ? i <= end : i >= end; i += step) {
|
|
13306
|
+
values.push(ce.number(i));
|
|
13307
|
+
}
|
|
13308
|
+
return successResult(values);
|
|
13309
|
+
}
|
|
13310
|
+
if (count > 1e3) {
|
|
13311
|
+
return {
|
|
13312
|
+
status: "non-enumerable",
|
|
13313
|
+
variable,
|
|
13314
|
+
domain,
|
|
13315
|
+
reason: "domain-too-large"
|
|
13316
|
+
};
|
|
13317
|
+
}
|
|
13318
|
+
}
|
|
13319
|
+
return {
|
|
13320
|
+
status: "non-enumerable",
|
|
13321
|
+
variable,
|
|
13322
|
+
domain,
|
|
13323
|
+
reason: "non-integer-bounds"
|
|
13324
|
+
};
|
|
13325
|
+
}
|
|
13326
|
+
if (isFunction2(domain, "Interval")) {
|
|
13327
|
+
let op1 = domain.op1;
|
|
13328
|
+
let op2 = domain.op2;
|
|
13329
|
+
let openStart = false;
|
|
13330
|
+
let openEnd = false;
|
|
13331
|
+
if (isFunction2(op1, "Open")) {
|
|
13332
|
+
openStart = true;
|
|
13333
|
+
op1 = op1.op1;
|
|
13334
|
+
} else if (isFunction2(op1, "Closed")) {
|
|
13335
|
+
op1 = op1.op1;
|
|
13336
|
+
}
|
|
13337
|
+
if (isFunction2(op2, "Open")) {
|
|
13338
|
+
openEnd = true;
|
|
13339
|
+
op2 = op2.op1;
|
|
13340
|
+
} else if (isFunction2(op2, "Closed")) {
|
|
13341
|
+
op2 = op2.op1;
|
|
13342
|
+
}
|
|
13343
|
+
let start = asSmallInteger(op1);
|
|
13344
|
+
let end = asSmallInteger(op2);
|
|
13345
|
+
if (start !== null && end !== null) {
|
|
13346
|
+
if (openStart) start += 1;
|
|
13347
|
+
if (openEnd) end -= 1;
|
|
13348
|
+
const count = end - start + 1;
|
|
13349
|
+
if (count > 0 && count <= 1e3) {
|
|
13350
|
+
const values = [];
|
|
13351
|
+
for (let i = start; i <= end; i++) {
|
|
13352
|
+
values.push(ce.number(i));
|
|
13353
|
+
}
|
|
13354
|
+
return successResult(values);
|
|
13355
|
+
}
|
|
13356
|
+
if (count > 1e3) {
|
|
13357
|
+
return {
|
|
13358
|
+
status: "non-enumerable",
|
|
13359
|
+
variable,
|
|
13360
|
+
domain,
|
|
13361
|
+
reason: "domain-too-large"
|
|
13362
|
+
};
|
|
13363
|
+
}
|
|
13364
|
+
}
|
|
13365
|
+
return {
|
|
13366
|
+
status: "non-enumerable",
|
|
13367
|
+
variable,
|
|
13368
|
+
domain,
|
|
13369
|
+
reason: "non-integer-bounds"
|
|
13370
|
+
};
|
|
13371
|
+
}
|
|
13372
|
+
const domainSymbol = sym(domain);
|
|
13373
|
+
if (domainSymbol) {
|
|
13374
|
+
const knownInfiniteSets = [
|
|
13375
|
+
"Integers",
|
|
13376
|
+
"NonNegativeIntegers",
|
|
13377
|
+
"PositiveIntegers",
|
|
13378
|
+
"NegativeIntegers",
|
|
13379
|
+
"Rationals",
|
|
13380
|
+
"Reals",
|
|
13381
|
+
"PositiveReals",
|
|
13382
|
+
"NonNegativeReals",
|
|
13383
|
+
"NegativeReals",
|
|
13384
|
+
"NonPositiveReals",
|
|
13385
|
+
"ExtendedReals",
|
|
13386
|
+
"Complexes",
|
|
13387
|
+
"ImaginaryNumbers",
|
|
13388
|
+
"Numbers",
|
|
13389
|
+
"ExtendedComplexes",
|
|
13390
|
+
"AlgebraicNumbers",
|
|
13391
|
+
"TranscendentalNumbers"
|
|
13392
|
+
];
|
|
13393
|
+
if (knownInfiniteSets.includes(domainSymbol)) {
|
|
13394
|
+
return {
|
|
13395
|
+
status: "non-enumerable",
|
|
13396
|
+
variable,
|
|
13397
|
+
domain,
|
|
13398
|
+
reason: "infinite-domain"
|
|
13399
|
+
};
|
|
13400
|
+
}
|
|
13401
|
+
const domainValue = domain.value;
|
|
13402
|
+
if (domainValue && domainValue.operator === "Set" && isFunction2(domainValue)) {
|
|
13403
|
+
const values = domainValue.ops;
|
|
13404
|
+
if (values && values.length <= 1e3) {
|
|
13405
|
+
return successResult([...values]);
|
|
13406
|
+
}
|
|
13407
|
+
if (values && values.length > 1e3) {
|
|
13408
|
+
return {
|
|
13409
|
+
status: "non-enumerable",
|
|
13410
|
+
variable,
|
|
13411
|
+
domain,
|
|
13412
|
+
reason: "domain-too-large"
|
|
13413
|
+
};
|
|
13414
|
+
}
|
|
13415
|
+
}
|
|
13416
|
+
return {
|
|
13417
|
+
status: "non-enumerable",
|
|
13418
|
+
variable,
|
|
13419
|
+
domain,
|
|
13420
|
+
reason: "unknown-domain"
|
|
13421
|
+
};
|
|
13422
|
+
}
|
|
13423
|
+
return {
|
|
13424
|
+
status: "non-enumerable",
|
|
13425
|
+
variable,
|
|
13426
|
+
domain,
|
|
13427
|
+
reason: "unrecognized-domain-type"
|
|
13428
|
+
};
|
|
13429
|
+
}
|
|
13430
|
+
|
|
12862
13431
|
// src/compute-engine/numerics/interval.ts
|
|
12863
13432
|
function isNumber2(expr) {
|
|
12864
13433
|
return expr?._kind === "number";
|
|
@@ -12913,6 +13482,20 @@ function interval(expr) {
|
|
|
12913
13482
|
}
|
|
12914
13483
|
return void 0;
|
|
12915
13484
|
}
|
|
13485
|
+
function intervalContains(int, val) {
|
|
13486
|
+
if (int.openStart ? val <= int.start : val < int.start) return false;
|
|
13487
|
+
if (int.openEnd ? val >= int.end : val > int.end) return false;
|
|
13488
|
+
return true;
|
|
13489
|
+
}
|
|
13490
|
+
|
|
13491
|
+
// src/compute-engine/numerics/random.ts
|
|
13492
|
+
function deterministicRandom(seed) {
|
|
13493
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
13494
|
+
return v - Math.floor(v);
|
|
13495
|
+
}
|
|
13496
|
+
function nextSeed(seed) {
|
|
13497
|
+
return seed + 0.6180339887498949;
|
|
13498
|
+
}
|
|
12916
13499
|
|
|
12917
13500
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
12918
13501
|
function canonical(ce, xs, scope) {
|
|
@@ -12920,8 +13503,236 @@ function canonical(ce, xs, scope) {
|
|
|
12920
13503
|
return xs.map((x) => ce.expr(x, { scope }));
|
|
12921
13504
|
}
|
|
12922
13505
|
|
|
13506
|
+
// src/common/type/reduce.ts
|
|
13507
|
+
function reduceType(type) {
|
|
13508
|
+
if (typeof type === "string") {
|
|
13509
|
+
if (!isValidPrimitiveType(type)) return "error";
|
|
13510
|
+
return type;
|
|
13511
|
+
}
|
|
13512
|
+
switch (type.kind) {
|
|
13513
|
+
case "union":
|
|
13514
|
+
return reduceUnionType(type);
|
|
13515
|
+
case "intersection":
|
|
13516
|
+
return reduceIntersectionType(type);
|
|
13517
|
+
case "negation":
|
|
13518
|
+
return reduceNegationType(type);
|
|
13519
|
+
case "collection":
|
|
13520
|
+
case "indexed_collection":
|
|
13521
|
+
return reduceCollectionType(type.kind, type);
|
|
13522
|
+
case "list":
|
|
13523
|
+
return reduceListType(type);
|
|
13524
|
+
case "set":
|
|
13525
|
+
return reduceSetType(type);
|
|
13526
|
+
case "tuple":
|
|
13527
|
+
return reduceTupleType(type);
|
|
13528
|
+
case "record":
|
|
13529
|
+
return reduceRecordType(type);
|
|
13530
|
+
case "dictionary":
|
|
13531
|
+
return reduceDictionaryType(type);
|
|
13532
|
+
case "signature":
|
|
13533
|
+
return reduceSignatureType(type);
|
|
13534
|
+
case "value":
|
|
13535
|
+
return type;
|
|
13536
|
+
case "reference":
|
|
13537
|
+
return type;
|
|
13538
|
+
default:
|
|
13539
|
+
throw new Error(`Unknown type kind: ${type}`);
|
|
13540
|
+
}
|
|
13541
|
+
}
|
|
13542
|
+
function decorate(t) {
|
|
13543
|
+
if (typeof t !== "object") return t;
|
|
13544
|
+
if (Object.isFrozen(t) || Object.prototype.hasOwnProperty.call(t, "toString"))
|
|
13545
|
+
return t;
|
|
13546
|
+
Object.defineProperty(t, "toString", { value: () => typeToString(t) });
|
|
13547
|
+
return t;
|
|
13548
|
+
}
|
|
13549
|
+
function reduceMembers(types) {
|
|
13550
|
+
const result = [];
|
|
13551
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13552
|
+
for (const t of types) {
|
|
13553
|
+
const reduced = reduceType(t);
|
|
13554
|
+
const key = typeof reduced === "string" ? reduced : typeToString(reduced);
|
|
13555
|
+
if (!seen.has(key)) {
|
|
13556
|
+
seen.add(key);
|
|
13557
|
+
result.push(reduced);
|
|
13558
|
+
}
|
|
13559
|
+
}
|
|
13560
|
+
return result;
|
|
13561
|
+
}
|
|
13562
|
+
function reduceNegationType(type) {
|
|
13563
|
+
const reducedType = reduceType(type.type);
|
|
13564
|
+
if (reducedType === "nothing") return "any";
|
|
13565
|
+
if (reducedType === "any") return "nothing";
|
|
13566
|
+
return decorate({ kind: "negation", type: reducedType });
|
|
13567
|
+
}
|
|
13568
|
+
function reduceUnionType(type) {
|
|
13569
|
+
const reducedTypes = reduceMembers(type.types);
|
|
13570
|
+
if (reducedTypes.length === 0) return "never";
|
|
13571
|
+
if (reducedTypes.some((type2) => type2 === "error")) return "error";
|
|
13572
|
+
if (reducedTypes.length === 1) return decorate(reducedTypes[0]);
|
|
13573
|
+
const acc = [];
|
|
13574
|
+
for (const current of reducedTypes) {
|
|
13575
|
+
if (acc.some((t) => isSubtype(current, t))) continue;
|
|
13576
|
+
for (let i = acc.length - 1; i >= 0; i--)
|
|
13577
|
+
if (isSubtype(acc[i], current)) acc.splice(i, 1);
|
|
13578
|
+
acc.push(current);
|
|
13579
|
+
}
|
|
13580
|
+
if (acc.length === 1) return decorate(acc[0]);
|
|
13581
|
+
return decorate({ kind: "union", types: acc });
|
|
13582
|
+
}
|
|
13583
|
+
function meet2(a, b) {
|
|
13584
|
+
if (isSubtype(a, b)) return a;
|
|
13585
|
+
if (isSubtype(b, a)) return b;
|
|
13586
|
+
if (typeof a === "object" && a.kind === "union") return meetUnion(a.types, b);
|
|
13587
|
+
if (typeof b === "object" && b.kind === "union") return meetUnion(b.types, a);
|
|
13588
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
13589
|
+
const maximals = meetPrimitiveTypes(a, b);
|
|
13590
|
+
if (maximals.length === 0) return "nothing";
|
|
13591
|
+
if (maximals.length === 1) return maximals[0];
|
|
13592
|
+
return { kind: "union", types: maximals };
|
|
13593
|
+
}
|
|
13594
|
+
return "nothing";
|
|
13595
|
+
}
|
|
13596
|
+
function meetUnion(types, b) {
|
|
13597
|
+
const members = types.map((t) => meet2(t, b)).filter((t) => t !== "nothing");
|
|
13598
|
+
if (members.length === 0) return "nothing";
|
|
13599
|
+
if (members.length === 1) return members[0];
|
|
13600
|
+
return reduceUnionType({ kind: "union", types: members });
|
|
13601
|
+
}
|
|
13602
|
+
function reduceIntersectionType(type) {
|
|
13603
|
+
const reducedTypes = reduceMembers(type.types);
|
|
13604
|
+
if (reducedTypes.length === 0) return "nothing";
|
|
13605
|
+
if (reducedTypes.some((type2) => type2 === "error")) return "error";
|
|
13606
|
+
let result = reducedTypes[0];
|
|
13607
|
+
for (let i = 1; i < reducedTypes.length; i++) {
|
|
13608
|
+
result = meet2(result, reducedTypes[i]);
|
|
13609
|
+
if (result === "nothing") return "nothing";
|
|
13610
|
+
}
|
|
13611
|
+
return decorate(result);
|
|
13612
|
+
}
|
|
13613
|
+
function reduceCollectionType(kind, type) {
|
|
13614
|
+
const reducedType = reduceType(type.elements);
|
|
13615
|
+
if (reducedType === "error") return "error";
|
|
13616
|
+
if (reducedType === "nothing") return decorate({ kind, elements: "nothing" });
|
|
13617
|
+
if (reducedType === "any") return kind;
|
|
13618
|
+
return decorate({
|
|
13619
|
+
...type,
|
|
13620
|
+
elements: reducedType
|
|
13621
|
+
});
|
|
13622
|
+
}
|
|
13623
|
+
function reduceListType(type) {
|
|
13624
|
+
const reducedType = reduceType(type.elements);
|
|
13625
|
+
if (reducedType === "error") return "error";
|
|
13626
|
+
if (reducedType === "nothing")
|
|
13627
|
+
return decorate({ kind: "list", elements: "nothing" });
|
|
13628
|
+
if (reducedType === "any") return "list";
|
|
13629
|
+
let dimensions = type.dimensions;
|
|
13630
|
+
if (dimensions) {
|
|
13631
|
+
dimensions = dimensions.filter((dim) => dim >= 1 || dim === -1);
|
|
13632
|
+
if (dimensions.length === 0) return "nothing";
|
|
13633
|
+
}
|
|
13634
|
+
return decorate({
|
|
13635
|
+
...type,
|
|
13636
|
+
dimensions,
|
|
13637
|
+
elements: reducedType
|
|
13638
|
+
});
|
|
13639
|
+
}
|
|
13640
|
+
function reduceSetType(type) {
|
|
13641
|
+
const reducedType = reduceType(type.elements);
|
|
13642
|
+
if (reducedType === "error") return "error";
|
|
13643
|
+
if (reducedType === "nothing")
|
|
13644
|
+
return decorate({ kind: "set", elements: "nothing" });
|
|
13645
|
+
if (reducedType === "any") return "set";
|
|
13646
|
+
return decorate({
|
|
13647
|
+
...type,
|
|
13648
|
+
elements: reducedType
|
|
13649
|
+
});
|
|
13650
|
+
}
|
|
13651
|
+
function reduceTupleType(type) {
|
|
13652
|
+
let reducedElements = type.elements.map((element) => ({
|
|
13653
|
+
...element,
|
|
13654
|
+
type: reduceType(element.type)
|
|
13655
|
+
}));
|
|
13656
|
+
if (reducedElements.length === 0) return "nothing";
|
|
13657
|
+
if (reducedElements.some((element) => element.type === "error"))
|
|
13658
|
+
return "error";
|
|
13659
|
+
reducedElements = reducedElements.filter(
|
|
13660
|
+
(element) => element.type !== "nothing"
|
|
13661
|
+
);
|
|
13662
|
+
return decorate({
|
|
13663
|
+
...type,
|
|
13664
|
+
elements: reducedElements
|
|
13665
|
+
});
|
|
13666
|
+
}
|
|
13667
|
+
function reduceRecordType(type) {
|
|
13668
|
+
let reducedElements = {};
|
|
13669
|
+
for (const [key, value] of Object.entries(type.elements))
|
|
13670
|
+
reducedElements[key] = reduceType(value);
|
|
13671
|
+
if (Object.values(reducedElements).some((type2) => type2 === "error"))
|
|
13672
|
+
return "error";
|
|
13673
|
+
reducedElements = Object.fromEntries(
|
|
13674
|
+
Object.entries(reducedElements).filter(([_, value]) => value !== "nothing")
|
|
13675
|
+
);
|
|
13676
|
+
if (Object.keys(reducedElements).length === 0) return "record";
|
|
13677
|
+
return decorate({
|
|
13678
|
+
...type,
|
|
13679
|
+
elements: reducedElements
|
|
13680
|
+
});
|
|
13681
|
+
}
|
|
13682
|
+
function reduceDictionaryType(type) {
|
|
13683
|
+
const reducedValues = reduceType(type.values);
|
|
13684
|
+
if (reducedValues === "error") return "error";
|
|
13685
|
+
if (reducedValues === "nothing") return "error";
|
|
13686
|
+
if (reducedValues === "any" || reducedValues === "unknown") return "any";
|
|
13687
|
+
return decorate({ kind: "dictionary", values: reducedValues });
|
|
13688
|
+
}
|
|
13689
|
+
function reduceSignatureType(type) {
|
|
13690
|
+
const reducedArgs = type.args?.map((arg) => ({
|
|
13691
|
+
...arg,
|
|
13692
|
+
type: reduceType(arg.type)
|
|
13693
|
+
}));
|
|
13694
|
+
let reducedOptArgs = type.optArgs?.map((arg) => ({
|
|
13695
|
+
...arg,
|
|
13696
|
+
type: reduceType(arg.type)
|
|
13697
|
+
}));
|
|
13698
|
+
let reducedVarArg = type.variadicArg ? {
|
|
13699
|
+
...type.variadicArg,
|
|
13700
|
+
type: reduceType(type.variadicArg.type)
|
|
13701
|
+
} : void 0;
|
|
13702
|
+
const reducedResult = reduceType(type.result);
|
|
13703
|
+
if (reducedArgs?.some((arg) => arg.type === "error")) return "error";
|
|
13704
|
+
if (reducedOptArgs?.some((arg) => arg.type === "error")) return "error";
|
|
13705
|
+
if (reducedVarArg?.type === "error") return "error";
|
|
13706
|
+
if (reducedResult === "error") return "error";
|
|
13707
|
+
reducedOptArgs = reducedOptArgs?.filter((arg) => arg.type !== "nothing");
|
|
13708
|
+
if (reducedArgs?.length === 0) reducedOptArgs = void 0;
|
|
13709
|
+
if (reducedOptArgs?.length === 0) reducedOptArgs = void 0;
|
|
13710
|
+
if (reducedVarArg?.type === "nothing") reducedVarArg = void 0;
|
|
13711
|
+
return decorate({
|
|
13712
|
+
...type,
|
|
13713
|
+
args: reducedArgs,
|
|
13714
|
+
optArgs: reducedOptArgs,
|
|
13715
|
+
variadicArg: reducedVarArg,
|
|
13716
|
+
variadicMin: reducedVarArg ? type.variadicMin : void 0,
|
|
13717
|
+
result: reducedResult
|
|
13718
|
+
});
|
|
13719
|
+
}
|
|
13720
|
+
|
|
13721
|
+
// src/compute-engine/library/sets.ts
|
|
13722
|
+
function typeIntersection(a, b) {
|
|
13723
|
+
return reduceType({ kind: "intersection", types: [a, b] });
|
|
13724
|
+
}
|
|
13725
|
+
function typeMembership(x, t) {
|
|
13726
|
+
const vt = x.type;
|
|
13727
|
+
if (vt.matches(t)) return true;
|
|
13728
|
+
if (typeIntersection(vt.type, t) === "nothing") return false;
|
|
13729
|
+
if (isNumber(x)) return false;
|
|
13730
|
+
return void 0;
|
|
13731
|
+
}
|
|
13732
|
+
|
|
12923
13733
|
// src/compute-engine/library/collections.ts
|
|
12924
13734
|
var DEFAULT_LINSPACE_COUNT = 50;
|
|
13735
|
+
var SET_BASE_HANDLERS = basicIndexedCollectionHandlers();
|
|
12925
13736
|
var COLLECTIONS_LIBRARY = {
|
|
12926
13737
|
//
|
|
12927
13738
|
// Data Structures
|
|
@@ -12944,11 +13755,38 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12944
13755
|
},
|
|
12945
13756
|
// Extensional set. Elements do not repeat. The order of the elements is not significant.
|
|
12946
13757
|
// For intensional set, use `Filter` with a condition, e.g. `Filter(RealNumbers, _ > 0)`
|
|
13758
|
+
//
|
|
13759
|
+
// A `Set` expression can also be a set-builder (comprehension), e.g.
|
|
13760
|
+
// `["Set", body, ["Element", k, domain, cond?]]` or
|
|
13761
|
+
// `["Set", body, ["Condition", ...]]` (see `parseSetComprehension()`).
|
|
13762
|
+
// Comprehensions are not literal 2-element sets: their elements are the
|
|
13763
|
+
// substituted bodies over the (filtered) domain.
|
|
12947
13764
|
Set: {
|
|
12948
13765
|
complexity: 8200,
|
|
12949
13766
|
signature: "(any*) -> set",
|
|
12950
|
-
type: (ops, { engine: _ce }) =>
|
|
13767
|
+
type: (ops, { engine: _ce }) => {
|
|
13768
|
+
if (parseSetComprehension(ops) !== null) return parseType("set");
|
|
13769
|
+
return parseType(`set<${BoxedType.widen(...ops.map((op) => op.type))}>`);
|
|
13770
|
+
},
|
|
12951
13771
|
canonical: canonicalSet,
|
|
13772
|
+
// The `lazy` flag suppresses the default operand evaluation: evaluating
|
|
13773
|
+
// the operands of a comprehension would mangle its indexing set (e.g.
|
|
13774
|
+
// the condition `gcd(n,k) = 1` with a free `k` evaluates to `False`).
|
|
13775
|
+
// Literal elements are evaluated explicitly in the `evaluate` handler.
|
|
13776
|
+
lazy: true,
|
|
13777
|
+
evaluate: (ops, { engine: ce, numericApproximation, materialization }) => {
|
|
13778
|
+
const comp = parseSetComprehension(ops);
|
|
13779
|
+
if (comp !== null) {
|
|
13780
|
+
const elements = enumerateSetComprehension(comp);
|
|
13781
|
+
if (elements === void 0 || elements.length > MAX_SIZE_EAGER_COLLECTION)
|
|
13782
|
+
return void 0;
|
|
13783
|
+
return ce.function("Set", elements);
|
|
13784
|
+
}
|
|
13785
|
+
return ce.function(
|
|
13786
|
+
"Set",
|
|
13787
|
+
ops.map((op) => op.evaluate({ numericApproximation, materialization }))
|
|
13788
|
+
);
|
|
13789
|
+
},
|
|
12952
13790
|
eq: (a, b) => {
|
|
12953
13791
|
if (a.operator !== b.operator) return false;
|
|
12954
13792
|
if (!isFunction2(a) || !isFunction2(b)) return false;
|
|
@@ -12957,10 +13795,75 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12957
13795
|
return a.ops.every(has);
|
|
12958
13796
|
},
|
|
12959
13797
|
collection: {
|
|
12960
|
-
...
|
|
13798
|
+
...SET_BASE_HANDLERS,
|
|
12961
13799
|
// A set is not indexable
|
|
12962
13800
|
at: void 0,
|
|
12963
|
-
indexWhere: void 0
|
|
13801
|
+
indexWhere: void 0,
|
|
13802
|
+
// A comprehension computes its elements on demand
|
|
13803
|
+
isLazy: (expr) => isFunction2(expr) && parseSetComprehension(expr.ops) !== null,
|
|
13804
|
+
count: (expr) => {
|
|
13805
|
+
if (!isFunction2(expr)) return 0;
|
|
13806
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13807
|
+
if (comp === null) return expr.nops;
|
|
13808
|
+
return enumerateSetComprehension(comp)?.length;
|
|
13809
|
+
},
|
|
13810
|
+
isEmpty: (expr) => {
|
|
13811
|
+
if (!isFunction2(expr)) return true;
|
|
13812
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13813
|
+
if (comp === null) return expr.nops === 0;
|
|
13814
|
+
const elements = enumerateSetComprehension(comp);
|
|
13815
|
+
return elements === void 0 ? void 0 : elements.length === 0;
|
|
13816
|
+
},
|
|
13817
|
+
isFinite: (expr) => {
|
|
13818
|
+
if (!isFunction2(expr)) return true;
|
|
13819
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13820
|
+
if (comp === null) return true;
|
|
13821
|
+
if (enumerateSetComprehension(comp) !== void 0) return true;
|
|
13822
|
+
if (comp.domain?.isFiniteCollection === true) return true;
|
|
13823
|
+
return void 0;
|
|
13824
|
+
},
|
|
13825
|
+
iterator: (expr) => {
|
|
13826
|
+
if (!isFunction2(expr)) return SET_BASE_HANDLERS.iterator(expr);
|
|
13827
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13828
|
+
if (comp === null) return SET_BASE_HANDLERS.iterator(expr);
|
|
13829
|
+
const elements = enumerateSetComprehension(comp);
|
|
13830
|
+
if (elements === void 0) return void 0;
|
|
13831
|
+
let i = 0;
|
|
13832
|
+
return {
|
|
13833
|
+
next: () => i >= elements.length ? { value: void 0, done: true } : { value: elements[i++], done: false }
|
|
13834
|
+
};
|
|
13835
|
+
},
|
|
13836
|
+
// Three-valued membership: `true` when an element matches, `false`
|
|
13837
|
+
// only when every element is definitively different from `target`
|
|
13838
|
+
// (concrete values), `undefined` otherwise — e.g. a symbolic target
|
|
13839
|
+
// (`Element(ω, {-1, 1})`) is indeterminate, not refuted.
|
|
13840
|
+
contains: (expr, target) => {
|
|
13841
|
+
if (!isFunction2(expr)) return void 0;
|
|
13842
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13843
|
+
if (comp !== null) return setComprehensionContains(comp, target);
|
|
13844
|
+
return literalSetContains(expr.ops, target);
|
|
13845
|
+
},
|
|
13846
|
+
elttype: (expr) => {
|
|
13847
|
+
if (!isFunction2(expr)) return SET_BASE_HANDLERS.elttype(expr);
|
|
13848
|
+
const comp = parseSetComprehension(expr.ops);
|
|
13849
|
+
if (comp === null) return SET_BASE_HANDLERS.elttype(expr);
|
|
13850
|
+
const elements = enumerateSetComprehension(comp);
|
|
13851
|
+
if (elements === void 0 || elements.length === 0) return "unknown";
|
|
13852
|
+
return widen(...elements.map((op) => op.type.type));
|
|
13853
|
+
}
|
|
13854
|
+
}
|
|
13855
|
+
},
|
|
13856
|
+
Length: {
|
|
13857
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
13858
|
+
complexity: 4e3,
|
|
13859
|
+
signature: "(any) -> integer",
|
|
13860
|
+
type: () => "integer",
|
|
13861
|
+
evaluate: ([xs], { engine }) => {
|
|
13862
|
+
if (!xs.isCollection) return void 0;
|
|
13863
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
13864
|
+
const n = xs.count;
|
|
13865
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
13866
|
+
return engine.number(n);
|
|
12964
13867
|
}
|
|
12965
13868
|
},
|
|
12966
13869
|
Tuple: {
|
|
@@ -13047,7 +13950,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13047
13950
|
},
|
|
13048
13951
|
contains: (expr, target) => {
|
|
13049
13952
|
const t = target.re;
|
|
13953
|
+
if (Number.isNaN(t))
|
|
13954
|
+
return typeMembership(target, "number") === false ? false : void 0;
|
|
13955
|
+
if (target.im !== 0) return false;
|
|
13050
13956
|
if (!isFinite(t)) return false;
|
|
13957
|
+
if (isFunction2(expr) && expr.ops.some((op) => Number.isNaN(op.re)))
|
|
13958
|
+
return void 0;
|
|
13051
13959
|
const [lower, upper, step] = range(expr);
|
|
13052
13960
|
if (step === 0) return false;
|
|
13053
13961
|
if (step > 0) {
|
|
@@ -13123,13 +14031,23 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13123
14031
|
signature: "(number, number) -> set<real>",
|
|
13124
14032
|
canonical: ([lo, hi], { engine }) => {
|
|
13125
14033
|
if (!lo || !hi) return null;
|
|
14034
|
+
const unwrap2 = (op) => {
|
|
14035
|
+
if (isFunction2(op, "Open")) return [op.op1, true];
|
|
14036
|
+
if (isFunction2(op, "Closed")) return [op.op1, false];
|
|
14037
|
+
return [op, false];
|
|
14038
|
+
};
|
|
14039
|
+
const [loVal, loOpen] = unwrap2(lo);
|
|
14040
|
+
const [hiVal, hiOpen] = unwrap2(hi);
|
|
13126
14041
|
const [lower, upper] = checkTypes(
|
|
13127
14042
|
engine,
|
|
13128
|
-
[
|
|
14043
|
+
[loVal.canonical, hiVal.canonical],
|
|
13129
14044
|
["number", "number"]
|
|
13130
14045
|
);
|
|
13131
14046
|
if (!lower.isValid || !upper.isValid) return null;
|
|
13132
|
-
return engine._fn("Interval", [
|
|
14047
|
+
return engine._fn("Interval", [
|
|
14048
|
+
loOpen ? engine._fn("Open", [lower]) : lower,
|
|
14049
|
+
hiOpen ? engine._fn("Open", [upper]) : upper
|
|
14050
|
+
]);
|
|
13133
14051
|
},
|
|
13134
14052
|
eq: (a, b) => {
|
|
13135
14053
|
const intervalA = interval(a);
|
|
@@ -13164,19 +14082,32 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13164
14082
|
},
|
|
13165
14083
|
isEmpty: (_expr) => {
|
|
13166
14084
|
const int = interval(_expr);
|
|
13167
|
-
if (!int) return
|
|
14085
|
+
if (!int) return void 0;
|
|
13168
14086
|
if (int.openStart && int.start === int.end) return true;
|
|
13169
14087
|
if (int.openEnd && int.start === int.end) return true;
|
|
13170
14088
|
if (int.openStart && int.openEnd) return false;
|
|
13171
14089
|
return int.start >= int.end;
|
|
13172
14090
|
},
|
|
13173
14091
|
isFinite: (_expr) => false,
|
|
14092
|
+
// Three-valued membership: `true` only when both bound checks are
|
|
14093
|
+
// entailed, `false` when a bound check (or the type of the target)
|
|
14094
|
+
// refutes membership, `undefined` otherwise (e.g. symbolic target
|
|
14095
|
+
// with unknown bounds). Endpoints may be ±Infinity.
|
|
13174
14096
|
contains: (expr, target) => {
|
|
13175
14097
|
const int = interval(expr);
|
|
13176
|
-
if (!int) return
|
|
13177
|
-
if (
|
|
13178
|
-
|
|
13179
|
-
|
|
14098
|
+
if (!int) return void 0;
|
|
14099
|
+
if (typeMembership(target, "number") === false) return false;
|
|
14100
|
+
const t = target.re;
|
|
14101
|
+
if (!Number.isNaN(t)) {
|
|
14102
|
+
if (target.im !== 0) return false;
|
|
14103
|
+
return intervalContains(int, t);
|
|
14104
|
+
}
|
|
14105
|
+
const aboveLower = int.openStart ? target.isGreater(int.start) : target.isGreaterEqual(int.start);
|
|
14106
|
+
if (aboveLower === false) return false;
|
|
14107
|
+
const belowUpper = int.openEnd ? target.isLess(int.end) : target.isLessEqual(int.end);
|
|
14108
|
+
if (belowUpper === false) return false;
|
|
14109
|
+
if (aboveLower === true && belowUpper === true) return true;
|
|
14110
|
+
return void 0;
|
|
13180
14111
|
},
|
|
13181
14112
|
eltsgn: (expr) => {
|
|
13182
14113
|
const i = interval(expr);
|
|
@@ -13216,10 +14147,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13216
14147
|
const upper = expr.op2.re;
|
|
13217
14148
|
let count = expr.op3.re;
|
|
13218
14149
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
14150
|
+
count = Math.floor(count);
|
|
13219
14151
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
13220
14152
|
if (index < 1 || index > count) return void 0;
|
|
14153
|
+
if (count === 1) return expr.engine.number(lower);
|
|
13221
14154
|
return expr.engine.number(
|
|
13222
|
-
lower + (upper - lower) * (index - 1) / count
|
|
14155
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
13223
14156
|
);
|
|
13224
14157
|
},
|
|
13225
14158
|
iterator: (expr) => {
|
|
@@ -13238,6 +14171,8 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13238
14171
|
!isFinite(expr.op3.re) ? DEFAULT_LINSPACE_COUNT : expr.op3.re
|
|
13239
14172
|
);
|
|
13240
14173
|
}
|
|
14174
|
+
totalCount = Math.floor(totalCount);
|
|
14175
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
13241
14176
|
let index = 1;
|
|
13242
14177
|
return {
|
|
13243
14178
|
next: () => {
|
|
@@ -13246,7 +14181,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13246
14181
|
index += 1;
|
|
13247
14182
|
return {
|
|
13248
14183
|
value: expr.engine.number(
|
|
13249
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
14184
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
13250
14185
|
),
|
|
13251
14186
|
done: false
|
|
13252
14187
|
};
|
|
@@ -13254,17 +14189,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13254
14189
|
};
|
|
13255
14190
|
},
|
|
13256
14191
|
contains: (expr, target) => {
|
|
13257
|
-
if (!target.type.matches("finite_real")) return false;
|
|
13258
|
-
if (!isFunction2(expr)) return false;
|
|
13259
14192
|
const t = target.re;
|
|
14193
|
+
if (Number.isNaN(t))
|
|
14194
|
+
return typeMembership(target, "number") === false ? false : void 0;
|
|
14195
|
+
if (target.im !== 0) return false;
|
|
14196
|
+
if (!isFinite(t)) return false;
|
|
14197
|
+
if (!isFunction2(expr)) return void 0;
|
|
13260
14198
|
const lower = expr.op1.re;
|
|
13261
14199
|
const upper = expr.op2.re;
|
|
14200
|
+
if (Number.isNaN(lower) || Number.isNaN(upper)) return void 0;
|
|
13262
14201
|
if (t < lower || t > upper) return false;
|
|
13263
14202
|
let count = expr.op3.re;
|
|
13264
14203
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
14204
|
+
count = Math.floor(count);
|
|
13265
14205
|
if (count === 0) return false;
|
|
13266
|
-
|
|
13267
|
-
|
|
14206
|
+
if (count === 1) return t === lower;
|
|
14207
|
+
const step = (upper - lower) / (count - 1);
|
|
14208
|
+
const k = (t - lower) / step;
|
|
14209
|
+
const tol = expr.engine.tolerance;
|
|
14210
|
+
const kRounded = Math.round(k);
|
|
14211
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
13268
14212
|
}
|
|
13269
14213
|
}
|
|
13270
14214
|
},
|
|
@@ -13283,8 +14227,18 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13283
14227
|
description: ["Return the number of elements in the collection."],
|
|
13284
14228
|
complexity: 8200,
|
|
13285
14229
|
signature: "(collection) -> integer",
|
|
13286
|
-
evaluate: ([xs], { engine }) =>
|
|
13287
|
-
|
|
14230
|
+
evaluate: ([xs], { engine }) => {
|
|
14231
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
14232
|
+
const n = xs.count;
|
|
14233
|
+
if (n === void 0) return void 0;
|
|
14234
|
+
return engine.number(n);
|
|
14235
|
+
},
|
|
14236
|
+
sgn: ([xs]) => {
|
|
14237
|
+
const empty = xs.isEmptyCollection;
|
|
14238
|
+
if (empty === true) return "zero";
|
|
14239
|
+
if (empty === false) return "positive";
|
|
14240
|
+
return void 0;
|
|
14241
|
+
}
|
|
13288
14242
|
},
|
|
13289
14243
|
IsEmpty: {
|
|
13290
14244
|
description: ["Return True if the collection is empty, False otherwise."],
|
|
@@ -13400,7 +14354,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13400
14354
|
},
|
|
13401
14355
|
collection: {
|
|
13402
14356
|
isLazy: (_expr) => true,
|
|
13403
|
-
count: (
|
|
14357
|
+
count: (expr) => {
|
|
14358
|
+
if (!isFunction2(expr)) return void 0;
|
|
14359
|
+
if (!expr.op1.isFiniteCollection) return Infinity;
|
|
14360
|
+
let n = 0;
|
|
14361
|
+
for (const _ of expr.each()) n++;
|
|
14362
|
+
return n;
|
|
14363
|
+
},
|
|
13404
14364
|
contains: (expr, target) => {
|
|
13405
14365
|
if (!isFunction2(expr)) return false;
|
|
13406
14366
|
if (!expr.contains(target)) return false;
|
|
@@ -13509,24 +14469,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13509
14469
|
type: (ops) => parseType(functionResult(ops[1].type.type) ?? "unknown"),
|
|
13510
14470
|
evaluate: ([collection, fn, initial], { engine: ce }) => {
|
|
13511
14471
|
if (!collection.isFiniteCollection) return void 0;
|
|
14472
|
+
const hasInitial = initial !== void 0;
|
|
13512
14473
|
initial ??= ce.Nothing;
|
|
13513
14474
|
if (initial.type.matches("real") && collection.type.matches(ce.type("collection<real>"))) {
|
|
13514
14475
|
const compiled = ce._compile(fn);
|
|
13515
|
-
if (compiled.calling
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
14476
|
+
if (compiled.calling === "lambda" && compiled.run) {
|
|
14477
|
+
return run(
|
|
14478
|
+
(function* () {
|
|
14479
|
+
let accumulator = hasInitial ? initial.re : NaN;
|
|
14480
|
+
let first = true;
|
|
14481
|
+
for (const item of collection.each()) {
|
|
14482
|
+
if (first && !hasInitial) accumulator = item.re;
|
|
14483
|
+
else accumulator = compiled.run(accumulator, item.re);
|
|
14484
|
+
first = false;
|
|
14485
|
+
yield;
|
|
14486
|
+
}
|
|
14487
|
+
return ce.expr(accumulator);
|
|
14488
|
+
})(),
|
|
14489
|
+
ce._timeRemaining
|
|
14490
|
+
);
|
|
14491
|
+
}
|
|
13530
14492
|
}
|
|
13531
14493
|
const f = applicable(fn);
|
|
13532
14494
|
return run(
|
|
@@ -13589,10 +14551,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13589
14551
|
description: [
|
|
13590
14552
|
"Access an element of an indexed collection.",
|
|
13591
14553
|
"If the index is negative, it is counted from the end.",
|
|
13592
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
14554
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
14555
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
14556
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
13593
14557
|
],
|
|
13594
14558
|
complexity: 8200,
|
|
13595
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
14559
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
13596
14560
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
13597
14561
|
evaluate: (ops, { engine: ce }) => {
|
|
13598
14562
|
let expr = ops[0];
|
|
@@ -13603,12 +14567,39 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13603
14567
|
if (!at) return void 0;
|
|
13604
14568
|
const opAtIndex = ops[index];
|
|
13605
14569
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
13606
|
-
if (s !== void 0)
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
14570
|
+
if (s !== void 0) {
|
|
14571
|
+
expr = at(expr, s) ?? ce.Nothing;
|
|
14572
|
+
index += 1;
|
|
14573
|
+
continue;
|
|
14574
|
+
}
|
|
14575
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
14576
|
+
const indices = Array.from(opAtIndex.each());
|
|
14577
|
+
const isMask = indices.every((m) => {
|
|
14578
|
+
const name = sym(m);
|
|
14579
|
+
return name === "True" || name === "False";
|
|
14580
|
+
});
|
|
14581
|
+
const picked = [];
|
|
14582
|
+
if (isMask) {
|
|
14583
|
+
indices.forEach((m, i2) => {
|
|
14584
|
+
if (sym(m) !== "True") return;
|
|
14585
|
+
const v = at(expr, i2 + 1);
|
|
14586
|
+
if (v !== void 0) picked.push(v);
|
|
14587
|
+
});
|
|
14588
|
+
} else {
|
|
14589
|
+
for (const m of indices) {
|
|
14590
|
+
const k = m.re;
|
|
14591
|
+
if (!Number.isInteger(k)) return void 0;
|
|
14592
|
+
const v = at(expr, k);
|
|
14593
|
+
if (v !== void 0) picked.push(v);
|
|
14594
|
+
}
|
|
14595
|
+
}
|
|
14596
|
+
expr = ce._fn("List", picked);
|
|
14597
|
+
index += 1;
|
|
14598
|
+
continue;
|
|
13611
14599
|
}
|
|
14600
|
+
const i = opAtIndex.re;
|
|
14601
|
+
if (!Number.isInteger(i)) return void 0;
|
|
14602
|
+
expr = at(expr, i) ?? ce.Nothing;
|
|
13612
14603
|
index += 1;
|
|
13613
14604
|
}
|
|
13614
14605
|
return expr;
|
|
@@ -13619,7 +14610,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13619
14610
|
description: ["Return `n` elements from a collection."],
|
|
13620
14611
|
complexity: 8200,
|
|
13621
14612
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13622
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14613
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13623
14614
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
13624
14615
|
if (!eager) return void 0;
|
|
13625
14616
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -13666,7 +14657,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13666
14657
|
description: ["Return the collection without the first n elements."],
|
|
13667
14658
|
complexity: 8200,
|
|
13668
14659
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13669
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14660
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13670
14661
|
collection: {
|
|
13671
14662
|
isLazy: (_expr) => true,
|
|
13672
14663
|
count: (expr) => {
|
|
@@ -13690,10 +14681,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13690
14681
|
const [xs, nExpr] = expr.ops;
|
|
13691
14682
|
const n = toInteger(nExpr) ?? 0;
|
|
13692
14683
|
if (n <= 0) return xs.each();
|
|
14684
|
+
const count = xs.count;
|
|
13693
14685
|
let index = n + 1;
|
|
13694
14686
|
return {
|
|
13695
14687
|
next: () => {
|
|
13696
|
-
|
|
14688
|
+
if (count !== void 0 && index > count)
|
|
14689
|
+
return { value: void 0, done: true };
|
|
14690
|
+
const value = xs.at(index++);
|
|
13697
14691
|
if (value === void 0) return { value: void 0, done: true };
|
|
13698
14692
|
return { value, done: false };
|
|
13699
14693
|
}
|
|
@@ -13704,7 +14698,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13704
14698
|
if (!isFunction2(expr)) return void 0;
|
|
13705
14699
|
const [xs, nExpr] = expr.ops;
|
|
13706
14700
|
const n = toInteger(nExpr) ?? 0;
|
|
13707
|
-
if (n <= 0) return
|
|
14701
|
+
if (n <= 0) return xs.at(index);
|
|
14702
|
+
if (index < 0) {
|
|
14703
|
+
const count = xs.count;
|
|
14704
|
+
if (count !== void 0 && -index > count - n) return void 0;
|
|
14705
|
+
return xs.at(index);
|
|
14706
|
+
}
|
|
14707
|
+
if (index < 1) return void 0;
|
|
13708
14708
|
return xs.at(index + n);
|
|
13709
14709
|
}
|
|
13710
14710
|
}
|
|
@@ -13786,11 +14786,15 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13786
14786
|
iterator: (expr) => {
|
|
13787
14787
|
if (!isFunction2(expr))
|
|
13788
14788
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14789
|
+
const op1 = expr.op1;
|
|
14790
|
+
const count = op1.count;
|
|
14791
|
+
let index = 2;
|
|
13789
14792
|
return {
|
|
13790
14793
|
next: () => {
|
|
13791
|
-
|
|
13792
|
-
|
|
13793
|
-
|
|
14794
|
+
if (count !== void 0 && index > count)
|
|
14795
|
+
return { value: void 0, done: true };
|
|
14796
|
+
const value = op1.at(index);
|
|
14797
|
+
if (value === void 0) return { value: void 0, done: true };
|
|
13794
14798
|
index += 1;
|
|
13795
14799
|
return { value, done: false };
|
|
13796
14800
|
}
|
|
@@ -13862,17 +14866,24 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13862
14866
|
],
|
|
13863
14867
|
complexity: 8200,
|
|
13864
14868
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
13865
|
-
type: ([xs]) => parseType(
|
|
14869
|
+
type: ([xs]) => parseType(
|
|
14870
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
14871
|
+
),
|
|
13866
14872
|
collection: {
|
|
13867
14873
|
isLazy: (_expr) => true,
|
|
13868
14874
|
count: (expr) => {
|
|
13869
14875
|
if (!isFunction2(expr)) return void 0;
|
|
13870
|
-
const start = toInteger(expr.op2) ?? 1;
|
|
13871
14876
|
const count = expr.op1.count;
|
|
13872
14877
|
if (count === void 0) return void 0;
|
|
13873
|
-
|
|
13874
|
-
if (start < 1)
|
|
13875
|
-
|
|
14878
|
+
let start = toInteger(expr.op2) ?? 1;
|
|
14879
|
+
if (start < 1) start = count + 1 + start;
|
|
14880
|
+
if (start < 1) start = 1;
|
|
14881
|
+
if (start > count) return 0;
|
|
14882
|
+
let end = toInteger(expr.op3) ?? count;
|
|
14883
|
+
if (end < 1) end = count + 1 + end;
|
|
14884
|
+
if (end < 1) end = 1;
|
|
14885
|
+
if (end > count) end = count;
|
|
14886
|
+
return Math.max(0, end - start + 1);
|
|
13876
14887
|
},
|
|
13877
14888
|
isFinite: (_expr) => true,
|
|
13878
14889
|
at: (expr, index) => {
|
|
@@ -13888,6 +14899,11 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13888
14899
|
if (end < 1) end = count + 1 + end;
|
|
13889
14900
|
if (end < 1) end = 1;
|
|
13890
14901
|
if (end > count) end = count;
|
|
14902
|
+
const length = end - start + 1;
|
|
14903
|
+
if (length <= 0) return void 0;
|
|
14904
|
+
if (index < 0) index = length + 1 + index;
|
|
14905
|
+
if (index < 1 || index > length) return void 0;
|
|
14906
|
+
return expr.op1.at(start + index - 1);
|
|
13891
14907
|
},
|
|
13892
14908
|
iterator: (expr) => {
|
|
13893
14909
|
if (!isFunction2(expr))
|
|
@@ -14151,7 +15167,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14151
15167
|
for (const item of xs.each()) {
|
|
14152
15168
|
const pred = sym(f([item]));
|
|
14153
15169
|
if (pred === "True") indices.push(ce.number(index));
|
|
14154
|
-
if (pred !== "False")
|
|
15170
|
+
else if (pred !== "False")
|
|
14155
15171
|
throw new Error(
|
|
14156
15172
|
`Filter predicate must return "True" or "False". ${spellCheckMessage(
|
|
14157
15173
|
fn
|
|
@@ -14194,16 +15210,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14194
15210
|
},
|
|
14195
15211
|
// Randomize the order of the elements in the collection.
|
|
14196
15212
|
Shuffle: {
|
|
14197
|
-
description: "Randomize the order of the elements in the collection.",
|
|
15213
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
14198
15214
|
complexity: 8200,
|
|
14199
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
15215
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
14200
15216
|
type: (ops) => ops[0].type,
|
|
14201
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
15217
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
14202
15218
|
if (!xs.isFiniteCollection) return void 0;
|
|
14203
15219
|
const data = Array.from(xs.each());
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
15220
|
+
const seed = seedOp?.re;
|
|
15221
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
15222
|
+
let s = seed;
|
|
15223
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
15224
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
15225
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
15226
|
+
s = nextSeed(s);
|
|
15227
|
+
}
|
|
15228
|
+
} else {
|
|
15229
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
15230
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
15231
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
15232
|
+
}
|
|
14207
15233
|
}
|
|
14208
15234
|
return ce.function(xs.operator, data);
|
|
14209
15235
|
}
|
|
@@ -14270,7 +15296,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14270
15296
|
if (t === "string")
|
|
14271
15297
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
14272
15298
|
return parseType(
|
|
14273
|
-
`tuple<list<${
|
|
15299
|
+
`tuple<list<${typeToString(
|
|
15300
|
+
collectionElementType(t) ?? "any"
|
|
15301
|
+
)}>, list<integer>>`
|
|
14274
15302
|
);
|
|
14275
15303
|
},
|
|
14276
15304
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -14286,7 +15314,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14286
15314
|
description: "Return a list of the unique elements of the collection.",
|
|
14287
15315
|
complexity: 8200,
|
|
14288
15316
|
signature: "(collection) -> list",
|
|
14289
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
15317
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14290
15318
|
evaluate: (ops, { engine: ce }) => {
|
|
14291
15319
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
14292
15320
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -14298,7 +15326,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14298
15326
|
wikidata: "Q381060",
|
|
14299
15327
|
complexity: 8200,
|
|
14300
15328
|
signature: "(collection, integer | function) -> list",
|
|
14301
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
15329
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14302
15330
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
14303
15331
|
if (!xs.isFiniteCollection) return void 0;
|
|
14304
15332
|
const k = toInteger(arg);
|
|
@@ -14388,11 +15416,25 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14388
15416
|
count: zipCount,
|
|
14389
15417
|
isFinite: (expr) => {
|
|
14390
15418
|
if (!isFunction2(expr)) return void 0;
|
|
14391
|
-
|
|
15419
|
+
if (expr.nops === 0) return true;
|
|
15420
|
+
let anyUnknown = false;
|
|
15421
|
+
for (const x of expr.ops) {
|
|
15422
|
+
const f = x.isFiniteCollection;
|
|
15423
|
+
if (f === true) return true;
|
|
15424
|
+
if (f === void 0) anyUnknown = true;
|
|
15425
|
+
}
|
|
15426
|
+
return anyUnknown ? void 0 : false;
|
|
14392
15427
|
},
|
|
14393
15428
|
isEmpty: (expr) => {
|
|
14394
15429
|
if (!isFunction2(expr)) return void 0;
|
|
14395
|
-
|
|
15430
|
+
if (expr.nops === 0) return true;
|
|
15431
|
+
let anyUnknown = false;
|
|
15432
|
+
for (const x of expr.ops) {
|
|
15433
|
+
const e = x.isEmptyCollection;
|
|
15434
|
+
if (e === true) return true;
|
|
15435
|
+
if (e === void 0) anyUnknown = true;
|
|
15436
|
+
}
|
|
15437
|
+
return anyUnknown ? void 0 : false;
|
|
14396
15438
|
},
|
|
14397
15439
|
iterator: (expr) => {
|
|
14398
15440
|
if (!isFunction2(expr))
|
|
@@ -14472,32 +15514,74 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14472
15514
|
}
|
|
14473
15515
|
}
|
|
14474
15516
|
},
|
|
14475
|
-
// Repeat(x) -> [x, x, ...]
|
|
14476
|
-
//
|
|
14477
|
-
// x is evaluated once. Although could use Hold()?
|
|
14478
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
15517
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
15518
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
14479
15519
|
Repeat: {
|
|
14480
|
-
description: "Produce
|
|
15520
|
+
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.",
|
|
14481
15521
|
complexity: 8200,
|
|
14482
|
-
signature: "(value: any) -> list",
|
|
15522
|
+
signature: "(value: any, count: integer?) -> list",
|
|
15523
|
+
evaluate: (ops, { engine }) => {
|
|
15524
|
+
if (ops.length !== 2) return void 0;
|
|
15525
|
+
const raw = toInteger(ops[1]);
|
|
15526
|
+
if (raw === null) return void 0;
|
|
15527
|
+
const n = Math.max(0, raw);
|
|
15528
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
15529
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
15530
|
+
},
|
|
14483
15531
|
collection: {
|
|
14484
|
-
isLazy: (
|
|
14485
|
-
count: () =>
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
|
|
14489
|
-
|
|
15532
|
+
isLazy: (expr) => isFunction2(expr) && expr.ops?.length === 1,
|
|
15533
|
+
count: (expr) => {
|
|
15534
|
+
if (!isFunction2(expr)) return void 0;
|
|
15535
|
+
if (expr.ops?.length === 2) {
|
|
15536
|
+
const n = toInteger(expr.op2);
|
|
15537
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
15538
|
+
}
|
|
15539
|
+
return Infinity;
|
|
15540
|
+
},
|
|
15541
|
+
isEmpty: (expr) => {
|
|
15542
|
+
if (!isFunction2(expr)) return void 0;
|
|
15543
|
+
if (expr.ops?.length === 2) {
|
|
15544
|
+
const n = toInteger(expr.op2);
|
|
15545
|
+
return n !== null ? n <= 0 : void 0;
|
|
15546
|
+
}
|
|
15547
|
+
return false;
|
|
15548
|
+
},
|
|
15549
|
+
isFinite: (expr) => isFunction2(expr) && expr.ops?.length === 2,
|
|
14490
15550
|
contains: (expr, target) => {
|
|
14491
15551
|
if (!isFunction2(expr)) return false;
|
|
15552
|
+
if (expr.ops?.length === 2) {
|
|
15553
|
+
const n = toInteger(expr.op2);
|
|
15554
|
+
if (n !== null && n <= 0) return false;
|
|
15555
|
+
}
|
|
14492
15556
|
return expr.op1.isSame(target);
|
|
14493
15557
|
},
|
|
14494
15558
|
iterator: (expr) => {
|
|
14495
15559
|
if (!isFunction2(expr))
|
|
14496
15560
|
return { next: () => ({ value: void 0, done: true }) };
|
|
15561
|
+
if (expr.ops?.length === 2) {
|
|
15562
|
+
const n = toInteger(expr.op2);
|
|
15563
|
+
if (n === null) {
|
|
15564
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
15565
|
+
}
|
|
15566
|
+
const count = Math.max(0, n);
|
|
15567
|
+
let i = 0;
|
|
15568
|
+
return {
|
|
15569
|
+
next: () => i++ < count ? { value: expr.op1, done: false } : { value: void 0, done: true }
|
|
15570
|
+
};
|
|
15571
|
+
}
|
|
14497
15572
|
return { next: () => ({ value: expr.op1, done: false }) };
|
|
14498
15573
|
},
|
|
14499
|
-
at
|
|
15574
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
15575
|
+
at: (expr, index) => {
|
|
14500
15576
|
if (!isFunction2(expr)) return void 0;
|
|
15577
|
+
if (typeof index !== "number") return void 0;
|
|
15578
|
+
if (expr.ops?.length === 2) {
|
|
15579
|
+
const n = toInteger(expr.op2);
|
|
15580
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
15581
|
+
if (index < 1 || index > count) return void 0;
|
|
15582
|
+
} else {
|
|
15583
|
+
if (index < 1) return void 0;
|
|
15584
|
+
}
|
|
14501
15585
|
return expr.op1;
|
|
14502
15586
|
}
|
|
14503
15587
|
}
|
|
@@ -14510,9 +15594,22 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14510
15594
|
signature: "(list) -> list",
|
|
14511
15595
|
collection: {
|
|
14512
15596
|
isLazy: (_expr) => true,
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
15597
|
+
// Cycling a non-empty collection is infinite; cycling an empty one is
|
|
15598
|
+
// empty. Inspect the *underlying* collection (`op1`) — reading
|
|
15599
|
+
// `expr.isEmptyCollection`/`expr.isFiniteCollection` here would re-enter
|
|
15600
|
+
// these same handlers and recurse infinitely.
|
|
15601
|
+
count: (expr) => {
|
|
15602
|
+
if (!isFunction2(expr)) return void 0;
|
|
15603
|
+
return expr.op1.isEmptyCollection ? 0 : Infinity;
|
|
15604
|
+
},
|
|
15605
|
+
isEmpty: (expr) => {
|
|
15606
|
+
if (!isFunction2(expr)) return void 0;
|
|
15607
|
+
return expr.op1.isEmptyCollection;
|
|
15608
|
+
},
|
|
15609
|
+
isFinite: (expr) => {
|
|
15610
|
+
if (!isFunction2(expr)) return void 0;
|
|
15611
|
+
return expr.op1.isEmptyCollection;
|
|
15612
|
+
},
|
|
14516
15613
|
contains: (expr, target) => {
|
|
14517
15614
|
if (!isFunction2(expr)) return false;
|
|
14518
15615
|
return expr.op1.contains(target) ?? false;
|
|
@@ -14526,7 +15623,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14526
15623
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14527
15624
|
return {
|
|
14528
15625
|
next: () => {
|
|
14529
|
-
const i = (index - 1
|
|
15626
|
+
const i = (index - 1) % l + 1;
|
|
14530
15627
|
const value = expr.op1.at(i);
|
|
14531
15628
|
if (value === void 0) return { value: void 0, done: true };
|
|
14532
15629
|
index += 1;
|
|
@@ -14648,7 +15745,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14648
15745
|
evaluate: (ops, { engine: ce }) => {
|
|
14649
15746
|
const elements = [];
|
|
14650
15747
|
for (const xs of ops) {
|
|
14651
|
-
if (xs.isCollection) elements.push(xs);
|
|
15748
|
+
if (!xs.isCollection) elements.push(xs);
|
|
14652
15749
|
else {
|
|
14653
15750
|
if (!xs.isFiniteCollection) return void 0;
|
|
14654
15751
|
elements.push(...Array.from(xs.each()));
|
|
@@ -14664,7 +15761,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14664
15761
|
evaluate: (ops, { engine: ce }) => {
|
|
14665
15762
|
const elements = [];
|
|
14666
15763
|
for (const xs of ops) {
|
|
14667
|
-
if (xs.isCollection) elements.push(xs);
|
|
15764
|
+
if (!xs.isCollection) elements.push(xs);
|
|
14668
15765
|
else {
|
|
14669
15766
|
if (!xs.isFiniteCollection) return void 0;
|
|
14670
15767
|
elements.push(...Array.from(xs.each()));
|
|
@@ -14757,11 +15854,129 @@ function canonicalList(ops, { engine: ce }) {
|
|
|
14757
15854
|
return ce._fn("List", ops);
|
|
14758
15855
|
}
|
|
14759
15856
|
function canonicalSet(ops, { engine }) {
|
|
15857
|
+
ops = ops.map((op) => op.canonical);
|
|
15858
|
+
if (parseSetComprehension(ops) !== null) return engine._fn("Set", [...ops]);
|
|
14760
15859
|
const set = [];
|
|
14761
15860
|
const has = (x) => set.some((y) => y.isSame(x));
|
|
14762
15861
|
for (const op of ops) if (!has(op)) set.push(op);
|
|
14763
15862
|
return engine._fn("Set", set);
|
|
14764
15863
|
}
|
|
15864
|
+
function parseSetComprehension(ops) {
|
|
15865
|
+
if (ops.length !== 2) return null;
|
|
15866
|
+
const [body, spec] = ops;
|
|
15867
|
+
const canon = (x) => x.isCanonical ? x : x.canonical;
|
|
15868
|
+
if (isFunction2(spec, "Element") && spec.nops >= 2) {
|
|
15869
|
+
if (!isSymbol2(spec.op1)) return null;
|
|
15870
|
+
const v = spec.op1.symbol;
|
|
15871
|
+
if (!body.has(v)) return null;
|
|
15872
|
+
const cond = spec.nops >= 3 && sym(spec.op3) !== "Nothing" ? spec.op3 : void 0;
|
|
15873
|
+
return { body, variable: v, domain: spec.op2, condition: cond };
|
|
15874
|
+
}
|
|
15875
|
+
if (isFunction2(spec, "Condition") && spec.nops >= 1) {
|
|
15876
|
+
const pred = spec.op1;
|
|
15877
|
+
if (isFunction2(body, "Element") && body.nops === 2 && isSymbol2(body.op1)) {
|
|
15878
|
+
return {
|
|
15879
|
+
body: body.op1,
|
|
15880
|
+
variable: body.op1.symbol,
|
|
15881
|
+
domain: canon(body.op2),
|
|
15882
|
+
condition: canon(pred)
|
|
15883
|
+
};
|
|
15884
|
+
}
|
|
15885
|
+
if (isFunction2(pred, "Element") && pred.nops === 2 && isSymbol2(pred.op1)) {
|
|
15886
|
+
const v = pred.op1.symbol;
|
|
15887
|
+
if (body.has(v))
|
|
15888
|
+
return {
|
|
15889
|
+
body,
|
|
15890
|
+
variable: v,
|
|
15891
|
+
domain: canon(pred.op2),
|
|
15892
|
+
condition: void 0
|
|
15893
|
+
};
|
|
15894
|
+
}
|
|
15895
|
+
if (isFunction2(pred, "And")) {
|
|
15896
|
+
const memberships = pred.ops.filter(
|
|
15897
|
+
(x) => isFunction2(x, "Element") && x.nops === 2 && isSymbol2(x.op1) && body.has(x.op1.symbol)
|
|
15898
|
+
);
|
|
15899
|
+
const membership = memberships.length === 1 ? memberships[0] : void 0;
|
|
15900
|
+
if (membership && isFunction2(membership, "Element") && isSymbol2(membership.op1)) {
|
|
15901
|
+
const rest = pred.ops.filter((x) => x !== membership).map(canon);
|
|
15902
|
+
const ce = body.engine;
|
|
15903
|
+
const cond = rest.length === 0 ? void 0 : rest.length === 1 ? rest[0] : ce._fn("And", rest);
|
|
15904
|
+
return {
|
|
15905
|
+
body,
|
|
15906
|
+
variable: membership.op1.symbol,
|
|
15907
|
+
domain: canon(membership.op2),
|
|
15908
|
+
condition: cond
|
|
15909
|
+
};
|
|
15910
|
+
}
|
|
15911
|
+
}
|
|
15912
|
+
return {
|
|
15913
|
+
body,
|
|
15914
|
+
variable: isSymbol2(body) ? body.symbol : void 0,
|
|
15915
|
+
domain: void 0,
|
|
15916
|
+
condition: pred
|
|
15917
|
+
};
|
|
15918
|
+
}
|
|
15919
|
+
return null;
|
|
15920
|
+
}
|
|
15921
|
+
function enumerateSetComprehension(comp) {
|
|
15922
|
+
const { body, variable, domain, condition } = comp;
|
|
15923
|
+
if (variable === void 0 || domain === void 0) return void 0;
|
|
15924
|
+
const ce = body.engine;
|
|
15925
|
+
const extract = (dom) => extractFiniteDomainWithReason(
|
|
15926
|
+
ce._fn("Element", [
|
|
15927
|
+
ce.symbol(variable),
|
|
15928
|
+
dom,
|
|
15929
|
+
...condition ? [condition] : []
|
|
15930
|
+
]),
|
|
15931
|
+
ce
|
|
15932
|
+
);
|
|
15933
|
+
let result = extract(domain);
|
|
15934
|
+
if (result.status !== "success") {
|
|
15935
|
+
const evaluatedDomain = domain.evaluate();
|
|
15936
|
+
if (!evaluatedDomain.isSame(domain)) result = extract(evaluatedDomain);
|
|
15937
|
+
}
|
|
15938
|
+
if (result.status !== "success") return void 0;
|
|
15939
|
+
const isIdentity = isSymbol2(body) && body.symbol === variable;
|
|
15940
|
+
const elements = [];
|
|
15941
|
+
for (const value of result.values) {
|
|
15942
|
+
const x = isIdentity ? value : body.subs({ [variable]: value }).evaluate();
|
|
15943
|
+
if (!elements.some((y) => y.isSame(x))) elements.push(x);
|
|
15944
|
+
}
|
|
15945
|
+
return elements;
|
|
15946
|
+
}
|
|
15947
|
+
function literalSetContains(ops, target) {
|
|
15948
|
+
let indeterminate = false;
|
|
15949
|
+
for (const op of ops) {
|
|
15950
|
+
if (target.isSame(op)) return true;
|
|
15951
|
+
if (isNumber(target) && isNumber(op)) {
|
|
15952
|
+
const eq2 = target.isEqual(op);
|
|
15953
|
+
if (eq2 === true) return true;
|
|
15954
|
+
if (eq2 !== false) indeterminate = true;
|
|
15955
|
+
} else if (isString(target) && isString(op)) {
|
|
15956
|
+
} else {
|
|
15957
|
+
indeterminate = true;
|
|
15958
|
+
}
|
|
15959
|
+
}
|
|
15960
|
+
return indeterminate ? void 0 : false;
|
|
15961
|
+
}
|
|
15962
|
+
function setComprehensionContains(comp, target) {
|
|
15963
|
+
const elements = enumerateSetComprehension(comp);
|
|
15964
|
+
if (elements !== void 0) return literalSetContains(elements, target);
|
|
15965
|
+
if (comp.domain !== void 0 && comp.variable !== void 0 && isSymbol2(comp.body) && comp.body.symbol === comp.variable) {
|
|
15966
|
+
const inDomain = comp.domain.contains(target);
|
|
15967
|
+
if (inDomain === false) return false;
|
|
15968
|
+
let condition = true;
|
|
15969
|
+
if (comp.condition !== void 0) {
|
|
15970
|
+
if (isNumber(target) || isString(target)) {
|
|
15971
|
+
const result = comp.condition.subs({ [comp.variable]: target }).evaluate();
|
|
15972
|
+
condition = sym(result) === "True" ? true : sym(result) === "False" ? false : void 0;
|
|
15973
|
+
} else condition = void 0;
|
|
15974
|
+
}
|
|
15975
|
+
if (condition === false) return false;
|
|
15976
|
+
if (inDomain === true && condition === true) return true;
|
|
15977
|
+
}
|
|
15978
|
+
return void 0;
|
|
15979
|
+
}
|
|
14765
15980
|
function tally(collection) {
|
|
14766
15981
|
const values = [];
|
|
14767
15982
|
const counts = [];
|
|
@@ -15001,7 +16216,11 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
15001
16216
|
op[1]
|
|
15002
16217
|
)}`;
|
|
15003
16218
|
} else {
|
|
15004
|
-
|
|
16219
|
+
const rightAssoc = h === "Power";
|
|
16220
|
+
resultStr = args.map((arg, i) => {
|
|
16221
|
+
const operandPrec = rightAssoc && i < args.length - 1 ? op[1] + 1 : op[1];
|
|
16222
|
+
return _BaseCompiler.compile(arg, target, operandPrec);
|
|
16223
|
+
}).join(` ${op[0]} `);
|
|
15005
16224
|
}
|
|
15006
16225
|
return op[1] < prec ? `(${resultStr})` : resultStr;
|
|
15007
16226
|
}
|
|
@@ -15206,6 +16425,13 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
15206
16425
|
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15207
16426
|
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15208
16427
|
* array or by unrolling when bounds are known at compile time.
|
|
16428
|
+
*
|
|
16429
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
16430
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
16431
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
16432
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
16433
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
16434
|
+
* current behavior.
|
|
15209
16435
|
*/
|
|
15210
16436
|
static compileForLoop(args, target) {
|
|
15211
16437
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -15687,6 +16913,17 @@ function compile(expr, options) {
|
|
|
15687
16913
|
`Compilation fallback for "${expr.operator}" (target: ${options?.to ?? "javascript"}): ${e.message}`
|
|
15688
16914
|
);
|
|
15689
16915
|
const ce = expr.engine;
|
|
16916
|
+
const target = options?.to ?? "javascript";
|
|
16917
|
+
if (isFunction2(expr, "Function")) {
|
|
16918
|
+
const lambdaRun = ((...args) => ce.function("Apply", [expr, ...args.map((a) => ce.box(a))]).evaluate().re);
|
|
16919
|
+
return {
|
|
16920
|
+
target,
|
|
16921
|
+
success: false,
|
|
16922
|
+
code: "",
|
|
16923
|
+
calling: "lambda",
|
|
16924
|
+
run: lambdaRun
|
|
16925
|
+
};
|
|
16926
|
+
}
|
|
15690
16927
|
const fallbackRun = ((vars) => {
|
|
15691
16928
|
ce.pushScope();
|
|
15692
16929
|
try {
|
|
@@ -15699,7 +16936,7 @@ function compile(expr, options) {
|
|
|
15699
16936
|
}
|
|
15700
16937
|
});
|
|
15701
16938
|
return {
|
|
15702
|
-
target
|
|
16939
|
+
target,
|
|
15703
16940
|
success: false,
|
|
15704
16941
|
code: "",
|
|
15705
16942
|
calling: "expression",
|
|
@@ -15753,6 +16990,11 @@ function foldTerms(terms, identity, op) {
|
|
|
15753
16990
|
if (symbolic.length === 1) return symbolic[0];
|
|
15754
16991
|
return symbolic.join(op === "+" ? " + " : " * ");
|
|
15755
16992
|
}
|
|
16993
|
+
function parenthesizeFactor(expr, code) {
|
|
16994
|
+
if (isFunction2(expr, "Add") || isFunction2(expr, "Subtract"))
|
|
16995
|
+
return `(${code})`;
|
|
16996
|
+
return code;
|
|
16997
|
+
}
|
|
15756
16998
|
function tryGetComplexParts(expr, compile2) {
|
|
15757
16999
|
if (isSymbol2(expr, "ImaginaryUnit")) {
|
|
15758
17000
|
return { re: null, im: "1.0" };
|
|
@@ -15777,7 +17019,9 @@ function tryGetComplexParts(expr, compile2) {
|
|
|
15777
17019
|
if (remaining.length === 0) {
|
|
15778
17020
|
return { re: null, im: formatFloat(iScale) };
|
|
15779
17021
|
}
|
|
15780
|
-
const compiledFactors = remaining.map(
|
|
17022
|
+
const compiledFactors = remaining.map(
|
|
17023
|
+
(r) => parenthesizeFactor(r, compile2(r))
|
|
17024
|
+
);
|
|
15781
17025
|
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
15782
17026
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
15783
17027
|
return { re: null, im: imCode };
|
|
@@ -19294,9 +20538,14 @@ var lanczos_7_c = [
|
|
|
19294
20538
|
];
|
|
19295
20539
|
function gammaln(z) {
|
|
19296
20540
|
if (z < 0) return NaN;
|
|
20541
|
+
let shift = 0;
|
|
20542
|
+
while (z < 10) {
|
|
20543
|
+
shift += Math.log(z);
|
|
20544
|
+
z += 1;
|
|
20545
|
+
}
|
|
19297
20546
|
const pi = Math.PI;
|
|
19298
20547
|
const z3 = z * z * z;
|
|
19299
|
-
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);
|
|
20548
|
+
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;
|
|
19300
20549
|
}
|
|
19301
20550
|
function gamma(z) {
|
|
19302
20551
|
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
|
|
@@ -19307,31 +20556,62 @@ function gamma(z) {
|
|
|
19307
20556
|
const t = z + gammaG + 0.5;
|
|
19308
20557
|
return Math.sqrt(2 * Math.PI) * Math.pow(t, z + 0.5) * Math.exp(-t) * x;
|
|
19309
20558
|
}
|
|
20559
|
+
function erfInvApprox(x) {
|
|
20560
|
+
const a = 0.147;
|
|
20561
|
+
const ln1mx2 = Math.log(1 - x * x);
|
|
20562
|
+
const b = 2 / (Math.PI * a) + ln1mx2 / 2;
|
|
20563
|
+
return Math.sign(x) * Math.sqrt(Math.sqrt(b * b - ln1mx2 / a) - b);
|
|
20564
|
+
}
|
|
19310
20565
|
function erfInv(x) {
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
const
|
|
19316
|
-
const
|
|
19317
|
-
|
|
19318
|
-
|
|
20566
|
+
if (Number.isNaN(x) || x < -1 || x > 1) return NaN;
|
|
20567
|
+
if (x === 0) return 0;
|
|
20568
|
+
if (x === 1) return Infinity;
|
|
20569
|
+
if (x === -1) return -Infinity;
|
|
20570
|
+
const sign2 = x < 0 ? -1 : 1;
|
|
20571
|
+
const ax = Math.abs(x);
|
|
20572
|
+
let y = erfInvApprox(ax);
|
|
20573
|
+
const c = Math.sqrt(Math.PI) / 2;
|
|
20574
|
+
for (let i = 0; i < 4; i++) y -= (erf(y) - ax) * c * Math.exp(y * y);
|
|
20575
|
+
return sign2 * y;
|
|
19319
20576
|
}
|
|
19320
20577
|
function erfc(x) {
|
|
19321
|
-
|
|
20578
|
+
if (Number.isNaN(x)) return NaN;
|
|
20579
|
+
if (!Number.isFinite(x)) return x > 0 ? 0 : 2;
|
|
20580
|
+
if (x < 0) return 2 - erfc(-x);
|
|
20581
|
+
if (x < 2) return 1 - erf(x);
|
|
20582
|
+
const tiny = 1e-300;
|
|
20583
|
+
let f = x === 0 ? tiny : x;
|
|
20584
|
+
let c = f;
|
|
20585
|
+
let d = 0;
|
|
20586
|
+
for (let k = 1; k <= 500; k++) {
|
|
20587
|
+
const a = k / 2;
|
|
20588
|
+
d = x + a * d;
|
|
20589
|
+
if (d === 0) d = tiny;
|
|
20590
|
+
d = 1 / d;
|
|
20591
|
+
c = x + a / c;
|
|
20592
|
+
if (c === 0) c = tiny;
|
|
20593
|
+
const delta = c * d;
|
|
20594
|
+
f *= delta;
|
|
20595
|
+
if (Math.abs(delta - 1) < 1e-17) break;
|
|
20596
|
+
}
|
|
20597
|
+
return Math.exp(-x * x) / (Math.sqrt(Math.PI) * f);
|
|
19322
20598
|
}
|
|
19323
20599
|
function erf(x) {
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
const a4 = -1.453152027;
|
|
19328
|
-
const a5 = 1.061405429;
|
|
19329
|
-
const p = 0.3275911;
|
|
20600
|
+
if (Number.isNaN(x)) return NaN;
|
|
20601
|
+
if (x === 0) return 0;
|
|
20602
|
+
if (!Number.isFinite(x)) return x > 0 ? 1 : -1;
|
|
19330
20603
|
const sign2 = x < 0 ? -1 : 1;
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
const
|
|
19334
|
-
|
|
20604
|
+
const ax = Math.abs(x);
|
|
20605
|
+
if (ax >= 6) return sign2;
|
|
20606
|
+
const x2 = ax * ax;
|
|
20607
|
+
let term = ax;
|
|
20608
|
+
let sum = ax;
|
|
20609
|
+
for (let n = 1; n < 200; n++) {
|
|
20610
|
+
term *= 2 * x2 / (2 * n + 1);
|
|
20611
|
+
sum += term;
|
|
20612
|
+
if (term < sum * 1e-18) break;
|
|
20613
|
+
}
|
|
20614
|
+
return sign2 * (2 / Math.sqrt(Math.PI)) * Math.exp(-x2) * sum;
|
|
19335
20615
|
}
|
|
19336
20616
|
var EULER_MASCHERONI = 0.5772156649015329;
|
|
19337
20617
|
var BERNOULLI_2K = [
|
|
@@ -19917,7 +21197,7 @@ function fresnelS(x) {
|
|
|
19917
21197
|
const t = x2 * x2;
|
|
19918
21198
|
return sign2 * x * x2 * polevl(t, SN) / polevl(t, SD);
|
|
19919
21199
|
}
|
|
19920
|
-
if (x <
|
|
21200
|
+
if (x < 36974) {
|
|
19921
21201
|
const x2 = x * x;
|
|
19922
21202
|
const t = Math.PI * x2;
|
|
19923
21203
|
const u = 1 / (t * t);
|
|
@@ -19942,7 +21222,7 @@ function fresnelC(x) {
|
|
|
19942
21222
|
const t = x2 * x2;
|
|
19943
21223
|
return sign2 * x * polevl(t, CN) / polevl(t, CD);
|
|
19944
21224
|
}
|
|
19945
|
-
if (x <
|
|
21225
|
+
if (x < 36974) {
|
|
19946
21226
|
const x2 = x * x;
|
|
19947
21227
|
const t = Math.PI * x2;
|
|
19948
21228
|
const u = 1 / (t * t);
|
|
@@ -20033,6 +21313,7 @@ function populationStandardDeviation(values) {
|
|
|
20033
21313
|
function kurtosis(values) {
|
|
20034
21314
|
let sum = 0;
|
|
20035
21315
|
let sum2 = 0;
|
|
21316
|
+
let sum3 = 0;
|
|
20036
21317
|
let sum4 = 0;
|
|
20037
21318
|
let count = 0;
|
|
20038
21319
|
for (const op of values) {
|
|
@@ -20040,12 +21321,16 @@ function kurtosis(values) {
|
|
|
20040
21321
|
if (!Number.isFinite(v)) return NaN;
|
|
20041
21322
|
sum += v;
|
|
20042
21323
|
sum2 += v * v;
|
|
21324
|
+
sum3 += v * v * v;
|
|
20043
21325
|
sum4 += v * v * v * v;
|
|
20044
21326
|
count++;
|
|
20045
21327
|
}
|
|
20046
21328
|
if (count === 0) return NaN;
|
|
20047
|
-
const
|
|
20048
|
-
|
|
21329
|
+
const n = count;
|
|
21330
|
+
const m = sum / n;
|
|
21331
|
+
const m2 = (sum2 - sum * sum / n) / n;
|
|
21332
|
+
const m4 = (sum4 - 4 * m * sum3 + 6 * m * m * sum2 - 4 * m * m * m * sum + n * m * m * m * m) / n;
|
|
21333
|
+
return m4 / (m2 * m2);
|
|
20049
21334
|
}
|
|
20050
21335
|
function skewness(values) {
|
|
20051
21336
|
let sum = 0;
|
|
@@ -20061,9 +21346,11 @@ function skewness(values) {
|
|
|
20061
21346
|
count++;
|
|
20062
21347
|
}
|
|
20063
21348
|
if (count === 0) return NaN;
|
|
20064
|
-
const
|
|
20065
|
-
const
|
|
20066
|
-
|
|
21349
|
+
const n = count;
|
|
21350
|
+
const m = sum / n;
|
|
21351
|
+
const m2 = (sum2 - sum * sum / n) / n;
|
|
21352
|
+
const m3 = (sum3 - 3 * m * sum2 + 3 * m * m * sum - n * m * m * m) / n;
|
|
21353
|
+
return m3 / Math.pow(m2, 3 / 2);
|
|
20067
21354
|
}
|
|
20068
21355
|
function mode(values) {
|
|
20069
21356
|
const counts = {};
|
|
@@ -20090,11 +21377,8 @@ function quartiles(values) {
|
|
|
20090
21377
|
return [q1, q2, q3];
|
|
20091
21378
|
}
|
|
20092
21379
|
function interquartileRange(values) {
|
|
20093
|
-
const
|
|
20094
|
-
|
|
20095
|
-
const lower = sorted.slice(0, mid);
|
|
20096
|
-
const upper = sorted.slice(mid + 1);
|
|
20097
|
-
return median(upper) - median(lower);
|
|
21380
|
+
const [q1, , q3] = quartiles(values);
|
|
21381
|
+
return q3 - q1;
|
|
20098
21382
|
}
|
|
20099
21383
|
|
|
20100
21384
|
// src/compute-engine/numerics/monte-carlo.ts
|
|
@@ -20293,6 +21577,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20293
21577
|
return `_SYS.cexp(${compile2(args[0])})`;
|
|
20294
21578
|
return `Math.exp(${compile2(args[0])})`;
|
|
20295
21579
|
},
|
|
21580
|
+
First: (args, compile2) => `${compile2(args[0])}[0]`,
|
|
20296
21581
|
Floor: (args, compile2) => {
|
|
20297
21582
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20298
21583
|
return `Math.floor(${compile2(args[0])})`;
|
|
@@ -20424,7 +21709,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20424
21709
|
if (parseFloat(step) === 1) {
|
|
20425
21710
|
const fStop = parseFloat(stop);
|
|
20426
21711
|
const fStart = parseFloat(start);
|
|
20427
|
-
if (fStop
|
|
21712
|
+
if (!isNaN(fStop) && !isNaN(fStart)) {
|
|
20428
21713
|
if (fStop - fStart < 50) {
|
|
20429
21714
|
return `[${Array.from(
|
|
20430
21715
|
{ length: fStop - fStart + 1 },
|
|
@@ -20435,9 +21720,9 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20435
21720
|
}, (_, i) => ${start} + i)`;
|
|
20436
21721
|
}
|
|
20437
21722
|
return `Array.from({length: ${stop} - ${start} + 1
|
|
20438
|
-
}, (
|
|
21723
|
+
}, (_e, i) => ${start} + i)`;
|
|
20439
21724
|
}
|
|
20440
|
-
return `Array.from({length: Math.floor((${stop} - ${start}) / ${step}) + 1}, (
|
|
21725
|
+
return `Array.from({length: Math.floor((${stop} - ${start}) / ${step}) + 1}, (_e, i) => ${start} + i * ${step})`;
|
|
20441
21726
|
},
|
|
20442
21727
|
Root: ([arg, exp3], compile2) => {
|
|
20443
21728
|
if (arg === null) throw new Error("Root: no argument");
|
|
@@ -20451,7 +21736,20 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20451
21736
|
if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
|
|
20452
21737
|
return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
|
|
20453
21738
|
},
|
|
20454
|
-
Random:
|
|
21739
|
+
Random: (args, compile2) => {
|
|
21740
|
+
if (args.length === 0) return "Math.random()";
|
|
21741
|
+
if (args.length === 2) {
|
|
21742
|
+
const m = compile2(args[0]);
|
|
21743
|
+
const n = compile2(args[1]);
|
|
21744
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
21745
|
+
}
|
|
21746
|
+
const arg = args[0];
|
|
21747
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
21748
|
+
return `Math.floor(Math.random() * (${compile2(arg)}))`;
|
|
21749
|
+
}
|
|
21750
|
+
const a = compile2(arg);
|
|
21751
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
21752
|
+
},
|
|
20455
21753
|
Round: (args, compile2) => {
|
|
20456
21754
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20457
21755
|
return `Math.round(${compile2(args[0])})`;
|
|
@@ -20479,6 +21777,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20479
21777
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile2(arg)})`;
|
|
20480
21778
|
return `1 / Math.cosh(${compile2(arg)})`;
|
|
20481
21779
|
},
|
|
21780
|
+
Second: (args, compile2) => `${compile2(args[0])}[1]`,
|
|
20482
21781
|
Heaviside: "_SYS.heaviside",
|
|
20483
21782
|
Sign: "Math.sign",
|
|
20484
21783
|
Sinc: "_SYS.sinc",
|
|
@@ -20511,6 +21810,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20511
21810
|
return `_SYS.ctanh(${compile2(args[0])})`;
|
|
20512
21811
|
return `Math.tanh(${compile2(args[0])})`;
|
|
20513
21812
|
},
|
|
21813
|
+
Third: (args, compile2) => `${compile2(args[0])}[2]`,
|
|
20514
21814
|
Mod: ([a, b], compile2) => {
|
|
20515
21815
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
20516
21816
|
const ca = compile2(a);
|
|
@@ -21579,6 +22879,14 @@ function gpuVec2(target) {
|
|
|
21579
22879
|
function gpuVec3(target) {
|
|
21580
22880
|
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
21581
22881
|
}
|
|
22882
|
+
function gpuNaN(target) {
|
|
22883
|
+
return target?.language === "wgsl" ? "bitcast<f32>(0x7fc00000u)" : "(0.0 / 0.0)";
|
|
22884
|
+
}
|
|
22885
|
+
function gpuConditional(cond, whenTrue, whenFalse, target) {
|
|
22886
|
+
if (target?.language === "wgsl")
|
|
22887
|
+
return `select(${whenFalse}, ${whenTrue}, ${cond})`;
|
|
22888
|
+
return `((${cond}) ? (${whenTrue}) : (${whenFalse}))`;
|
|
22889
|
+
}
|
|
21582
22890
|
function readStringLiteral(expr) {
|
|
21583
22891
|
if (!isString(expr)) return null;
|
|
21584
22892
|
return expr.string?.toLowerCase() ?? null;
|
|
@@ -21696,7 +23004,7 @@ var GPU_FUNCTIONS = {
|
|
|
21696
23004
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
21697
23005
|
const v2 = gpuVec2(target);
|
|
21698
23006
|
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
21699
|
-
const factors = realFactors.map((f) => compile2(f));
|
|
23007
|
+
const factors = realFactors.map((f) => parenthesizeFactor(f, compile2(f)));
|
|
21700
23008
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
21701
23009
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
21702
23010
|
return `${v2}(0.0, ${imCode})`;
|
|
@@ -21705,7 +23013,7 @@ var GPU_FUNCTIONS = {
|
|
|
21705
23013
|
const complexCodes = [];
|
|
21706
23014
|
for (const a of args) {
|
|
21707
23015
|
if (BaseCompiler.isComplexValued(a)) complexCodes.push(compile2(a));
|
|
21708
|
-
else realCodes.push(compile2(a));
|
|
23016
|
+
else realCodes.push(parenthesizeFactor(a, compile2(a)));
|
|
21709
23017
|
}
|
|
21710
23018
|
const scalarCode = foldTerms(realCodes, "1.0", "*");
|
|
21711
23019
|
let result = complexCodes[0];
|
|
@@ -21783,13 +23091,23 @@ var GPU_FUNCTIONS = {
|
|
|
21783
23091
|
return `_gpu_ccos(${compile2(args[0])})`;
|
|
21784
23092
|
return `cos(${compile2(args[0])})`;
|
|
21785
23093
|
},
|
|
21786
|
-
Degrees
|
|
23094
|
+
// CE's `Degrees` converts degrees→radians (Degrees(180) = π), which is
|
|
23095
|
+
// GLSL's `radians()`. GLSL's `degrees()` is the inverse (rad→deg).
|
|
23096
|
+
Degrees: "radians",
|
|
21787
23097
|
Exp: (args, compile2) => {
|
|
21788
23098
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
21789
23099
|
return `_gpu_cexp(${compile2(args[0])})`;
|
|
21790
23100
|
return `exp(${compile2(args[0])})`;
|
|
21791
23101
|
},
|
|
21792
23102
|
Exp2: "exp2",
|
|
23103
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
23104
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
23105
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
23106
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
23107
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
23108
|
+
First: (args, compile2) => `${compile2(args[0])}.x`,
|
|
23109
|
+
Second: (args, compile2) => `${compile2(args[0])}.y`,
|
|
23110
|
+
Third: (args, compile2) => `${compile2(args[0])}.z`,
|
|
21793
23111
|
Floor: (args, compile2) => {
|
|
21794
23112
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21795
23113
|
return `floor(${compile2(args[0])})`;
|
|
@@ -21804,6 +23122,43 @@ var GPU_FUNCTIONS = {
|
|
|
21804
23122
|
Max: "max",
|
|
21805
23123
|
Min: "min",
|
|
21806
23124
|
Mix: "mix",
|
|
23125
|
+
// Control-flow forms — the base compiler's default emits a JS ternary and a
|
|
23126
|
+
// bare `NaN`, neither of which is valid GPU code (WGSL has no `?:`, and no
|
|
23127
|
+
// shader language has a `NaN` identifier). Emit `select(...)` for WGSL and a
|
|
23128
|
+
// language-appropriate NaN.
|
|
23129
|
+
If: (args, compile2, target) => {
|
|
23130
|
+
if (args.length !== 3) throw new Error("If: wrong number of arguments");
|
|
23131
|
+
return gpuConditional(
|
|
23132
|
+
compile2(args[0]),
|
|
23133
|
+
compile2(args[1]),
|
|
23134
|
+
compile2(args[2]),
|
|
23135
|
+
target
|
|
23136
|
+
);
|
|
23137
|
+
},
|
|
23138
|
+
When: (args, compile2, target) => {
|
|
23139
|
+
if (args.length !== 2)
|
|
23140
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
23141
|
+
if (isSymbol2(args[1], "True")) return `(${compile2(args[0])})`;
|
|
23142
|
+
if (isSymbol2(args[1], "False")) return gpuNaN(target);
|
|
23143
|
+
return gpuConditional(
|
|
23144
|
+
compile2(args[1]),
|
|
23145
|
+
compile2(args[0]),
|
|
23146
|
+
gpuNaN(target),
|
|
23147
|
+
target
|
|
23148
|
+
);
|
|
23149
|
+
},
|
|
23150
|
+
Which: (args, compile2, target) => {
|
|
23151
|
+
if (args.length < 2 || args.length % 2 !== 0)
|
|
23152
|
+
throw new Error("Which: expected condition/value pairs");
|
|
23153
|
+
const build = (i) => {
|
|
23154
|
+
if (i >= args.length) return gpuNaN(target);
|
|
23155
|
+
const cond = args[i];
|
|
23156
|
+
const val = args[i + 1];
|
|
23157
|
+
if (isSymbol2(cond, "True")) return `(${compile2(val)})`;
|
|
23158
|
+
return gpuConditional(compile2(cond), compile2(val), build(i + 2), target);
|
|
23159
|
+
};
|
|
23160
|
+
return build(0);
|
|
23161
|
+
},
|
|
21807
23162
|
Power: (args, compile2, target) => {
|
|
21808
23163
|
const base = args[0];
|
|
21809
23164
|
const exp3 = args[1];
|
|
@@ -22267,6 +23622,39 @@ var GPU_FUNCTIONS = {
|
|
|
22267
23622
|
// Sum/Product — unrolled or for-loop
|
|
22268
23623
|
Sum: (args, compile2, target) => compileGPUSumProduct("Sum", args, compile2, target),
|
|
22269
23624
|
Product: (args, compile2, target) => compileGPUSumProduct("Product", args, compile2, target),
|
|
23625
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
23626
|
+
Range: (args, _compile, target) => {
|
|
23627
|
+
if (args.length < 2 || args.length > 3) {
|
|
23628
|
+
throw new Error(
|
|
23629
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
23630
|
+
);
|
|
23631
|
+
}
|
|
23632
|
+
const lo = args[0].re;
|
|
23633
|
+
const hi = args[1].re;
|
|
23634
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
23635
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
23636
|
+
throw new Error(
|
|
23637
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
23638
|
+
);
|
|
23639
|
+
}
|
|
23640
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
23641
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
23642
|
+
if (count === 0) {
|
|
23643
|
+
throw new Error(
|
|
23644
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
23645
|
+
);
|
|
23646
|
+
}
|
|
23647
|
+
if (count > 256) {
|
|
23648
|
+
throw new Error(
|
|
23649
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
23650
|
+
);
|
|
23651
|
+
}
|
|
23652
|
+
const values = [];
|
|
23653
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
23654
|
+
const isWGSL = target.language === "wgsl";
|
|
23655
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
23656
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
23657
|
+
},
|
|
22270
23658
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
22271
23659
|
Loop: (args, _compile, target) => {
|
|
22272
23660
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -22295,6 +23683,134 @@ var GPU_FUNCTIONS = {
|
|
|
22295
23683
|
${bodyCode};
|
|
22296
23684
|
}`;
|
|
22297
23685
|
},
|
|
23686
|
+
// Statistical functions
|
|
23687
|
+
/**
|
|
23688
|
+
* GCD of two scalar arguments.
|
|
23689
|
+
*
|
|
23690
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
23691
|
+
* Only two-argument form is supported in GPU targets.
|
|
23692
|
+
*/
|
|
23693
|
+
GCD: (args, compile2) => {
|
|
23694
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
23695
|
+
if (args.length > 2)
|
|
23696
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
23697
|
+
const a = args[0];
|
|
23698
|
+
const b = args[1];
|
|
23699
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
23700
|
+
return `_gpu_gcd(${compile2(a)}, ${compile2(b)})`;
|
|
23701
|
+
},
|
|
23702
|
+
/**
|
|
23703
|
+
* Variance of a compile-time-known list.
|
|
23704
|
+
*
|
|
23705
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
23706
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
23707
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
23708
|
+
*/
|
|
23709
|
+
Variance: (args, compile2) => {
|
|
23710
|
+
let elems;
|
|
23711
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
23712
|
+
elems = args[0].ops;
|
|
23713
|
+
} else if (args.length >= 2) {
|
|
23714
|
+
elems = args;
|
|
23715
|
+
} else {
|
|
23716
|
+
throw new Error(
|
|
23717
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
23718
|
+
);
|
|
23719
|
+
}
|
|
23720
|
+
const n = elems.length;
|
|
23721
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
23722
|
+
const compiled = elems.map((e) => compile2(e));
|
|
23723
|
+
const sum = compiled.join(" + ");
|
|
23724
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
23725
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
23726
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
23727
|
+
},
|
|
23728
|
+
/**
|
|
23729
|
+
* Median of a compile-time-known list.
|
|
23730
|
+
*
|
|
23731
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
23732
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
23733
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
23734
|
+
*
|
|
23735
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
23736
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
23737
|
+
*/
|
|
23738
|
+
Median: (args, compile2) => {
|
|
23739
|
+
let elems;
|
|
23740
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
23741
|
+
elems = args[0].ops;
|
|
23742
|
+
} else if (args.length >= 1) {
|
|
23743
|
+
elems = args;
|
|
23744
|
+
} else {
|
|
23745
|
+
throw new Error(
|
|
23746
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
23747
|
+
);
|
|
23748
|
+
}
|
|
23749
|
+
const n = elems.length;
|
|
23750
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
23751
|
+
if (n > 8) {
|
|
23752
|
+
throw new Error(
|
|
23753
|
+
`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.`
|
|
23754
|
+
);
|
|
23755
|
+
}
|
|
23756
|
+
const compiled = elems.map((e) => compile2(e));
|
|
23757
|
+
if (n === 1) return compiled[0];
|
|
23758
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
23759
|
+
},
|
|
23760
|
+
/**
|
|
23761
|
+
* Deterministic pseudorandom for GPU.
|
|
23762
|
+
*
|
|
23763
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
23764
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
23765
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
23766
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
23767
|
+
* integer-returning operators in this target.
|
|
23768
|
+
*
|
|
23769
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
23770
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
23771
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
23772
|
+
* caller must provide an explicit seed.
|
|
23773
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
23774
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
23775
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
23776
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
23777
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
23778
|
+
*
|
|
23779
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
23780
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
23781
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
23782
|
+
* `sin` differences.
|
|
23783
|
+
*/
|
|
23784
|
+
Random: (args, compile2, target) => {
|
|
23785
|
+
if (args.length === 0) {
|
|
23786
|
+
if (target.language === "wgsl") {
|
|
23787
|
+
throw new Error(
|
|
23788
|
+
"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."
|
|
23789
|
+
);
|
|
23790
|
+
}
|
|
23791
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
23792
|
+
}
|
|
23793
|
+
if (args.length === 1) {
|
|
23794
|
+
const arg = args[0];
|
|
23795
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
23796
|
+
const compiled = compile2(arg);
|
|
23797
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
23798
|
+
}
|
|
23799
|
+
return `_gpu_random(${compile2(arg)})`;
|
|
23800
|
+
}
|
|
23801
|
+
if (args.length === 2) {
|
|
23802
|
+
if (target.language === "wgsl") {
|
|
23803
|
+
throw new Error(
|
|
23804
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
23805
|
+
);
|
|
23806
|
+
}
|
|
23807
|
+
const m = compile2(args[0]);
|
|
23808
|
+
const n = compile2(args[1]);
|
|
23809
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
23810
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
23811
|
+
}
|
|
23812
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
23813
|
+
},
|
|
22298
23814
|
// Function (lambda) — not supported in GPU
|
|
22299
23815
|
Function: () => {
|
|
22300
23816
|
throw new Error(
|
|
@@ -22330,7 +23846,7 @@ function compileGPUMatrix(args, compile2, vecFn, matFn, arrayFn) {
|
|
|
22330
23846
|
}
|
|
22331
23847
|
return compile2(body);
|
|
22332
23848
|
}
|
|
22333
|
-
var
|
|
23849
|
+
var GPU_GAMMA_PREAMBLE_GLSL = `
|
|
22334
23850
|
float _gpu_gamma(float z) {
|
|
22335
23851
|
const float PI = 3.14159265358979;
|
|
22336
23852
|
// For z < 0.5, use reflection formula with inlined Lanczos (non-recursive)
|
|
@@ -22362,7 +23878,37 @@ float _gpu_gammaln(float z) {
|
|
|
22362
23878
|
+ 1.0 / (1260.0 * z3 * z * z);
|
|
22363
23879
|
}
|
|
22364
23880
|
`;
|
|
22365
|
-
var
|
|
23881
|
+
var GPU_GAMMA_PREAMBLE_WGSL = `
|
|
23882
|
+
fn _gpu_gamma(z: f32) -> f32 {
|
|
23883
|
+
let PI = 3.14159265358979;
|
|
23884
|
+
var w = z;
|
|
23885
|
+
if (z < 0.5) { w = 1.0 - z; }
|
|
23886
|
+
w = w - 1.0;
|
|
23887
|
+
var x = 0.99999999999980993;
|
|
23888
|
+
x = x + 676.5203681218851 / (w + 1.0);
|
|
23889
|
+
x = x + -1259.1392167224028 / (w + 2.0);
|
|
23890
|
+
x = x + 771.32342877765313 / (w + 3.0);
|
|
23891
|
+
x = x + -176.61502916214059 / (w + 4.0);
|
|
23892
|
+
x = x + 12.507343278686905 / (w + 5.0);
|
|
23893
|
+
x = x + -0.13857109526572012 / (w + 6.0);
|
|
23894
|
+
x = x + 9.9843695780195716e-6 / (w + 7.0);
|
|
23895
|
+
x = x + 1.5056327351493116e-7 / (w + 8.0);
|
|
23896
|
+
let t = w + 7.5;
|
|
23897
|
+
let g = sqrt(2.0 * PI) * pow(t, w + 0.5) * exp(-t) * x;
|
|
23898
|
+
if (z < 0.5) { return PI / (sin(PI * z) * g); }
|
|
23899
|
+
return g;
|
|
23900
|
+
}
|
|
23901
|
+
|
|
23902
|
+
fn _gpu_gammaln(z: f32) -> f32 {
|
|
23903
|
+
let z3 = z * z * z;
|
|
23904
|
+
return z * log(z) - z - 0.5 * log(z)
|
|
23905
|
+
+ 0.5 * log(2.0 * 3.14159265358979)
|
|
23906
|
+
+ 1.0 / (12.0 * z)
|
|
23907
|
+
- 1.0 / (360.0 * z3)
|
|
23908
|
+
+ 1.0 / (1260.0 * z3 * z * z);
|
|
23909
|
+
}
|
|
23910
|
+
`;
|
|
23911
|
+
var GPU_ERF_PREAMBLE_GLSL = `
|
|
22366
23912
|
float _gpu_erf(float x) {
|
|
22367
23913
|
float ax = abs(x);
|
|
22368
23914
|
float t = 1.0 / (1.0 + 0.3275911 * ax);
|
|
@@ -22381,6 +23927,26 @@ float _gpu_erfinv(float x) {
|
|
|
22381
23927
|
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);
|
|
22382
23928
|
}
|
|
22383
23929
|
`;
|
|
23930
|
+
var GPU_ERF_PREAMBLE_WGSL = `
|
|
23931
|
+
fn _gpu_erf(x: f32) -> f32 {
|
|
23932
|
+
let ax = abs(x);
|
|
23933
|
+
let t = 1.0 / (1.0 + 0.3275911 * ax);
|
|
23934
|
+
let y = ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t;
|
|
23935
|
+
let result = 1.0 - y * exp(-ax * ax);
|
|
23936
|
+
if (x < 0.0) { return -result; }
|
|
23937
|
+
return result;
|
|
23938
|
+
}
|
|
23939
|
+
|
|
23940
|
+
fn _gpu_erfinv(x: f32) -> f32 {
|
|
23941
|
+
let pi = 3.14159265358979;
|
|
23942
|
+
let x2 = x * x;
|
|
23943
|
+
let x3 = x * x2;
|
|
23944
|
+
let x5 = x3 * x2;
|
|
23945
|
+
let x7 = x5 * x2;
|
|
23946
|
+
let x9 = x7 * x2;
|
|
23947
|
+
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);
|
|
23948
|
+
}
|
|
23949
|
+
`;
|
|
22384
23950
|
var GPU_HEAVISIDE_PREAMBLE_GLSL = `
|
|
22385
23951
|
float _gpu_heaviside(float x) {
|
|
22386
23952
|
if (x < 0.0) return 0.0;
|
|
@@ -22894,6 +24460,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
22894
24460
|
return 1.0;
|
|
22895
24461
|
}
|
|
22896
24462
|
`;
|
|
24463
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
24464
|
+
float _gpu_gcd(float a, float b) {
|
|
24465
|
+
a = abs(a); b = abs(b);
|
|
24466
|
+
for (int i = 0; i < 32; i++) {
|
|
24467
|
+
if (b < 0.5) break;
|
|
24468
|
+
float t = mod(a, b);
|
|
24469
|
+
a = b;
|
|
24470
|
+
b = t;
|
|
24471
|
+
}
|
|
24472
|
+
return a;
|
|
24473
|
+
}
|
|
24474
|
+
`;
|
|
24475
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
24476
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
24477
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
24478
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
24479
|
+
if (b < 0.5) { break; }
|
|
24480
|
+
let t = a % b;
|
|
24481
|
+
a = b;
|
|
24482
|
+
b = t;
|
|
24483
|
+
}
|
|
24484
|
+
return a;
|
|
24485
|
+
}
|
|
24486
|
+
`;
|
|
24487
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
24488
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
24489
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
24490
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
24491
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
24492
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
24493
|
+
float _gpu_random(float seed) {
|
|
24494
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
24495
|
+
}
|
|
24496
|
+
`;
|
|
24497
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
24498
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
24499
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
24500
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
24501
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
24502
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
24503
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
24504
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
24505
|
+
}
|
|
24506
|
+
`;
|
|
24507
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
24508
|
+
float _gpu_median_2(float a, float b) {
|
|
24509
|
+
return (a + b) * 0.5;
|
|
24510
|
+
}
|
|
24511
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
24512
|
+
return max(min(a, b), min(max(a, b), c));
|
|
24513
|
+
}
|
|
24514
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
24515
|
+
float lo = max(min(a, b), min(c, d));
|
|
24516
|
+
float hi = min(max(a, b), max(c, d));
|
|
24517
|
+
return (lo + hi) * 0.5;
|
|
24518
|
+
}
|
|
24519
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
24520
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
24521
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
24522
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24523
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24524
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24525
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24526
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
24527
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24528
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
24529
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24530
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24531
|
+
return v2;
|
|
24532
|
+
}
|
|
24533
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
24534
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
24535
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24536
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24537
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24538
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24539
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24540
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24541
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24542
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24543
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24544
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24545
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24546
|
+
return (v2 + v3) * 0.5;
|
|
24547
|
+
}
|
|
24548
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
24549
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
24550
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24551
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24552
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24553
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24554
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24555
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24556
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24557
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24558
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24559
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24560
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24561
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24562
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24563
|
+
return v3;
|
|
24564
|
+
}
|
|
24565
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
24566
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
24567
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24568
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24569
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24570
|
+
t=min(v6,v7); v7=max(v6,v7); v6=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(v4,v6); v6=max(v4,v6); v4=t;
|
|
24574
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
24575
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24576
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24577
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24578
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
24579
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24580
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24581
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
24582
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24583
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24584
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24585
|
+
return (v3 + v4) * 0.5;
|
|
24586
|
+
}
|
|
24587
|
+
`;
|
|
24588
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
24589
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
24590
|
+
return (a + b) * 0.5;
|
|
24591
|
+
}
|
|
24592
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
24593
|
+
return max(min(a, b), min(max(a, b), c));
|
|
24594
|
+
}
|
|
24595
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
24596
|
+
let lo = max(min(a, b), min(c, d));
|
|
24597
|
+
let hi = min(max(a, b), max(c, d));
|
|
24598
|
+
return (lo + hi) * 0.5;
|
|
24599
|
+
}
|
|
24600
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
24601
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
24602
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
24603
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24604
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24605
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24606
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24607
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
24608
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24609
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
24610
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24611
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24612
|
+
return v2;
|
|
24613
|
+
}
|
|
24614
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
24615
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
24616
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24617
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24618
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24619
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24620
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24621
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24622
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24623
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24624
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24625
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24626
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24627
|
+
return (v2 + v3) * 0.5;
|
|
24628
|
+
}
|
|
24629
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
24630
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
24631
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24632
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24633
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24634
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
24635
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
24636
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
24637
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24638
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24639
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24640
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24641
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24642
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24643
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24644
|
+
return v3;
|
|
24645
|
+
}
|
|
24646
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
24647
|
+
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;
|
|
24648
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
24649
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
24650
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
24651
|
+
t=min(v6,v7); v7=max(v6,v7); v6=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(v4,v6); v6=max(v4,v6); v4=t;
|
|
24655
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
24656
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
24657
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
24658
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
24659
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
24660
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
24661
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24662
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
24663
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
24664
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
24665
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
24666
|
+
return (v3 + v4) * 0.5;
|
|
24667
|
+
}
|
|
24668
|
+
`;
|
|
22897
24669
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
22898
24670
|
float _gpu_srgb_to_linear(float c) {
|
|
22899
24671
|
if (c <= 0.04045) return c / 12.92;
|
|
@@ -23554,8 +25326,10 @@ var GPUShaderTarget = class {
|
|
|
23554
25326
|
};
|
|
23555
25327
|
let preamble = "";
|
|
23556
25328
|
preamble += buildComplexPreamble(code, this.languageId);
|
|
23557
|
-
if (code.includes("_gpu_gamma"))
|
|
23558
|
-
|
|
25329
|
+
if (code.includes("_gpu_gamma"))
|
|
25330
|
+
preamble += this.languageId === "wgsl" ? GPU_GAMMA_PREAMBLE_WGSL : GPU_GAMMA_PREAMBLE_GLSL;
|
|
25331
|
+
if (code.includes("_gpu_erf"))
|
|
25332
|
+
preamble += this.languageId === "wgsl" ? GPU_ERF_PREAMBLE_WGSL : GPU_ERF_PREAMBLE_GLSL;
|
|
23559
25333
|
if (code.includes("_gpu_heaviside"))
|
|
23560
25334
|
preamble += this.languageId === "wgsl" ? GPU_HEAVISIDE_PREAMBLE_WGSL : GPU_HEAVISIDE_PREAMBLE_GLSL;
|
|
23561
25335
|
if (code.includes("_gpu_sinc"))
|
|
@@ -23571,6 +25345,12 @@ var GPUShaderTarget = class {
|
|
|
23571
25345
|
if (code.includes("_fractal_")) {
|
|
23572
25346
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
23573
25347
|
}
|
|
25348
|
+
if (code.includes("_gpu_random"))
|
|
25349
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
25350
|
+
if (code.includes("_gpu_gcd"))
|
|
25351
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
25352
|
+
if (code.includes("_gpu_median_"))
|
|
25353
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
23574
25354
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
23575
25355
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
23576
25356
|
}
|
|
@@ -24335,9 +26115,18 @@ function negate(x) {
|
|
|
24335
26115
|
return ok({ lo: -xVal.hi, hi: -xVal.lo });
|
|
24336
26116
|
}
|
|
24337
26117
|
function _mul(a, b) {
|
|
24338
|
-
const products = [
|
|
26118
|
+
const products = [
|
|
26119
|
+
_prod(a.lo, b.lo),
|
|
26120
|
+
_prod(a.lo, b.hi),
|
|
26121
|
+
_prod(a.hi, b.lo),
|
|
26122
|
+
_prod(a.hi, b.hi)
|
|
26123
|
+
];
|
|
24339
26124
|
return { lo: Math.min(...products), hi: Math.max(...products) };
|
|
24340
26125
|
}
|
|
26126
|
+
function _prod(x, y) {
|
|
26127
|
+
if (x === 0 || y === 0) return 0;
|
|
26128
|
+
return x * y;
|
|
26129
|
+
}
|
|
24341
26130
|
function mul3(a, b) {
|
|
24342
26131
|
const unwrapped = unwrapOrPropagate(a, b);
|
|
24343
26132
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -24671,6 +26460,7 @@ function mod(a, b) {
|
|
|
24671
26460
|
const period = Math.abs(
|
|
24672
26461
|
bVal.lo === bVal.hi ? bVal.lo : Math.max(Math.abs(bVal.lo), Math.abs(bVal.hi))
|
|
24673
26462
|
);
|
|
26463
|
+
const divisorNegative = bVal.hi < 0;
|
|
24674
26464
|
const flo = Math.floor(aVal.lo / period);
|
|
24675
26465
|
const fhi = Math.floor(aVal.hi / period);
|
|
24676
26466
|
if (flo !== fhi) {
|
|
@@ -24678,6 +26468,11 @@ function mod(a, b) {
|
|
|
24678
26468
|
}
|
|
24679
26469
|
const modLo = aVal.lo - period * flo;
|
|
24680
26470
|
const modHi = aVal.hi - period * flo;
|
|
26471
|
+
if (divisorNegative) {
|
|
26472
|
+
if (modLo === 0)
|
|
26473
|
+
return { kind: "singular", at: aVal.lo, continuity: "right" };
|
|
26474
|
+
return ok({ lo: modLo - period, hi: modHi - period });
|
|
26475
|
+
}
|
|
24681
26476
|
return ok({ lo: Math.min(modLo, modHi), hi: Math.max(modLo, modHi) });
|
|
24682
26477
|
}
|
|
24683
26478
|
function remainder(a, b) {
|
|
@@ -24709,6 +26504,23 @@ function gamma2(x) {
|
|
|
24709
26504
|
const [xVal] = unwrapped;
|
|
24710
26505
|
return _gamma(xVal);
|
|
24711
26506
|
}
|
|
26507
|
+
var GAMMA_NEG_EXTREMA_X = [
|
|
26508
|
+
-0.504083008264455,
|
|
26509
|
+
-1.573498473162391,
|
|
26510
|
+
-2.610720868444145,
|
|
26511
|
+
-3.635293366436901,
|
|
26512
|
+
-4.653163765628266,
|
|
26513
|
+
-5.667162441556885,
|
|
26514
|
+
-6.678418213073426,
|
|
26515
|
+
-7.687788325031709,
|
|
26516
|
+
-8.695764163640956,
|
|
26517
|
+
-9.702672540001863
|
|
26518
|
+
];
|
|
26519
|
+
function gammaNegStripExtremum(lo) {
|
|
26520
|
+
const n = Math.floor(lo);
|
|
26521
|
+
const idx = -n - 1;
|
|
26522
|
+
return idx >= 0 && idx < GAMMA_NEG_EXTREMA_X.length ? GAMMA_NEG_EXTREMA_X[idx] : null;
|
|
26523
|
+
}
|
|
24712
26524
|
function _gamma(x) {
|
|
24713
26525
|
if (x.hi >= 0 && x.lo <= 0) {
|
|
24714
26526
|
return { kind: "singular", at: 0 };
|
|
@@ -24721,7 +26533,21 @@ function _gamma(x) {
|
|
|
24721
26533
|
}
|
|
24722
26534
|
const gLo = gamma(x.lo);
|
|
24723
26535
|
const gHi = gamma(x.hi);
|
|
24724
|
-
|
|
26536
|
+
let lo = Math.min(gLo, gHi);
|
|
26537
|
+
let hi = Math.max(gLo, gHi);
|
|
26538
|
+
const xStar = gammaNegStripExtremum(x.lo);
|
|
26539
|
+
if (xStar !== null) {
|
|
26540
|
+
if (xStar >= x.lo && xStar <= x.hi) {
|
|
26541
|
+
const g = gamma(xStar);
|
|
26542
|
+
lo = Math.min(lo, g);
|
|
26543
|
+
hi = Math.max(hi, g);
|
|
26544
|
+
}
|
|
26545
|
+
} else {
|
|
26546
|
+
const stripEven = Math.floor(x.lo) % 2 === 0;
|
|
26547
|
+
if (stripEven) lo = Math.min(lo, 0);
|
|
26548
|
+
else hi = Math.max(hi, 0);
|
|
26549
|
+
}
|
|
26550
|
+
return ok({ lo, hi });
|
|
24725
26551
|
}
|
|
24726
26552
|
if (x.lo >= GAMMA_MIN_X) {
|
|
24727
26553
|
return ok({ lo: gamma(x.lo), hi: gamma(x.hi) });
|
|
@@ -24752,7 +26578,15 @@ function _gammaln(x) {
|
|
|
24752
26578
|
}
|
|
24753
26579
|
const gLo = gammaln(x.lo);
|
|
24754
26580
|
const gHi = gammaln(x.hi);
|
|
24755
|
-
|
|
26581
|
+
let lo = Math.min(gLo, gHi);
|
|
26582
|
+
const hi = Math.max(gLo, gHi);
|
|
26583
|
+
const xStar = gammaNegStripExtremum(x.lo);
|
|
26584
|
+
if (xStar !== null) {
|
|
26585
|
+
if (xStar >= x.lo && xStar <= x.hi) lo = Math.min(lo, gammaln(xStar));
|
|
26586
|
+
} else {
|
|
26587
|
+
lo = -Infinity;
|
|
26588
|
+
}
|
|
26589
|
+
return ok({ lo, hi });
|
|
24756
26590
|
}
|
|
24757
26591
|
return ok({ lo: gammaln(x.lo), hi: gammaln(x.hi) });
|
|
24758
26592
|
}
|
|
@@ -24778,6 +26612,33 @@ function factorial22(x) {
|
|
|
24778
26612
|
return ok({ lo: Math.min(fLo, fHi), hi: Math.max(fLo, fHi) });
|
|
24779
26613
|
return ok({ lo: fLo, hi: fHi });
|
|
24780
26614
|
}
|
|
26615
|
+
var MAX_INT_ENUM_POINTS = 4096;
|
|
26616
|
+
function integerPoints(lo, hi, cap) {
|
|
26617
|
+
const a = Math.round(lo);
|
|
26618
|
+
const b = Math.round(hi);
|
|
26619
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return null;
|
|
26620
|
+
if (b - a + 1 > cap) return null;
|
|
26621
|
+
const out = [];
|
|
26622
|
+
for (let i = a; i <= b; i++) out.push(i);
|
|
26623
|
+
return out;
|
|
26624
|
+
}
|
|
26625
|
+
function enumerateInteger2(a, b, f) {
|
|
26626
|
+
const xs = integerPoints(a.lo, a.hi, MAX_INT_ENUM_POINTS);
|
|
26627
|
+
const ys = integerPoints(b.lo, b.hi, MAX_INT_ENUM_POINTS);
|
|
26628
|
+
if (!xs || !ys || xs.length * ys.length > MAX_INT_ENUM_POINTS) return null;
|
|
26629
|
+
let lo = Infinity;
|
|
26630
|
+
let hi = -Infinity;
|
|
26631
|
+
for (const x of xs)
|
|
26632
|
+
for (const y of ys) {
|
|
26633
|
+
const v = f(x, y);
|
|
26634
|
+
if (Number.isFinite(v)) {
|
|
26635
|
+
if (v < lo) lo = v;
|
|
26636
|
+
if (v > hi) hi = v;
|
|
26637
|
+
}
|
|
26638
|
+
}
|
|
26639
|
+
if (lo === Infinity) return null;
|
|
26640
|
+
return ok({ lo, hi });
|
|
26641
|
+
}
|
|
24781
26642
|
function binomial(n, k) {
|
|
24782
26643
|
const uN = unwrapOrPropagate(n);
|
|
24783
26644
|
if (!Array.isArray(uN)) return uN;
|
|
@@ -24785,13 +26646,10 @@ function binomial(n, k) {
|
|
|
24785
26646
|
if (!Array.isArray(uK)) return uK;
|
|
24786
26647
|
const [nVal] = uN;
|
|
24787
26648
|
const [kVal] = uK;
|
|
24788
|
-
const
|
|
24789
|
-
|
|
24790
|
-
|
|
24791
|
-
|
|
24792
|
-
choose(Math.round(nVal.hi), Math.round(kVal.hi))
|
|
24793
|
-
];
|
|
24794
|
-
return ok({ lo: Math.min(...vals), hi: Math.max(...vals) });
|
|
26649
|
+
const enumerated = enumerateInteger2(nVal, kVal, choose);
|
|
26650
|
+
if (enumerated) return enumerated;
|
|
26651
|
+
const nMax = Math.round(nVal.hi);
|
|
26652
|
+
return ok({ lo: 0, hi: choose(nMax, Math.floor(nMax / 2)) });
|
|
24795
26653
|
}
|
|
24796
26654
|
function gcd3(a, b) {
|
|
24797
26655
|
const uA = unwrapOrPropagate(a);
|
|
@@ -24800,13 +26658,15 @@ function gcd3(a, b) {
|
|
|
24800
26658
|
if (!Array.isArray(uB)) return uB;
|
|
24801
26659
|
const [aVal] = uA;
|
|
24802
26660
|
const [bVal] = uB;
|
|
24803
|
-
const
|
|
24804
|
-
|
|
24805
|
-
|
|
24806
|
-
|
|
24807
|
-
|
|
24808
|
-
|
|
24809
|
-
|
|
26661
|
+
const enumerated = enumerateInteger2(aVal, bVal, gcd);
|
|
26662
|
+
if (enumerated) return enumerated;
|
|
26663
|
+
const m = Math.max(
|
|
26664
|
+
Math.abs(Math.round(aVal.lo)),
|
|
26665
|
+
Math.abs(Math.round(aVal.hi)),
|
|
26666
|
+
Math.abs(Math.round(bVal.lo)),
|
|
26667
|
+
Math.abs(Math.round(bVal.hi))
|
|
26668
|
+
);
|
|
26669
|
+
return ok({ lo: 0, hi: m });
|
|
24810
26670
|
}
|
|
24811
26671
|
function lcm3(a, b) {
|
|
24812
26672
|
const uA = unwrapOrPropagate(a);
|
|
@@ -24815,13 +26675,11 @@ function lcm3(a, b) {
|
|
|
24815
26675
|
if (!Array.isArray(uB)) return uB;
|
|
24816
26676
|
const [aVal] = uA;
|
|
24817
26677
|
const [bVal] = uB;
|
|
24818
|
-
const
|
|
24819
|
-
|
|
24820
|
-
|
|
24821
|
-
|
|
24822
|
-
|
|
24823
|
-
];
|
|
24824
|
-
return ok({ lo: Math.min(...vals), hi: Math.max(...vals) });
|
|
26678
|
+
const enumerated = enumerateInteger2(aVal, bVal, lcm);
|
|
26679
|
+
if (enumerated) return enumerated;
|
|
26680
|
+
const ma = Math.max(Math.abs(Math.round(aVal.lo)), Math.abs(Math.round(aVal.hi)));
|
|
26681
|
+
const mb = Math.max(Math.abs(Math.round(bVal.lo)), Math.abs(Math.round(bVal.hi)));
|
|
26682
|
+
return ok({ lo: 0, hi: ma * mb });
|
|
24825
26683
|
}
|
|
24826
26684
|
function chop2(x) {
|
|
24827
26685
|
const unwrapped = unwrapOrPropagate(x);
|
|
@@ -25213,7 +27071,6 @@ var SINC_EXTREMA = [
|
|
|
25213
27071
|
29.8116,
|
|
25214
27072
|
32.95639
|
|
25215
27073
|
];
|
|
25216
|
-
var SINC_GLOBAL_LO = -0.21724;
|
|
25217
27074
|
function sinc2(x) {
|
|
25218
27075
|
const unwrapped = unwrapOrPropagate(x);
|
|
25219
27076
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -25234,8 +27091,14 @@ function sinc2(x) {
|
|
|
25234
27091
|
if (e >= xVal.lo && e <= xVal.hi) update(sincVal(e));
|
|
25235
27092
|
if (-e >= xVal.lo && -e <= xVal.hi) update(sincVal(-e));
|
|
25236
27093
|
}
|
|
25237
|
-
|
|
25238
|
-
|
|
27094
|
+
let minBeyondAbs = Infinity;
|
|
27095
|
+
if (xVal.hi > lastExtremum)
|
|
27096
|
+
minBeyondAbs = Math.min(minBeyondAbs, Math.max(xVal.lo, lastExtremum));
|
|
27097
|
+
if (xVal.lo < -lastExtremum)
|
|
27098
|
+
minBeyondAbs = Math.min(minBeyondAbs, -Math.min(xVal.hi, -lastExtremum));
|
|
27099
|
+
if (Number.isFinite(minBeyondAbs) && minBeyondAbs > 0) {
|
|
27100
|
+
update(1 / minBeyondAbs);
|
|
27101
|
+
update(-1 / minBeyondAbs);
|
|
25239
27102
|
}
|
|
25240
27103
|
return ok({ lo, hi });
|
|
25241
27104
|
}
|
|
@@ -25261,8 +27124,21 @@ function fresnelS2(x) {
|
|
|
25261
27124
|
if (e >= xVal.lo && e <= xVal.hi) update(fresnelS(e));
|
|
25262
27125
|
if (-e >= xVal.lo && -e <= xVal.hi) update(fresnelS(-e));
|
|
25263
27126
|
}
|
|
27127
|
+
fresnelConvergenceBound(xVal, FRESNEL_S_EXTREMA, fresnelS, update);
|
|
25264
27128
|
return ok({ lo, hi });
|
|
25265
27129
|
}
|
|
27130
|
+
function fresnelConvergenceBound(xVal, extrema, scalar, update) {
|
|
27131
|
+
const lastE = extrema[extrema.length - 1];
|
|
27132
|
+
const amp = Math.abs(scalar(lastE) - 0.5);
|
|
27133
|
+
if (xVal.hi > lastE) {
|
|
27134
|
+
update(0.5 + amp);
|
|
27135
|
+
update(0.5 - amp);
|
|
27136
|
+
}
|
|
27137
|
+
if (xVal.lo < -lastE) {
|
|
27138
|
+
update(-0.5 - amp);
|
|
27139
|
+
update(-0.5 + amp);
|
|
27140
|
+
}
|
|
27141
|
+
}
|
|
25266
27142
|
function fresnelC2(x) {
|
|
25267
27143
|
const unwrapped = unwrapOrPropagate(x);
|
|
25268
27144
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
@@ -25279,6 +27155,7 @@ function fresnelC2(x) {
|
|
|
25279
27155
|
if (e >= xVal.lo && e <= xVal.hi) update(fresnelC(e));
|
|
25280
27156
|
if (-e >= xVal.lo && -e <= xVal.hi) update(fresnelC(-e));
|
|
25281
27157
|
}
|
|
27158
|
+
fresnelConvergenceBound(xVal, FRESNEL_C_EXTREMA, fresnelC, update);
|
|
25282
27159
|
return ok({ lo, hi });
|
|
25283
27160
|
}
|
|
25284
27161
|
|
|
@@ -25386,11 +27263,9 @@ function clamp(x, lo, hi) {
|
|
|
25386
27263
|
const unwrapped = unwrapOrPropagate(x, lo, hi);
|
|
25387
27264
|
if (!Array.isArray(unwrapped)) return unwrapped;
|
|
25388
27265
|
const [xVal, loVal, hiVal] = unwrapped;
|
|
25389
|
-
const
|
|
25390
|
-
const
|
|
25391
|
-
|
|
25392
|
-
return { kind: "empty" };
|
|
25393
|
-
}
|
|
27266
|
+
const lowered = { lo: Math.max(xVal.lo, loVal.lo), hi: Math.max(xVal.hi, loVal.hi) };
|
|
27267
|
+
const resultLo = Math.min(lowered.lo, hiVal.lo);
|
|
27268
|
+
const resultHi = Math.min(lowered.hi, hiVal.hi);
|
|
25394
27269
|
return { kind: "interval", value: { lo: resultLo, hi: resultHi } };
|
|
25395
27270
|
}
|
|
25396
27271
|
|
|
@@ -25723,7 +27598,7 @@ function extractIntervalLimits(limitsExpr) {
|
|
|
25723
27598
|
function compileIntervalBound(expr, numVal, target) {
|
|
25724
27599
|
if (numVal !== void 0) return String(numVal);
|
|
25725
27600
|
const compiled = BaseCompiler.compile(expr, target);
|
|
25726
|
-
return `Math.floor((${compiled})
|
|
27601
|
+
return `Math.floor(((_b) => (_b && _b.value ? _b.value.hi : _b.hi))(${compiled}))`;
|
|
25727
27602
|
}
|
|
25728
27603
|
function compileIntervalSumProduct(kind, args, _compile, target) {
|
|
25729
27604
|
if (!args[0]) throw new Error(`${kind}: no body`);
|
|
@@ -25909,7 +27784,7 @@ function compileToIntervalTarget(expr, target) {
|
|
|
25909
27784
|
}
|
|
25910
27785
|
|
|
25911
27786
|
// src/compile.ts
|
|
25912
|
-
var version = "0.
|
|
27787
|
+
var version = "0.59.0";
|
|
25913
27788
|
export {
|
|
25914
27789
|
BaseCompiler,
|
|
25915
27790
|
GLSLTarget,
|