@cortex-js/compute-engine 0.56.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compile.esm.js +1137 -92
- package/dist/compile.min.esm.js +261 -61
- package/dist/compile.min.umd.cjs +262 -62
- package/dist/compile.umd.cjs +1137 -92
- package/dist/compute-engine.esm.js +1751 -176
- package/dist/compute-engine.min.esm.js +273 -73
- package/dist/compute-engine.min.umd.cjs +272 -72
- package/dist/compute-engine.umd.cjs +1751 -176
- package/dist/core.esm.js +1750 -175
- package/dist/core.min.esm.js +271 -71
- package/dist/core.min.umd.cjs +271 -71
- package/dist/core.umd.cjs +1750 -175
- package/dist/interval.esm.js +357 -28
- package/dist/interval.min.esm.js +6 -6
- package/dist/interval.min.umd.cjs +6 -6
- package/dist/interval.umd.cjs +357 -28
- package/dist/latex-syntax.esm.js +398 -28
- package/dist/latex-syntax.min.esm.js +6 -6
- package/dist/latex-syntax.min.umd.cjs +6 -6
- package/dist/latex-syntax.umd.cjs +398 -28
- package/dist/math-json.esm.js +2 -2
- package/dist/math-json.min.esm.js +2 -2
- package/dist/math-json.min.umd.cjs +2 -2
- package/dist/math-json.umd.cjs +2 -2
- package/dist/numerics.esm.js +38 -3
- package/dist/numerics.min.esm.js +3 -3
- package/dist/numerics.min.umd.cjs +4 -4
- package/dist/numerics.umd.cjs +38 -3
- 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 -1
- package/dist/types/common/type/parser.d.ts +1 -1
- package/dist/types/common/type/primitive.d.ts +1 -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 +1 -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 +1 -1
- package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +8 -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 +1 -1
- 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/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 +22 -10
- 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/rules.d.ts +1 -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 +62 -6
- package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
- package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
- package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/gpu-target.d.ts +44 -1
- package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
- 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 +1 -1
- 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/global-types.d.ts +1 -1
- package/dist/types/compute-engine/index.d.ts +18 -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 +1 -1
- package/dist/types/compute-engine/interval/index.d.ts +1 -1
- 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 +1 -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 +1 -1
- 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 -1
- 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 +40 -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 +5 -3
- 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 +1 -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 +1 -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 +1 -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/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 +1 -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 +1 -1
- 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 +1 -1
- package/dist/types/compute-engine/types-definitions.d.ts +1 -1
- package/dist/types/compute-engine/types-engine.d.ts +51 -1
- package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-expression.d.ts +69 -1
- package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
- 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/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 +1 -1
package/dist/compile.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 0.58.0 */
|
|
2
2
|
|
|
3
3
|
// src/compute-engine/numerics/richardson.ts
|
|
4
4
|
function extrapolate(f, x0, options = {}) {
|
|
@@ -3535,7 +3535,42 @@ function widen2(a, b) {
|
|
|
3535
3535
|
if (b === "nothing") return a;
|
|
3536
3536
|
if (isSubtype(a, b)) return b;
|
|
3537
3537
|
if (isSubtype(b, a)) return a;
|
|
3538
|
-
|
|
3538
|
+
const sup = superType(a, b);
|
|
3539
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
3540
|
+
return sup;
|
|
3541
|
+
}
|
|
3542
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
3543
|
+
"scalar",
|
|
3544
|
+
"value",
|
|
3545
|
+
"function",
|
|
3546
|
+
"expression",
|
|
3547
|
+
"collection",
|
|
3548
|
+
"indexed_collection",
|
|
3549
|
+
"list",
|
|
3550
|
+
"set",
|
|
3551
|
+
"tuple",
|
|
3552
|
+
"record",
|
|
3553
|
+
"dictionary",
|
|
3554
|
+
"map",
|
|
3555
|
+
"any"
|
|
3556
|
+
]);
|
|
3557
|
+
function unionTypes(a, b) {
|
|
3558
|
+
const members = [];
|
|
3559
|
+
const push = (t) => {
|
|
3560
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
3561
|
+
for (const m of t.types) push(m);
|
|
3562
|
+
return;
|
|
3563
|
+
}
|
|
3564
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
3565
|
+
if (!members.some(
|
|
3566
|
+
(m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
|
|
3567
|
+
))
|
|
3568
|
+
members.push(t);
|
|
3569
|
+
};
|
|
3570
|
+
push(a);
|
|
3571
|
+
push(b);
|
|
3572
|
+
if (members.length === 1) return members[0];
|
|
3573
|
+
return { kind: "union", types: members };
|
|
3539
3574
|
}
|
|
3540
3575
|
function narrow(...types) {
|
|
3541
3576
|
if (types.length === 0) return "nothing";
|
|
@@ -3609,7 +3644,7 @@ function collectionElementType(type) {
|
|
|
3609
3644
|
if (type.kind === "set") return type.elements;
|
|
3610
3645
|
if (type.kind === "tuple") return widen(...type.elements.map((x) => x.type));
|
|
3611
3646
|
if (type.kind === "dictionary")
|
|
3612
|
-
return parseType(`tuple<string, ${type.values}>`);
|
|
3647
|
+
return parseType(`tuple<string, ${typeToString(type.values)}>`);
|
|
3613
3648
|
if (type.kind === "record") {
|
|
3614
3649
|
return parseType(
|
|
3615
3650
|
`tuple<string, ${typeToString(widen(...Object.values(type.elements)))}>`
|
|
@@ -5178,6 +5213,64 @@ function parseQuantifier(kind) {
|
|
|
5178
5213
|
}
|
|
5179
5214
|
|
|
5180
5215
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
5216
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
5217
|
+
x: "First",
|
|
5218
|
+
y: "Second",
|
|
5219
|
+
z: "Third",
|
|
5220
|
+
real: "Real",
|
|
5221
|
+
re: "Real",
|
|
5222
|
+
imag: "Imaginary",
|
|
5223
|
+
im: "Imaginary",
|
|
5224
|
+
count: "Length",
|
|
5225
|
+
total: "Sum",
|
|
5226
|
+
max: "Max",
|
|
5227
|
+
min: "Min"
|
|
5228
|
+
};
|
|
5229
|
+
function memberHead(name) {
|
|
5230
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
5231
|
+
}
|
|
5232
|
+
function parseComponentAccess(parser, lhs) {
|
|
5233
|
+
parser.skipVisualSpace();
|
|
5234
|
+
if (parser.match("\\operatorname")) {
|
|
5235
|
+
const name = parser.parseStringGroup();
|
|
5236
|
+
if (name === null) return null;
|
|
5237
|
+
const head = memberHead(name.trim());
|
|
5238
|
+
if (head === null) return null;
|
|
5239
|
+
return [head, lhs];
|
|
5240
|
+
}
|
|
5241
|
+
const tok = parser.peek;
|
|
5242
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
5243
|
+
const bare = tok.slice(1);
|
|
5244
|
+
const head = memberHead(bare);
|
|
5245
|
+
if (head !== null) {
|
|
5246
|
+
parser.nextToken();
|
|
5247
|
+
return [head, lhs];
|
|
5248
|
+
}
|
|
5249
|
+
return null;
|
|
5250
|
+
}
|
|
5251
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
5252
|
+
const head = memberHead(tok);
|
|
5253
|
+
if (head === null) return null;
|
|
5254
|
+
parser.nextToken();
|
|
5255
|
+
return [head, lhs];
|
|
5256
|
+
}
|
|
5257
|
+
return null;
|
|
5258
|
+
}
|
|
5259
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
5260
|
+
parser.addBoundary(close);
|
|
5261
|
+
parser.skipVisualSpace();
|
|
5262
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
5263
|
+
if (cond === null) {
|
|
5264
|
+
parser.removeBoundary();
|
|
5265
|
+
return null;
|
|
5266
|
+
}
|
|
5267
|
+
parser.skipVisualSpace();
|
|
5268
|
+
if (!parser.matchBoundary()) {
|
|
5269
|
+
parser.removeBoundary();
|
|
5270
|
+
return null;
|
|
5271
|
+
}
|
|
5272
|
+
return ["When", lhs, cond];
|
|
5273
|
+
}
|
|
5181
5274
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
5182
5275
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
5183
5276
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -5453,15 +5546,16 @@ var DEFINITIONS_CORE = [
|
|
|
5453
5546
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
5454
5547
|
parse: parseAssign
|
|
5455
5548
|
},
|
|
5456
|
-
// General colon operator (type annotation, mapping notation)
|
|
5457
|
-
// Precedence below
|
|
5458
|
-
// and below arrows (270) so
|
|
5549
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
5550
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
5551
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
5552
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
5459
5553
|
{
|
|
5460
5554
|
name: "Colon",
|
|
5461
5555
|
latexTrigger: ":",
|
|
5462
5556
|
kind: "infix",
|
|
5463
5557
|
associativity: "right",
|
|
5464
|
-
precedence:
|
|
5558
|
+
precedence: 240,
|
|
5465
5559
|
serialize: (serializer, expr) => joinLatex([
|
|
5466
5560
|
serializer.serialize(operand(expr, 1)),
|
|
5467
5561
|
"\\colon",
|
|
@@ -5472,7 +5566,7 @@ var DEFINITIONS_CORE = [
|
|
|
5472
5566
|
latexTrigger: "\\colon",
|
|
5473
5567
|
kind: "infix",
|
|
5474
5568
|
associativity: "right",
|
|
5475
|
-
precedence:
|
|
5569
|
+
precedence: 240,
|
|
5476
5570
|
parse: "Colon"
|
|
5477
5571
|
},
|
|
5478
5572
|
{
|
|
@@ -5649,6 +5743,15 @@ var DEFINITIONS_CORE = [
|
|
|
5649
5743
|
}
|
|
5650
5744
|
},
|
|
5651
5745
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
5746
|
+
// Component-access postfix: expr.member (C3)
|
|
5747
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
5748
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
5749
|
+
{
|
|
5750
|
+
kind: "postfix",
|
|
5751
|
+
precedence: 850,
|
|
5752
|
+
latexTrigger: ["."],
|
|
5753
|
+
parse: parseComponentAccess
|
|
5754
|
+
},
|
|
5652
5755
|
{
|
|
5653
5756
|
name: "At",
|
|
5654
5757
|
kind: "postfix",
|
|
@@ -5669,6 +5772,29 @@ var DEFINITIONS_CORE = [
|
|
|
5669
5772
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
5670
5773
|
parse: parseAt("\\right", "\\rbrack")
|
|
5671
5774
|
},
|
|
5775
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
5776
|
+
{
|
|
5777
|
+
name: "When",
|
|
5778
|
+
kind: "postfix",
|
|
5779
|
+
precedence: 800,
|
|
5780
|
+
latexTrigger: ["\\left", "\\{"],
|
|
5781
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
5782
|
+
serialize: (serializer, expr) => {
|
|
5783
|
+
const e = operand(expr, 1);
|
|
5784
|
+
const cond = operand(expr, 2);
|
|
5785
|
+
if (!e || !cond) return "";
|
|
5786
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
5787
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
5788
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
5789
|
+
}
|
|
5790
|
+
},
|
|
5791
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
5792
|
+
{
|
|
5793
|
+
kind: "postfix",
|
|
5794
|
+
precedence: 800,
|
|
5795
|
+
latexTrigger: ["\\{"],
|
|
5796
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
5797
|
+
},
|
|
5672
5798
|
{
|
|
5673
5799
|
kind: "postfix",
|
|
5674
5800
|
latexTrigger: ["_"],
|
|
@@ -5751,6 +5877,29 @@ var DEFINITIONS_CORE = [
|
|
|
5751
5877
|
return "";
|
|
5752
5878
|
}
|
|
5753
5879
|
},
|
|
5880
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
5881
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
5882
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
5883
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
5884
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
5885
|
+
{
|
|
5886
|
+
latexTrigger: [".", ".", "."],
|
|
5887
|
+
kind: "infix",
|
|
5888
|
+
precedence: 800,
|
|
5889
|
+
parse: parseRange
|
|
5890
|
+
},
|
|
5891
|
+
{
|
|
5892
|
+
latexTrigger: ["\\ldots"],
|
|
5893
|
+
kind: "infix",
|
|
5894
|
+
precedence: 800,
|
|
5895
|
+
parse: parseRange
|
|
5896
|
+
},
|
|
5897
|
+
{
|
|
5898
|
+
latexTrigger: ["\\dots"],
|
|
5899
|
+
kind: "infix",
|
|
5900
|
+
precedence: 800,
|
|
5901
|
+
parse: parseRange
|
|
5902
|
+
},
|
|
5754
5903
|
{
|
|
5755
5904
|
latexTrigger: [";"],
|
|
5756
5905
|
kind: "infix",
|
|
@@ -5935,13 +6084,24 @@ var DEFINITIONS_CORE = [
|
|
|
5935
6084
|
const args = operands(expr);
|
|
5936
6085
|
if (!args || args.length < 2) return "";
|
|
5937
6086
|
const body = args[0];
|
|
5938
|
-
const
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
6087
|
+
const elements = args.slice(1);
|
|
6088
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
6089
|
+
if (!allElements) {
|
|
6090
|
+
return joinLatex([
|
|
6091
|
+
"\\operatorname{Loop}(",
|
|
6092
|
+
serializer.serialize(body),
|
|
6093
|
+
", ",
|
|
6094
|
+
serializer.serialize(elements[0]),
|
|
6095
|
+
")"
|
|
6096
|
+
]);
|
|
6097
|
+
}
|
|
6098
|
+
if (elements.length === 1) {
|
|
6099
|
+
const elem = elements[0];
|
|
6100
|
+
const index = operand(elem, 1);
|
|
6101
|
+
const coll = operand(elem, 2);
|
|
6102
|
+
if (operator(coll) === "Range") {
|
|
6103
|
+
const lo = operand(coll, 1);
|
|
6104
|
+
const hi = operand(coll, 2);
|
|
5945
6105
|
return joinLatex([
|
|
5946
6106
|
"\\text{for }",
|
|
5947
6107
|
serializer.serialize(index),
|
|
@@ -5953,13 +6113,27 @@ var DEFINITIONS_CORE = [
|
|
|
5953
6113
|
serializer.serialize(body)
|
|
5954
6114
|
]);
|
|
5955
6115
|
}
|
|
6116
|
+
return joinLatex([
|
|
6117
|
+
serializer.serialize(body),
|
|
6118
|
+
" \\operatorname{for} ",
|
|
6119
|
+
serializer.serialize(index),
|
|
6120
|
+
" = ",
|
|
6121
|
+
serializer.serialize(coll)
|
|
6122
|
+
]);
|
|
5956
6123
|
}
|
|
6124
|
+
const bindings = elements.map((elem) => {
|
|
6125
|
+
const name = operand(elem, 1);
|
|
6126
|
+
const coll = operand(elem, 2);
|
|
6127
|
+
return joinLatex([
|
|
6128
|
+
serializer.serialize(name),
|
|
6129
|
+
" = ",
|
|
6130
|
+
serializer.serialize(coll)
|
|
6131
|
+
]);
|
|
6132
|
+
}).join(", ");
|
|
5957
6133
|
return joinLatex([
|
|
5958
|
-
"\\operatorname{Loop}(",
|
|
5959
6134
|
serializer.serialize(body),
|
|
5960
|
-
"
|
|
5961
|
-
|
|
5962
|
-
")"
|
|
6135
|
+
" \\operatorname{for} ",
|
|
6136
|
+
bindings
|
|
5963
6137
|
]);
|
|
5964
6138
|
}
|
|
5965
6139
|
},
|
|
@@ -5992,6 +6166,18 @@ var DEFINITIONS_CORE = [
|
|
|
5992
6166
|
precedence: 245,
|
|
5993
6167
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
5994
6168
|
},
|
|
6169
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
6170
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
6171
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
6172
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
6173
|
+
// bindings can be comma-separated below us.
|
|
6174
|
+
{
|
|
6175
|
+
symbolTrigger: "for",
|
|
6176
|
+
kind: "infix",
|
|
6177
|
+
associativity: "none",
|
|
6178
|
+
precedence: 19,
|
|
6179
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
6180
|
+
},
|
|
5995
6181
|
// \operatorname{break}
|
|
5996
6182
|
{
|
|
5997
6183
|
symbolTrigger: "break",
|
|
@@ -6196,7 +6382,10 @@ var DEFINITIONS_CORE = [
|
|
|
6196
6382
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
6197
6383
|
parser.addBoundary([")"]);
|
|
6198
6384
|
const expr = parser.parseExpression(until);
|
|
6199
|
-
if (!parser.matchBoundary())
|
|
6385
|
+
if (!parser.matchBoundary()) {
|
|
6386
|
+
parser.removeBoundary();
|
|
6387
|
+
return null;
|
|
6388
|
+
}
|
|
6200
6389
|
if (!parser.match("<}>")) return null;
|
|
6201
6390
|
return ["Derivative", lhs, expr];
|
|
6202
6391
|
}
|
|
@@ -6637,7 +6826,12 @@ function parseBrackets(parser, body) {
|
|
|
6637
6826
|
if (isEmptySequence(body)) return ["List"];
|
|
6638
6827
|
const h = operator(body);
|
|
6639
6828
|
if (h === "Range" || h === "Linspace") return body;
|
|
6640
|
-
if (h === "Sequence")
|
|
6829
|
+
if (h === "Sequence") {
|
|
6830
|
+
const elems = operands(body);
|
|
6831
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6832
|
+
if (inferred) return inferred;
|
|
6833
|
+
return ["List", ...elems];
|
|
6834
|
+
}
|
|
6641
6835
|
if (h === "Delimiter") {
|
|
6642
6836
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
6643
6837
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -6650,12 +6844,37 @@ function parseBrackets(parser, body) {
|
|
|
6650
6844
|
}
|
|
6651
6845
|
if (delim === "," || delim === ".,.") {
|
|
6652
6846
|
body = operand(body, 1);
|
|
6653
|
-
if (operator(body) === "Sequence")
|
|
6847
|
+
if (operator(body) === "Sequence") {
|
|
6848
|
+
const elems = operands(body);
|
|
6849
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6850
|
+
if (inferred) return inferred;
|
|
6851
|
+
return ["List", ...elems];
|
|
6852
|
+
}
|
|
6654
6853
|
return ["List", body ?? "Nothing"];
|
|
6655
6854
|
}
|
|
6656
6855
|
}
|
|
6657
6856
|
return ["List", body];
|
|
6658
6857
|
}
|
|
6858
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
6859
|
+
if (elems.length < 4) return null;
|
|
6860
|
+
const penultimate = elems[elems.length - 2];
|
|
6861
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
6862
|
+
const samples = elems.slice(0, -2);
|
|
6863
|
+
const endExpr = elems[elems.length - 1];
|
|
6864
|
+
if (samples.length < 2) return null;
|
|
6865
|
+
const sampleNums = samples.map(machineValue);
|
|
6866
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
6867
|
+
const nums = sampleNums;
|
|
6868
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
6869
|
+
const tol = parser.options.tolerance;
|
|
6870
|
+
if (Math.abs(step) < tol)
|
|
6871
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
6872
|
+
for (let i = 1; i < nums.length; i++) {
|
|
6873
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
6874
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
6875
|
+
}
|
|
6876
|
+
return ["Range", nums[0], endExpr, step];
|
|
6877
|
+
}
|
|
6659
6878
|
function serializeList(serializer, expr) {
|
|
6660
6879
|
if (nops(expr) > 1 && operands(expr).every((x) => {
|
|
6661
6880
|
const op = operator(x);
|
|
@@ -6907,6 +7126,38 @@ function parseForExpression(parser, until) {
|
|
|
6907
7126
|
["Element", index, ["Range", lower, upper]]
|
|
6908
7127
|
];
|
|
6909
7128
|
}
|
|
7129
|
+
function parseForComprehension(parser, lhs, until) {
|
|
7130
|
+
const bindingTerminator = {
|
|
7131
|
+
minPrec: 21,
|
|
7132
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
7133
|
+
condition: (p) => {
|
|
7134
|
+
if (until?.condition?.(p)) return true;
|
|
7135
|
+
const saved = p.index;
|
|
7136
|
+
p.skipVisualSpace();
|
|
7137
|
+
const isComma = p.peek === ",";
|
|
7138
|
+
p.index = saved;
|
|
7139
|
+
if (isComma) return true;
|
|
7140
|
+
if (peekKeyword(p, "where")) return true;
|
|
7141
|
+
if (peekKeyword(p, "with")) return true;
|
|
7142
|
+
return false;
|
|
7143
|
+
}
|
|
7144
|
+
};
|
|
7145
|
+
const elements = [];
|
|
7146
|
+
do {
|
|
7147
|
+
parser.skipVisualSpace();
|
|
7148
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
7149
|
+
if (binding === null) break;
|
|
7150
|
+
const op = operator(binding);
|
|
7151
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
7152
|
+
const name = operand(binding, 1);
|
|
7153
|
+
const list = operand(binding, 2);
|
|
7154
|
+
if (!name || !list) return null;
|
|
7155
|
+
elements.push(["Element", name, list]);
|
|
7156
|
+
parser.skipVisualSpace();
|
|
7157
|
+
} while (parser.match(","));
|
|
7158
|
+
if (elements.length === 0) return null;
|
|
7159
|
+
return ["Loop", lhs, ...elements];
|
|
7160
|
+
}
|
|
6910
7161
|
function parseWhereExpression(parser, lhs, until) {
|
|
6911
7162
|
const bindingTerminator = {
|
|
6912
7163
|
minPrec: 21,
|
|
@@ -6929,6 +7180,25 @@ function parseWhereExpression(parser, lhs, until) {
|
|
|
6929
7180
|
parser.skipVisualSpace();
|
|
6930
7181
|
} while (parser.match(","));
|
|
6931
7182
|
if (bindings.length === 0) return null;
|
|
7183
|
+
const forStart = parser.index;
|
|
7184
|
+
if (matchKeyword(parser, "for")) {
|
|
7185
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
7186
|
+
if (loop) {
|
|
7187
|
+
const block2 = [];
|
|
7188
|
+
for (const b of bindings) {
|
|
7189
|
+
const normalized = normalizeLocalAssign(b);
|
|
7190
|
+
if (operator(normalized) === "Assign") {
|
|
7191
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
7192
|
+
block2.push(normalized);
|
|
7193
|
+
} else {
|
|
7194
|
+
block2.push(normalized);
|
|
7195
|
+
}
|
|
7196
|
+
}
|
|
7197
|
+
block2.push(loop);
|
|
7198
|
+
return ["Block", ...block2];
|
|
7199
|
+
}
|
|
7200
|
+
parser.index = forStart;
|
|
7201
|
+
}
|
|
6932
7202
|
const block = [];
|
|
6933
7203
|
for (const b of bindings) {
|
|
6934
7204
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -7142,6 +7412,17 @@ function parseIntervalBody(body, openLeft, openRight) {
|
|
|
7142
7412
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
7143
7413
|
return ["Interval", lowerExpr, upperExpr];
|
|
7144
7414
|
}
|
|
7415
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
7416
|
+
"Less",
|
|
7417
|
+
"LessEqual",
|
|
7418
|
+
"Greater",
|
|
7419
|
+
"GreaterEqual",
|
|
7420
|
+
"Equal",
|
|
7421
|
+
"NotEqual",
|
|
7422
|
+
"And",
|
|
7423
|
+
"Or",
|
|
7424
|
+
"Not"
|
|
7425
|
+
]);
|
|
7145
7426
|
var DEFINITIONS_SETS = [
|
|
7146
7427
|
//
|
|
7147
7428
|
// Constants
|
|
@@ -7400,18 +7681,58 @@ var DEFINITIONS_SETS = [
|
|
|
7400
7681
|
closeTrigger: "}",
|
|
7401
7682
|
parse: (_parser, body) => {
|
|
7402
7683
|
if (isEmptySequence(body)) return "EmptySet";
|
|
7684
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
7685
|
+
body = operand(body, 1);
|
|
7686
|
+
}
|
|
7403
7687
|
const h = operator(body);
|
|
7404
|
-
if (h === "Divides"
|
|
7688
|
+
if (h === "Divides") {
|
|
7405
7689
|
const expr = operand(body, 1);
|
|
7406
7690
|
const condition = operand(body, 2);
|
|
7407
7691
|
if (expr !== null && condition !== null)
|
|
7408
7692
|
return ["Set", expr, ["Condition", condition]];
|
|
7409
7693
|
}
|
|
7410
|
-
if (
|
|
7411
|
-
|
|
7694
|
+
if (h === "Colon") {
|
|
7695
|
+
const lhs = operand(body, 1);
|
|
7696
|
+
const rhs = operand(body, 2);
|
|
7697
|
+
if (lhs !== null && rhs !== null) {
|
|
7698
|
+
const lhsOp = operator(lhs);
|
|
7699
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
7700
|
+
return ["Which", lhs, rhs];
|
|
7701
|
+
}
|
|
7702
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
7703
|
+
}
|
|
7704
|
+
}
|
|
7705
|
+
if (h === "Sequence") {
|
|
7706
|
+
const elements = operands(body);
|
|
7707
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
7708
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
7709
|
+
const lhs = operand(el, 1);
|
|
7710
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
7711
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
7712
|
+
});
|
|
7713
|
+
if (allPiecewise) {
|
|
7714
|
+
const whichOps = [];
|
|
7715
|
+
for (let i = 0; i < elements.length; i++) {
|
|
7716
|
+
const el = elements[i];
|
|
7717
|
+
if (operator(el) === "Colon") {
|
|
7718
|
+
const cond = operand(el, 1);
|
|
7719
|
+
const val = operand(el, 2);
|
|
7720
|
+
if (cond === null || val === null) {
|
|
7721
|
+
return ["Set", ...elements];
|
|
7722
|
+
}
|
|
7723
|
+
whichOps.push(cond, val);
|
|
7724
|
+
} else {
|
|
7725
|
+
if (i !== elements.length - 1) {
|
|
7726
|
+
return ["Set", ...elements];
|
|
7727
|
+
}
|
|
7728
|
+
whichOps.push("True", el);
|
|
7729
|
+
}
|
|
7730
|
+
}
|
|
7731
|
+
return ["Which", ...whichOps];
|
|
7732
|
+
}
|
|
7733
|
+
return ["Set", ...elements];
|
|
7412
7734
|
}
|
|
7413
|
-
|
|
7414
|
-
return ["Set", ...operands(body)];
|
|
7735
|
+
return ["Set", body];
|
|
7415
7736
|
},
|
|
7416
7737
|
serialize: (serializer, expr) => {
|
|
7417
7738
|
if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
|
|
@@ -9385,7 +9706,8 @@ function parseTrig(op) {
|
|
|
9385
9706
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
9386
9707
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
9387
9708
|
});
|
|
9388
|
-
const
|
|
9709
|
+
const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
|
|
9710
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
9389
9711
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
9390
9712
|
};
|
|
9391
9713
|
}
|
|
@@ -11508,10 +11830,17 @@ var DEFINITIONS_OTHERS = [
|
|
|
11508
11830
|
// The capitalized library entries already exist; these are pure parse
|
|
11509
11831
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11510
11832
|
// ---------------------------------------------------------------------------
|
|
11833
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
11511
11834
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11512
11835
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11513
11836
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11514
11837
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
11838
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
11839
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
11840
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
11841
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
11842
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
11843
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
11515
11844
|
// ---------------------------------------------------------------------------
|
|
11516
11845
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11517
11846
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -12702,6 +13031,15 @@ function interval(expr) {
|
|
|
12702
13031
|
return void 0;
|
|
12703
13032
|
}
|
|
12704
13033
|
|
|
13034
|
+
// src/compute-engine/numerics/random.ts
|
|
13035
|
+
function deterministicRandom(seed) {
|
|
13036
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
13037
|
+
return v - Math.floor(v);
|
|
13038
|
+
}
|
|
13039
|
+
function nextSeed(seed) {
|
|
13040
|
+
return seed + 0.6180339887498949;
|
|
13041
|
+
}
|
|
13042
|
+
|
|
12705
13043
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
12706
13044
|
function canonical(ce, xs, scope) {
|
|
12707
13045
|
if (xs.every((x) => x.isCanonical)) return xs;
|
|
@@ -12751,6 +13089,19 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12751
13089
|
indexWhere: void 0
|
|
12752
13090
|
}
|
|
12753
13091
|
},
|
|
13092
|
+
Length: {
|
|
13093
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
13094
|
+
complexity: 4e3,
|
|
13095
|
+
signature: "(any) -> integer",
|
|
13096
|
+
type: () => "integer",
|
|
13097
|
+
evaluate: ([xs], { engine }) => {
|
|
13098
|
+
if (!xs.isCollection) return void 0;
|
|
13099
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
13100
|
+
const n = xs.count;
|
|
13101
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
13102
|
+
return engine.number(n);
|
|
13103
|
+
}
|
|
13104
|
+
},
|
|
12754
13105
|
Tuple: {
|
|
12755
13106
|
description: "A fixed number of heterogeneous elements",
|
|
12756
13107
|
complexity: 8200,
|
|
@@ -12803,7 +13154,11 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12803
13154
|
//
|
|
12804
13155
|
Range: {
|
|
12805
13156
|
complexity: 8200,
|
|
12806
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
13157
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
13158
|
+
type: (ops) => {
|
|
13159
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
13160
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
13161
|
+
},
|
|
12807
13162
|
canonical: (ops, { engine: ce }) => {
|
|
12808
13163
|
if (ops.length === 0) return null;
|
|
12809
13164
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -12827,19 +13182,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12827
13182
|
const [lower, upper, step] = range(expr);
|
|
12828
13183
|
if (step === 0) return 0;
|
|
12829
13184
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
12830
|
-
return
|
|
13185
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12831
13186
|
},
|
|
12832
13187
|
contains: (expr, target) => {
|
|
12833
|
-
if (!target.type.matches("integer")) return false;
|
|
12834
13188
|
const t = target.re;
|
|
13189
|
+
if (!isFinite(t)) return false;
|
|
12835
13190
|
const [lower, upper, step] = range(expr);
|
|
12836
13191
|
if (step === 0) return false;
|
|
12837
|
-
if (step > 0)
|
|
12838
|
-
|
|
13192
|
+
if (step > 0) {
|
|
13193
|
+
if (t < lower || t > upper) return false;
|
|
13194
|
+
} else {
|
|
13195
|
+
if (t > lower || t < upper) return false;
|
|
13196
|
+
}
|
|
13197
|
+
const k = (t - lower) / step;
|
|
13198
|
+
const tol = expr.engine.tolerance;
|
|
13199
|
+
const kRounded = Math.round(k);
|
|
13200
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
12839
13201
|
},
|
|
12840
13202
|
iterator: (expr) => {
|
|
12841
13203
|
const [lower, upper, step] = range(expr);
|
|
12842
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
13204
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12843
13205
|
let index = 1;
|
|
12844
13206
|
return {
|
|
12845
13207
|
next: () => {
|
|
@@ -12857,7 +13219,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12857
13219
|
at: (expr, index) => {
|
|
12858
13220
|
if (typeof index !== "number") return void 0;
|
|
12859
13221
|
const [lower, upper, step] = range(expr);
|
|
12860
|
-
if (
|
|
13222
|
+
if (step === 0) return void 0;
|
|
13223
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
13224
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
12861
13225
|
return expr.engine.number(lower + step * (index - 1));
|
|
12862
13226
|
},
|
|
12863
13227
|
indexWhere: void 0,
|
|
@@ -12882,7 +13246,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12882
13246
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
12883
13247
|
return lower >= upper ? "positive" : "negative";
|
|
12884
13248
|
},
|
|
12885
|
-
elttype: (
|
|
13249
|
+
elttype: (expr) => {
|
|
13250
|
+
if (!isFunction2(expr)) return "finite_integer";
|
|
13251
|
+
for (let i = 1; i <= expr.nops; i++) {
|
|
13252
|
+
if (!expr[`op${i}`].isInteger) return "finite_real";
|
|
13253
|
+
}
|
|
13254
|
+
return "finite_integer";
|
|
13255
|
+
}
|
|
12886
13256
|
}
|
|
12887
13257
|
},
|
|
12888
13258
|
Interval: {
|
|
@@ -12985,10 +13355,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12985
13355
|
const upper = expr.op2.re;
|
|
12986
13356
|
let count = expr.op3.re;
|
|
12987
13357
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
13358
|
+
count = Math.floor(count);
|
|
12988
13359
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
12989
13360
|
if (index < 1 || index > count) return void 0;
|
|
13361
|
+
if (count === 1) return expr.engine.number(lower);
|
|
12990
13362
|
return expr.engine.number(
|
|
12991
|
-
lower + (upper - lower) * (index - 1) / count
|
|
13363
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
12992
13364
|
);
|
|
12993
13365
|
},
|
|
12994
13366
|
iterator: (expr) => {
|
|
@@ -13007,6 +13379,8 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13007
13379
|
!isFinite(expr.op3.re) ? DEFAULT_LINSPACE_COUNT : expr.op3.re
|
|
13008
13380
|
);
|
|
13009
13381
|
}
|
|
13382
|
+
totalCount = Math.floor(totalCount);
|
|
13383
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
13010
13384
|
let index = 1;
|
|
13011
13385
|
return {
|
|
13012
13386
|
next: () => {
|
|
@@ -13015,7 +13389,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13015
13389
|
index += 1;
|
|
13016
13390
|
return {
|
|
13017
13391
|
value: expr.engine.number(
|
|
13018
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
13392
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
13019
13393
|
),
|
|
13020
13394
|
done: false
|
|
13021
13395
|
};
|
|
@@ -13031,9 +13405,14 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13031
13405
|
if (t < lower || t > upper) return false;
|
|
13032
13406
|
let count = expr.op3.re;
|
|
13033
13407
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
13408
|
+
count = Math.floor(count);
|
|
13034
13409
|
if (count === 0) return false;
|
|
13035
|
-
|
|
13036
|
-
|
|
13410
|
+
if (count === 1) return t === lower;
|
|
13411
|
+
const step = (upper - lower) / (count - 1);
|
|
13412
|
+
const k = (t - lower) / step;
|
|
13413
|
+
const tol = expr.engine.tolerance;
|
|
13414
|
+
const kRounded = Math.round(k);
|
|
13415
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
13037
13416
|
}
|
|
13038
13417
|
}
|
|
13039
13418
|
},
|
|
@@ -13358,10 +13737,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13358
13737
|
description: [
|
|
13359
13738
|
"Access an element of an indexed collection.",
|
|
13360
13739
|
"If the index is negative, it is counted from the end.",
|
|
13361
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
13740
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
13741
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
13742
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
13362
13743
|
],
|
|
13363
13744
|
complexity: 8200,
|
|
13364
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
13745
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
13365
13746
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
13366
13747
|
evaluate: (ops, { engine: ce }) => {
|
|
13367
13748
|
let expr = ops[0];
|
|
@@ -13372,12 +13753,39 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13372
13753
|
if (!at) return void 0;
|
|
13373
13754
|
const opAtIndex = ops[index];
|
|
13374
13755
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
13375
|
-
if (s !== void 0)
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13756
|
+
if (s !== void 0) {
|
|
13757
|
+
expr = at(expr, s) ?? ce.Nothing;
|
|
13758
|
+
index += 1;
|
|
13759
|
+
continue;
|
|
13760
|
+
}
|
|
13761
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
13762
|
+
const indices = Array.from(opAtIndex.each());
|
|
13763
|
+
const isMask = indices.every((m) => {
|
|
13764
|
+
const name = sym(m);
|
|
13765
|
+
return name === "True" || name === "False";
|
|
13766
|
+
});
|
|
13767
|
+
const picked = [];
|
|
13768
|
+
if (isMask) {
|
|
13769
|
+
indices.forEach((m, i2) => {
|
|
13770
|
+
if (sym(m) !== "True") return;
|
|
13771
|
+
const v = at(expr, i2 + 1);
|
|
13772
|
+
if (v !== void 0) picked.push(v);
|
|
13773
|
+
});
|
|
13774
|
+
} else {
|
|
13775
|
+
for (const m of indices) {
|
|
13776
|
+
const k = m.re;
|
|
13777
|
+
if (!Number.isInteger(k)) return void 0;
|
|
13778
|
+
const v = at(expr, k);
|
|
13779
|
+
if (v !== void 0) picked.push(v);
|
|
13780
|
+
}
|
|
13781
|
+
}
|
|
13782
|
+
expr = ce._fn("List", picked);
|
|
13783
|
+
index += 1;
|
|
13784
|
+
continue;
|
|
13380
13785
|
}
|
|
13786
|
+
const i = opAtIndex.re;
|
|
13787
|
+
if (!Number.isInteger(i)) return void 0;
|
|
13788
|
+
expr = at(expr, i) ?? ce.Nothing;
|
|
13381
13789
|
index += 1;
|
|
13382
13790
|
}
|
|
13383
13791
|
return expr;
|
|
@@ -13388,7 +13796,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13388
13796
|
description: ["Return `n` elements from a collection."],
|
|
13389
13797
|
complexity: 8200,
|
|
13390
13798
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13391
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
13799
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13392
13800
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
13393
13801
|
if (!eager) return void 0;
|
|
13394
13802
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -13435,7 +13843,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13435
13843
|
description: ["Return the collection without the first n elements."],
|
|
13436
13844
|
complexity: 8200,
|
|
13437
13845
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13438
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
13846
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13439
13847
|
collection: {
|
|
13440
13848
|
isLazy: (_expr) => true,
|
|
13441
13849
|
count: (expr) => {
|
|
@@ -13480,15 +13888,45 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13480
13888
|
},
|
|
13481
13889
|
First: {
|
|
13482
13890
|
complexity: 8200,
|
|
13483
|
-
signature: "(
|
|
13891
|
+
signature: "(any) -> any",
|
|
13484
13892
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13485
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13893
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13894
|
+
if (!xs.isCollection)
|
|
13895
|
+
return ce.error([
|
|
13896
|
+
"incompatible-type",
|
|
13897
|
+
`'collection'`,
|
|
13898
|
+
xs.type.toString()
|
|
13899
|
+
]);
|
|
13900
|
+
return xs.at(1) ?? ce.Nothing;
|
|
13901
|
+
}
|
|
13486
13902
|
},
|
|
13487
13903
|
Second: {
|
|
13488
13904
|
complexity: 8200,
|
|
13489
|
-
signature: "(
|
|
13905
|
+
signature: "(any) -> any",
|
|
13906
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13907
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13908
|
+
if (!xs.isCollection)
|
|
13909
|
+
return ce.error([
|
|
13910
|
+
"incompatible-type",
|
|
13911
|
+
`'collection'`,
|
|
13912
|
+
xs.type.toString()
|
|
13913
|
+
]);
|
|
13914
|
+
return xs.at(2) ?? ce.Nothing;
|
|
13915
|
+
}
|
|
13916
|
+
},
|
|
13917
|
+
Third: {
|
|
13918
|
+
complexity: 8200,
|
|
13919
|
+
signature: "(any) -> any",
|
|
13490
13920
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13491
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13921
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13922
|
+
if (!xs.isCollection)
|
|
13923
|
+
return ce.error([
|
|
13924
|
+
"incompatible-type",
|
|
13925
|
+
`'collection'`,
|
|
13926
|
+
xs.type.toString()
|
|
13927
|
+
]);
|
|
13928
|
+
return xs.at(3) ?? ce.Nothing;
|
|
13929
|
+
}
|
|
13492
13930
|
},
|
|
13493
13931
|
Last: {
|
|
13494
13932
|
complexity: 8200,
|
|
@@ -13601,7 +14039,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13601
14039
|
],
|
|
13602
14040
|
complexity: 8200,
|
|
13603
14041
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
13604
|
-
type: ([xs]) => parseType(
|
|
14042
|
+
type: ([xs]) => parseType(
|
|
14043
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
14044
|
+
),
|
|
13605
14045
|
collection: {
|
|
13606
14046
|
isLazy: (_expr) => true,
|
|
13607
14047
|
count: (expr) => {
|
|
@@ -13933,16 +14373,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13933
14373
|
},
|
|
13934
14374
|
// Randomize the order of the elements in the collection.
|
|
13935
14375
|
Shuffle: {
|
|
13936
|
-
description: "Randomize the order of the elements in the collection.",
|
|
14376
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
13937
14377
|
complexity: 8200,
|
|
13938
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
14378
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
13939
14379
|
type: (ops) => ops[0].type,
|
|
13940
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
14380
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
13941
14381
|
if (!xs.isFiniteCollection) return void 0;
|
|
13942
14382
|
const data = Array.from(xs.each());
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
14383
|
+
const seed = seedOp?.re;
|
|
14384
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
14385
|
+
let s = seed;
|
|
14386
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
14387
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
14388
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
14389
|
+
s = nextSeed(s);
|
|
14390
|
+
}
|
|
14391
|
+
} else {
|
|
14392
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
14393
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
14394
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
14395
|
+
}
|
|
13946
14396
|
}
|
|
13947
14397
|
return ce.function(xs.operator, data);
|
|
13948
14398
|
}
|
|
@@ -14009,7 +14459,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14009
14459
|
if (t === "string")
|
|
14010
14460
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
14011
14461
|
return parseType(
|
|
14012
|
-
`tuple<list<${
|
|
14462
|
+
`tuple<list<${typeToString(
|
|
14463
|
+
collectionElementType(t) ?? "any"
|
|
14464
|
+
)}>, list<integer>>`
|
|
14013
14465
|
);
|
|
14014
14466
|
},
|
|
14015
14467
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -14025,7 +14477,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14025
14477
|
description: "Return a list of the unique elements of the collection.",
|
|
14026
14478
|
complexity: 8200,
|
|
14027
14479
|
signature: "(collection) -> list",
|
|
14028
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14480
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14029
14481
|
evaluate: (ops, { engine: ce }) => {
|
|
14030
14482
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
14031
14483
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -14037,7 +14489,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14037
14489
|
wikidata: "Q381060",
|
|
14038
14490
|
complexity: 8200,
|
|
14039
14491
|
signature: "(collection, integer | function) -> list",
|
|
14040
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14492
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14041
14493
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
14042
14494
|
if (!xs.isFiniteCollection) return void 0;
|
|
14043
14495
|
const k = toInteger(arg);
|
|
@@ -14211,32 +14663,74 @@ var COLLECTIONS_LIBRARY = {
|
|
|
14211
14663
|
}
|
|
14212
14664
|
}
|
|
14213
14665
|
},
|
|
14214
|
-
// Repeat(x) -> [x, x, ...]
|
|
14215
|
-
//
|
|
14216
|
-
// x is evaluated once. Although could use Hold()?
|
|
14217
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
14666
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
14667
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
14218
14668
|
Repeat: {
|
|
14219
|
-
description: "Produce
|
|
14669
|
+
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.",
|
|
14220
14670
|
complexity: 8200,
|
|
14221
|
-
signature: "(value: any) -> list",
|
|
14671
|
+
signature: "(value: any, count: integer?) -> list",
|
|
14672
|
+
evaluate: (ops, { engine }) => {
|
|
14673
|
+
if (ops.length !== 2) return void 0;
|
|
14674
|
+
const raw = toInteger(ops[1]);
|
|
14675
|
+
if (raw === null) return void 0;
|
|
14676
|
+
const n = Math.max(0, raw);
|
|
14677
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
14678
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
14679
|
+
},
|
|
14222
14680
|
collection: {
|
|
14223
|
-
isLazy: (
|
|
14224
|
-
count: () =>
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14681
|
+
isLazy: (expr) => isFunction2(expr) && expr.ops?.length === 1,
|
|
14682
|
+
count: (expr) => {
|
|
14683
|
+
if (!isFunction2(expr)) return void 0;
|
|
14684
|
+
if (expr.ops?.length === 2) {
|
|
14685
|
+
const n = toInteger(expr.op2);
|
|
14686
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
14687
|
+
}
|
|
14688
|
+
return Infinity;
|
|
14689
|
+
},
|
|
14690
|
+
isEmpty: (expr) => {
|
|
14691
|
+
if (!isFunction2(expr)) return void 0;
|
|
14692
|
+
if (expr.ops?.length === 2) {
|
|
14693
|
+
const n = toInteger(expr.op2);
|
|
14694
|
+
return n !== null ? n <= 0 : void 0;
|
|
14695
|
+
}
|
|
14696
|
+
return false;
|
|
14697
|
+
},
|
|
14698
|
+
isFinite: (expr) => isFunction2(expr) && expr.ops?.length === 2,
|
|
14229
14699
|
contains: (expr, target) => {
|
|
14230
14700
|
if (!isFunction2(expr)) return false;
|
|
14701
|
+
if (expr.ops?.length === 2) {
|
|
14702
|
+
const n = toInteger(expr.op2);
|
|
14703
|
+
if (n !== null && n <= 0) return false;
|
|
14704
|
+
}
|
|
14231
14705
|
return expr.op1.isSame(target);
|
|
14232
14706
|
},
|
|
14233
14707
|
iterator: (expr) => {
|
|
14234
14708
|
if (!isFunction2(expr))
|
|
14235
14709
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14710
|
+
if (expr.ops?.length === 2) {
|
|
14711
|
+
const n = toInteger(expr.op2);
|
|
14712
|
+
if (n === null) {
|
|
14713
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
14714
|
+
}
|
|
14715
|
+
const count = Math.max(0, n);
|
|
14716
|
+
let i = 0;
|
|
14717
|
+
return {
|
|
14718
|
+
next: () => i++ < count ? { value: expr.op1, done: false } : { value: void 0, done: true }
|
|
14719
|
+
};
|
|
14720
|
+
}
|
|
14236
14721
|
return { next: () => ({ value: expr.op1, done: false }) };
|
|
14237
14722
|
},
|
|
14238
|
-
at
|
|
14723
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
14724
|
+
at: (expr, index) => {
|
|
14239
14725
|
if (!isFunction2(expr)) return void 0;
|
|
14726
|
+
if (typeof index !== "number") return void 0;
|
|
14727
|
+
if (expr.ops?.length === 2) {
|
|
14728
|
+
const n = toInteger(expr.op2);
|
|
14729
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
14730
|
+
if (index < 1 || index > count) return void 0;
|
|
14731
|
+
} else {
|
|
14732
|
+
if (index < 1) return void 0;
|
|
14733
|
+
}
|
|
14240
14734
|
return expr.op1;
|
|
14241
14735
|
}
|
|
14242
14736
|
}
|
|
@@ -14467,17 +14961,14 @@ function range(expr) {
|
|
|
14467
14961
|
if (!isFunction2(expr)) return [1, 0, 0];
|
|
14468
14962
|
if (expr.nops === 0) return [1, 0, 0];
|
|
14469
14963
|
let op1 = expr.op1.re;
|
|
14470
|
-
if (!isFinite(op1)) op1 = 1;
|
|
14471
|
-
else op1 = Math.round(op1);
|
|
14964
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
14472
14965
|
if (expr.nops === 1) return [1, op1, 1];
|
|
14473
14966
|
let op2 = expr.op2.re;
|
|
14474
14967
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
14475
|
-
|
|
14476
|
-
if (expr.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
14968
|
+
if (expr.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
14477
14969
|
let op3 = expr.op3.re;
|
|
14478
|
-
if (!isFinite(op3)) op3 = 1;
|
|
14479
|
-
|
|
14480
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
14970
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
14971
|
+
return [op1, op2, op3];
|
|
14481
14972
|
}
|
|
14482
14973
|
function canonicalList(ops, { engine: ce }) {
|
|
14483
14974
|
const op1 = ops[0];
|
|
@@ -14826,6 +15317,23 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14826
15317
|
};
|
|
14827
15318
|
return compilePair(0);
|
|
14828
15319
|
}
|
|
15320
|
+
if (h === "When") {
|
|
15321
|
+
if (args.length !== 2)
|
|
15322
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
15323
|
+
const fn2 = target.functions?.(h);
|
|
15324
|
+
if (fn2) {
|
|
15325
|
+
if (typeof fn2 === "function") {
|
|
15326
|
+
return fn2(args, (expr) => _BaseCompiler.compile(expr, target), target);
|
|
15327
|
+
}
|
|
15328
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
15329
|
+
}
|
|
15330
|
+
if (isSymbol2(args[1], "True"))
|
|
15331
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
15332
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
15333
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
15334
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
15335
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
15336
|
+
}
|
|
14829
15337
|
if (h === "Block") {
|
|
14830
15338
|
return _BaseCompiler.compileBlock(args, target);
|
|
14831
15339
|
}
|
|
@@ -14900,17 +15408,98 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14900
15408
|
)}${target.ws("\n")}})()`;
|
|
14901
15409
|
}
|
|
14902
15410
|
/**
|
|
14903
|
-
* Compile a Loop expression
|
|
14904
|
-
* Generates: (() => { for (let i = lo; i <= hi; i++) { body } })()
|
|
15411
|
+
* Compile a Loop expression.
|
|
14905
15412
|
*
|
|
14906
|
-
*
|
|
14907
|
-
*
|
|
14908
|
-
*
|
|
15413
|
+
* Two forms are supported:
|
|
15414
|
+
*
|
|
15415
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
15416
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
15417
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
15418
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
15419
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
15420
|
+
* references to the loop index inside the body are re-wrapped via
|
|
15421
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
15422
|
+
*
|
|
15423
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
15424
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
15425
|
+
* When two or more `Element` clauses are present — or when the single
|
|
15426
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
15427
|
+
* comprehension that collects results into an array. Each clause
|
|
15428
|
+
* produces a `for (const name of collection)` loop, nested
|
|
15429
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
15430
|
+
*
|
|
15431
|
+
* Example output (JS):
|
|
15432
|
+
* ```js
|
|
15433
|
+
* (() => { const result = [];
|
|
15434
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
15435
|
+
* return result; })()
|
|
15436
|
+
* ```
|
|
15437
|
+
*
|
|
15438
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
15439
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15440
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15441
|
+
* array or by unrolling when bounds are known at compile time.
|
|
15442
|
+
*
|
|
15443
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
15444
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
15445
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
15446
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
15447
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
15448
|
+
* current behavior.
|
|
14909
15449
|
*/
|
|
14910
15450
|
static compileForLoop(args, target) {
|
|
14911
15451
|
if (!args[0]) throw new Error("Loop: no body");
|
|
14912
15452
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
14913
|
-
const
|
|
15453
|
+
const body = args[0];
|
|
15454
|
+
const elements = args.slice(1);
|
|
15455
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
15456
|
+
if (useComprehension) {
|
|
15457
|
+
const lang = target.language ?? "";
|
|
15458
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
15459
|
+
throw new Error(
|
|
15460
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
15461
|
+
);
|
|
15462
|
+
}
|
|
15463
|
+
const narrowedElements = [];
|
|
15464
|
+
for (let i = 0; i < elements.length; i++) {
|
|
15465
|
+
const elem = elements[i];
|
|
15466
|
+
if (!isFunction2(elem, "Element"))
|
|
15467
|
+
throw new Error(
|
|
15468
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
15469
|
+
);
|
|
15470
|
+
if (!isSymbol2(elem.ops[0]))
|
|
15471
|
+
throw new Error(
|
|
15472
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
15473
|
+
);
|
|
15474
|
+
narrowedElements.push(elem);
|
|
15475
|
+
}
|
|
15476
|
+
const loopVarSet = new Set(
|
|
15477
|
+
narrowedElements.map(
|
|
15478
|
+
(e) => e.ops[0].symbol
|
|
15479
|
+
)
|
|
15480
|
+
);
|
|
15481
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
15482
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
15483
|
+
...target,
|
|
15484
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
15485
|
+
} : target;
|
|
15486
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
15487
|
+
let inner = `result.push(${bodyCode});`;
|
|
15488
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
15489
|
+
const elem = narrowedElements[i];
|
|
15490
|
+
const name = elem.ops[0].symbol;
|
|
15491
|
+
const collExpr = elem.ops[1];
|
|
15492
|
+
let collection;
|
|
15493
|
+
if (isFunction2(collExpr, "Range")) {
|
|
15494
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
15495
|
+
} else {
|
|
15496
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
15497
|
+
}
|
|
15498
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
15499
|
+
}
|
|
15500
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
15501
|
+
}
|
|
15502
|
+
const indexing = elements[0];
|
|
14914
15503
|
if (!isFunction2(indexing, "Element"))
|
|
14915
15504
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
14916
15505
|
const indexExpr = indexing.ops[0];
|
|
@@ -14928,13 +15517,72 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14928
15517
|
...target,
|
|
14929
15518
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
14930
15519
|
};
|
|
14931
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
15520
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
14932
15521
|
return `(() => {${target.ws(
|
|
14933
15522
|
"\n"
|
|
14934
15523
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
14935
15524
|
"\n"
|
|
14936
15525
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
14937
15526
|
}
|
|
15527
|
+
/**
|
|
15528
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
15529
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
15530
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
15531
|
+
*
|
|
15532
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
15533
|
+
* are not statically numeric we accept the Range (the historical
|
|
15534
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
15535
|
+
* left as a known limitation; callers can force the iterable path by
|
|
15536
|
+
* supplying an explicit step.
|
|
15537
|
+
*/
|
|
15538
|
+
static isLegacyCompatibleRange(coll) {
|
|
15539
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
15540
|
+
if (coll.ops.length >= 3) {
|
|
15541
|
+
const stepExpr = coll.ops[2];
|
|
15542
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
15543
|
+
}
|
|
15544
|
+
const lo = coll.ops[0];
|
|
15545
|
+
const hi = coll.ops[1];
|
|
15546
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
15547
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
15548
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
15549
|
+
return true;
|
|
15550
|
+
}
|
|
15551
|
+
/**
|
|
15552
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
15553
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
15554
|
+
* `library/collections.ts` Range:
|
|
15555
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
15556
|
+
* element = lo + step * k (0-indexed)
|
|
15557
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
15558
|
+
*
|
|
15559
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
15560
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
15561
|
+
*/
|
|
15562
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
15563
|
+
const loExpr = rangeExpr.ops[0];
|
|
15564
|
+
const hiExpr = rangeExpr.ops[1];
|
|
15565
|
+
const stepExpr = rangeExpr.ops[2];
|
|
15566
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
15567
|
+
const lo2 = loExpr.re;
|
|
15568
|
+
const hi2 = hiExpr.re;
|
|
15569
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
15570
|
+
if (step2 === 0) return "[]";
|
|
15571
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
15572
|
+
if (step2 === 1) {
|
|
15573
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
15574
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
15575
|
+
}
|
|
15576
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
15577
|
+
}
|
|
15578
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
15579
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
15580
|
+
if (stepExpr === void 0) {
|
|
15581
|
+
return `((_lo,_hi)=>{const _st=_hi>=_lo?1:-1;return Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k);})(${lo},${hi})`;
|
|
15582
|
+
}
|
|
15583
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
15584
|
+
return `((_lo,_hi,_st)=>_st===0?[]:Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k))(${lo},${hi},${step})`;
|
|
15585
|
+
}
|
|
14938
15586
|
/**
|
|
14939
15587
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
14940
15588
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -19885,6 +20533,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
19885
20533
|
return `_SYS.cexp(${compile2(args[0])})`;
|
|
19886
20534
|
return `Math.exp(${compile2(args[0])})`;
|
|
19887
20535
|
},
|
|
20536
|
+
First: (args, compile2) => `${compile2(args[0])}[0]`,
|
|
19888
20537
|
Floor: (args, compile2) => {
|
|
19889
20538
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19890
20539
|
return `Math.floor(${compile2(args[0])})`;
|
|
@@ -20043,7 +20692,20 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20043
20692
|
if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
|
|
20044
20693
|
return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
|
|
20045
20694
|
},
|
|
20046
|
-
Random:
|
|
20695
|
+
Random: (args, compile2) => {
|
|
20696
|
+
if (args.length === 0) return "Math.random()";
|
|
20697
|
+
if (args.length === 2) {
|
|
20698
|
+
const m = compile2(args[0]);
|
|
20699
|
+
const n = compile2(args[1]);
|
|
20700
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
20701
|
+
}
|
|
20702
|
+
const arg = args[0];
|
|
20703
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
20704
|
+
return `Math.floor(Math.random() * (${compile2(arg)}))`;
|
|
20705
|
+
}
|
|
20706
|
+
const a = compile2(arg);
|
|
20707
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
20708
|
+
},
|
|
20047
20709
|
Round: (args, compile2) => {
|
|
20048
20710
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20049
20711
|
return `Math.round(${compile2(args[0])})`;
|
|
@@ -20071,6 +20733,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20071
20733
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile2(arg)})`;
|
|
20072
20734
|
return `1 / Math.cosh(${compile2(arg)})`;
|
|
20073
20735
|
},
|
|
20736
|
+
Second: (args, compile2) => `${compile2(args[0])}[1]`,
|
|
20074
20737
|
Heaviside: "_SYS.heaviside",
|
|
20075
20738
|
Sign: "Math.sign",
|
|
20076
20739
|
Sinc: "_SYS.sinc",
|
|
@@ -20103,6 +20766,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20103
20766
|
return `_SYS.ctanh(${compile2(args[0])})`;
|
|
20104
20767
|
return `Math.tanh(${compile2(args[0])})`;
|
|
20105
20768
|
},
|
|
20769
|
+
Third: (args, compile2) => `${compile2(args[0])}[2]`,
|
|
20106
20770
|
Mod: ([a, b], compile2) => {
|
|
20107
20771
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
20108
20772
|
const ca = compile2(a);
|
|
@@ -21382,6 +22046,14 @@ var GPU_FUNCTIONS = {
|
|
|
21382
22046
|
return `exp(${compile2(args[0])})`;
|
|
21383
22047
|
},
|
|
21384
22048
|
Exp2: "exp2",
|
|
22049
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
22050
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
22051
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
22052
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
22053
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
22054
|
+
First: (args, compile2) => `${compile2(args[0])}.x`,
|
|
22055
|
+
Second: (args, compile2) => `${compile2(args[0])}.y`,
|
|
22056
|
+
Third: (args, compile2) => `${compile2(args[0])}.z`,
|
|
21385
22057
|
Floor: (args, compile2) => {
|
|
21386
22058
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21387
22059
|
return `floor(${compile2(args[0])})`;
|
|
@@ -21859,6 +22531,39 @@ var GPU_FUNCTIONS = {
|
|
|
21859
22531
|
// Sum/Product — unrolled or for-loop
|
|
21860
22532
|
Sum: (args, compile2, target) => compileGPUSumProduct("Sum", args, compile2, target),
|
|
21861
22533
|
Product: (args, compile2, target) => compileGPUSumProduct("Product", args, compile2, target),
|
|
22534
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
22535
|
+
Range: (args, _compile, target) => {
|
|
22536
|
+
if (args.length < 2 || args.length > 3) {
|
|
22537
|
+
throw new Error(
|
|
22538
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
22539
|
+
);
|
|
22540
|
+
}
|
|
22541
|
+
const lo = args[0].re;
|
|
22542
|
+
const hi = args[1].re;
|
|
22543
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
22544
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
22545
|
+
throw new Error(
|
|
22546
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
22547
|
+
);
|
|
22548
|
+
}
|
|
22549
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
22550
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
22551
|
+
if (count === 0) {
|
|
22552
|
+
throw new Error(
|
|
22553
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
22554
|
+
);
|
|
22555
|
+
}
|
|
22556
|
+
if (count > 256) {
|
|
22557
|
+
throw new Error(
|
|
22558
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
22559
|
+
);
|
|
22560
|
+
}
|
|
22561
|
+
const values = [];
|
|
22562
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
22563
|
+
const isWGSL = target.language === "wgsl";
|
|
22564
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
22565
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
22566
|
+
},
|
|
21862
22567
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
21863
22568
|
Loop: (args, _compile, target) => {
|
|
21864
22569
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -21887,6 +22592,134 @@ var GPU_FUNCTIONS = {
|
|
|
21887
22592
|
${bodyCode};
|
|
21888
22593
|
}`;
|
|
21889
22594
|
},
|
|
22595
|
+
// Statistical functions
|
|
22596
|
+
/**
|
|
22597
|
+
* GCD of two scalar arguments.
|
|
22598
|
+
*
|
|
22599
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
22600
|
+
* Only two-argument form is supported in GPU targets.
|
|
22601
|
+
*/
|
|
22602
|
+
GCD: (args, compile2) => {
|
|
22603
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
22604
|
+
if (args.length > 2)
|
|
22605
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
22606
|
+
const a = args[0];
|
|
22607
|
+
const b = args[1];
|
|
22608
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
22609
|
+
return `_gpu_gcd(${compile2(a)}, ${compile2(b)})`;
|
|
22610
|
+
},
|
|
22611
|
+
/**
|
|
22612
|
+
* Variance of a compile-time-known list.
|
|
22613
|
+
*
|
|
22614
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
22615
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
22616
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
22617
|
+
*/
|
|
22618
|
+
Variance: (args, compile2) => {
|
|
22619
|
+
let elems;
|
|
22620
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
22621
|
+
elems = args[0].ops;
|
|
22622
|
+
} else if (args.length >= 2) {
|
|
22623
|
+
elems = args;
|
|
22624
|
+
} else {
|
|
22625
|
+
throw new Error(
|
|
22626
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
22627
|
+
);
|
|
22628
|
+
}
|
|
22629
|
+
const n = elems.length;
|
|
22630
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
22631
|
+
const compiled = elems.map((e) => compile2(e));
|
|
22632
|
+
const sum = compiled.join(" + ");
|
|
22633
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
22634
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
22635
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
22636
|
+
},
|
|
22637
|
+
/**
|
|
22638
|
+
* Median of a compile-time-known list.
|
|
22639
|
+
*
|
|
22640
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
22641
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
22642
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
22643
|
+
*
|
|
22644
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
22645
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
22646
|
+
*/
|
|
22647
|
+
Median: (args, compile2) => {
|
|
22648
|
+
let elems;
|
|
22649
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
22650
|
+
elems = args[0].ops;
|
|
22651
|
+
} else if (args.length >= 1) {
|
|
22652
|
+
elems = args;
|
|
22653
|
+
} else {
|
|
22654
|
+
throw new Error(
|
|
22655
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
22656
|
+
);
|
|
22657
|
+
}
|
|
22658
|
+
const n = elems.length;
|
|
22659
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
22660
|
+
if (n > 8) {
|
|
22661
|
+
throw new Error(
|
|
22662
|
+
`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.`
|
|
22663
|
+
);
|
|
22664
|
+
}
|
|
22665
|
+
const compiled = elems.map((e) => compile2(e));
|
|
22666
|
+
if (n === 1) return compiled[0];
|
|
22667
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
22668
|
+
},
|
|
22669
|
+
/**
|
|
22670
|
+
* Deterministic pseudorandom for GPU.
|
|
22671
|
+
*
|
|
22672
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
22673
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
22674
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
22675
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
22676
|
+
* integer-returning operators in this target.
|
|
22677
|
+
*
|
|
22678
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
22679
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
22680
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
22681
|
+
* caller must provide an explicit seed.
|
|
22682
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
22683
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
22684
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
22685
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
22686
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
22687
|
+
*
|
|
22688
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
22689
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
22690
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
22691
|
+
* `sin` differences.
|
|
22692
|
+
*/
|
|
22693
|
+
Random: (args, compile2, target) => {
|
|
22694
|
+
if (args.length === 0) {
|
|
22695
|
+
if (target.language === "wgsl") {
|
|
22696
|
+
throw new Error(
|
|
22697
|
+
"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."
|
|
22698
|
+
);
|
|
22699
|
+
}
|
|
22700
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
22701
|
+
}
|
|
22702
|
+
if (args.length === 1) {
|
|
22703
|
+
const arg = args[0];
|
|
22704
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
22705
|
+
const compiled = compile2(arg);
|
|
22706
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
22707
|
+
}
|
|
22708
|
+
return `_gpu_random(${compile2(arg)})`;
|
|
22709
|
+
}
|
|
22710
|
+
if (args.length === 2) {
|
|
22711
|
+
if (target.language === "wgsl") {
|
|
22712
|
+
throw new Error(
|
|
22713
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
22714
|
+
);
|
|
22715
|
+
}
|
|
22716
|
+
const m = compile2(args[0]);
|
|
22717
|
+
const n = compile2(args[1]);
|
|
22718
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
22719
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
22720
|
+
}
|
|
22721
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
22722
|
+
},
|
|
21890
22723
|
// Function (lambda) — not supported in GPU
|
|
21891
22724
|
Function: () => {
|
|
21892
22725
|
throw new Error(
|
|
@@ -22486,6 +23319,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
22486
23319
|
return 1.0;
|
|
22487
23320
|
}
|
|
22488
23321
|
`;
|
|
23322
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
23323
|
+
float _gpu_gcd(float a, float b) {
|
|
23324
|
+
a = abs(a); b = abs(b);
|
|
23325
|
+
for (int i = 0; i < 32; i++) {
|
|
23326
|
+
if (b < 0.5) break;
|
|
23327
|
+
float t = mod(a, b);
|
|
23328
|
+
a = b;
|
|
23329
|
+
b = t;
|
|
23330
|
+
}
|
|
23331
|
+
return a;
|
|
23332
|
+
}
|
|
23333
|
+
`;
|
|
23334
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
23335
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
23336
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
23337
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
23338
|
+
if (b < 0.5) { break; }
|
|
23339
|
+
let t = a % b;
|
|
23340
|
+
a = b;
|
|
23341
|
+
b = t;
|
|
23342
|
+
}
|
|
23343
|
+
return a;
|
|
23344
|
+
}
|
|
23345
|
+
`;
|
|
23346
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
23347
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
23348
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
23349
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
23350
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
23351
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
23352
|
+
float _gpu_random(float seed) {
|
|
23353
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
23354
|
+
}
|
|
23355
|
+
`;
|
|
23356
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
23357
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
23358
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
23359
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
23360
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
23361
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
23362
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
23363
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
23364
|
+
}
|
|
23365
|
+
`;
|
|
23366
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
23367
|
+
float _gpu_median_2(float a, float b) {
|
|
23368
|
+
return (a + b) * 0.5;
|
|
23369
|
+
}
|
|
23370
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
23371
|
+
return max(min(a, b), min(max(a, b), c));
|
|
23372
|
+
}
|
|
23373
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
23374
|
+
float lo = max(min(a, b), min(c, d));
|
|
23375
|
+
float hi = min(max(a, b), max(c, d));
|
|
23376
|
+
return (lo + hi) * 0.5;
|
|
23377
|
+
}
|
|
23378
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
23379
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
23380
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
23381
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23382
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23383
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23384
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23385
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
23386
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23387
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
23388
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23389
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23390
|
+
return v2;
|
|
23391
|
+
}
|
|
23392
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
23393
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
23394
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23395
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23396
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23397
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23398
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23399
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23400
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23401
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23402
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23403
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23404
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23405
|
+
return (v2 + v3) * 0.5;
|
|
23406
|
+
}
|
|
23407
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
23408
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
23409
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23410
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23411
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23412
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23413
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23414
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23415
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23416
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23417
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23418
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23419
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23420
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23421
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23422
|
+
return v3;
|
|
23423
|
+
}
|
|
23424
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
23425
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
23426
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23427
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23428
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23429
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
23430
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23431
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23432
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23433
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
23434
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23435
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23436
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23437
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
23438
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23439
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23440
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
23441
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23442
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23443
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23444
|
+
return (v3 + v4) * 0.5;
|
|
23445
|
+
}
|
|
23446
|
+
`;
|
|
23447
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
23448
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
23449
|
+
return (a + b) * 0.5;
|
|
23450
|
+
}
|
|
23451
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
23452
|
+
return max(min(a, b), min(max(a, b), c));
|
|
23453
|
+
}
|
|
23454
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
23455
|
+
let lo = max(min(a, b), min(c, d));
|
|
23456
|
+
let hi = min(max(a, b), max(c, d));
|
|
23457
|
+
return (lo + hi) * 0.5;
|
|
23458
|
+
}
|
|
23459
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
23460
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
23461
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
23462
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23463
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23464
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23465
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23466
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
23467
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23468
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
23469
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23470
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23471
|
+
return v2;
|
|
23472
|
+
}
|
|
23473
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
23474
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
23475
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23476
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23477
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23478
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23479
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23480
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23481
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23482
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23483
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23484
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23485
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23486
|
+
return (v2 + v3) * 0.5;
|
|
23487
|
+
}
|
|
23488
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
23489
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
23490
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23491
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23492
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23493
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23494
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23495
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23496
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23497
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23498
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23499
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23500
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23501
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23502
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23503
|
+
return v3;
|
|
23504
|
+
}
|
|
23505
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
23506
|
+
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;
|
|
23507
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23508
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23509
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23510
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
23511
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23512
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23513
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23514
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
23515
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23516
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23517
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23518
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
23519
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23520
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23521
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
23522
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23523
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23524
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23525
|
+
return (v3 + v4) * 0.5;
|
|
23526
|
+
}
|
|
23527
|
+
`;
|
|
22489
23528
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
22490
23529
|
float _gpu_srgb_to_linear(float c) {
|
|
22491
23530
|
if (c <= 0.04045) return c / 12.92;
|
|
@@ -23163,6 +24202,12 @@ var GPUShaderTarget = class {
|
|
|
23163
24202
|
if (code.includes("_fractal_")) {
|
|
23164
24203
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
23165
24204
|
}
|
|
24205
|
+
if (code.includes("_gpu_random"))
|
|
24206
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
24207
|
+
if (code.includes("_gpu_gcd"))
|
|
24208
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
24209
|
+
if (code.includes("_gpu_median_"))
|
|
24210
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
23166
24211
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
23167
24212
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
23168
24213
|
}
|
|
@@ -25501,7 +26546,7 @@ function compileToIntervalTarget(expr, target) {
|
|
|
25501
26546
|
}
|
|
25502
26547
|
|
|
25503
26548
|
// src/compile.ts
|
|
25504
|
-
var version = "0.
|
|
26549
|
+
var version = "0.58.0";
|
|
25505
26550
|
export {
|
|
25506
26551
|
BaseCompiler,
|
|
25507
26552
|
GLSLTarget,
|