@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.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compile 0.
|
|
1
|
+
/** Compile 0.58.0 */
|
|
2
2
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Compile = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var Compile = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -3568,7 +3568,42 @@ var Compile = (() => {
|
|
|
3568
3568
|
if (b === "nothing") return a;
|
|
3569
3569
|
if (isSubtype(a, b)) return b;
|
|
3570
3570
|
if (isSubtype(b, a)) return a;
|
|
3571
|
-
|
|
3571
|
+
const sup = superType(a, b);
|
|
3572
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
3573
|
+
return sup;
|
|
3574
|
+
}
|
|
3575
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
3576
|
+
"scalar",
|
|
3577
|
+
"value",
|
|
3578
|
+
"function",
|
|
3579
|
+
"expression",
|
|
3580
|
+
"collection",
|
|
3581
|
+
"indexed_collection",
|
|
3582
|
+
"list",
|
|
3583
|
+
"set",
|
|
3584
|
+
"tuple",
|
|
3585
|
+
"record",
|
|
3586
|
+
"dictionary",
|
|
3587
|
+
"map",
|
|
3588
|
+
"any"
|
|
3589
|
+
]);
|
|
3590
|
+
function unionTypes(a, b) {
|
|
3591
|
+
const members = [];
|
|
3592
|
+
const push = (t) => {
|
|
3593
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
3594
|
+
for (const m of t.types) push(m);
|
|
3595
|
+
return;
|
|
3596
|
+
}
|
|
3597
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
3598
|
+
if (!members.some(
|
|
3599
|
+
(m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
|
|
3600
|
+
))
|
|
3601
|
+
members.push(t);
|
|
3602
|
+
};
|
|
3603
|
+
push(a);
|
|
3604
|
+
push(b);
|
|
3605
|
+
if (members.length === 1) return members[0];
|
|
3606
|
+
return { kind: "union", types: members };
|
|
3572
3607
|
}
|
|
3573
3608
|
function narrow(...types) {
|
|
3574
3609
|
if (types.length === 0) return "nothing";
|
|
@@ -3642,7 +3677,7 @@ var Compile = (() => {
|
|
|
3642
3677
|
if (type.kind === "set") return type.elements;
|
|
3643
3678
|
if (type.kind === "tuple") return widen(...type.elements.map((x) => x.type));
|
|
3644
3679
|
if (type.kind === "dictionary")
|
|
3645
|
-
return parseType(`tuple<string, ${type.values}>`);
|
|
3680
|
+
return parseType(`tuple<string, ${typeToString(type.values)}>`);
|
|
3646
3681
|
if (type.kind === "record") {
|
|
3647
3682
|
return parseType(
|
|
3648
3683
|
`tuple<string, ${typeToString(widen(...Object.values(type.elements)))}>`
|
|
@@ -5211,6 +5246,64 @@ var Compile = (() => {
|
|
|
5211
5246
|
}
|
|
5212
5247
|
|
|
5213
5248
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
5249
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
5250
|
+
x: "First",
|
|
5251
|
+
y: "Second",
|
|
5252
|
+
z: "Third",
|
|
5253
|
+
real: "Real",
|
|
5254
|
+
re: "Real",
|
|
5255
|
+
imag: "Imaginary",
|
|
5256
|
+
im: "Imaginary",
|
|
5257
|
+
count: "Length",
|
|
5258
|
+
total: "Sum",
|
|
5259
|
+
max: "Max",
|
|
5260
|
+
min: "Min"
|
|
5261
|
+
};
|
|
5262
|
+
function memberHead(name) {
|
|
5263
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
5264
|
+
}
|
|
5265
|
+
function parseComponentAccess(parser, lhs) {
|
|
5266
|
+
parser.skipVisualSpace();
|
|
5267
|
+
if (parser.match("\\operatorname")) {
|
|
5268
|
+
const name = parser.parseStringGroup();
|
|
5269
|
+
if (name === null) return null;
|
|
5270
|
+
const head = memberHead(name.trim());
|
|
5271
|
+
if (head === null) return null;
|
|
5272
|
+
return [head, lhs];
|
|
5273
|
+
}
|
|
5274
|
+
const tok = parser.peek;
|
|
5275
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
5276
|
+
const bare = tok.slice(1);
|
|
5277
|
+
const head = memberHead(bare);
|
|
5278
|
+
if (head !== null) {
|
|
5279
|
+
parser.nextToken();
|
|
5280
|
+
return [head, lhs];
|
|
5281
|
+
}
|
|
5282
|
+
return null;
|
|
5283
|
+
}
|
|
5284
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
5285
|
+
const head = memberHead(tok);
|
|
5286
|
+
if (head === null) return null;
|
|
5287
|
+
parser.nextToken();
|
|
5288
|
+
return [head, lhs];
|
|
5289
|
+
}
|
|
5290
|
+
return null;
|
|
5291
|
+
}
|
|
5292
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
5293
|
+
parser.addBoundary(close);
|
|
5294
|
+
parser.skipVisualSpace();
|
|
5295
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
5296
|
+
if (cond === null) {
|
|
5297
|
+
parser.removeBoundary();
|
|
5298
|
+
return null;
|
|
5299
|
+
}
|
|
5300
|
+
parser.skipVisualSpace();
|
|
5301
|
+
if (!parser.matchBoundary()) {
|
|
5302
|
+
parser.removeBoundary();
|
|
5303
|
+
return null;
|
|
5304
|
+
}
|
|
5305
|
+
return ["When", lhs, cond];
|
|
5306
|
+
}
|
|
5214
5307
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
5215
5308
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
5216
5309
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -5486,15 +5579,16 @@ var Compile = (() => {
|
|
|
5486
5579
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
5487
5580
|
parse: parseAssign
|
|
5488
5581
|
},
|
|
5489
|
-
// General colon operator (type annotation, mapping notation)
|
|
5490
|
-
// Precedence below
|
|
5491
|
-
// and below arrows (270) so
|
|
5582
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
5583
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
5584
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
5585
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
5492
5586
|
{
|
|
5493
5587
|
name: "Colon",
|
|
5494
5588
|
latexTrigger: ":",
|
|
5495
5589
|
kind: "infix",
|
|
5496
5590
|
associativity: "right",
|
|
5497
|
-
precedence:
|
|
5591
|
+
precedence: 240,
|
|
5498
5592
|
serialize: (serializer, expr) => joinLatex([
|
|
5499
5593
|
serializer.serialize(operand(expr, 1)),
|
|
5500
5594
|
"\\colon",
|
|
@@ -5505,7 +5599,7 @@ var Compile = (() => {
|
|
|
5505
5599
|
latexTrigger: "\\colon",
|
|
5506
5600
|
kind: "infix",
|
|
5507
5601
|
associativity: "right",
|
|
5508
|
-
precedence:
|
|
5602
|
+
precedence: 240,
|
|
5509
5603
|
parse: "Colon"
|
|
5510
5604
|
},
|
|
5511
5605
|
{
|
|
@@ -5682,6 +5776,15 @@ var Compile = (() => {
|
|
|
5682
5776
|
}
|
|
5683
5777
|
},
|
|
5684
5778
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
5779
|
+
// Component-access postfix: expr.member (C3)
|
|
5780
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
5781
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
5782
|
+
{
|
|
5783
|
+
kind: "postfix",
|
|
5784
|
+
precedence: 850,
|
|
5785
|
+
latexTrigger: ["."],
|
|
5786
|
+
parse: parseComponentAccess
|
|
5787
|
+
},
|
|
5685
5788
|
{
|
|
5686
5789
|
name: "At",
|
|
5687
5790
|
kind: "postfix",
|
|
@@ -5702,6 +5805,29 @@ var Compile = (() => {
|
|
|
5702
5805
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
5703
5806
|
parse: parseAt("\\right", "\\rbrack")
|
|
5704
5807
|
},
|
|
5808
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
5809
|
+
{
|
|
5810
|
+
name: "When",
|
|
5811
|
+
kind: "postfix",
|
|
5812
|
+
precedence: 800,
|
|
5813
|
+
latexTrigger: ["\\left", "\\{"],
|
|
5814
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
5815
|
+
serialize: (serializer, expr) => {
|
|
5816
|
+
const e = operand(expr, 1);
|
|
5817
|
+
const cond = operand(expr, 2);
|
|
5818
|
+
if (!e || !cond) return "";
|
|
5819
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
5820
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
5821
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
5822
|
+
}
|
|
5823
|
+
},
|
|
5824
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
5825
|
+
{
|
|
5826
|
+
kind: "postfix",
|
|
5827
|
+
precedence: 800,
|
|
5828
|
+
latexTrigger: ["\\{"],
|
|
5829
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
5830
|
+
},
|
|
5705
5831
|
{
|
|
5706
5832
|
kind: "postfix",
|
|
5707
5833
|
latexTrigger: ["_"],
|
|
@@ -5784,6 +5910,29 @@ var Compile = (() => {
|
|
|
5784
5910
|
return "";
|
|
5785
5911
|
}
|
|
5786
5912
|
},
|
|
5913
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
5914
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
5915
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
5916
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
5917
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
5918
|
+
{
|
|
5919
|
+
latexTrigger: [".", ".", "."],
|
|
5920
|
+
kind: "infix",
|
|
5921
|
+
precedence: 800,
|
|
5922
|
+
parse: parseRange
|
|
5923
|
+
},
|
|
5924
|
+
{
|
|
5925
|
+
latexTrigger: ["\\ldots"],
|
|
5926
|
+
kind: "infix",
|
|
5927
|
+
precedence: 800,
|
|
5928
|
+
parse: parseRange
|
|
5929
|
+
},
|
|
5930
|
+
{
|
|
5931
|
+
latexTrigger: ["\\dots"],
|
|
5932
|
+
kind: "infix",
|
|
5933
|
+
precedence: 800,
|
|
5934
|
+
parse: parseRange
|
|
5935
|
+
},
|
|
5787
5936
|
{
|
|
5788
5937
|
latexTrigger: [";"],
|
|
5789
5938
|
kind: "infix",
|
|
@@ -5968,13 +6117,24 @@ var Compile = (() => {
|
|
|
5968
6117
|
const args = operands(expr);
|
|
5969
6118
|
if (!args || args.length < 2) return "";
|
|
5970
6119
|
const body = args[0];
|
|
5971
|
-
const
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
6120
|
+
const elements = args.slice(1);
|
|
6121
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
6122
|
+
if (!allElements) {
|
|
6123
|
+
return joinLatex([
|
|
6124
|
+
"\\operatorname{Loop}(",
|
|
6125
|
+
serializer.serialize(body),
|
|
6126
|
+
", ",
|
|
6127
|
+
serializer.serialize(elements[0]),
|
|
6128
|
+
")"
|
|
6129
|
+
]);
|
|
6130
|
+
}
|
|
6131
|
+
if (elements.length === 1) {
|
|
6132
|
+
const elem = elements[0];
|
|
6133
|
+
const index = operand(elem, 1);
|
|
6134
|
+
const coll = operand(elem, 2);
|
|
6135
|
+
if (operator(coll) === "Range") {
|
|
6136
|
+
const lo = operand(coll, 1);
|
|
6137
|
+
const hi = operand(coll, 2);
|
|
5978
6138
|
return joinLatex([
|
|
5979
6139
|
"\\text{for }",
|
|
5980
6140
|
serializer.serialize(index),
|
|
@@ -5986,13 +6146,27 @@ var Compile = (() => {
|
|
|
5986
6146
|
serializer.serialize(body)
|
|
5987
6147
|
]);
|
|
5988
6148
|
}
|
|
6149
|
+
return joinLatex([
|
|
6150
|
+
serializer.serialize(body),
|
|
6151
|
+
" \\operatorname{for} ",
|
|
6152
|
+
serializer.serialize(index),
|
|
6153
|
+
" = ",
|
|
6154
|
+
serializer.serialize(coll)
|
|
6155
|
+
]);
|
|
5989
6156
|
}
|
|
6157
|
+
const bindings = elements.map((elem) => {
|
|
6158
|
+
const name = operand(elem, 1);
|
|
6159
|
+
const coll = operand(elem, 2);
|
|
6160
|
+
return joinLatex([
|
|
6161
|
+
serializer.serialize(name),
|
|
6162
|
+
" = ",
|
|
6163
|
+
serializer.serialize(coll)
|
|
6164
|
+
]);
|
|
6165
|
+
}).join(", ");
|
|
5990
6166
|
return joinLatex([
|
|
5991
|
-
"\\operatorname{Loop}(",
|
|
5992
6167
|
serializer.serialize(body),
|
|
5993
|
-
"
|
|
5994
|
-
|
|
5995
|
-
")"
|
|
6168
|
+
" \\operatorname{for} ",
|
|
6169
|
+
bindings
|
|
5996
6170
|
]);
|
|
5997
6171
|
}
|
|
5998
6172
|
},
|
|
@@ -6025,6 +6199,18 @@ var Compile = (() => {
|
|
|
6025
6199
|
precedence: 245,
|
|
6026
6200
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
6027
6201
|
},
|
|
6202
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
6203
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
6204
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
6205
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
6206
|
+
// bindings can be comma-separated below us.
|
|
6207
|
+
{
|
|
6208
|
+
symbolTrigger: "for",
|
|
6209
|
+
kind: "infix",
|
|
6210
|
+
associativity: "none",
|
|
6211
|
+
precedence: 19,
|
|
6212
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
6213
|
+
},
|
|
6028
6214
|
// \operatorname{break}
|
|
6029
6215
|
{
|
|
6030
6216
|
symbolTrigger: "break",
|
|
@@ -6229,7 +6415,10 @@ var Compile = (() => {
|
|
|
6229
6415
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
6230
6416
|
parser.addBoundary([")"]);
|
|
6231
6417
|
const expr = parser.parseExpression(until);
|
|
6232
|
-
if (!parser.matchBoundary())
|
|
6418
|
+
if (!parser.matchBoundary()) {
|
|
6419
|
+
parser.removeBoundary();
|
|
6420
|
+
return null;
|
|
6421
|
+
}
|
|
6233
6422
|
if (!parser.match("<}>")) return null;
|
|
6234
6423
|
return ["Derivative", lhs, expr];
|
|
6235
6424
|
}
|
|
@@ -6670,7 +6859,12 @@ var Compile = (() => {
|
|
|
6670
6859
|
if (isEmptySequence(body)) return ["List"];
|
|
6671
6860
|
const h = operator(body);
|
|
6672
6861
|
if (h === "Range" || h === "Linspace") return body;
|
|
6673
|
-
if (h === "Sequence")
|
|
6862
|
+
if (h === "Sequence") {
|
|
6863
|
+
const elems = operands(body);
|
|
6864
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6865
|
+
if (inferred) return inferred;
|
|
6866
|
+
return ["List", ...elems];
|
|
6867
|
+
}
|
|
6674
6868
|
if (h === "Delimiter") {
|
|
6675
6869
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
6676
6870
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -6683,12 +6877,37 @@ var Compile = (() => {
|
|
|
6683
6877
|
}
|
|
6684
6878
|
if (delim === "," || delim === ".,.") {
|
|
6685
6879
|
body = operand(body, 1);
|
|
6686
|
-
if (operator(body) === "Sequence")
|
|
6880
|
+
if (operator(body) === "Sequence") {
|
|
6881
|
+
const elems = operands(body);
|
|
6882
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6883
|
+
if (inferred) return inferred;
|
|
6884
|
+
return ["List", ...elems];
|
|
6885
|
+
}
|
|
6687
6886
|
return ["List", body ?? "Nothing"];
|
|
6688
6887
|
}
|
|
6689
6888
|
}
|
|
6690
6889
|
return ["List", body];
|
|
6691
6890
|
}
|
|
6891
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
6892
|
+
if (elems.length < 4) return null;
|
|
6893
|
+
const penultimate = elems[elems.length - 2];
|
|
6894
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
6895
|
+
const samples = elems.slice(0, -2);
|
|
6896
|
+
const endExpr = elems[elems.length - 1];
|
|
6897
|
+
if (samples.length < 2) return null;
|
|
6898
|
+
const sampleNums = samples.map(machineValue);
|
|
6899
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
6900
|
+
const nums = sampleNums;
|
|
6901
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
6902
|
+
const tol = parser.options.tolerance;
|
|
6903
|
+
if (Math.abs(step) < tol)
|
|
6904
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
6905
|
+
for (let i = 1; i < nums.length; i++) {
|
|
6906
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
6907
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
6908
|
+
}
|
|
6909
|
+
return ["Range", nums[0], endExpr, step];
|
|
6910
|
+
}
|
|
6692
6911
|
function serializeList(serializer, expr) {
|
|
6693
6912
|
if (nops(expr) > 1 && operands(expr).every((x) => {
|
|
6694
6913
|
const op = operator(x);
|
|
@@ -6940,6 +7159,38 @@ var Compile = (() => {
|
|
|
6940
7159
|
["Element", index, ["Range", lower, upper]]
|
|
6941
7160
|
];
|
|
6942
7161
|
}
|
|
7162
|
+
function parseForComprehension(parser, lhs, until) {
|
|
7163
|
+
const bindingTerminator = {
|
|
7164
|
+
minPrec: 21,
|
|
7165
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
7166
|
+
condition: (p) => {
|
|
7167
|
+
if (until?.condition?.(p)) return true;
|
|
7168
|
+
const saved = p.index;
|
|
7169
|
+
p.skipVisualSpace();
|
|
7170
|
+
const isComma = p.peek === ",";
|
|
7171
|
+
p.index = saved;
|
|
7172
|
+
if (isComma) return true;
|
|
7173
|
+
if (peekKeyword(p, "where")) return true;
|
|
7174
|
+
if (peekKeyword(p, "with")) return true;
|
|
7175
|
+
return false;
|
|
7176
|
+
}
|
|
7177
|
+
};
|
|
7178
|
+
const elements = [];
|
|
7179
|
+
do {
|
|
7180
|
+
parser.skipVisualSpace();
|
|
7181
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
7182
|
+
if (binding === null) break;
|
|
7183
|
+
const op = operator(binding);
|
|
7184
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
7185
|
+
const name = operand(binding, 1);
|
|
7186
|
+
const list = operand(binding, 2);
|
|
7187
|
+
if (!name || !list) return null;
|
|
7188
|
+
elements.push(["Element", name, list]);
|
|
7189
|
+
parser.skipVisualSpace();
|
|
7190
|
+
} while (parser.match(","));
|
|
7191
|
+
if (elements.length === 0) return null;
|
|
7192
|
+
return ["Loop", lhs, ...elements];
|
|
7193
|
+
}
|
|
6943
7194
|
function parseWhereExpression(parser, lhs, until) {
|
|
6944
7195
|
const bindingTerminator = {
|
|
6945
7196
|
minPrec: 21,
|
|
@@ -6962,6 +7213,25 @@ var Compile = (() => {
|
|
|
6962
7213
|
parser.skipVisualSpace();
|
|
6963
7214
|
} while (parser.match(","));
|
|
6964
7215
|
if (bindings.length === 0) return null;
|
|
7216
|
+
const forStart = parser.index;
|
|
7217
|
+
if (matchKeyword(parser, "for")) {
|
|
7218
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
7219
|
+
if (loop) {
|
|
7220
|
+
const block2 = [];
|
|
7221
|
+
for (const b of bindings) {
|
|
7222
|
+
const normalized = normalizeLocalAssign(b);
|
|
7223
|
+
if (operator(normalized) === "Assign") {
|
|
7224
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
7225
|
+
block2.push(normalized);
|
|
7226
|
+
} else {
|
|
7227
|
+
block2.push(normalized);
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
block2.push(loop);
|
|
7231
|
+
return ["Block", ...block2];
|
|
7232
|
+
}
|
|
7233
|
+
parser.index = forStart;
|
|
7234
|
+
}
|
|
6965
7235
|
const block = [];
|
|
6966
7236
|
for (const b of bindings) {
|
|
6967
7237
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -7175,6 +7445,17 @@ var Compile = (() => {
|
|
|
7175
7445
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
7176
7446
|
return ["Interval", lowerExpr, upperExpr];
|
|
7177
7447
|
}
|
|
7448
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
7449
|
+
"Less",
|
|
7450
|
+
"LessEqual",
|
|
7451
|
+
"Greater",
|
|
7452
|
+
"GreaterEqual",
|
|
7453
|
+
"Equal",
|
|
7454
|
+
"NotEqual",
|
|
7455
|
+
"And",
|
|
7456
|
+
"Or",
|
|
7457
|
+
"Not"
|
|
7458
|
+
]);
|
|
7178
7459
|
var DEFINITIONS_SETS = [
|
|
7179
7460
|
//
|
|
7180
7461
|
// Constants
|
|
@@ -7433,18 +7714,58 @@ var Compile = (() => {
|
|
|
7433
7714
|
closeTrigger: "}",
|
|
7434
7715
|
parse: (_parser, body) => {
|
|
7435
7716
|
if (isEmptySequence(body)) return "EmptySet";
|
|
7717
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
7718
|
+
body = operand(body, 1);
|
|
7719
|
+
}
|
|
7436
7720
|
const h = operator(body);
|
|
7437
|
-
if (h === "Divides"
|
|
7721
|
+
if (h === "Divides") {
|
|
7438
7722
|
const expr = operand(body, 1);
|
|
7439
7723
|
const condition = operand(body, 2);
|
|
7440
7724
|
if (expr !== null && condition !== null)
|
|
7441
7725
|
return ["Set", expr, ["Condition", condition]];
|
|
7442
7726
|
}
|
|
7443
|
-
if (
|
|
7444
|
-
|
|
7727
|
+
if (h === "Colon") {
|
|
7728
|
+
const lhs = operand(body, 1);
|
|
7729
|
+
const rhs = operand(body, 2);
|
|
7730
|
+
if (lhs !== null && rhs !== null) {
|
|
7731
|
+
const lhsOp = operator(lhs);
|
|
7732
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
7733
|
+
return ["Which", lhs, rhs];
|
|
7734
|
+
}
|
|
7735
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
7736
|
+
}
|
|
7445
7737
|
}
|
|
7446
|
-
if (
|
|
7447
|
-
|
|
7738
|
+
if (h === "Sequence") {
|
|
7739
|
+
const elements = operands(body);
|
|
7740
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
7741
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
7742
|
+
const lhs = operand(el, 1);
|
|
7743
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
7744
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
7745
|
+
});
|
|
7746
|
+
if (allPiecewise) {
|
|
7747
|
+
const whichOps = [];
|
|
7748
|
+
for (let i = 0; i < elements.length; i++) {
|
|
7749
|
+
const el = elements[i];
|
|
7750
|
+
if (operator(el) === "Colon") {
|
|
7751
|
+
const cond = operand(el, 1);
|
|
7752
|
+
const val = operand(el, 2);
|
|
7753
|
+
if (cond === null || val === null) {
|
|
7754
|
+
return ["Set", ...elements];
|
|
7755
|
+
}
|
|
7756
|
+
whichOps.push(cond, val);
|
|
7757
|
+
} else {
|
|
7758
|
+
if (i !== elements.length - 1) {
|
|
7759
|
+
return ["Set", ...elements];
|
|
7760
|
+
}
|
|
7761
|
+
whichOps.push("True", el);
|
|
7762
|
+
}
|
|
7763
|
+
}
|
|
7764
|
+
return ["Which", ...whichOps];
|
|
7765
|
+
}
|
|
7766
|
+
return ["Set", ...elements];
|
|
7767
|
+
}
|
|
7768
|
+
return ["Set", body];
|
|
7448
7769
|
},
|
|
7449
7770
|
serialize: (serializer, expr) => {
|
|
7450
7771
|
if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
|
|
@@ -9418,7 +9739,8 @@ var Compile = (() => {
|
|
|
9418
9739
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
9419
9740
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
9420
9741
|
});
|
|
9421
|
-
const
|
|
9742
|
+
const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
|
|
9743
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
9422
9744
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
9423
9745
|
};
|
|
9424
9746
|
}
|
|
@@ -11541,10 +11863,17 @@ var Compile = (() => {
|
|
|
11541
11863
|
// The capitalized library entries already exist; these are pure parse
|
|
11542
11864
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11543
11865
|
// ---------------------------------------------------------------------------
|
|
11866
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
11544
11867
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11545
11868
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11546
11869
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11547
11870
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
11871
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
11872
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
11873
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
11874
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
11875
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
11876
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
11548
11877
|
// ---------------------------------------------------------------------------
|
|
11549
11878
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11550
11879
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -12735,6 +13064,15 @@ ${lines.join("\n")}`;
|
|
|
12735
13064
|
return void 0;
|
|
12736
13065
|
}
|
|
12737
13066
|
|
|
13067
|
+
// src/compute-engine/numerics/random.ts
|
|
13068
|
+
function deterministicRandom(seed) {
|
|
13069
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
13070
|
+
return v - Math.floor(v);
|
|
13071
|
+
}
|
|
13072
|
+
function nextSeed(seed) {
|
|
13073
|
+
return seed + 0.6180339887498949;
|
|
13074
|
+
}
|
|
13075
|
+
|
|
12738
13076
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
12739
13077
|
function canonical(ce, xs, scope) {
|
|
12740
13078
|
if (xs.every((x) => x.isCanonical)) return xs;
|
|
@@ -12784,6 +13122,19 @@ ${lines.join("\n")}`;
|
|
|
12784
13122
|
indexWhere: void 0
|
|
12785
13123
|
}
|
|
12786
13124
|
},
|
|
13125
|
+
Length: {
|
|
13126
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
13127
|
+
complexity: 4e3,
|
|
13128
|
+
signature: "(any) -> integer",
|
|
13129
|
+
type: () => "integer",
|
|
13130
|
+
evaluate: ([xs], { engine }) => {
|
|
13131
|
+
if (!xs.isCollection) return void 0;
|
|
13132
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
13133
|
+
const n = xs.count;
|
|
13134
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
13135
|
+
return engine.number(n);
|
|
13136
|
+
}
|
|
13137
|
+
},
|
|
12787
13138
|
Tuple: {
|
|
12788
13139
|
description: "A fixed number of heterogeneous elements",
|
|
12789
13140
|
complexity: 8200,
|
|
@@ -12836,7 +13187,11 @@ ${lines.join("\n")}`;
|
|
|
12836
13187
|
//
|
|
12837
13188
|
Range: {
|
|
12838
13189
|
complexity: 8200,
|
|
12839
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
13190
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
13191
|
+
type: (ops) => {
|
|
13192
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
13193
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
13194
|
+
},
|
|
12840
13195
|
canonical: (ops, { engine: ce }) => {
|
|
12841
13196
|
if (ops.length === 0) return null;
|
|
12842
13197
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -12860,19 +13215,26 @@ ${lines.join("\n")}`;
|
|
|
12860
13215
|
const [lower, upper, step] = range(expr);
|
|
12861
13216
|
if (step === 0) return 0;
|
|
12862
13217
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
12863
|
-
return
|
|
13218
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12864
13219
|
},
|
|
12865
13220
|
contains: (expr, target) => {
|
|
12866
|
-
if (!target.type.matches("integer")) return false;
|
|
12867
13221
|
const t = target.re;
|
|
13222
|
+
if (!isFinite(t)) return false;
|
|
12868
13223
|
const [lower, upper, step] = range(expr);
|
|
12869
13224
|
if (step === 0) return false;
|
|
12870
|
-
if (step > 0)
|
|
12871
|
-
|
|
13225
|
+
if (step > 0) {
|
|
13226
|
+
if (t < lower || t > upper) return false;
|
|
13227
|
+
} else {
|
|
13228
|
+
if (t > lower || t < upper) return false;
|
|
13229
|
+
}
|
|
13230
|
+
const k = (t - lower) / step;
|
|
13231
|
+
const tol = expr.engine.tolerance;
|
|
13232
|
+
const kRounded = Math.round(k);
|
|
13233
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
12872
13234
|
},
|
|
12873
13235
|
iterator: (expr) => {
|
|
12874
13236
|
const [lower, upper, step] = range(expr);
|
|
12875
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
13237
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12876
13238
|
let index = 1;
|
|
12877
13239
|
return {
|
|
12878
13240
|
next: () => {
|
|
@@ -12890,7 +13252,9 @@ ${lines.join("\n")}`;
|
|
|
12890
13252
|
at: (expr, index) => {
|
|
12891
13253
|
if (typeof index !== "number") return void 0;
|
|
12892
13254
|
const [lower, upper, step] = range(expr);
|
|
12893
|
-
if (
|
|
13255
|
+
if (step === 0) return void 0;
|
|
13256
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
13257
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
12894
13258
|
return expr.engine.number(lower + step * (index - 1));
|
|
12895
13259
|
},
|
|
12896
13260
|
indexWhere: void 0,
|
|
@@ -12915,7 +13279,13 @@ ${lines.join("\n")}`;
|
|
|
12915
13279
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
12916
13280
|
return lower >= upper ? "positive" : "negative";
|
|
12917
13281
|
},
|
|
12918
|
-
elttype: (
|
|
13282
|
+
elttype: (expr) => {
|
|
13283
|
+
if (!isFunction2(expr)) return "finite_integer";
|
|
13284
|
+
for (let i = 1; i <= expr.nops; i++) {
|
|
13285
|
+
if (!expr[`op${i}`].isInteger) return "finite_real";
|
|
13286
|
+
}
|
|
13287
|
+
return "finite_integer";
|
|
13288
|
+
}
|
|
12919
13289
|
}
|
|
12920
13290
|
},
|
|
12921
13291
|
Interval: {
|
|
@@ -13018,10 +13388,12 @@ ${lines.join("\n")}`;
|
|
|
13018
13388
|
const upper = expr.op2.re;
|
|
13019
13389
|
let count = expr.op3.re;
|
|
13020
13390
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
13391
|
+
count = Math.floor(count);
|
|
13021
13392
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
13022
13393
|
if (index < 1 || index > count) return void 0;
|
|
13394
|
+
if (count === 1) return expr.engine.number(lower);
|
|
13023
13395
|
return expr.engine.number(
|
|
13024
|
-
lower + (upper - lower) * (index - 1) / count
|
|
13396
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
13025
13397
|
);
|
|
13026
13398
|
},
|
|
13027
13399
|
iterator: (expr) => {
|
|
@@ -13040,6 +13412,8 @@ ${lines.join("\n")}`;
|
|
|
13040
13412
|
!isFinite(expr.op3.re) ? DEFAULT_LINSPACE_COUNT : expr.op3.re
|
|
13041
13413
|
);
|
|
13042
13414
|
}
|
|
13415
|
+
totalCount = Math.floor(totalCount);
|
|
13416
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
13043
13417
|
let index = 1;
|
|
13044
13418
|
return {
|
|
13045
13419
|
next: () => {
|
|
@@ -13048,7 +13422,7 @@ ${lines.join("\n")}`;
|
|
|
13048
13422
|
index += 1;
|
|
13049
13423
|
return {
|
|
13050
13424
|
value: expr.engine.number(
|
|
13051
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
13425
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
13052
13426
|
),
|
|
13053
13427
|
done: false
|
|
13054
13428
|
};
|
|
@@ -13064,9 +13438,14 @@ ${lines.join("\n")}`;
|
|
|
13064
13438
|
if (t < lower || t > upper) return false;
|
|
13065
13439
|
let count = expr.op3.re;
|
|
13066
13440
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
13441
|
+
count = Math.floor(count);
|
|
13067
13442
|
if (count === 0) return false;
|
|
13068
|
-
|
|
13069
|
-
|
|
13443
|
+
if (count === 1) return t === lower;
|
|
13444
|
+
const step = (upper - lower) / (count - 1);
|
|
13445
|
+
const k = (t - lower) / step;
|
|
13446
|
+
const tol = expr.engine.tolerance;
|
|
13447
|
+
const kRounded = Math.round(k);
|
|
13448
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
13070
13449
|
}
|
|
13071
13450
|
}
|
|
13072
13451
|
},
|
|
@@ -13391,10 +13770,12 @@ ${lines.join("\n")}`;
|
|
|
13391
13770
|
description: [
|
|
13392
13771
|
"Access an element of an indexed collection.",
|
|
13393
13772
|
"If the index is negative, it is counted from the end.",
|
|
13394
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
13773
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
13774
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
13775
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
13395
13776
|
],
|
|
13396
13777
|
complexity: 8200,
|
|
13397
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
13778
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
13398
13779
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
13399
13780
|
evaluate: (ops, { engine: ce }) => {
|
|
13400
13781
|
let expr = ops[0];
|
|
@@ -13405,12 +13786,39 @@ ${lines.join("\n")}`;
|
|
|
13405
13786
|
if (!at) return void 0;
|
|
13406
13787
|
const opAtIndex = ops[index];
|
|
13407
13788
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
13408
|
-
if (s !== void 0)
|
|
13409
|
-
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
expr = at(expr, i) ?? ce.Nothing;
|
|
13789
|
+
if (s !== void 0) {
|
|
13790
|
+
expr = at(expr, s) ?? ce.Nothing;
|
|
13791
|
+
index += 1;
|
|
13792
|
+
continue;
|
|
13413
13793
|
}
|
|
13794
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
13795
|
+
const indices = Array.from(opAtIndex.each());
|
|
13796
|
+
const isMask = indices.every((m) => {
|
|
13797
|
+
const name = sym(m);
|
|
13798
|
+
return name === "True" || name === "False";
|
|
13799
|
+
});
|
|
13800
|
+
const picked = [];
|
|
13801
|
+
if (isMask) {
|
|
13802
|
+
indices.forEach((m, i2) => {
|
|
13803
|
+
if (sym(m) !== "True") return;
|
|
13804
|
+
const v = at(expr, i2 + 1);
|
|
13805
|
+
if (v !== void 0) picked.push(v);
|
|
13806
|
+
});
|
|
13807
|
+
} else {
|
|
13808
|
+
for (const m of indices) {
|
|
13809
|
+
const k = m.re;
|
|
13810
|
+
if (!Number.isInteger(k)) return void 0;
|
|
13811
|
+
const v = at(expr, k);
|
|
13812
|
+
if (v !== void 0) picked.push(v);
|
|
13813
|
+
}
|
|
13814
|
+
}
|
|
13815
|
+
expr = ce._fn("List", picked);
|
|
13816
|
+
index += 1;
|
|
13817
|
+
continue;
|
|
13818
|
+
}
|
|
13819
|
+
const i = opAtIndex.re;
|
|
13820
|
+
if (!Number.isInteger(i)) return void 0;
|
|
13821
|
+
expr = at(expr, i) ?? ce.Nothing;
|
|
13414
13822
|
index += 1;
|
|
13415
13823
|
}
|
|
13416
13824
|
return expr;
|
|
@@ -13421,7 +13829,7 @@ ${lines.join("\n")}`;
|
|
|
13421
13829
|
description: ["Return `n` elements from a collection."],
|
|
13422
13830
|
complexity: 8200,
|
|
13423
13831
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13424
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
13832
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13425
13833
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
13426
13834
|
if (!eager) return void 0;
|
|
13427
13835
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -13468,7 +13876,7 @@ ${lines.join("\n")}`;
|
|
|
13468
13876
|
description: ["Return the collection without the first n elements."],
|
|
13469
13877
|
complexity: 8200,
|
|
13470
13878
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
13471
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
13879
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
13472
13880
|
collection: {
|
|
13473
13881
|
isLazy: (_expr) => true,
|
|
13474
13882
|
count: (expr) => {
|
|
@@ -13513,15 +13921,45 @@ ${lines.join("\n")}`;
|
|
|
13513
13921
|
},
|
|
13514
13922
|
First: {
|
|
13515
13923
|
complexity: 8200,
|
|
13516
|
-
signature: "(
|
|
13924
|
+
signature: "(any) -> any",
|
|
13517
13925
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13518
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13926
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13927
|
+
if (!xs.isCollection)
|
|
13928
|
+
return ce.error([
|
|
13929
|
+
"incompatible-type",
|
|
13930
|
+
`'collection'`,
|
|
13931
|
+
xs.type.toString()
|
|
13932
|
+
]);
|
|
13933
|
+
return xs.at(1) ?? ce.Nothing;
|
|
13934
|
+
}
|
|
13519
13935
|
},
|
|
13520
13936
|
Second: {
|
|
13521
13937
|
complexity: 8200,
|
|
13522
|
-
signature: "(
|
|
13938
|
+
signature: "(any) -> any",
|
|
13523
13939
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13524
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13940
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13941
|
+
if (!xs.isCollection)
|
|
13942
|
+
return ce.error([
|
|
13943
|
+
"incompatible-type",
|
|
13944
|
+
`'collection'`,
|
|
13945
|
+
xs.type.toString()
|
|
13946
|
+
]);
|
|
13947
|
+
return xs.at(2) ?? ce.Nothing;
|
|
13948
|
+
}
|
|
13949
|
+
},
|
|
13950
|
+
Third: {
|
|
13951
|
+
complexity: 8200,
|
|
13952
|
+
signature: "(any) -> any",
|
|
13953
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13954
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13955
|
+
if (!xs.isCollection)
|
|
13956
|
+
return ce.error([
|
|
13957
|
+
"incompatible-type",
|
|
13958
|
+
`'collection'`,
|
|
13959
|
+
xs.type.toString()
|
|
13960
|
+
]);
|
|
13961
|
+
return xs.at(3) ?? ce.Nothing;
|
|
13962
|
+
}
|
|
13525
13963
|
},
|
|
13526
13964
|
Last: {
|
|
13527
13965
|
complexity: 8200,
|
|
@@ -13634,7 +14072,9 @@ ${lines.join("\n")}`;
|
|
|
13634
14072
|
],
|
|
13635
14073
|
complexity: 8200,
|
|
13636
14074
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
13637
|
-
type: ([xs]) => parseType(
|
|
14075
|
+
type: ([xs]) => parseType(
|
|
14076
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
14077
|
+
),
|
|
13638
14078
|
collection: {
|
|
13639
14079
|
isLazy: (_expr) => true,
|
|
13640
14080
|
count: (expr) => {
|
|
@@ -13966,16 +14406,26 @@ ${lines.join("\n")}`;
|
|
|
13966
14406
|
},
|
|
13967
14407
|
// Randomize the order of the elements in the collection.
|
|
13968
14408
|
Shuffle: {
|
|
13969
|
-
description: "Randomize the order of the elements in the collection.",
|
|
14409
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
13970
14410
|
complexity: 8200,
|
|
13971
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
14411
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
13972
14412
|
type: (ops) => ops[0].type,
|
|
13973
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
14413
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
13974
14414
|
if (!xs.isFiniteCollection) return void 0;
|
|
13975
14415
|
const data = Array.from(xs.each());
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
14416
|
+
const seed = seedOp?.re;
|
|
14417
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
14418
|
+
let s = seed;
|
|
14419
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
14420
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
14421
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
14422
|
+
s = nextSeed(s);
|
|
14423
|
+
}
|
|
14424
|
+
} else {
|
|
14425
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
14426
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
14427
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
14428
|
+
}
|
|
13979
14429
|
}
|
|
13980
14430
|
return ce.function(xs.operator, data);
|
|
13981
14431
|
}
|
|
@@ -14042,7 +14492,9 @@ ${lines.join("\n")}`;
|
|
|
14042
14492
|
if (t === "string")
|
|
14043
14493
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
14044
14494
|
return parseType(
|
|
14045
|
-
`tuple<list<${
|
|
14495
|
+
`tuple<list<${typeToString(
|
|
14496
|
+
collectionElementType(t) ?? "any"
|
|
14497
|
+
)}>, list<integer>>`
|
|
14046
14498
|
);
|
|
14047
14499
|
},
|
|
14048
14500
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -14058,7 +14510,7 @@ ${lines.join("\n")}`;
|
|
|
14058
14510
|
description: "Return a list of the unique elements of the collection.",
|
|
14059
14511
|
complexity: 8200,
|
|
14060
14512
|
signature: "(collection) -> list",
|
|
14061
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14513
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14062
14514
|
evaluate: (ops, { engine: ce }) => {
|
|
14063
14515
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
14064
14516
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -14070,7 +14522,7 @@ ${lines.join("\n")}`;
|
|
|
14070
14522
|
wikidata: "Q381060",
|
|
14071
14523
|
complexity: 8200,
|
|
14072
14524
|
signature: "(collection, integer | function) -> list",
|
|
14073
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
14525
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
14074
14526
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
14075
14527
|
if (!xs.isFiniteCollection) return void 0;
|
|
14076
14528
|
const k = toInteger(arg);
|
|
@@ -14244,32 +14696,74 @@ ${lines.join("\n")}`;
|
|
|
14244
14696
|
}
|
|
14245
14697
|
}
|
|
14246
14698
|
},
|
|
14247
|
-
// Repeat(x) -> [x, x, ...]
|
|
14248
|
-
//
|
|
14249
|
-
// x is evaluated once. Although could use Hold()?
|
|
14250
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
14699
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
14700
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
14251
14701
|
Repeat: {
|
|
14252
|
-
description: "Produce
|
|
14702
|
+
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.",
|
|
14253
14703
|
complexity: 8200,
|
|
14254
|
-
signature: "(value: any) -> list",
|
|
14704
|
+
signature: "(value: any, count: integer?) -> list",
|
|
14705
|
+
evaluate: (ops, { engine }) => {
|
|
14706
|
+
if (ops.length !== 2) return void 0;
|
|
14707
|
+
const raw = toInteger(ops[1]);
|
|
14708
|
+
if (raw === null) return void 0;
|
|
14709
|
+
const n = Math.max(0, raw);
|
|
14710
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
14711
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
14712
|
+
},
|
|
14255
14713
|
collection: {
|
|
14256
|
-
isLazy: (
|
|
14257
|
-
count: () =>
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14714
|
+
isLazy: (expr) => isFunction2(expr) && expr.ops?.length === 1,
|
|
14715
|
+
count: (expr) => {
|
|
14716
|
+
if (!isFunction2(expr)) return void 0;
|
|
14717
|
+
if (expr.ops?.length === 2) {
|
|
14718
|
+
const n = toInteger(expr.op2);
|
|
14719
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
14720
|
+
}
|
|
14721
|
+
return Infinity;
|
|
14722
|
+
},
|
|
14723
|
+
isEmpty: (expr) => {
|
|
14724
|
+
if (!isFunction2(expr)) return void 0;
|
|
14725
|
+
if (expr.ops?.length === 2) {
|
|
14726
|
+
const n = toInteger(expr.op2);
|
|
14727
|
+
return n !== null ? n <= 0 : void 0;
|
|
14728
|
+
}
|
|
14729
|
+
return false;
|
|
14730
|
+
},
|
|
14731
|
+
isFinite: (expr) => isFunction2(expr) && expr.ops?.length === 2,
|
|
14262
14732
|
contains: (expr, target) => {
|
|
14263
14733
|
if (!isFunction2(expr)) return false;
|
|
14734
|
+
if (expr.ops?.length === 2) {
|
|
14735
|
+
const n = toInteger(expr.op2);
|
|
14736
|
+
if (n !== null && n <= 0) return false;
|
|
14737
|
+
}
|
|
14264
14738
|
return expr.op1.isSame(target);
|
|
14265
14739
|
},
|
|
14266
14740
|
iterator: (expr) => {
|
|
14267
14741
|
if (!isFunction2(expr))
|
|
14268
14742
|
return { next: () => ({ value: void 0, done: true }) };
|
|
14743
|
+
if (expr.ops?.length === 2) {
|
|
14744
|
+
const n = toInteger(expr.op2);
|
|
14745
|
+
if (n === null) {
|
|
14746
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
14747
|
+
}
|
|
14748
|
+
const count = Math.max(0, n);
|
|
14749
|
+
let i = 0;
|
|
14750
|
+
return {
|
|
14751
|
+
next: () => i++ < count ? { value: expr.op1, done: false } : { value: void 0, done: true }
|
|
14752
|
+
};
|
|
14753
|
+
}
|
|
14269
14754
|
return { next: () => ({ value: expr.op1, done: false }) };
|
|
14270
14755
|
},
|
|
14271
|
-
at
|
|
14756
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
14757
|
+
at: (expr, index) => {
|
|
14272
14758
|
if (!isFunction2(expr)) return void 0;
|
|
14759
|
+
if (typeof index !== "number") return void 0;
|
|
14760
|
+
if (expr.ops?.length === 2) {
|
|
14761
|
+
const n = toInteger(expr.op2);
|
|
14762
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
14763
|
+
if (index < 1 || index > count) return void 0;
|
|
14764
|
+
} else {
|
|
14765
|
+
if (index < 1) return void 0;
|
|
14766
|
+
}
|
|
14273
14767
|
return expr.op1;
|
|
14274
14768
|
}
|
|
14275
14769
|
}
|
|
@@ -14500,17 +14994,14 @@ ${lines.join("\n")}`;
|
|
|
14500
14994
|
if (!isFunction2(expr)) return [1, 0, 0];
|
|
14501
14995
|
if (expr.nops === 0) return [1, 0, 0];
|
|
14502
14996
|
let op1 = expr.op1.re;
|
|
14503
|
-
if (!isFinite(op1)) op1 = 1;
|
|
14504
|
-
else op1 = Math.round(op1);
|
|
14997
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
14505
14998
|
if (expr.nops === 1) return [1, op1, 1];
|
|
14506
14999
|
let op2 = expr.op2.re;
|
|
14507
15000
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
14508
|
-
|
|
14509
|
-
if (expr.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
15001
|
+
if (expr.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
14510
15002
|
let op3 = expr.op3.re;
|
|
14511
|
-
if (!isFinite(op3)) op3 = 1;
|
|
14512
|
-
|
|
14513
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
15003
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
15004
|
+
return [op1, op2, op3];
|
|
14514
15005
|
}
|
|
14515
15006
|
function canonicalList(ops, { engine: ce }) {
|
|
14516
15007
|
const op1 = ops[0];
|
|
@@ -14859,6 +15350,23 @@ ${lines.join("\n")}`;
|
|
|
14859
15350
|
};
|
|
14860
15351
|
return compilePair(0);
|
|
14861
15352
|
}
|
|
15353
|
+
if (h === "When") {
|
|
15354
|
+
if (args.length !== 2)
|
|
15355
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
15356
|
+
const fn2 = target.functions?.(h);
|
|
15357
|
+
if (fn2) {
|
|
15358
|
+
if (typeof fn2 === "function") {
|
|
15359
|
+
return fn2(args, (expr) => _BaseCompiler.compile(expr, target), target);
|
|
15360
|
+
}
|
|
15361
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
15362
|
+
}
|
|
15363
|
+
if (isSymbol2(args[1], "True"))
|
|
15364
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
15365
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
15366
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
15367
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
15368
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
15369
|
+
}
|
|
14862
15370
|
if (h === "Block") {
|
|
14863
15371
|
return _BaseCompiler.compileBlock(args, target);
|
|
14864
15372
|
}
|
|
@@ -14933,17 +15441,98 @@ ${lines.join("\n")}`;
|
|
|
14933
15441
|
)}${target.ws("\n")}})()`;
|
|
14934
15442
|
}
|
|
14935
15443
|
/**
|
|
14936
|
-
* Compile a Loop expression
|
|
14937
|
-
*
|
|
15444
|
+
* Compile a Loop expression.
|
|
15445
|
+
*
|
|
15446
|
+
* Two forms are supported:
|
|
15447
|
+
*
|
|
15448
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
15449
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
15450
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
15451
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
15452
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
15453
|
+
* references to the loop index inside the body are re-wrapped via
|
|
15454
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
15455
|
+
*
|
|
15456
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
15457
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
15458
|
+
* When two or more `Element` clauses are present — or when the single
|
|
15459
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
15460
|
+
* comprehension that collects results into an array. Each clause
|
|
15461
|
+
* produces a `for (const name of collection)` loop, nested
|
|
15462
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
15463
|
+
*
|
|
15464
|
+
* Example output (JS):
|
|
15465
|
+
* ```js
|
|
15466
|
+
* (() => { const result = [];
|
|
15467
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
15468
|
+
* return result; })()
|
|
15469
|
+
* ```
|
|
14938
15470
|
*
|
|
14939
|
-
*
|
|
14940
|
-
*
|
|
14941
|
-
*
|
|
15471
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
15472
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15473
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15474
|
+
* array or by unrolling when bounds are known at compile time.
|
|
15475
|
+
*
|
|
15476
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
15477
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
15478
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
15479
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
15480
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
15481
|
+
* current behavior.
|
|
14942
15482
|
*/
|
|
14943
15483
|
static compileForLoop(args, target) {
|
|
14944
15484
|
if (!args[0]) throw new Error("Loop: no body");
|
|
14945
15485
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
14946
|
-
const
|
|
15486
|
+
const body = args[0];
|
|
15487
|
+
const elements = args.slice(1);
|
|
15488
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
15489
|
+
if (useComprehension) {
|
|
15490
|
+
const lang = target.language ?? "";
|
|
15491
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
15492
|
+
throw new Error(
|
|
15493
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
15494
|
+
);
|
|
15495
|
+
}
|
|
15496
|
+
const narrowedElements = [];
|
|
15497
|
+
for (let i = 0; i < elements.length; i++) {
|
|
15498
|
+
const elem = elements[i];
|
|
15499
|
+
if (!isFunction2(elem, "Element"))
|
|
15500
|
+
throw new Error(
|
|
15501
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
15502
|
+
);
|
|
15503
|
+
if (!isSymbol2(elem.ops[0]))
|
|
15504
|
+
throw new Error(
|
|
15505
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
15506
|
+
);
|
|
15507
|
+
narrowedElements.push(elem);
|
|
15508
|
+
}
|
|
15509
|
+
const loopVarSet = new Set(
|
|
15510
|
+
narrowedElements.map(
|
|
15511
|
+
(e) => e.ops[0].symbol
|
|
15512
|
+
)
|
|
15513
|
+
);
|
|
15514
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
15515
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
15516
|
+
...target,
|
|
15517
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
15518
|
+
} : target;
|
|
15519
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
15520
|
+
let inner = `result.push(${bodyCode});`;
|
|
15521
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
15522
|
+
const elem = narrowedElements[i];
|
|
15523
|
+
const name = elem.ops[0].symbol;
|
|
15524
|
+
const collExpr = elem.ops[1];
|
|
15525
|
+
let collection;
|
|
15526
|
+
if (isFunction2(collExpr, "Range")) {
|
|
15527
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
15528
|
+
} else {
|
|
15529
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
15530
|
+
}
|
|
15531
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
15532
|
+
}
|
|
15533
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
15534
|
+
}
|
|
15535
|
+
const indexing = elements[0];
|
|
14947
15536
|
if (!isFunction2(indexing, "Element"))
|
|
14948
15537
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
14949
15538
|
const indexExpr = indexing.ops[0];
|
|
@@ -14961,13 +15550,72 @@ ${lines.join("\n")}`;
|
|
|
14961
15550
|
...target,
|
|
14962
15551
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
14963
15552
|
};
|
|
14964
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
15553
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
14965
15554
|
return `(() => {${target.ws(
|
|
14966
15555
|
"\n"
|
|
14967
15556
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
14968
15557
|
"\n"
|
|
14969
15558
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
14970
15559
|
}
|
|
15560
|
+
/**
|
|
15561
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
15562
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
15563
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
15564
|
+
*
|
|
15565
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
15566
|
+
* are not statically numeric we accept the Range (the historical
|
|
15567
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
15568
|
+
* left as a known limitation; callers can force the iterable path by
|
|
15569
|
+
* supplying an explicit step.
|
|
15570
|
+
*/
|
|
15571
|
+
static isLegacyCompatibleRange(coll) {
|
|
15572
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
15573
|
+
if (coll.ops.length >= 3) {
|
|
15574
|
+
const stepExpr = coll.ops[2];
|
|
15575
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
15576
|
+
}
|
|
15577
|
+
const lo = coll.ops[0];
|
|
15578
|
+
const hi = coll.ops[1];
|
|
15579
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
15580
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
15581
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
15582
|
+
return true;
|
|
15583
|
+
}
|
|
15584
|
+
/**
|
|
15585
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
15586
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
15587
|
+
* `library/collections.ts` Range:
|
|
15588
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
15589
|
+
* element = lo + step * k (0-indexed)
|
|
15590
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
15591
|
+
*
|
|
15592
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
15593
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
15594
|
+
*/
|
|
15595
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
15596
|
+
const loExpr = rangeExpr.ops[0];
|
|
15597
|
+
const hiExpr = rangeExpr.ops[1];
|
|
15598
|
+
const stepExpr = rangeExpr.ops[2];
|
|
15599
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
15600
|
+
const lo2 = loExpr.re;
|
|
15601
|
+
const hi2 = hiExpr.re;
|
|
15602
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
15603
|
+
if (step2 === 0) return "[]";
|
|
15604
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
15605
|
+
if (step2 === 1) {
|
|
15606
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
15607
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
15608
|
+
}
|
|
15609
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
15610
|
+
}
|
|
15611
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
15612
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
15613
|
+
if (stepExpr === void 0) {
|
|
15614
|
+
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})`;
|
|
15615
|
+
}
|
|
15616
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
15617
|
+
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})`;
|
|
15618
|
+
}
|
|
14971
15619
|
/**
|
|
14972
15620
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
14973
15621
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -19918,6 +20566,7 @@ ${lines.join("\n")}`;
|
|
|
19918
20566
|
return `_SYS.cexp(${compile2(args[0])})`;
|
|
19919
20567
|
return `Math.exp(${compile2(args[0])})`;
|
|
19920
20568
|
},
|
|
20569
|
+
First: (args, compile2) => `${compile2(args[0])}[0]`,
|
|
19921
20570
|
Floor: (args, compile2) => {
|
|
19922
20571
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19923
20572
|
return `Math.floor(${compile2(args[0])})`;
|
|
@@ -20076,7 +20725,20 @@ ${lines.join("\n")}`;
|
|
|
20076
20725
|
if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
|
|
20077
20726
|
return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
|
|
20078
20727
|
},
|
|
20079
|
-
Random:
|
|
20728
|
+
Random: (args, compile2) => {
|
|
20729
|
+
if (args.length === 0) return "Math.random()";
|
|
20730
|
+
if (args.length === 2) {
|
|
20731
|
+
const m = compile2(args[0]);
|
|
20732
|
+
const n = compile2(args[1]);
|
|
20733
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
20734
|
+
}
|
|
20735
|
+
const arg = args[0];
|
|
20736
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
20737
|
+
return `Math.floor(Math.random() * (${compile2(arg)}))`;
|
|
20738
|
+
}
|
|
20739
|
+
const a = compile2(arg);
|
|
20740
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
20741
|
+
},
|
|
20080
20742
|
Round: (args, compile2) => {
|
|
20081
20743
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
20082
20744
|
return `Math.round(${compile2(args[0])})`;
|
|
@@ -20104,6 +20766,7 @@ ${lines.join("\n")}`;
|
|
|
20104
20766
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile2(arg)})`;
|
|
20105
20767
|
return `1 / Math.cosh(${compile2(arg)})`;
|
|
20106
20768
|
},
|
|
20769
|
+
Second: (args, compile2) => `${compile2(args[0])}[1]`,
|
|
20107
20770
|
Heaviside: "_SYS.heaviside",
|
|
20108
20771
|
Sign: "Math.sign",
|
|
20109
20772
|
Sinc: "_SYS.sinc",
|
|
@@ -20136,6 +20799,7 @@ ${lines.join("\n")}`;
|
|
|
20136
20799
|
return `_SYS.ctanh(${compile2(args[0])})`;
|
|
20137
20800
|
return `Math.tanh(${compile2(args[0])})`;
|
|
20138
20801
|
},
|
|
20802
|
+
Third: (args, compile2) => `${compile2(args[0])}[2]`,
|
|
20139
20803
|
Mod: ([a, b], compile2) => {
|
|
20140
20804
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
20141
20805
|
const ca = compile2(a);
|
|
@@ -21415,6 +22079,14 @@ ${lines.join("\n")}`;
|
|
|
21415
22079
|
return `exp(${compile2(args[0])})`;
|
|
21416
22080
|
},
|
|
21417
22081
|
Exp2: "exp2",
|
|
22082
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
22083
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
22084
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
22085
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
22086
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
22087
|
+
First: (args, compile2) => `${compile2(args[0])}.x`,
|
|
22088
|
+
Second: (args, compile2) => `${compile2(args[0])}.y`,
|
|
22089
|
+
Third: (args, compile2) => `${compile2(args[0])}.z`,
|
|
21418
22090
|
Floor: (args, compile2) => {
|
|
21419
22091
|
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21420
22092
|
return `floor(${compile2(args[0])})`;
|
|
@@ -21892,6 +22564,39 @@ ${lines.join("\n")}`;
|
|
|
21892
22564
|
// Sum/Product — unrolled or for-loop
|
|
21893
22565
|
Sum: (args, compile2, target) => compileGPUSumProduct("Sum", args, compile2, target),
|
|
21894
22566
|
Product: (args, compile2, target) => compileGPUSumProduct("Product", args, compile2, target),
|
|
22567
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
22568
|
+
Range: (args, _compile, target) => {
|
|
22569
|
+
if (args.length < 2 || args.length > 3) {
|
|
22570
|
+
throw new Error(
|
|
22571
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
22572
|
+
);
|
|
22573
|
+
}
|
|
22574
|
+
const lo = args[0].re;
|
|
22575
|
+
const hi = args[1].re;
|
|
22576
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
22577
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
22578
|
+
throw new Error(
|
|
22579
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
22580
|
+
);
|
|
22581
|
+
}
|
|
22582
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
22583
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
22584
|
+
if (count === 0) {
|
|
22585
|
+
throw new Error(
|
|
22586
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
22587
|
+
);
|
|
22588
|
+
}
|
|
22589
|
+
if (count > 256) {
|
|
22590
|
+
throw new Error(
|
|
22591
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
22592
|
+
);
|
|
22593
|
+
}
|
|
22594
|
+
const values = [];
|
|
22595
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
22596
|
+
const isWGSL = target.language === "wgsl";
|
|
22597
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
22598
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
22599
|
+
},
|
|
21895
22600
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
21896
22601
|
Loop: (args, _compile, target) => {
|
|
21897
22602
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -21920,6 +22625,134 @@ ${lines.join("\n")}`;
|
|
|
21920
22625
|
${bodyCode};
|
|
21921
22626
|
}`;
|
|
21922
22627
|
},
|
|
22628
|
+
// Statistical functions
|
|
22629
|
+
/**
|
|
22630
|
+
* GCD of two scalar arguments.
|
|
22631
|
+
*
|
|
22632
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
22633
|
+
* Only two-argument form is supported in GPU targets.
|
|
22634
|
+
*/
|
|
22635
|
+
GCD: (args, compile2) => {
|
|
22636
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
22637
|
+
if (args.length > 2)
|
|
22638
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
22639
|
+
const a = args[0];
|
|
22640
|
+
const b = args[1];
|
|
22641
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
22642
|
+
return `_gpu_gcd(${compile2(a)}, ${compile2(b)})`;
|
|
22643
|
+
},
|
|
22644
|
+
/**
|
|
22645
|
+
* Variance of a compile-time-known list.
|
|
22646
|
+
*
|
|
22647
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
22648
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
22649
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
22650
|
+
*/
|
|
22651
|
+
Variance: (args, compile2) => {
|
|
22652
|
+
let elems;
|
|
22653
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
22654
|
+
elems = args[0].ops;
|
|
22655
|
+
} else if (args.length >= 2) {
|
|
22656
|
+
elems = args;
|
|
22657
|
+
} else {
|
|
22658
|
+
throw new Error(
|
|
22659
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
22660
|
+
);
|
|
22661
|
+
}
|
|
22662
|
+
const n = elems.length;
|
|
22663
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
22664
|
+
const compiled = elems.map((e) => compile2(e));
|
|
22665
|
+
const sum = compiled.join(" + ");
|
|
22666
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
22667
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
22668
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
22669
|
+
},
|
|
22670
|
+
/**
|
|
22671
|
+
* Median of a compile-time-known list.
|
|
22672
|
+
*
|
|
22673
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
22674
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
22675
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
22676
|
+
*
|
|
22677
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
22678
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
22679
|
+
*/
|
|
22680
|
+
Median: (args, compile2) => {
|
|
22681
|
+
let elems;
|
|
22682
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
22683
|
+
elems = args[0].ops;
|
|
22684
|
+
} else if (args.length >= 1) {
|
|
22685
|
+
elems = args;
|
|
22686
|
+
} else {
|
|
22687
|
+
throw new Error(
|
|
22688
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
22689
|
+
);
|
|
22690
|
+
}
|
|
22691
|
+
const n = elems.length;
|
|
22692
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
22693
|
+
if (n > 8) {
|
|
22694
|
+
throw new Error(
|
|
22695
|
+
`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.`
|
|
22696
|
+
);
|
|
22697
|
+
}
|
|
22698
|
+
const compiled = elems.map((e) => compile2(e));
|
|
22699
|
+
if (n === 1) return compiled[0];
|
|
22700
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
22701
|
+
},
|
|
22702
|
+
/**
|
|
22703
|
+
* Deterministic pseudorandom for GPU.
|
|
22704
|
+
*
|
|
22705
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
22706
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
22707
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
22708
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
22709
|
+
* integer-returning operators in this target.
|
|
22710
|
+
*
|
|
22711
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
22712
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
22713
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
22714
|
+
* caller must provide an explicit seed.
|
|
22715
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
22716
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
22717
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
22718
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
22719
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
22720
|
+
*
|
|
22721
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
22722
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
22723
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
22724
|
+
* `sin` differences.
|
|
22725
|
+
*/
|
|
22726
|
+
Random: (args, compile2, target) => {
|
|
22727
|
+
if (args.length === 0) {
|
|
22728
|
+
if (target.language === "wgsl") {
|
|
22729
|
+
throw new Error(
|
|
22730
|
+
"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."
|
|
22731
|
+
);
|
|
22732
|
+
}
|
|
22733
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
22734
|
+
}
|
|
22735
|
+
if (args.length === 1) {
|
|
22736
|
+
const arg = args[0];
|
|
22737
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
22738
|
+
const compiled = compile2(arg);
|
|
22739
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
22740
|
+
}
|
|
22741
|
+
return `_gpu_random(${compile2(arg)})`;
|
|
22742
|
+
}
|
|
22743
|
+
if (args.length === 2) {
|
|
22744
|
+
if (target.language === "wgsl") {
|
|
22745
|
+
throw new Error(
|
|
22746
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
22747
|
+
);
|
|
22748
|
+
}
|
|
22749
|
+
const m = compile2(args[0]);
|
|
22750
|
+
const n = compile2(args[1]);
|
|
22751
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
22752
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
22753
|
+
}
|
|
22754
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
22755
|
+
},
|
|
21923
22756
|
// Function (lambda) — not supported in GPU
|
|
21924
22757
|
Function: () => {
|
|
21925
22758
|
throw new Error(
|
|
@@ -22518,6 +23351,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
22518
23351
|
}
|
|
22519
23352
|
return 1.0;
|
|
22520
23353
|
}
|
|
23354
|
+
`;
|
|
23355
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
23356
|
+
float _gpu_gcd(float a, float b) {
|
|
23357
|
+
a = abs(a); b = abs(b);
|
|
23358
|
+
for (int i = 0; i < 32; i++) {
|
|
23359
|
+
if (b < 0.5) break;
|
|
23360
|
+
float t = mod(a, b);
|
|
23361
|
+
a = b;
|
|
23362
|
+
b = t;
|
|
23363
|
+
}
|
|
23364
|
+
return a;
|
|
23365
|
+
}
|
|
23366
|
+
`;
|
|
23367
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
23368
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
23369
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
23370
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
23371
|
+
if (b < 0.5) { break; }
|
|
23372
|
+
let t = a % b;
|
|
23373
|
+
a = b;
|
|
23374
|
+
b = t;
|
|
23375
|
+
}
|
|
23376
|
+
return a;
|
|
23377
|
+
}
|
|
23378
|
+
`;
|
|
23379
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
23380
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
23381
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
23382
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
23383
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
23384
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
23385
|
+
float _gpu_random(float seed) {
|
|
23386
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
23387
|
+
}
|
|
23388
|
+
`;
|
|
23389
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
23390
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
23391
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
23392
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
23393
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
23394
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
23395
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
23396
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
23397
|
+
}
|
|
23398
|
+
`;
|
|
23399
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
23400
|
+
float _gpu_median_2(float a, float b) {
|
|
23401
|
+
return (a + b) * 0.5;
|
|
23402
|
+
}
|
|
23403
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
23404
|
+
return max(min(a, b), min(max(a, b), c));
|
|
23405
|
+
}
|
|
23406
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
23407
|
+
float lo = max(min(a, b), min(c, d));
|
|
23408
|
+
float hi = min(max(a, b), max(c, d));
|
|
23409
|
+
return (lo + hi) * 0.5;
|
|
23410
|
+
}
|
|
23411
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
23412
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
23413
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
23414
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23415
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23416
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23417
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23418
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
23419
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23420
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
23421
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23422
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23423
|
+
return v2;
|
|
23424
|
+
}
|
|
23425
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
23426
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
23427
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23428
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23429
|
+
t=min(v4,v5); v5=max(v4,v5); v4=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(v0,v4); v4=max(v0,v4); v0=t;
|
|
23433
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23434
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23435
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23436
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23437
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23438
|
+
return (v2 + v3) * 0.5;
|
|
23439
|
+
}
|
|
23440
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
23441
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
23442
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23443
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23444
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23445
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23446
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23447
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23448
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23449
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23450
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23451
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23452
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23453
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23454
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23455
|
+
return v3;
|
|
23456
|
+
}
|
|
23457
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
23458
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
23459
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23460
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23461
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23462
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
23463
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23464
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23465
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23466
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
23467
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23468
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23469
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23470
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
23471
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23472
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23473
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
23474
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23475
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23476
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23477
|
+
return (v3 + v4) * 0.5;
|
|
23478
|
+
}
|
|
23479
|
+
`;
|
|
23480
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
23481
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
23482
|
+
return (a + b) * 0.5;
|
|
23483
|
+
}
|
|
23484
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
23485
|
+
return max(min(a, b), min(max(a, b), c));
|
|
23486
|
+
}
|
|
23487
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
23488
|
+
let lo = max(min(a, b), min(c, d));
|
|
23489
|
+
let hi = min(max(a, b), max(c, d));
|
|
23490
|
+
return (lo + hi) * 0.5;
|
|
23491
|
+
}
|
|
23492
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
23493
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
23494
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
23495
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23496
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23497
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23498
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23499
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
23500
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23501
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
23502
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23503
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23504
|
+
return v2;
|
|
23505
|
+
}
|
|
23506
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
23507
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
23508
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23509
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23510
|
+
t=min(v4,v5); v5=max(v4,v5); v4=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(v0,v4); v4=max(v0,v4); v0=t;
|
|
23514
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23515
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23516
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23517
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23518
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23519
|
+
return (v2 + v3) * 0.5;
|
|
23520
|
+
}
|
|
23521
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
23522
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
23523
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23524
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23525
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23526
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23527
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23528
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23529
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23530
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23531
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23532
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23533
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23534
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23535
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23536
|
+
return v3;
|
|
23537
|
+
}
|
|
23538
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
23539
|
+
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;
|
|
23540
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
23541
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
23542
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
23543
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
23544
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
23545
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
23546
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
23547
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
23548
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
23549
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
23550
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
23551
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
23552
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
23553
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23554
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
23555
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
23556
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
23557
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
23558
|
+
return (v3 + v4) * 0.5;
|
|
23559
|
+
}
|
|
22521
23560
|
`;
|
|
22522
23561
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
22523
23562
|
float _gpu_srgb_to_linear(float c) {
|
|
@@ -23196,6 +24235,12 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
|
23196
24235
|
if (code.includes("_fractal_")) {
|
|
23197
24236
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
23198
24237
|
}
|
|
24238
|
+
if (code.includes("_gpu_random"))
|
|
24239
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
24240
|
+
if (code.includes("_gpu_gcd"))
|
|
24241
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
24242
|
+
if (code.includes("_gpu_median_"))
|
|
24243
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
23199
24244
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
23200
24245
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
23201
24246
|
}
|
|
@@ -25534,7 +26579,7 @@ ${code}`;
|
|
|
25534
26579
|
}
|
|
25535
26580
|
|
|
25536
26581
|
// src/compile.ts
|
|
25537
|
-
var version = "0.
|
|
26582
|
+
var version = "0.58.0";
|
|
25538
26583
|
return __toCommonJS(compile_exports);
|
|
25539
26584
|
})();
|
|
25540
26585
|
/*! Bundled license information:
|