@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/core.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 0.58.0 */
|
|
2
2
|
|
|
3
3
|
// node_modules/complex-esm/dist/src/complex.js
|
|
4
4
|
var cosh = Math.cosh || function(x) {
|
|
@@ -4268,7 +4268,42 @@ function widen2(a, b) {
|
|
|
4268
4268
|
if (b === "nothing") return a;
|
|
4269
4269
|
if (isSubtype(a, b)) return b;
|
|
4270
4270
|
if (isSubtype(b, a)) return a;
|
|
4271
|
-
|
|
4271
|
+
const sup = superType(a, b);
|
|
4272
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
4273
|
+
return sup;
|
|
4274
|
+
}
|
|
4275
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
4276
|
+
"scalar",
|
|
4277
|
+
"value",
|
|
4278
|
+
"function",
|
|
4279
|
+
"expression",
|
|
4280
|
+
"collection",
|
|
4281
|
+
"indexed_collection",
|
|
4282
|
+
"list",
|
|
4283
|
+
"set",
|
|
4284
|
+
"tuple",
|
|
4285
|
+
"record",
|
|
4286
|
+
"dictionary",
|
|
4287
|
+
"map",
|
|
4288
|
+
"any"
|
|
4289
|
+
]);
|
|
4290
|
+
function unionTypes(a, b) {
|
|
4291
|
+
const members = [];
|
|
4292
|
+
const push = (t) => {
|
|
4293
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
4294
|
+
for (const m of t.types) push(m);
|
|
4295
|
+
return;
|
|
4296
|
+
}
|
|
4297
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
4298
|
+
if (!members.some(
|
|
4299
|
+
(m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
|
|
4300
|
+
))
|
|
4301
|
+
members.push(t);
|
|
4302
|
+
};
|
|
4303
|
+
push(a);
|
|
4304
|
+
push(b);
|
|
4305
|
+
if (members.length === 1) return members[0];
|
|
4306
|
+
return { kind: "union", types: members };
|
|
4272
4307
|
}
|
|
4273
4308
|
function narrow(...types) {
|
|
4274
4309
|
if (types.length === 0) return "nothing";
|
|
@@ -4346,7 +4381,7 @@ function collectionElementType(type2) {
|
|
|
4346
4381
|
if (type2.kind === "set") return type2.elements;
|
|
4347
4382
|
if (type2.kind === "tuple") return widen(...type2.elements.map((x) => x.type));
|
|
4348
4383
|
if (type2.kind === "dictionary")
|
|
4349
|
-
return parseType(`tuple<string, ${type2.values}>`);
|
|
4384
|
+
return parseType(`tuple<string, ${typeToString(type2.values)}>`);
|
|
4350
4385
|
if (type2.kind === "record") {
|
|
4351
4386
|
return parseType(
|
|
4352
4387
|
`tuple<string, ${typeToString(widen(...Object.values(type2.elements)))}>`
|
|
@@ -5892,6 +5927,84 @@ function sym(expr2) {
|
|
|
5892
5927
|
}
|
|
5893
5928
|
|
|
5894
5929
|
// src/compute-engine/boxed-expression/inequality-bounds.ts
|
|
5930
|
+
function extractIntervalBounds(expr2, symbol2) {
|
|
5931
|
+
if (isFunction2(expr2, "When")) {
|
|
5932
|
+
const cond = expr2.op2;
|
|
5933
|
+
if (!cond) return void 0;
|
|
5934
|
+
return extractIntervalBounds(cond, symbol2);
|
|
5935
|
+
}
|
|
5936
|
+
if (isFunction2(expr2, "Multiply")) {
|
|
5937
|
+
const ops = expr2.ops;
|
|
5938
|
+
if (!ops) return void 0;
|
|
5939
|
+
const merged = {};
|
|
5940
|
+
for (const sub2 of ops) {
|
|
5941
|
+
if (isFunction2(sub2, "When")) {
|
|
5942
|
+
const sub_ = extractIntervalBounds(sub2, symbol2);
|
|
5943
|
+
if (sub_ !== void 0) _mergeBounds(merged, sub_);
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
return _hasAnyBound(merged) ? merged : void 0;
|
|
5947
|
+
}
|
|
5948
|
+
const result = {};
|
|
5949
|
+
if (isFunction2(expr2, "And")) {
|
|
5950
|
+
const ops = expr2.ops;
|
|
5951
|
+
if (!ops) return void 0;
|
|
5952
|
+
for (const sub2 of ops) {
|
|
5953
|
+
const subBounds = extractIntervalBounds(sub2, symbol2);
|
|
5954
|
+
if (subBounds === void 0) continue;
|
|
5955
|
+
_mergeBounds(result, subBounds);
|
|
5956
|
+
}
|
|
5957
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
5958
|
+
}
|
|
5959
|
+
const op = expr2.operator;
|
|
5960
|
+
if ((op === "Less" || op === "LessEqual" || op === "Greater" || op === "GreaterEqual") && isFunction2(expr2)) {
|
|
5961
|
+
const isStrict = op === "Less" || op === "Greater";
|
|
5962
|
+
const ops = expr2.ops;
|
|
5963
|
+
if (!ops || ops.length < 2) return void 0;
|
|
5964
|
+
const flipped = op === "Greater" || op === "GreaterEqual" ? [...ops].reverse() : ops;
|
|
5965
|
+
for (let i = 0; i < flipped.length; i++) {
|
|
5966
|
+
if (isSymbol2(flipped[i], symbol2)) {
|
|
5967
|
+
if (i > 0) {
|
|
5968
|
+
const candidate = flipped[i - 1];
|
|
5969
|
+
if (result.lower === void 0 || candidate.isGreater(result.lower) === true) {
|
|
5970
|
+
result.lower = candidate;
|
|
5971
|
+
result.lowerStrict = isStrict;
|
|
5972
|
+
}
|
|
5973
|
+
}
|
|
5974
|
+
if (i < flipped.length - 1) {
|
|
5975
|
+
const candidate = flipped[i + 1];
|
|
5976
|
+
if (result.upper === void 0 || candidate.isLess(result.upper) === true) {
|
|
5977
|
+
result.upper = candidate;
|
|
5978
|
+
result.upperStrict = isStrict;
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5983
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
5984
|
+
}
|
|
5985
|
+
return void 0;
|
|
5986
|
+
}
|
|
5987
|
+
function _mergeBounds(into, from) {
|
|
5988
|
+
if (from.lower !== void 0) {
|
|
5989
|
+
if (into.lower === void 0 || from.lower.isGreater(into.lower) === true) {
|
|
5990
|
+
into.lower = from.lower;
|
|
5991
|
+
into.lowerStrict = from.lowerStrict;
|
|
5992
|
+
} else if (from.lower.isSame(into.lower)) {
|
|
5993
|
+
into.lowerStrict = into.lowerStrict || from.lowerStrict;
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
if (from.upper !== void 0) {
|
|
5997
|
+
if (into.upper === void 0 || from.upper.isLess(into.upper) === true) {
|
|
5998
|
+
into.upper = from.upper;
|
|
5999
|
+
into.upperStrict = from.upperStrict;
|
|
6000
|
+
} else if (from.upper.isSame(into.upper)) {
|
|
6001
|
+
into.upperStrict = into.upperStrict || from.upperStrict;
|
|
6002
|
+
}
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
6005
|
+
function _hasAnyBound(b) {
|
|
6006
|
+
return b.lower !== void 0 || b.upper !== void 0;
|
|
6007
|
+
}
|
|
5895
6008
|
function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
5896
6009
|
const result = {};
|
|
5897
6010
|
const assumptions = ce.context?.assumptions;
|
|
@@ -5908,8 +6021,8 @@ function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
|
5908
6021
|
const isStrict = op === "Less";
|
|
5909
6022
|
if (isFunction2(lhs, "Negate") && isSymbol2(lhs.op1, symbol2)) {
|
|
5910
6023
|
const bound = ce.Zero;
|
|
5911
|
-
if (result.
|
|
5912
|
-
result.
|
|
6024
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6025
|
+
result.lower = bound;
|
|
5913
6026
|
result.lowerStrict = isStrict;
|
|
5914
6027
|
}
|
|
5915
6028
|
}
|
|
@@ -5928,16 +6041,16 @@ function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
|
5928
6041
|
}
|
|
5929
6042
|
if (hasNegatedSymbol && constantSum !== 0) {
|
|
5930
6043
|
const bound = ce.expr(constantSum);
|
|
5931
|
-
if (result.
|
|
5932
|
-
result.
|
|
6044
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6045
|
+
result.lower = bound;
|
|
5933
6046
|
result.lowerStrict = isStrict;
|
|
5934
6047
|
}
|
|
5935
6048
|
}
|
|
5936
6049
|
}
|
|
5937
6050
|
if (isSymbol2(lhs, symbol2)) {
|
|
5938
6051
|
const bound = ce.Zero;
|
|
5939
|
-
if (result.
|
|
5940
|
-
result.
|
|
6052
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6053
|
+
result.upper = bound;
|
|
5941
6054
|
result.upperStrict = isStrict;
|
|
5942
6055
|
}
|
|
5943
6056
|
}
|
|
@@ -5956,8 +6069,8 @@ function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
|
5956
6069
|
}
|
|
5957
6070
|
if (hasSymbol && constantSum !== 0) {
|
|
5958
6071
|
const bound = ce.expr(-constantSum);
|
|
5959
|
-
if (result.
|
|
5960
|
-
result.
|
|
6072
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6073
|
+
result.upper = bound;
|
|
5961
6074
|
result.upperStrict = isStrict;
|
|
5962
6075
|
}
|
|
5963
6076
|
}
|
|
@@ -6177,8 +6290,8 @@ function cmp(a, b) {
|
|
|
6177
6290
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, b.symbol);
|
|
6178
6291
|
const aNum = typeof a.numericValue === "number" ? a.numericValue : a.numericValue.re;
|
|
6179
6292
|
if (aNum !== void 0 && Number.isFinite(aNum)) {
|
|
6180
|
-
if (bounds.
|
|
6181
|
-
const lb = bounds.
|
|
6293
|
+
if (bounds.lower !== void 0) {
|
|
6294
|
+
const lb = bounds.lower;
|
|
6182
6295
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6183
6296
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6184
6297
|
if (lowerNum > aNum) return "<";
|
|
@@ -6186,8 +6299,8 @@ function cmp(a, b) {
|
|
|
6186
6299
|
if (lowerNum === aNum && !bounds.lowerStrict) return "<=";
|
|
6187
6300
|
}
|
|
6188
6301
|
}
|
|
6189
|
-
if (bounds.
|
|
6190
|
-
const ub = bounds.
|
|
6302
|
+
if (bounds.upper !== void 0) {
|
|
6303
|
+
const ub = bounds.upper;
|
|
6191
6304
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6192
6305
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6193
6306
|
if (upperNum < aNum) return ">";
|
|
@@ -6217,8 +6330,8 @@ function cmp(a, b) {
|
|
|
6217
6330
|
if (typeof b === "number") {
|
|
6218
6331
|
if (isSymbol2(a)) {
|
|
6219
6332
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6220
|
-
if (bounds.
|
|
6221
|
-
const lb = bounds.
|
|
6333
|
+
if (bounds.lower !== void 0) {
|
|
6334
|
+
const lb = bounds.lower;
|
|
6222
6335
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6223
6336
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6224
6337
|
if (lowerNum > b) return ">";
|
|
@@ -6226,8 +6339,8 @@ function cmp(a, b) {
|
|
|
6226
6339
|
if (lowerNum === b && !bounds.lowerStrict) return ">=";
|
|
6227
6340
|
}
|
|
6228
6341
|
}
|
|
6229
|
-
if (bounds.
|
|
6230
|
-
const ub = bounds.
|
|
6342
|
+
if (bounds.upper !== void 0) {
|
|
6343
|
+
const ub = bounds.upper;
|
|
6231
6344
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6232
6345
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6233
6346
|
if (upperNum < b) return "<";
|
|
@@ -6283,8 +6396,8 @@ function cmp(a, b) {
|
|
|
6283
6396
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6284
6397
|
const bNum = typeof b.numericValue === "number" ? b.numericValue : b.numericValue.re;
|
|
6285
6398
|
if (bNum !== void 0 && Number.isFinite(bNum)) {
|
|
6286
|
-
if (bounds.
|
|
6287
|
-
const lb = bounds.
|
|
6399
|
+
if (bounds.lower !== void 0) {
|
|
6400
|
+
const lb = bounds.lower;
|
|
6288
6401
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6289
6402
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6290
6403
|
if (lowerNum > bNum) return ">";
|
|
@@ -6292,8 +6405,8 @@ function cmp(a, b) {
|
|
|
6292
6405
|
if (lowerNum === bNum && !bounds.lowerStrict) return ">=";
|
|
6293
6406
|
}
|
|
6294
6407
|
}
|
|
6295
|
-
if (bounds.
|
|
6296
|
-
const ub = bounds.
|
|
6408
|
+
if (bounds.upper !== void 0) {
|
|
6409
|
+
const ub = bounds.upper;
|
|
6297
6410
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6298
6411
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6299
6412
|
if (upperNum < bNum) return "<";
|
|
@@ -6831,6 +6944,12 @@ var _BoxedOperatorDefinition = class {
|
|
|
6831
6944
|
scoped = false;
|
|
6832
6945
|
signature;
|
|
6833
6946
|
inferredSignature = true;
|
|
6947
|
+
/** True if this operator definition was created from a user-defined
|
|
6948
|
+
* function literal (e.g. via `ce.assign('f', ce.parse('x \\mapsto x^2'))`).
|
|
6949
|
+
* Used to enable auto-broadcasting when applied to indexed collections.
|
|
6950
|
+
* @internal
|
|
6951
|
+
*/
|
|
6952
|
+
_isLambda = false;
|
|
6834
6953
|
type;
|
|
6835
6954
|
sgn;
|
|
6836
6955
|
eq;
|
|
@@ -6988,6 +7107,8 @@ var _BoxedOperatorDefinition = class {
|
|
|
6988
7107
|
this.engine._typeResolver
|
|
6989
7108
|
);
|
|
6990
7109
|
}
|
|
7110
|
+
if (isFunction2(boxedFn) && boxedFn.operator === "Function")
|
|
7111
|
+
this._isLambda = true;
|
|
6991
7112
|
const fn = applicable(boxedFn);
|
|
6992
7113
|
evaluate2 = (xs, _options) => fn(xs);
|
|
6993
7114
|
Object.defineProperty(evaluate2, "toString", {
|
|
@@ -7838,8 +7959,15 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
7838
7959
|
*
|
|
7839
7960
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7840
7961
|
* (via `fractionalDigits: 'auto'`).
|
|
7962
|
+
*
|
|
7963
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
7964
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
7965
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
7966
|
+
* re-serialization if no verbatim is available.
|
|
7841
7967
|
*/
|
|
7842
7968
|
toLatex(options) {
|
|
7969
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
7970
|
+
return this.verbatimLatex;
|
|
7843
7971
|
if (this.isLazyCollection) {
|
|
7844
7972
|
const materialized = this.evaluate({
|
|
7845
7973
|
materialization: options?.materialization ?? true
|
|
@@ -8297,6 +8425,29 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
8297
8425
|
get isReal() {
|
|
8298
8426
|
return void 0;
|
|
8299
8427
|
}
|
|
8428
|
+
toSignedFunction() {
|
|
8429
|
+
const op = this.operator;
|
|
8430
|
+
if (op === void 0 || this.ops === void 0 || this.ops.length < 2) {
|
|
8431
|
+
return void 0;
|
|
8432
|
+
}
|
|
8433
|
+
const [lhs, rhs] = this.ops;
|
|
8434
|
+
const engine = this.engine;
|
|
8435
|
+
switch (op) {
|
|
8436
|
+
case "Equal":
|
|
8437
|
+
case "NotEqual":
|
|
8438
|
+
case "Less":
|
|
8439
|
+
case "LessEqual":
|
|
8440
|
+
return engine.function("Subtract", [lhs, rhs]);
|
|
8441
|
+
case "Greater":
|
|
8442
|
+
case "GreaterEqual":
|
|
8443
|
+
return engine.function("Subtract", [rhs, lhs]);
|
|
8444
|
+
default:
|
|
8445
|
+
return void 0;
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
8448
|
+
getInterval(symbol2) {
|
|
8449
|
+
return extractIntervalBounds(this, symbol2);
|
|
8450
|
+
}
|
|
8300
8451
|
simplify(_options) {
|
|
8301
8452
|
return this;
|
|
8302
8453
|
}
|
|
@@ -9982,6 +10133,64 @@ function parseQuantifier(kind) {
|
|
|
9982
10133
|
}
|
|
9983
10134
|
|
|
9984
10135
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
10136
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
10137
|
+
x: "First",
|
|
10138
|
+
y: "Second",
|
|
10139
|
+
z: "Third",
|
|
10140
|
+
real: "Real",
|
|
10141
|
+
re: "Real",
|
|
10142
|
+
imag: "Imaginary",
|
|
10143
|
+
im: "Imaginary",
|
|
10144
|
+
count: "Length",
|
|
10145
|
+
total: "Sum",
|
|
10146
|
+
max: "Max",
|
|
10147
|
+
min: "Min"
|
|
10148
|
+
};
|
|
10149
|
+
function memberHead(name) {
|
|
10150
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10151
|
+
}
|
|
10152
|
+
function parseComponentAccess(parser, lhs) {
|
|
10153
|
+
parser.skipVisualSpace();
|
|
10154
|
+
if (parser.match("\\operatorname")) {
|
|
10155
|
+
const name = parser.parseStringGroup();
|
|
10156
|
+
if (name === null) return null;
|
|
10157
|
+
const head = memberHead(name.trim());
|
|
10158
|
+
if (head === null) return null;
|
|
10159
|
+
return [head, lhs];
|
|
10160
|
+
}
|
|
10161
|
+
const tok = parser.peek;
|
|
10162
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10163
|
+
const bare = tok.slice(1);
|
|
10164
|
+
const head = memberHead(bare);
|
|
10165
|
+
if (head !== null) {
|
|
10166
|
+
parser.nextToken();
|
|
10167
|
+
return [head, lhs];
|
|
10168
|
+
}
|
|
10169
|
+
return null;
|
|
10170
|
+
}
|
|
10171
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10172
|
+
const head = memberHead(tok);
|
|
10173
|
+
if (head === null) return null;
|
|
10174
|
+
parser.nextToken();
|
|
10175
|
+
return [head, lhs];
|
|
10176
|
+
}
|
|
10177
|
+
return null;
|
|
10178
|
+
}
|
|
10179
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10180
|
+
parser.addBoundary(close);
|
|
10181
|
+
parser.skipVisualSpace();
|
|
10182
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10183
|
+
if (cond === null) {
|
|
10184
|
+
parser.removeBoundary();
|
|
10185
|
+
return null;
|
|
10186
|
+
}
|
|
10187
|
+
parser.skipVisualSpace();
|
|
10188
|
+
if (!parser.matchBoundary()) {
|
|
10189
|
+
parser.removeBoundary();
|
|
10190
|
+
return null;
|
|
10191
|
+
}
|
|
10192
|
+
return ["When", lhs, cond];
|
|
10193
|
+
}
|
|
9985
10194
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
9986
10195
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
9987
10196
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10257,15 +10466,16 @@ var DEFINITIONS_CORE = [
|
|
|
10257
10466
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
10258
10467
|
parse: parseAssign
|
|
10259
10468
|
},
|
|
10260
|
-
// General colon operator (type annotation, mapping notation)
|
|
10261
|
-
// Precedence below
|
|
10262
|
-
// and below arrows (270) so
|
|
10469
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
10470
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
10471
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
10472
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
10263
10473
|
{
|
|
10264
10474
|
name: "Colon",
|
|
10265
10475
|
latexTrigger: ":",
|
|
10266
10476
|
kind: "infix",
|
|
10267
10477
|
associativity: "right",
|
|
10268
|
-
precedence:
|
|
10478
|
+
precedence: 240,
|
|
10269
10479
|
serialize: (serializer, expr2) => joinLatex([
|
|
10270
10480
|
serializer.serialize(operand(expr2, 1)),
|
|
10271
10481
|
"\\colon",
|
|
@@ -10276,7 +10486,7 @@ var DEFINITIONS_CORE = [
|
|
|
10276
10486
|
latexTrigger: "\\colon",
|
|
10277
10487
|
kind: "infix",
|
|
10278
10488
|
associativity: "right",
|
|
10279
|
-
precedence:
|
|
10489
|
+
precedence: 240,
|
|
10280
10490
|
parse: "Colon"
|
|
10281
10491
|
},
|
|
10282
10492
|
{
|
|
@@ -10453,6 +10663,15 @@ var DEFINITIONS_CORE = [
|
|
|
10453
10663
|
}
|
|
10454
10664
|
},
|
|
10455
10665
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10666
|
+
// Component-access postfix: expr.member (C3)
|
|
10667
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10668
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10669
|
+
{
|
|
10670
|
+
kind: "postfix",
|
|
10671
|
+
precedence: 850,
|
|
10672
|
+
latexTrigger: ["."],
|
|
10673
|
+
parse: parseComponentAccess
|
|
10674
|
+
},
|
|
10456
10675
|
{
|
|
10457
10676
|
name: "At",
|
|
10458
10677
|
kind: "postfix",
|
|
@@ -10473,6 +10692,29 @@ var DEFINITIONS_CORE = [
|
|
|
10473
10692
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10474
10693
|
parse: parseAt("\\right", "\\rbrack")
|
|
10475
10694
|
},
|
|
10695
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10696
|
+
{
|
|
10697
|
+
name: "When",
|
|
10698
|
+
kind: "postfix",
|
|
10699
|
+
precedence: 800,
|
|
10700
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10701
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10702
|
+
serialize: (serializer, expr2) => {
|
|
10703
|
+
const e = operand(expr2, 1);
|
|
10704
|
+
const cond = operand(expr2, 2);
|
|
10705
|
+
if (!e || !cond) return "";
|
|
10706
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10707
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10708
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10709
|
+
}
|
|
10710
|
+
},
|
|
10711
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10712
|
+
{
|
|
10713
|
+
kind: "postfix",
|
|
10714
|
+
precedence: 800,
|
|
10715
|
+
latexTrigger: ["\\{"],
|
|
10716
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10717
|
+
},
|
|
10476
10718
|
{
|
|
10477
10719
|
kind: "postfix",
|
|
10478
10720
|
latexTrigger: ["_"],
|
|
@@ -10555,6 +10797,29 @@ var DEFINITIONS_CORE = [
|
|
|
10555
10797
|
return "";
|
|
10556
10798
|
}
|
|
10557
10799
|
},
|
|
10800
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10801
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10802
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10803
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10804
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10805
|
+
{
|
|
10806
|
+
latexTrigger: [".", ".", "."],
|
|
10807
|
+
kind: "infix",
|
|
10808
|
+
precedence: 800,
|
|
10809
|
+
parse: parseRange
|
|
10810
|
+
},
|
|
10811
|
+
{
|
|
10812
|
+
latexTrigger: ["\\ldots"],
|
|
10813
|
+
kind: "infix",
|
|
10814
|
+
precedence: 800,
|
|
10815
|
+
parse: parseRange
|
|
10816
|
+
},
|
|
10817
|
+
{
|
|
10818
|
+
latexTrigger: ["\\dots"],
|
|
10819
|
+
kind: "infix",
|
|
10820
|
+
precedence: 800,
|
|
10821
|
+
parse: parseRange
|
|
10822
|
+
},
|
|
10558
10823
|
{
|
|
10559
10824
|
latexTrigger: [";"],
|
|
10560
10825
|
kind: "infix",
|
|
@@ -10739,13 +11004,24 @@ var DEFINITIONS_CORE = [
|
|
|
10739
11004
|
const args = operands(expr2);
|
|
10740
11005
|
if (!args || args.length < 2) return "";
|
|
10741
11006
|
const body = args[0];
|
|
10742
|
-
const
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
11007
|
+
const elements = args.slice(1);
|
|
11008
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
11009
|
+
if (!allElements) {
|
|
11010
|
+
return joinLatex([
|
|
11011
|
+
"\\operatorname{Loop}(",
|
|
11012
|
+
serializer.serialize(body),
|
|
11013
|
+
", ",
|
|
11014
|
+
serializer.serialize(elements[0]),
|
|
11015
|
+
")"
|
|
11016
|
+
]);
|
|
11017
|
+
}
|
|
11018
|
+
if (elements.length === 1) {
|
|
11019
|
+
const elem = elements[0];
|
|
11020
|
+
const index = operand(elem, 1);
|
|
11021
|
+
const coll = operand(elem, 2);
|
|
11022
|
+
if (operator(coll) === "Range") {
|
|
11023
|
+
const lo = operand(coll, 1);
|
|
11024
|
+
const hi = operand(coll, 2);
|
|
10749
11025
|
return joinLatex([
|
|
10750
11026
|
"\\text{for }",
|
|
10751
11027
|
serializer.serialize(index),
|
|
@@ -10757,13 +11033,27 @@ var DEFINITIONS_CORE = [
|
|
|
10757
11033
|
serializer.serialize(body)
|
|
10758
11034
|
]);
|
|
10759
11035
|
}
|
|
11036
|
+
return joinLatex([
|
|
11037
|
+
serializer.serialize(body),
|
|
11038
|
+
" \\operatorname{for} ",
|
|
11039
|
+
serializer.serialize(index),
|
|
11040
|
+
" = ",
|
|
11041
|
+
serializer.serialize(coll)
|
|
11042
|
+
]);
|
|
10760
11043
|
}
|
|
11044
|
+
const bindings = elements.map((elem) => {
|
|
11045
|
+
const name = operand(elem, 1);
|
|
11046
|
+
const coll = operand(elem, 2);
|
|
11047
|
+
return joinLatex([
|
|
11048
|
+
serializer.serialize(name),
|
|
11049
|
+
" = ",
|
|
11050
|
+
serializer.serialize(coll)
|
|
11051
|
+
]);
|
|
11052
|
+
}).join(", ");
|
|
10761
11053
|
return joinLatex([
|
|
10762
|
-
"\\operatorname{Loop}(",
|
|
10763
11054
|
serializer.serialize(body),
|
|
10764
|
-
"
|
|
10765
|
-
|
|
10766
|
-
")"
|
|
11055
|
+
" \\operatorname{for} ",
|
|
11056
|
+
bindings
|
|
10767
11057
|
]);
|
|
10768
11058
|
}
|
|
10769
11059
|
},
|
|
@@ -10796,6 +11086,18 @@ var DEFINITIONS_CORE = [
|
|
|
10796
11086
|
precedence: 245,
|
|
10797
11087
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10798
11088
|
},
|
|
11089
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
11090
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
11091
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
11092
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
11093
|
+
// bindings can be comma-separated below us.
|
|
11094
|
+
{
|
|
11095
|
+
symbolTrigger: "for",
|
|
11096
|
+
kind: "infix",
|
|
11097
|
+
associativity: "none",
|
|
11098
|
+
precedence: 19,
|
|
11099
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
11100
|
+
},
|
|
10799
11101
|
// \operatorname{break}
|
|
10800
11102
|
{
|
|
10801
11103
|
symbolTrigger: "break",
|
|
@@ -11000,7 +11302,10 @@ var DEFINITIONS_CORE = [
|
|
|
11000
11302
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
11001
11303
|
parser.addBoundary([")"]);
|
|
11002
11304
|
const expr2 = parser.parseExpression(until);
|
|
11003
|
-
if (!parser.matchBoundary())
|
|
11305
|
+
if (!parser.matchBoundary()) {
|
|
11306
|
+
parser.removeBoundary();
|
|
11307
|
+
return null;
|
|
11308
|
+
}
|
|
11004
11309
|
if (!parser.match("<}>")) return null;
|
|
11005
11310
|
return ["Derivative", lhs, expr2];
|
|
11006
11311
|
}
|
|
@@ -11441,7 +11746,12 @@ function parseBrackets(parser, body) {
|
|
|
11441
11746
|
if (isEmptySequence(body)) return ["List"];
|
|
11442
11747
|
const h = operator(body);
|
|
11443
11748
|
if (h === "Range" || h === "Linspace") return body;
|
|
11444
|
-
if (h === "Sequence")
|
|
11749
|
+
if (h === "Sequence") {
|
|
11750
|
+
const elems = operands(body);
|
|
11751
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11752
|
+
if (inferred) return inferred;
|
|
11753
|
+
return ["List", ...elems];
|
|
11754
|
+
}
|
|
11445
11755
|
if (h === "Delimiter") {
|
|
11446
11756
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11447
11757
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11454,12 +11764,37 @@ function parseBrackets(parser, body) {
|
|
|
11454
11764
|
}
|
|
11455
11765
|
if (delim === "," || delim === ".,.") {
|
|
11456
11766
|
body = operand(body, 1);
|
|
11457
|
-
if (operator(body) === "Sequence")
|
|
11767
|
+
if (operator(body) === "Sequence") {
|
|
11768
|
+
const elems = operands(body);
|
|
11769
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11770
|
+
if (inferred) return inferred;
|
|
11771
|
+
return ["List", ...elems];
|
|
11772
|
+
}
|
|
11458
11773
|
return ["List", body ?? "Nothing"];
|
|
11459
11774
|
}
|
|
11460
11775
|
}
|
|
11461
11776
|
return ["List", body];
|
|
11462
11777
|
}
|
|
11778
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11779
|
+
if (elems.length < 4) return null;
|
|
11780
|
+
const penultimate = elems[elems.length - 2];
|
|
11781
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11782
|
+
const samples = elems.slice(0, -2);
|
|
11783
|
+
const endExpr = elems[elems.length - 1];
|
|
11784
|
+
if (samples.length < 2) return null;
|
|
11785
|
+
const sampleNums = samples.map(machineValue);
|
|
11786
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11787
|
+
const nums = sampleNums;
|
|
11788
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11789
|
+
const tol = parser.options.tolerance;
|
|
11790
|
+
if (Math.abs(step) < tol)
|
|
11791
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11792
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11793
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11794
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11795
|
+
}
|
|
11796
|
+
return ["Range", nums[0], endExpr, step];
|
|
11797
|
+
}
|
|
11463
11798
|
function serializeList(serializer, expr2) {
|
|
11464
11799
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11465
11800
|
const op = operator(x);
|
|
@@ -11711,6 +12046,38 @@ function parseForExpression(parser, until) {
|
|
|
11711
12046
|
["Element", index, ["Range", lower, upper]]
|
|
11712
12047
|
];
|
|
11713
12048
|
}
|
|
12049
|
+
function parseForComprehension(parser, lhs, until) {
|
|
12050
|
+
const bindingTerminator = {
|
|
12051
|
+
minPrec: 21,
|
|
12052
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
12053
|
+
condition: (p) => {
|
|
12054
|
+
if (until?.condition?.(p)) return true;
|
|
12055
|
+
const saved = p.index;
|
|
12056
|
+
p.skipVisualSpace();
|
|
12057
|
+
const isComma = p.peek === ",";
|
|
12058
|
+
p.index = saved;
|
|
12059
|
+
if (isComma) return true;
|
|
12060
|
+
if (peekKeyword(p, "where")) return true;
|
|
12061
|
+
if (peekKeyword(p, "with")) return true;
|
|
12062
|
+
return false;
|
|
12063
|
+
}
|
|
12064
|
+
};
|
|
12065
|
+
const elements = [];
|
|
12066
|
+
do {
|
|
12067
|
+
parser.skipVisualSpace();
|
|
12068
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
12069
|
+
if (binding === null) break;
|
|
12070
|
+
const op = operator(binding);
|
|
12071
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
12072
|
+
const name = operand(binding, 1);
|
|
12073
|
+
const list = operand(binding, 2);
|
|
12074
|
+
if (!name || !list) return null;
|
|
12075
|
+
elements.push(["Element", name, list]);
|
|
12076
|
+
parser.skipVisualSpace();
|
|
12077
|
+
} while (parser.match(","));
|
|
12078
|
+
if (elements.length === 0) return null;
|
|
12079
|
+
return ["Loop", lhs, ...elements];
|
|
12080
|
+
}
|
|
11714
12081
|
function parseWhereExpression(parser, lhs, until) {
|
|
11715
12082
|
const bindingTerminator = {
|
|
11716
12083
|
minPrec: 21,
|
|
@@ -11733,6 +12100,25 @@ function parseWhereExpression(parser, lhs, until) {
|
|
|
11733
12100
|
parser.skipVisualSpace();
|
|
11734
12101
|
} while (parser.match(","));
|
|
11735
12102
|
if (bindings.length === 0) return null;
|
|
12103
|
+
const forStart = parser.index;
|
|
12104
|
+
if (matchKeyword(parser, "for")) {
|
|
12105
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
12106
|
+
if (loop) {
|
|
12107
|
+
const block2 = [];
|
|
12108
|
+
for (const b of bindings) {
|
|
12109
|
+
const normalized = normalizeLocalAssign(b);
|
|
12110
|
+
if (operator(normalized) === "Assign") {
|
|
12111
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
12112
|
+
block2.push(normalized);
|
|
12113
|
+
} else {
|
|
12114
|
+
block2.push(normalized);
|
|
12115
|
+
}
|
|
12116
|
+
}
|
|
12117
|
+
block2.push(loop);
|
|
12118
|
+
return ["Block", ...block2];
|
|
12119
|
+
}
|
|
12120
|
+
parser.index = forStart;
|
|
12121
|
+
}
|
|
11736
12122
|
const block = [];
|
|
11737
12123
|
for (const b of bindings) {
|
|
11738
12124
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -11946,6 +12332,17 @@ function parseIntervalBody(body, openLeft, openRight) {
|
|
|
11946
12332
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
11947
12333
|
return ["Interval", lowerExpr, upperExpr];
|
|
11948
12334
|
}
|
|
12335
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
12336
|
+
"Less",
|
|
12337
|
+
"LessEqual",
|
|
12338
|
+
"Greater",
|
|
12339
|
+
"GreaterEqual",
|
|
12340
|
+
"Equal",
|
|
12341
|
+
"NotEqual",
|
|
12342
|
+
"And",
|
|
12343
|
+
"Or",
|
|
12344
|
+
"Not"
|
|
12345
|
+
]);
|
|
11949
12346
|
var DEFINITIONS_SETS = [
|
|
11950
12347
|
//
|
|
11951
12348
|
// Constants
|
|
@@ -12204,18 +12601,58 @@ var DEFINITIONS_SETS = [
|
|
|
12204
12601
|
closeTrigger: "}",
|
|
12205
12602
|
parse: (_parser, body) => {
|
|
12206
12603
|
if (isEmptySequence(body)) return "EmptySet";
|
|
12604
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
12605
|
+
body = operand(body, 1);
|
|
12606
|
+
}
|
|
12207
12607
|
const h = operator(body);
|
|
12208
|
-
if (h === "Divides"
|
|
12608
|
+
if (h === "Divides") {
|
|
12209
12609
|
const expr2 = operand(body, 1);
|
|
12210
12610
|
const condition = operand(body, 2);
|
|
12211
12611
|
if (expr2 !== null && condition !== null)
|
|
12212
12612
|
return ["Set", expr2, ["Condition", condition]];
|
|
12213
12613
|
}
|
|
12214
|
-
if (
|
|
12215
|
-
|
|
12614
|
+
if (h === "Colon") {
|
|
12615
|
+
const lhs = operand(body, 1);
|
|
12616
|
+
const rhs = operand(body, 2);
|
|
12617
|
+
if (lhs !== null && rhs !== null) {
|
|
12618
|
+
const lhsOp = operator(lhs);
|
|
12619
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
12620
|
+
return ["Which", lhs, rhs];
|
|
12621
|
+
}
|
|
12622
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
12623
|
+
}
|
|
12624
|
+
}
|
|
12625
|
+
if (h === "Sequence") {
|
|
12626
|
+
const elements = operands(body);
|
|
12627
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
12628
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
12629
|
+
const lhs = operand(el, 1);
|
|
12630
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
12631
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
12632
|
+
});
|
|
12633
|
+
if (allPiecewise) {
|
|
12634
|
+
const whichOps = [];
|
|
12635
|
+
for (let i = 0; i < elements.length; i++) {
|
|
12636
|
+
const el = elements[i];
|
|
12637
|
+
if (operator(el) === "Colon") {
|
|
12638
|
+
const cond = operand(el, 1);
|
|
12639
|
+
const val = operand(el, 2);
|
|
12640
|
+
if (cond === null || val === null) {
|
|
12641
|
+
return ["Set", ...elements];
|
|
12642
|
+
}
|
|
12643
|
+
whichOps.push(cond, val);
|
|
12644
|
+
} else {
|
|
12645
|
+
if (i !== elements.length - 1) {
|
|
12646
|
+
return ["Set", ...elements];
|
|
12647
|
+
}
|
|
12648
|
+
whichOps.push("True", el);
|
|
12649
|
+
}
|
|
12650
|
+
}
|
|
12651
|
+
return ["Which", ...whichOps];
|
|
12652
|
+
}
|
|
12653
|
+
return ["Set", ...elements];
|
|
12216
12654
|
}
|
|
12217
|
-
|
|
12218
|
-
return ["Set", ...operands(body)];
|
|
12655
|
+
return ["Set", body];
|
|
12219
12656
|
},
|
|
12220
12657
|
serialize: (serializer, expr2) => {
|
|
12221
12658
|
if (nops(expr2) === 2 && operator(operand(expr2, 2)) === "Condition") {
|
|
@@ -14219,7 +14656,8 @@ function parseTrig(op) {
|
|
|
14219
14656
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
14220
14657
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
14221
14658
|
});
|
|
14222
|
-
const
|
|
14659
|
+
const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
|
|
14660
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
14223
14661
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
14224
14662
|
};
|
|
14225
14663
|
}
|
|
@@ -16435,10 +16873,17 @@ var DEFINITIONS_OTHERS = [
|
|
|
16435
16873
|
// The capitalized library entries already exist; these are pure parse
|
|
16436
16874
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16437
16875
|
// ---------------------------------------------------------------------------
|
|
16876
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
16438
16877
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16439
16878
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16440
16879
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16441
16880
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16881
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
16882
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
16883
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
16884
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
16885
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
16886
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
16442
16887
|
// ---------------------------------------------------------------------------
|
|
16443
16888
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16444
16889
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -19482,6 +19927,19 @@ var _Parser = class __Parser {
|
|
|
19482
19927
|
} while (postfix !== null);
|
|
19483
19928
|
}
|
|
19484
19929
|
if (result !== null) result = this.parseSupsub(result);
|
|
19930
|
+
if (result !== null) {
|
|
19931
|
+
let postfix = null;
|
|
19932
|
+
let index = this.index;
|
|
19933
|
+
do {
|
|
19934
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
19935
|
+
result = postfix ?? result;
|
|
19936
|
+
if (this.index === index && postfix !== null) {
|
|
19937
|
+
console.assert(this.index !== index, "No token consumed");
|
|
19938
|
+
break;
|
|
19939
|
+
}
|
|
19940
|
+
index = this.index;
|
|
19941
|
+
} while (postfix !== null);
|
|
19942
|
+
}
|
|
19485
19943
|
if (result === null) {
|
|
19486
19944
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19487
19945
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -19990,6 +20448,28 @@ function toDecimalNumber(wholePart, fractionalPart, exp3) {
|
|
|
19990
20448
|
}
|
|
19991
20449
|
|
|
19992
20450
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20451
|
+
var DOT_NOTATION_MAP = {
|
|
20452
|
+
First: ".x",
|
|
20453
|
+
Second: ".y",
|
|
20454
|
+
Third: ".z",
|
|
20455
|
+
Real: ".\\operatorname{real}",
|
|
20456
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20457
|
+
Length: ".\\operatorname{count}",
|
|
20458
|
+
Sum: ".\\operatorname{total}",
|
|
20459
|
+
Max: ".\\max",
|
|
20460
|
+
Min: ".\\min"
|
|
20461
|
+
};
|
|
20462
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20463
|
+
if (!serializer.options.dotNotation) return null;
|
|
20464
|
+
const ops = operands(expr2);
|
|
20465
|
+
if (!ops || ops.length !== 1) return null;
|
|
20466
|
+
const head = operator(expr2);
|
|
20467
|
+
if (!head) return null;
|
|
20468
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20469
|
+
if (suffix === void 0) return null;
|
|
20470
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20471
|
+
return `${lhs}${suffix}`;
|
|
20472
|
+
}
|
|
19993
20473
|
var ACCENT_MODIFIERS = {
|
|
19994
20474
|
deg: (s) => `${s}\\degree`,
|
|
19995
20475
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -20033,6 +20513,7 @@ var Serializer5 = class {
|
|
|
20033
20513
|
constructor(dictionary, options) {
|
|
20034
20514
|
this.dictionary = dictionary;
|
|
20035
20515
|
this.options = {
|
|
20516
|
+
dotNotation: false,
|
|
20036
20517
|
dmsFormat: false,
|
|
20037
20518
|
angleNormalization: "none",
|
|
20038
20519
|
...options
|
|
@@ -20131,6 +20612,8 @@ var Serializer5 = class {
|
|
|
20131
20612
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
20132
20613
|
}
|
|
20133
20614
|
serializeFunction(expr2, def) {
|
|
20615
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20616
|
+
if (dotResult !== null) return dotResult;
|
|
20134
20617
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
20135
20618
|
const h = operator(expr2);
|
|
20136
20619
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20373,6 +20856,8 @@ function defaultParseOptions(opts) {
|
|
|
20373
20856
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20374
20857
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20375
20858
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20859
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20860
|
+
tolerance: 1e-7,
|
|
20376
20861
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20377
20862
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20378
20863
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20405,6 +20890,7 @@ function defaultSerializeOptions(opts) {
|
|
|
20405
20890
|
invisiblePlus: "",
|
|
20406
20891
|
multiply: "\\times",
|
|
20407
20892
|
missingSymbol: "\\blacksquare",
|
|
20893
|
+
dotNotation: false,
|
|
20408
20894
|
dmsFormat: false,
|
|
20409
20895
|
angleNormalization: "none",
|
|
20410
20896
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -22239,6 +22725,15 @@ function expressionTensorInfo(operator2, rows) {
|
|
|
22239
22725
|
}
|
|
22240
22726
|
} else {
|
|
22241
22727
|
for (const item of t) {
|
|
22728
|
+
const op = item.operator;
|
|
22729
|
+
if (op === "Tuple" || op === "Pair" || op === "Single" || op === "Triple" || op === "Quadruple" || op === "KeyValuePair" || op === "Dictionary" || op === "Set" || op === "Record") {
|
|
22730
|
+
valid = false;
|
|
22731
|
+
return;
|
|
22732
|
+
}
|
|
22733
|
+
if (item.type.type === "string") {
|
|
22734
|
+
valid = false;
|
|
22735
|
+
return;
|
|
22736
|
+
}
|
|
22242
22737
|
dtype = getSupertype(dtype, getExpressionDatatype(item));
|
|
22243
22738
|
}
|
|
22244
22739
|
}
|
|
@@ -27274,6 +27769,15 @@ function interval(expr2) {
|
|
|
27274
27769
|
return void 0;
|
|
27275
27770
|
}
|
|
27276
27771
|
|
|
27772
|
+
// src/compute-engine/numerics/random.ts
|
|
27773
|
+
function deterministicRandom(seed) {
|
|
27774
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
27775
|
+
return v - Math.floor(v);
|
|
27776
|
+
}
|
|
27777
|
+
function nextSeed(seed) {
|
|
27778
|
+
return seed + 0.6180339887498949;
|
|
27779
|
+
}
|
|
27780
|
+
|
|
27277
27781
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
27278
27782
|
function canonical(ce, xs, scope) {
|
|
27279
27783
|
if (xs.every((x) => x.isCanonical)) return xs;
|
|
@@ -27323,6 +27827,19 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27323
27827
|
indexWhere: void 0
|
|
27324
27828
|
}
|
|
27325
27829
|
},
|
|
27830
|
+
Length: {
|
|
27831
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
27832
|
+
complexity: 4e3,
|
|
27833
|
+
signature: "(any) -> integer",
|
|
27834
|
+
type: () => "integer",
|
|
27835
|
+
evaluate: ([xs], { engine }) => {
|
|
27836
|
+
if (!xs.isCollection) return void 0;
|
|
27837
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
27838
|
+
const n = xs.count;
|
|
27839
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
27840
|
+
return engine.number(n);
|
|
27841
|
+
}
|
|
27842
|
+
},
|
|
27326
27843
|
Tuple: {
|
|
27327
27844
|
description: "A fixed number of heterogeneous elements",
|
|
27328
27845
|
complexity: 8200,
|
|
@@ -27375,7 +27892,11 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27375
27892
|
//
|
|
27376
27893
|
Range: {
|
|
27377
27894
|
complexity: 8200,
|
|
27378
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27895
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27896
|
+
type: (ops) => {
|
|
27897
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27898
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27899
|
+
},
|
|
27379
27900
|
canonical: (ops, { engine: ce }) => {
|
|
27380
27901
|
if (ops.length === 0) return null;
|
|
27381
27902
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27399,19 +27920,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27399
27920
|
const [lower, upper, step] = range(expr2);
|
|
27400
27921
|
if (step === 0) return 0;
|
|
27401
27922
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27402
|
-
return
|
|
27923
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27403
27924
|
},
|
|
27404
27925
|
contains: (expr2, target) => {
|
|
27405
|
-
if (!target.type.matches("integer")) return false;
|
|
27406
27926
|
const t = target.re;
|
|
27927
|
+
if (!isFinite(t)) return false;
|
|
27407
27928
|
const [lower, upper, step] = range(expr2);
|
|
27408
27929
|
if (step === 0) return false;
|
|
27409
|
-
if (step > 0)
|
|
27410
|
-
|
|
27930
|
+
if (step > 0) {
|
|
27931
|
+
if (t < lower || t > upper) return false;
|
|
27932
|
+
} else {
|
|
27933
|
+
if (t > lower || t < upper) return false;
|
|
27934
|
+
}
|
|
27935
|
+
const k = (t - lower) / step;
|
|
27936
|
+
const tol = expr2.engine.tolerance;
|
|
27937
|
+
const kRounded = Math.round(k);
|
|
27938
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27411
27939
|
},
|
|
27412
27940
|
iterator: (expr2) => {
|
|
27413
27941
|
const [lower, upper, step] = range(expr2);
|
|
27414
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
27942
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27415
27943
|
let index = 1;
|
|
27416
27944
|
return {
|
|
27417
27945
|
next: () => {
|
|
@@ -27429,7 +27957,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27429
27957
|
at: (expr2, index) => {
|
|
27430
27958
|
if (typeof index !== "number") return void 0;
|
|
27431
27959
|
const [lower, upper, step] = range(expr2);
|
|
27432
|
-
if (
|
|
27960
|
+
if (step === 0) return void 0;
|
|
27961
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27962
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27433
27963
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27434
27964
|
},
|
|
27435
27965
|
indexWhere: void 0,
|
|
@@ -27454,7 +27984,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27454
27984
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27455
27985
|
return lower >= upper ? "positive" : "negative";
|
|
27456
27986
|
},
|
|
27457
|
-
elttype: (
|
|
27987
|
+
elttype: (expr2) => {
|
|
27988
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
27989
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
27990
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
27991
|
+
}
|
|
27992
|
+
return "finite_integer";
|
|
27993
|
+
}
|
|
27458
27994
|
}
|
|
27459
27995
|
},
|
|
27460
27996
|
Interval: {
|
|
@@ -27557,10 +28093,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27557
28093
|
const upper = expr2.op2.re;
|
|
27558
28094
|
let count = expr2.op3.re;
|
|
27559
28095
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28096
|
+
count = Math.floor(count);
|
|
27560
28097
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
27561
28098
|
if (index < 1 || index > count) return void 0;
|
|
28099
|
+
if (count === 1) return expr2.engine.number(lower);
|
|
27562
28100
|
return expr2.engine.number(
|
|
27563
|
-
lower + (upper - lower) * (index - 1) / count
|
|
28101
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
27564
28102
|
);
|
|
27565
28103
|
},
|
|
27566
28104
|
iterator: (expr2) => {
|
|
@@ -27579,6 +28117,8 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27579
28117
|
!isFinite(expr2.op3.re) ? DEFAULT_LINSPACE_COUNT : expr2.op3.re
|
|
27580
28118
|
);
|
|
27581
28119
|
}
|
|
28120
|
+
totalCount = Math.floor(totalCount);
|
|
28121
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
27582
28122
|
let index = 1;
|
|
27583
28123
|
return {
|
|
27584
28124
|
next: () => {
|
|
@@ -27587,7 +28127,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27587
28127
|
index += 1;
|
|
27588
28128
|
return {
|
|
27589
28129
|
value: expr2.engine.number(
|
|
27590
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
28130
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
27591
28131
|
),
|
|
27592
28132
|
done: false
|
|
27593
28133
|
};
|
|
@@ -27603,9 +28143,14 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27603
28143
|
if (t < lower || t > upper) return false;
|
|
27604
28144
|
let count = expr2.op3.re;
|
|
27605
28145
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28146
|
+
count = Math.floor(count);
|
|
27606
28147
|
if (count === 0) return false;
|
|
27607
|
-
|
|
27608
|
-
|
|
28148
|
+
if (count === 1) return t === lower;
|
|
28149
|
+
const step = (upper - lower) / (count - 1);
|
|
28150
|
+
const k = (t - lower) / step;
|
|
28151
|
+
const tol = expr2.engine.tolerance;
|
|
28152
|
+
const kRounded = Math.round(k);
|
|
28153
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
27609
28154
|
}
|
|
27610
28155
|
}
|
|
27611
28156
|
},
|
|
@@ -27930,10 +28475,12 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27930
28475
|
description: [
|
|
27931
28476
|
"Access an element of an indexed collection.",
|
|
27932
28477
|
"If the index is negative, it is counted from the end.",
|
|
27933
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
28478
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
28479
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
28480
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
27934
28481
|
],
|
|
27935
28482
|
complexity: 8200,
|
|
27936
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
28483
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
27937
28484
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
27938
28485
|
evaluate: (ops, { engine: ce }) => {
|
|
27939
28486
|
let expr2 = ops[0];
|
|
@@ -27944,12 +28491,39 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27944
28491
|
if (!at) return void 0;
|
|
27945
28492
|
const opAtIndex = ops[index];
|
|
27946
28493
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
27947
|
-
if (s !== void 0)
|
|
27948
|
-
|
|
27949
|
-
|
|
27950
|
-
|
|
27951
|
-
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
28494
|
+
if (s !== void 0) {
|
|
28495
|
+
expr2 = at(expr2, s) ?? ce.Nothing;
|
|
28496
|
+
index += 1;
|
|
28497
|
+
continue;
|
|
27952
28498
|
}
|
|
28499
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
28500
|
+
const indices = Array.from(opAtIndex.each());
|
|
28501
|
+
const isMask = indices.every((m) => {
|
|
28502
|
+
const name = sym(m);
|
|
28503
|
+
return name === "True" || name === "False";
|
|
28504
|
+
});
|
|
28505
|
+
const picked = [];
|
|
28506
|
+
if (isMask) {
|
|
28507
|
+
indices.forEach((m, i2) => {
|
|
28508
|
+
if (sym(m) !== "True") return;
|
|
28509
|
+
const v = at(expr2, i2 + 1);
|
|
28510
|
+
if (v !== void 0) picked.push(v);
|
|
28511
|
+
});
|
|
28512
|
+
} else {
|
|
28513
|
+
for (const m of indices) {
|
|
28514
|
+
const k = m.re;
|
|
28515
|
+
if (!Number.isInteger(k)) return void 0;
|
|
28516
|
+
const v = at(expr2, k);
|
|
28517
|
+
if (v !== void 0) picked.push(v);
|
|
28518
|
+
}
|
|
28519
|
+
}
|
|
28520
|
+
expr2 = ce._fn("List", picked);
|
|
28521
|
+
index += 1;
|
|
28522
|
+
continue;
|
|
28523
|
+
}
|
|
28524
|
+
const i = opAtIndex.re;
|
|
28525
|
+
if (!Number.isInteger(i)) return void 0;
|
|
28526
|
+
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
27953
28527
|
index += 1;
|
|
27954
28528
|
}
|
|
27955
28529
|
return expr2;
|
|
@@ -27960,7 +28534,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27960
28534
|
description: ["Return `n` elements from a collection."],
|
|
27961
28535
|
complexity: 8200,
|
|
27962
28536
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
27963
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
28537
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
27964
28538
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
27965
28539
|
if (!eager) return void 0;
|
|
27966
28540
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -28007,7 +28581,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28007
28581
|
description: ["Return the collection without the first n elements."],
|
|
28008
28582
|
complexity: 8200,
|
|
28009
28583
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
28010
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
28584
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28011
28585
|
collection: {
|
|
28012
28586
|
isLazy: (_expr) => true,
|
|
28013
28587
|
count: (expr2) => {
|
|
@@ -28052,15 +28626,45 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28052
28626
|
},
|
|
28053
28627
|
First: {
|
|
28054
28628
|
complexity: 8200,
|
|
28055
|
-
signature: "(
|
|
28629
|
+
signature: "(any) -> any",
|
|
28056
28630
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28057
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28631
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28632
|
+
if (!xs.isCollection)
|
|
28633
|
+
return ce.error([
|
|
28634
|
+
"incompatible-type",
|
|
28635
|
+
`'collection'`,
|
|
28636
|
+
xs.type.toString()
|
|
28637
|
+
]);
|
|
28638
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28639
|
+
}
|
|
28058
28640
|
},
|
|
28059
28641
|
Second: {
|
|
28060
28642
|
complexity: 8200,
|
|
28061
|
-
signature: "(
|
|
28643
|
+
signature: "(any) -> any",
|
|
28644
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28645
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28646
|
+
if (!xs.isCollection)
|
|
28647
|
+
return ce.error([
|
|
28648
|
+
"incompatible-type",
|
|
28649
|
+
`'collection'`,
|
|
28650
|
+
xs.type.toString()
|
|
28651
|
+
]);
|
|
28652
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28653
|
+
}
|
|
28654
|
+
},
|
|
28655
|
+
Third: {
|
|
28656
|
+
complexity: 8200,
|
|
28657
|
+
signature: "(any) -> any",
|
|
28062
28658
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28063
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28659
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28660
|
+
if (!xs.isCollection)
|
|
28661
|
+
return ce.error([
|
|
28662
|
+
"incompatible-type",
|
|
28663
|
+
`'collection'`,
|
|
28664
|
+
xs.type.toString()
|
|
28665
|
+
]);
|
|
28666
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28667
|
+
}
|
|
28064
28668
|
},
|
|
28065
28669
|
Last: {
|
|
28066
28670
|
complexity: 8200,
|
|
@@ -28173,7 +28777,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28173
28777
|
],
|
|
28174
28778
|
complexity: 8200,
|
|
28175
28779
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
28176
|
-
type: ([xs]) => parseType(
|
|
28780
|
+
type: ([xs]) => parseType(
|
|
28781
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
28782
|
+
),
|
|
28177
28783
|
collection: {
|
|
28178
28784
|
isLazy: (_expr) => true,
|
|
28179
28785
|
count: (expr2) => {
|
|
@@ -28505,16 +29111,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28505
29111
|
},
|
|
28506
29112
|
// Randomize the order of the elements in the collection.
|
|
28507
29113
|
Shuffle: {
|
|
28508
|
-
description: "Randomize the order of the elements in the collection.",
|
|
29114
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
28509
29115
|
complexity: 8200,
|
|
28510
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
29116
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
28511
29117
|
type: (ops) => ops[0].type,
|
|
28512
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
29118
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
28513
29119
|
if (!xs.isFiniteCollection) return void 0;
|
|
28514
29120
|
const data = Array.from(xs.each());
|
|
28515
|
-
|
|
28516
|
-
|
|
28517
|
-
|
|
29121
|
+
const seed = seedOp?.re;
|
|
29122
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
29123
|
+
let s = seed;
|
|
29124
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29125
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
29126
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29127
|
+
s = nextSeed(s);
|
|
29128
|
+
}
|
|
29129
|
+
} else {
|
|
29130
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29131
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
29132
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29133
|
+
}
|
|
28518
29134
|
}
|
|
28519
29135
|
return ce.function(xs.operator, data);
|
|
28520
29136
|
}
|
|
@@ -28581,7 +29197,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28581
29197
|
if (t === "string")
|
|
28582
29198
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
28583
29199
|
return parseType(
|
|
28584
|
-
`tuple<list<${
|
|
29200
|
+
`tuple<list<${typeToString(
|
|
29201
|
+
collectionElementType(t) ?? "any"
|
|
29202
|
+
)}>, list<integer>>`
|
|
28585
29203
|
);
|
|
28586
29204
|
},
|
|
28587
29205
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -28597,7 +29215,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28597
29215
|
description: "Return a list of the unique elements of the collection.",
|
|
28598
29216
|
complexity: 8200,
|
|
28599
29217
|
signature: "(collection) -> list",
|
|
28600
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29218
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28601
29219
|
evaluate: (ops, { engine: ce }) => {
|
|
28602
29220
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
28603
29221
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -28609,7 +29227,7 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28609
29227
|
wikidata: "Q381060",
|
|
28610
29228
|
complexity: 8200,
|
|
28611
29229
|
signature: "(collection, integer | function) -> list",
|
|
28612
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29230
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28613
29231
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
28614
29232
|
if (!xs.isFiniteCollection) return void 0;
|
|
28615
29233
|
const k = toInteger(arg);
|
|
@@ -28783,32 +29401,74 @@ var COLLECTIONS_LIBRARY = {
|
|
|
28783
29401
|
}
|
|
28784
29402
|
}
|
|
28785
29403
|
},
|
|
28786
|
-
// Repeat(x) -> [x, x, ...]
|
|
28787
|
-
//
|
|
28788
|
-
// x is evaluated once. Although could use Hold()?
|
|
28789
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
29404
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
29405
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
28790
29406
|
Repeat: {
|
|
28791
|
-
description: "Produce
|
|
29407
|
+
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.",
|
|
28792
29408
|
complexity: 8200,
|
|
28793
|
-
signature: "(value: any) -> list",
|
|
29409
|
+
signature: "(value: any, count: integer?) -> list",
|
|
29410
|
+
evaluate: (ops, { engine }) => {
|
|
29411
|
+
if (ops.length !== 2) return void 0;
|
|
29412
|
+
const raw = toInteger(ops[1]);
|
|
29413
|
+
if (raw === null) return void 0;
|
|
29414
|
+
const n = Math.max(0, raw);
|
|
29415
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
29416
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
29417
|
+
},
|
|
28794
29418
|
collection: {
|
|
28795
|
-
isLazy: (
|
|
28796
|
-
count: () =>
|
|
28797
|
-
|
|
28798
|
-
|
|
28799
|
-
|
|
28800
|
-
|
|
29419
|
+
isLazy: (expr2) => isFunction2(expr2) && expr2.ops?.length === 1,
|
|
29420
|
+
count: (expr2) => {
|
|
29421
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29422
|
+
if (expr2.ops?.length === 2) {
|
|
29423
|
+
const n = toInteger(expr2.op2);
|
|
29424
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
29425
|
+
}
|
|
29426
|
+
return Infinity;
|
|
29427
|
+
},
|
|
29428
|
+
isEmpty: (expr2) => {
|
|
29429
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29430
|
+
if (expr2.ops?.length === 2) {
|
|
29431
|
+
const n = toInteger(expr2.op2);
|
|
29432
|
+
return n !== null ? n <= 0 : void 0;
|
|
29433
|
+
}
|
|
29434
|
+
return false;
|
|
29435
|
+
},
|
|
29436
|
+
isFinite: (expr2) => isFunction2(expr2) && expr2.ops?.length === 2,
|
|
28801
29437
|
contains: (expr2, target) => {
|
|
28802
29438
|
if (!isFunction2(expr2)) return false;
|
|
29439
|
+
if (expr2.ops?.length === 2) {
|
|
29440
|
+
const n = toInteger(expr2.op2);
|
|
29441
|
+
if (n !== null && n <= 0) return false;
|
|
29442
|
+
}
|
|
28803
29443
|
return expr2.op1.isSame(target);
|
|
28804
29444
|
},
|
|
28805
29445
|
iterator: (expr2) => {
|
|
28806
29446
|
if (!isFunction2(expr2))
|
|
28807
29447
|
return { next: () => ({ value: void 0, done: true }) };
|
|
29448
|
+
if (expr2.ops?.length === 2) {
|
|
29449
|
+
const n = toInteger(expr2.op2);
|
|
29450
|
+
if (n === null) {
|
|
29451
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
29452
|
+
}
|
|
29453
|
+
const count = Math.max(0, n);
|
|
29454
|
+
let i = 0;
|
|
29455
|
+
return {
|
|
29456
|
+
next: () => i++ < count ? { value: expr2.op1, done: false } : { value: void 0, done: true }
|
|
29457
|
+
};
|
|
29458
|
+
}
|
|
28808
29459
|
return { next: () => ({ value: expr2.op1, done: false }) };
|
|
28809
29460
|
},
|
|
28810
|
-
at
|
|
29461
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
29462
|
+
at: (expr2, index) => {
|
|
28811
29463
|
if (!isFunction2(expr2)) return void 0;
|
|
29464
|
+
if (typeof index !== "number") return void 0;
|
|
29465
|
+
if (expr2.ops?.length === 2) {
|
|
29466
|
+
const n = toInteger(expr2.op2);
|
|
29467
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
29468
|
+
if (index < 1 || index > count) return void 0;
|
|
29469
|
+
} else {
|
|
29470
|
+
if (index < 1) return void 0;
|
|
29471
|
+
}
|
|
28812
29472
|
return expr2.op1;
|
|
28813
29473
|
}
|
|
28814
29474
|
}
|
|
@@ -29039,17 +29699,14 @@ function range(expr2) {
|
|
|
29039
29699
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
29040
29700
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
29041
29701
|
let op1 = expr2.op1.re;
|
|
29042
|
-
if (!isFinite(op1)) op1 = 1;
|
|
29043
|
-
else op1 = Math.round(op1);
|
|
29702
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
29044
29703
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
29045
29704
|
let op2 = expr2.op2.re;
|
|
29046
29705
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
29047
|
-
|
|
29048
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29706
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
29049
29707
|
let op3 = expr2.op3.re;
|
|
29050
|
-
if (!isFinite(op3)) op3 = 1;
|
|
29051
|
-
|
|
29052
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29708
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29709
|
+
return [op1, op2, op3];
|
|
29053
29710
|
}
|
|
29054
29711
|
function rangeLast(r) {
|
|
29055
29712
|
const [lower, upper, step] = r;
|
|
@@ -31097,11 +31754,12 @@ var ARITHMETIC_LIBRARY = [
|
|
|
31097
31754
|
);
|
|
31098
31755
|
}
|
|
31099
31756
|
},
|
|
31100
|
-
|
|
31101
|
-
|
|
31102
|
-
|
|
31103
|
-
|
|
31104
|
-
|
|
31757
|
+
Complex: {
|
|
31758
|
+
description: 'Construct a complex number from real and imaginary parts. Converted directly to a BoxedNumber during boxing; this entry exists so `operatorInfo("Complex")` returns a signature.',
|
|
31759
|
+
wikidata: "Q11567",
|
|
31760
|
+
complexity: 500,
|
|
31761
|
+
signature: "(real: number, imaginary: number) -> complex"
|
|
31762
|
+
},
|
|
31105
31763
|
Divide: {
|
|
31106
31764
|
description: "Quotient of a numerator and one or more denominators.",
|
|
31107
31765
|
wikidata: "Q1226939",
|
|
@@ -32451,48 +33109,83 @@ var ARITHMETIC_LIBRARY = [
|
|
|
32451
33109
|
}
|
|
32452
33110
|
},
|
|
32453
33111
|
Sum: {
|
|
32454
|
-
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`",
|
|
33112
|
+
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`; `Sum(L)` sums the elements of a collection `L`",
|
|
32455
33113
|
wikidata: "Q218005",
|
|
32456
33114
|
complexity: 1e3,
|
|
32457
33115
|
broadcastable: false,
|
|
32458
33116
|
scoped: true,
|
|
32459
33117
|
lazy: true,
|
|
32460
|
-
signature: "(
|
|
32461
|
-
canonical: ([body, ...bounds], { scope }) =>
|
|
32462
|
-
|
|
33118
|
+
signature: "(any, tuple*) -> number",
|
|
33119
|
+
canonical: ([body, ...bounds], { scope, engine: ce }) => {
|
|
33120
|
+
if (bounds.length === 0) {
|
|
33121
|
+
const canon = body?.canonical;
|
|
33122
|
+
if (canon?.isCollection) return ce._fn("Sum", [canon]);
|
|
33123
|
+
}
|
|
33124
|
+
return canonicalBigop("Sum", body, bounds, scope);
|
|
33125
|
+
},
|
|
33126
|
+
evaluate: ([first, ...rest], { engine, numericApproximation: numericApproximation2 }) => {
|
|
33127
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33128
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33129
|
+
const result2 = run(
|
|
33130
|
+
reduceCollection2(
|
|
33131
|
+
first,
|
|
33132
|
+
engine.Zero,
|
|
33133
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33134
|
+
),
|
|
33135
|
+
engine._timeRemaining
|
|
33136
|
+
);
|
|
33137
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33138
|
+
}
|
|
32463
33139
|
const result = run(
|
|
32464
33140
|
reduceBigOp(
|
|
32465
|
-
|
|
32466
|
-
|
|
33141
|
+
first,
|
|
33142
|
+
rest,
|
|
32467
33143
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32468
33144
|
engine.Zero
|
|
32469
33145
|
),
|
|
32470
33146
|
engine._timeRemaining
|
|
32471
33147
|
);
|
|
32472
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32473
|
-
return void 0;
|
|
32474
|
-
}
|
|
33148
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32475
33149
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32476
33150
|
},
|
|
32477
|
-
evaluateAsync: async (
|
|
33151
|
+
evaluateAsync: async ([first, ...rest], { engine, signal, numericApproximation: numericApproximation2 }) => {
|
|
33152
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33153
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33154
|
+
const result2 = await runAsync(
|
|
33155
|
+
reduceCollection2(
|
|
33156
|
+
first,
|
|
33157
|
+
engine.Zero,
|
|
33158
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33159
|
+
),
|
|
33160
|
+
engine._timeRemaining,
|
|
33161
|
+
signal
|
|
33162
|
+
);
|
|
33163
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33164
|
+
}
|
|
32478
33165
|
const result = await runAsync(
|
|
32479
33166
|
reduceBigOp(
|
|
32480
|
-
|
|
32481
|
-
|
|
33167
|
+
first,
|
|
33168
|
+
rest,
|
|
32482
33169
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32483
33170
|
engine.Zero
|
|
32484
33171
|
),
|
|
32485
33172
|
engine._timeRemaining,
|
|
32486
33173
|
signal
|
|
32487
33174
|
);
|
|
32488
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32489
|
-
return void 0;
|
|
32490
|
-
}
|
|
33175
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32491
33176
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32492
33177
|
}
|
|
32493
33178
|
}
|
|
32494
33179
|
}
|
|
32495
33180
|
];
|
|
33181
|
+
function* reduceCollection2(collection, init, combine) {
|
|
33182
|
+
let acc = init;
|
|
33183
|
+
for (const x of collection.each()) {
|
|
33184
|
+
acc = combine(acc, x);
|
|
33185
|
+
yield acc;
|
|
33186
|
+
}
|
|
33187
|
+
return acc;
|
|
33188
|
+
}
|
|
32496
33189
|
function evaluateAbs(arg) {
|
|
32497
33190
|
const ce = arg.engine;
|
|
32498
33191
|
if (isNumber(arg)) {
|
|
@@ -42729,7 +43422,7 @@ var COLORS_LIBRARY = {
|
|
|
42729
43422
|
var CONTROL_STRUCTURES_LIBRARY = [
|
|
42730
43423
|
{
|
|
42731
43424
|
Block: {
|
|
42732
|
-
description: "Evaluate a sequence of expressions in a local scope.",
|
|
43425
|
+
description: "Evaluate a sequence of expressions in a local scope, **sequentially**. Each operand is evaluated in order; later operands observe side effects (`Assign`, `Declare`) of earlier operands. The block's value is the value of the last expression. Short-circuiting heads (`Return`, `Break`, `Continue`) terminate the sequence early.\n\nIMPORTANT \u2014 consumers translating *simultaneous* action tuples (e.g. Desmos `(a \u2192 1, b \u2192 a + 1)` where `b` reads the *pre-action* `a`) must rewrite to a snapshot-then-commit Block: bind each RHS to a fresh temp first, then assign the temps to the LHS symbols. See `docs/architecture/actions-and-randomness.md` for the canonical recipe.",
|
|
42733
43426
|
lazy: true,
|
|
42734
43427
|
scoped: true,
|
|
42735
43428
|
signature: "(unknown*) -> unknown",
|
|
@@ -42779,12 +43472,42 @@ var CONTROL_STRUCTURES_LIBRARY = [
|
|
|
42779
43472
|
}
|
|
42780
43473
|
},
|
|
42781
43474
|
Loop: {
|
|
42782
|
-
description: "Evaluate a body expression over
|
|
43475
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
42783
43476
|
lazy: true,
|
|
42784
|
-
signature: "(body:expression,
|
|
42785
|
-
type: ([body]) =>
|
|
42786
|
-
|
|
42787
|
-
|
|
43477
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43478
|
+
type: ([body]) => {
|
|
43479
|
+
if (!body) return "nothing";
|
|
43480
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43481
|
+
},
|
|
43482
|
+
canonical: canonicalLoop,
|
|
43483
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43484
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43485
|
+
},
|
|
43486
|
+
When: {
|
|
43487
|
+
description: 'Conditional/restriction value. `When(e, cond)` evaluates to:\n - `e` when `cond` evaluates to `True`\n - `Undefined` when `cond` evaluates to `False` (the "masking rule"; consumers like 2D plotters skip masked points)\n - `When(e, cond_simplified)` when `cond` is indeterminate (holds)\nStacked restrictions canonicalize: `When(When(e, c1), c2)` \u2192 `When(e, And(c1, c2))`.\nCompiles to ternary `(cond) ? (e) : NaN` in JS and GLSL.',
|
|
43488
|
+
lazy: true,
|
|
43489
|
+
signature: "(expression, boolean) -> any",
|
|
43490
|
+
type: ([expr2]) => expr2.type,
|
|
43491
|
+
canonical: (args, { engine: ce }) => {
|
|
43492
|
+
if (args.length !== 2) return null;
|
|
43493
|
+
const [expr2, cond] = args;
|
|
43494
|
+
if (isFunction2(expr2, "When")) {
|
|
43495
|
+
const inner = expr2.op1.canonical;
|
|
43496
|
+
const innerCond = expr2.op2.canonical;
|
|
43497
|
+
return ce._fn("When", [
|
|
43498
|
+
inner,
|
|
43499
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43500
|
+
]);
|
|
43501
|
+
}
|
|
43502
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43503
|
+
},
|
|
43504
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43505
|
+
const c = cond.evaluate();
|
|
43506
|
+
const cs = sym(c);
|
|
43507
|
+
if (cs === "True") return expr2.evaluate();
|
|
43508
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43509
|
+
return ce._fn("When", [expr2, c]);
|
|
43510
|
+
}
|
|
42788
43511
|
},
|
|
42789
43512
|
Which: {
|
|
42790
43513
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42844,9 +43567,141 @@ function canonicalBlock(ops, options) {
|
|
|
42844
43567
|
);
|
|
42845
43568
|
return result;
|
|
42846
43569
|
}
|
|
42847
|
-
function
|
|
43570
|
+
function canonicalLoop(ops, options) {
|
|
43571
|
+
const { engine: ce, scope } = options;
|
|
43572
|
+
if (ops.length === 0) return null;
|
|
43573
|
+
if (ops.length === 1) {
|
|
43574
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43575
|
+
}
|
|
43576
|
+
const body = ops[0];
|
|
43577
|
+
const iterators = ops.slice(1);
|
|
43578
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43579
|
+
if (!allElement) {
|
|
43580
|
+
return ce._fn(
|
|
43581
|
+
"Loop",
|
|
43582
|
+
ops.map((op) => op.canonical)
|
|
43583
|
+
);
|
|
43584
|
+
}
|
|
43585
|
+
const loopScope = scope ?? {
|
|
43586
|
+
parent: ce.context.lexicalScope,
|
|
43587
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43588
|
+
};
|
|
43589
|
+
loopScope.noAutoDeclare = true;
|
|
43590
|
+
ce.pushScope(loopScope);
|
|
43591
|
+
let canonicalIterators;
|
|
43592
|
+
let canonicalBody;
|
|
43593
|
+
try {
|
|
43594
|
+
canonicalIterators = iterators.map((it) => {
|
|
43595
|
+
if (!isFunction2(it, "Element")) {
|
|
43596
|
+
return ce._fn("Element", [
|
|
43597
|
+
ce.error("missing").canonical,
|
|
43598
|
+
ce.error("missing").canonical
|
|
43599
|
+
]);
|
|
43600
|
+
}
|
|
43601
|
+
const indexExpr = it.ops[0];
|
|
43602
|
+
const collExpr = it.ops[1];
|
|
43603
|
+
if (!indexExpr || !collExpr) {
|
|
43604
|
+
return ce._fn("Element", [
|
|
43605
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43606
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43607
|
+
]);
|
|
43608
|
+
}
|
|
43609
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43610
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43611
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43612
|
+
}
|
|
43613
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43614
|
+
});
|
|
43615
|
+
canonicalBody = body.canonical;
|
|
43616
|
+
} finally {
|
|
43617
|
+
ce.popScope();
|
|
43618
|
+
loopScope.noAutoDeclare = false;
|
|
43619
|
+
}
|
|
43620
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43621
|
+
scope: loopScope
|
|
43622
|
+
});
|
|
43623
|
+
}
|
|
43624
|
+
function* runLoop(body, elements, ce) {
|
|
42848
43625
|
body ??= ce.Nothing;
|
|
42849
43626
|
if (sym(body) === "Nothing") return body;
|
|
43627
|
+
if (elements.length === 0) {
|
|
43628
|
+
const result = body.evaluate();
|
|
43629
|
+
yield result;
|
|
43630
|
+
return result;
|
|
43631
|
+
}
|
|
43632
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43633
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43634
|
+
}
|
|
43635
|
+
const results = [];
|
|
43636
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43637
|
+
const freshScope = {
|
|
43638
|
+
parent: ce.context.lexicalScope,
|
|
43639
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43640
|
+
};
|
|
43641
|
+
ce._pushEvalContext(freshScope);
|
|
43642
|
+
try {
|
|
43643
|
+
for (const elem of elements) {
|
|
43644
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43645
|
+
const idx = elem.ops[0];
|
|
43646
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43647
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43648
|
+
ce.declare(idx.symbol, "unknown");
|
|
43649
|
+
}
|
|
43650
|
+
}
|
|
43651
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43652
|
+
} finally {
|
|
43653
|
+
ce._popEvalContext();
|
|
43654
|
+
}
|
|
43655
|
+
if (state.stopped && state.value !== void 0) {
|
|
43656
|
+
if (!state.broke) return state.value;
|
|
43657
|
+
return state.value;
|
|
43658
|
+
}
|
|
43659
|
+
return ce.function("List", results);
|
|
43660
|
+
}
|
|
43661
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43662
|
+
if (state.stopped) return;
|
|
43663
|
+
if (index === elements.length) {
|
|
43664
|
+
const result = body.evaluate();
|
|
43665
|
+
state.count += 1;
|
|
43666
|
+
if (state.count > ce.iterationLimit)
|
|
43667
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43668
|
+
if (isFunction2(result, "Break")) {
|
|
43669
|
+
state.stopped = true;
|
|
43670
|
+
state.broke = true;
|
|
43671
|
+
state.value = result.op1;
|
|
43672
|
+
return;
|
|
43673
|
+
}
|
|
43674
|
+
if (result.operator === "Return") {
|
|
43675
|
+
state.stopped = true;
|
|
43676
|
+
state.value = result;
|
|
43677
|
+
return;
|
|
43678
|
+
}
|
|
43679
|
+
results.push(result);
|
|
43680
|
+
yield result;
|
|
43681
|
+
return;
|
|
43682
|
+
}
|
|
43683
|
+
const elem = elements[index];
|
|
43684
|
+
if (!isFunction2(elem, "Element")) {
|
|
43685
|
+
return;
|
|
43686
|
+
}
|
|
43687
|
+
const indexExpr = elem.ops[0];
|
|
43688
|
+
const collExpr = elem.ops[1];
|
|
43689
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43690
|
+
return;
|
|
43691
|
+
}
|
|
43692
|
+
const name = indexExpr.symbol;
|
|
43693
|
+
const collection = collExpr.evaluate();
|
|
43694
|
+
if (!collection?.isCollection) {
|
|
43695
|
+
return;
|
|
43696
|
+
}
|
|
43697
|
+
const skipAssign = name === "Nothing";
|
|
43698
|
+
for (const value of collection.each()) {
|
|
43699
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43700
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43701
|
+
if (state.stopped) return;
|
|
43702
|
+
}
|
|
43703
|
+
}
|
|
43704
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42850
43705
|
if (collection?.isCollection) {
|
|
42851
43706
|
let result = void 0;
|
|
42852
43707
|
const fn = applicable(body);
|
|
@@ -44488,7 +45343,7 @@ var CORE_LIBRARY = [
|
|
|
44488
45343
|
evaluate: (ops) => apply(ops[0], ops.slice(1))
|
|
44489
45344
|
},
|
|
44490
45345
|
Assign: {
|
|
44491
|
-
description: "Assign a value to a symbol or define a sequence",
|
|
45346
|
+
description: "Assign a value to a symbol or define a sequence. The RHS is evaluated immediately and `ce.assign(name, val)` mutates the binding in the current scope chain. When used inside a `Block`, the assignment is visible to subsequent statements in the block (sequential semantics).",
|
|
44492
45347
|
lazy: true,
|
|
44493
45348
|
pure: false,
|
|
44494
45349
|
signature: "(symbol | expression, any) -> any",
|
|
@@ -44619,7 +45474,12 @@ var CORE_LIBRARY = [
|
|
|
44619
45474
|
evaluate: (ops, { engine: ce }) => {
|
|
44620
45475
|
const symbolName2 = sym(ops[0].evaluate());
|
|
44621
45476
|
if (!symbolName2) return void 0;
|
|
45477
|
+
const currentScope = ce.context.lexicalScope;
|
|
45478
|
+
const existing = currentScope.bindings.get(symbolName2);
|
|
45479
|
+
const existingValueDef = existing && isValueDef(existing) ? existing : void 0;
|
|
45480
|
+
const isAutoDeclareHere = !!existingValueDef && existingValueDef.value.inferredType && existingValueDef.value.value === void 0;
|
|
44622
45481
|
if (!ops[1]) {
|
|
45482
|
+
if (isAutoDeclareHere) return ce.Nothing;
|
|
44623
45483
|
ce.declare(symbolName2, { inferred: true, type: "unknown" });
|
|
44624
45484
|
return ce.Nothing;
|
|
44625
45485
|
}
|
|
@@ -44628,6 +45488,11 @@ var CORE_LIBRARY = [
|
|
|
44628
45488
|
(isString(t) ? t.string : void 0) ?? sym(t) ?? void 0
|
|
44629
45489
|
);
|
|
44630
45490
|
if (!isValidType(type2)) return void 0;
|
|
45491
|
+
if (isAutoDeclareHere && existingValueDef) {
|
|
45492
|
+
existingValueDef.value.type = ce.type(type2);
|
|
45493
|
+
existingValueDef.value.inferredType = false;
|
|
45494
|
+
return ce.Nothing;
|
|
45495
|
+
}
|
|
44631
45496
|
ce.declare(symbolName2, type2);
|
|
44632
45497
|
return ce.Nothing;
|
|
44633
45498
|
}
|
|
@@ -44745,33 +45610,41 @@ var CORE_LIBRARY = [
|
|
|
44745
45610
|
},
|
|
44746
45611
|
Random: {
|
|
44747
45612
|
description: [
|
|
44748
|
-
"Random():
|
|
44749
|
-
"Random(
|
|
44750
|
-
"Random(
|
|
45613
|
+
"Random(): non-deterministic float in [0, 1)",
|
|
45614
|
+
"Random(seed: real): deterministic float in [0, 1) from a real seed",
|
|
45615
|
+
"Random(n: integer): non-deterministic integer in [0, n)",
|
|
45616
|
+
"Random(m: integer, n: integer): non-deterministic integer in [m, n)"
|
|
44751
45617
|
],
|
|
44752
45618
|
pure: false,
|
|
44753
|
-
|
|
44754
|
-
|
|
44755
|
-
|
|
44756
|
-
|
|
45619
|
+
// Signature accepts: nothing, one number, or two integers.
|
|
45620
|
+
// Use `number` (not `integer`) for the single-arg case so float seeds
|
|
45621
|
+
// type-check; runtime dispatch differentiates integer vs real.
|
|
45622
|
+
signature: "(number?, integer?) -> finite_number",
|
|
45623
|
+
type: ([first, second]) => {
|
|
45624
|
+
if (first === void 0) return "finite_number";
|
|
45625
|
+
if (second !== void 0) return "finite_integer";
|
|
45626
|
+
if (first.type.matches("integer")) return "finite_integer";
|
|
45627
|
+
return "finite_number";
|
|
44757
45628
|
},
|
|
44758
45629
|
sgn: () => "non-negative",
|
|
44759
45630
|
evaluate: (ops, { engine: ce }) => {
|
|
44760
45631
|
if (ops.length === 0) return ce.number(Math.random());
|
|
44761
|
-
const [
|
|
44762
|
-
|
|
44763
|
-
|
|
44764
|
-
|
|
44765
|
-
lower = 0;
|
|
44766
|
-
upper = Math.floor(lowerOp.re - 1);
|
|
44767
|
-
if (isNaN(upper)) upper = 0;
|
|
44768
|
-
} else {
|
|
44769
|
-
lower = Math.floor(lowerOp.re);
|
|
44770
|
-
upper = Math.floor(upperOp.re);
|
|
45632
|
+
const [firstOp, secondOp] = ops;
|
|
45633
|
+
if (secondOp !== void 0) {
|
|
45634
|
+
let lower = Math.floor(firstOp.re);
|
|
45635
|
+
let upper = Math.floor(secondOp.re);
|
|
44771
45636
|
if (isNaN(lower)) lower = 0;
|
|
44772
45637
|
if (isNaN(upper)) upper = 0;
|
|
45638
|
+
return ce.number(lower + Math.floor(Math.random() * (upper - lower)));
|
|
45639
|
+
}
|
|
45640
|
+
if (firstOp.type.matches("integer")) {
|
|
45641
|
+
let n = Math.floor(firstOp.re);
|
|
45642
|
+
if (isNaN(n)) n = 0;
|
|
45643
|
+
return ce.number(Math.floor(Math.random() * n));
|
|
44773
45644
|
}
|
|
44774
|
-
|
|
45645
|
+
const seed = firstOp.re;
|
|
45646
|
+
if (isNaN(seed)) return ce.number(0);
|
|
45647
|
+
return ce.number(deterministicRandom(seed));
|
|
44775
45648
|
}
|
|
44776
45649
|
},
|
|
44777
45650
|
// @todo: need review
|
|
@@ -45227,6 +46100,14 @@ var CORE_LIBRARY = [
|
|
|
45227
46100
|
To: {
|
|
45228
46101
|
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45229
46102
|
signature: "(any, any) -> nothing"
|
|
46103
|
+
},
|
|
46104
|
+
Colon: {
|
|
46105
|
+
description: "Type annotation (`a : b`) \u2014 opaque typed head.",
|
|
46106
|
+
signature: "(any, any) -> expression"
|
|
46107
|
+
},
|
|
46108
|
+
Prime: {
|
|
46109
|
+
description: "Derivative or prime notation (`f'`, `f^{(n)}`) \u2014 opaque typed head until a derivative library handler runs.",
|
|
46110
|
+
signature: "(any, integer?) -> expression"
|
|
45230
46111
|
}
|
|
45231
46112
|
}
|
|
45232
46113
|
];
|
|
@@ -50267,18 +51148,28 @@ var STATISTICS_LIBRARY = [
|
|
|
50267
51148
|
},
|
|
50268
51149
|
{
|
|
50269
51150
|
Sample: {
|
|
50270
|
-
description: "Return a random sample of k elements from the collection, without replacement.",
|
|
51151
|
+
description: "Return a random sample of k elements from the collection, without replacement. With an optional `seed` argument, the sample is deterministic.",
|
|
50271
51152
|
complexity: 8200,
|
|
50272
|
-
signature: "(collection, integer) -> list",
|
|
50273
|
-
evaluate: ([xs, nArg], { engine: ce }) => {
|
|
51153
|
+
signature: "(collection, integer, real?) -> list",
|
|
51154
|
+
evaluate: ([xs, nArg, seedArg], { engine: ce }) => {
|
|
50274
51155
|
if (!xs.isFiniteCollection) return void 0;
|
|
50275
51156
|
const k = toInteger(nArg);
|
|
50276
51157
|
if (k === null || k < 0) return void 0;
|
|
50277
51158
|
const data = Array.from(xs.each());
|
|
50278
51159
|
if (k > data.length) return void 0;
|
|
50279
|
-
|
|
50280
|
-
|
|
50281
|
-
|
|
51160
|
+
const seed = seedArg?.re;
|
|
51161
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
51162
|
+
let s = seed;
|
|
51163
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51164
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
51165
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51166
|
+
s = nextSeed(s);
|
|
51167
|
+
}
|
|
51168
|
+
} else {
|
|
51169
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51170
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
51171
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51172
|
+
}
|
|
50282
51173
|
}
|
|
50283
51174
|
const sample = data.slice(0, k);
|
|
50284
51175
|
return ce.function("List", sample);
|
|
@@ -53099,6 +53990,20 @@ var BoxedFunction = class extends _BoxedExpression {
|
|
|
53099
53990
|
if (results.length === 1) return results[0];
|
|
53100
53991
|
return this.engine._fn("List", results);
|
|
53101
53992
|
}
|
|
53993
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
53994
|
+
const items = zip(this._ops);
|
|
53995
|
+
if (items) {
|
|
53996
|
+
const results = [];
|
|
53997
|
+
while (true) {
|
|
53998
|
+
const { done, value } = items.next();
|
|
53999
|
+
if (done) break;
|
|
54000
|
+
results.push(
|
|
54001
|
+
this.engine._fn(this.operator, value).evaluate(options)
|
|
54002
|
+
);
|
|
54003
|
+
}
|
|
54004
|
+
return this.engine._fn("List", results);
|
|
54005
|
+
}
|
|
54006
|
+
}
|
|
53102
54007
|
if (materialization !== false && !def.evaluate && this.isLazyCollection)
|
|
53103
54008
|
return materialize(this, def, options);
|
|
53104
54009
|
const tail = holdMap(this, (x) => x.evaluate(options));
|
|
@@ -53145,6 +54050,22 @@ var BoxedFunction = class extends _BoxedExpression {
|
|
|
53145
54050
|
(resolved) => this.engine._fn("List", resolved)
|
|
53146
54051
|
);
|
|
53147
54052
|
}
|
|
54053
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
54054
|
+
const items = zip(this._ops);
|
|
54055
|
+
if (items) {
|
|
54056
|
+
const results = [];
|
|
54057
|
+
while (true) {
|
|
54058
|
+
const { done, value } = items.next();
|
|
54059
|
+
if (done) break;
|
|
54060
|
+
results.push(
|
|
54061
|
+
this.engine._fn(this.operator, value).evaluateAsync(options)
|
|
54062
|
+
);
|
|
54063
|
+
}
|
|
54064
|
+
return Promise.all(results).then(
|
|
54065
|
+
(resolved) => this.engine._fn("List", resolved)
|
|
54066
|
+
);
|
|
54067
|
+
}
|
|
54068
|
+
}
|
|
53148
54069
|
const tail = await holdMapAsync(
|
|
53149
54070
|
this,
|
|
53150
54071
|
async (x) => await x.evaluateAsync(options)
|
|
@@ -53359,8 +54280,47 @@ function applyFunctionLiteral(expr2, def, options) {
|
|
|
53359
54280
|
const ops = expr2.ops.map((x) => x.evaluate(options));
|
|
53360
54281
|
if (!value || value.type.isUnknown)
|
|
53361
54282
|
return expr2.engine.function(expr2.operator, ops);
|
|
54283
|
+
if (ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(value.type.type)) {
|
|
54284
|
+
const items = zip(ops);
|
|
54285
|
+
if (items) {
|
|
54286
|
+
const results = [];
|
|
54287
|
+
while (true) {
|
|
54288
|
+
const { done, value: zipped } = items.next();
|
|
54289
|
+
if (done) break;
|
|
54290
|
+
results.push(apply(value, zipped).evaluate(options));
|
|
54291
|
+
}
|
|
54292
|
+
return expr2.engine._fn("List", results);
|
|
54293
|
+
}
|
|
54294
|
+
}
|
|
53362
54295
|
return apply(value, ops);
|
|
53363
54296
|
}
|
|
54297
|
+
function paramsAreScalar(source) {
|
|
54298
|
+
const sigType = isOperatorDefinition(source) ? source.signature?.type : source;
|
|
54299
|
+
if (!sigType || typeof sigType === "string") return true;
|
|
54300
|
+
if (sigType.kind !== "signature") return true;
|
|
54301
|
+
const args = [
|
|
54302
|
+
...sigType.args ?? [],
|
|
54303
|
+
...sigType.optArgs ?? [],
|
|
54304
|
+
...sigType.variadicArg ? [sigType.variadicArg] : []
|
|
54305
|
+
];
|
|
54306
|
+
return args.every((arg) => isScalarType(arg.type));
|
|
54307
|
+
}
|
|
54308
|
+
function isOperatorDefinition(source) {
|
|
54309
|
+
return typeof source === "object" && source !== null && "signature" in source;
|
|
54310
|
+
}
|
|
54311
|
+
function isScalarType(t) {
|
|
54312
|
+
if (typeof t === "string") {
|
|
54313
|
+
if (t === "collection" || t === "indexed_collection" || t === "list" || t === "tuple" || t === "set" || t === "dictionary" || t === "record" || t === "function")
|
|
54314
|
+
return false;
|
|
54315
|
+
return true;
|
|
54316
|
+
}
|
|
54317
|
+
if (t.kind === "collection" || t.kind === "indexed_collection" || t.kind === "list" || t.kind === "tuple" || t.kind === "set" || t.kind === "dictionary" || t.kind === "record" || t.kind === "signature")
|
|
54318
|
+
return false;
|
|
54319
|
+
if (t.kind === "union" || t.kind === "intersection")
|
|
54320
|
+
return t.types.every((x) => isScalarType(x));
|
|
54321
|
+
if (t.kind === "negation") return isScalarType(t.type);
|
|
54322
|
+
return true;
|
|
54323
|
+
}
|
|
53364
54324
|
function materialize(expr2, def, options) {
|
|
53365
54325
|
if (!expr2.isValid || options?.materialization === false) return expr2;
|
|
53366
54326
|
let materialization = options?.materialization ?? false;
|
|
@@ -53368,6 +54328,11 @@ function materialize(expr2, def, options) {
|
|
|
53368
54328
|
materialization = DEFAULT_MATERIALIZATION;
|
|
53369
54329
|
const isIndexed = expr2.isIndexedCollection;
|
|
53370
54330
|
const isFinite2 = expr2.isFiniteCollection;
|
|
54331
|
+
if (isIndexed && isFinite2) {
|
|
54332
|
+
const count = expr2.count;
|
|
54333
|
+
if (count !== void 0 && count > expr2.engine.maxCollectionSize)
|
|
54334
|
+
return expr2;
|
|
54335
|
+
}
|
|
53371
54336
|
const xs = [];
|
|
53372
54337
|
if (!expr2.isEmptyCollection) {
|
|
53373
54338
|
if (!isIndexed || !isFinite2) {
|
|
@@ -53595,7 +54560,7 @@ var BoxedDictionary = class _BoxedDictionary extends _BoxedExpression {
|
|
|
53595
54560
|
const eltType = widen(
|
|
53596
54561
|
...Object.values(this._keyValues).map((op) => op.type.type)
|
|
53597
54562
|
);
|
|
53598
|
-
this._type =
|
|
54563
|
+
this._type = new BoxedType({ kind: "dictionary", values: eltType });
|
|
53599
54564
|
return this._type;
|
|
53600
54565
|
}
|
|
53601
54566
|
get isPure() {
|
|
@@ -53873,6 +54838,7 @@ function box(ce, expr2, options) {
|
|
|
53873
54838
|
}
|
|
53874
54839
|
if (typeof expr2 === "number" || expr2 instanceof BigDecimal || expr2 instanceof Complex)
|
|
53875
54840
|
return ce.number(expr2);
|
|
54841
|
+
if (typeof expr2 === "boolean") return ce.symbol(expr2 ? "True" : "False");
|
|
53876
54842
|
if (typeof expr2 === "string") {
|
|
53877
54843
|
if (matchesSymbol(expr2)) {
|
|
53878
54844
|
const sym2 = symbol(expr2);
|
|
@@ -54929,6 +55895,23 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
54929
55895
|
};
|
|
54930
55896
|
return compilePair(0);
|
|
54931
55897
|
}
|
|
55898
|
+
if (h === "When") {
|
|
55899
|
+
if (args.length !== 2)
|
|
55900
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55901
|
+
const fn2 = target.functions?.(h);
|
|
55902
|
+
if (fn2) {
|
|
55903
|
+
if (typeof fn2 === "function") {
|
|
55904
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55905
|
+
}
|
|
55906
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55907
|
+
}
|
|
55908
|
+
if (isSymbol2(args[1], "True"))
|
|
55909
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55910
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55911
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55912
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55913
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55914
|
+
}
|
|
54932
55915
|
if (h === "Block") {
|
|
54933
55916
|
return _BaseCompiler.compileBlock(args, target);
|
|
54934
55917
|
}
|
|
@@ -55003,17 +55986,98 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
55003
55986
|
)}${target.ws("\n")}})()`;
|
|
55004
55987
|
}
|
|
55005
55988
|
/**
|
|
55006
|
-
* Compile a Loop expression
|
|
55007
|
-
*
|
|
55989
|
+
* Compile a Loop expression.
|
|
55990
|
+
*
|
|
55991
|
+
* Two forms are supported:
|
|
55992
|
+
*
|
|
55993
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
55994
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
55995
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
55996
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
55997
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
55998
|
+
* references to the loop index inside the body are re-wrapped via
|
|
55999
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
55008
56000
|
*
|
|
55009
|
-
*
|
|
55010
|
-
*
|
|
55011
|
-
*
|
|
56001
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
56002
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
56003
|
+
* When two or more `Element` clauses are present — or when the single
|
|
56004
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
56005
|
+
* comprehension that collects results into an array. Each clause
|
|
56006
|
+
* produces a `for (const name of collection)` loop, nested
|
|
56007
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
56008
|
+
*
|
|
56009
|
+
* Example output (JS):
|
|
56010
|
+
* ```js
|
|
56011
|
+
* (() => { const result = [];
|
|
56012
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
56013
|
+
* return result; })()
|
|
56014
|
+
* ```
|
|
56015
|
+
*
|
|
56016
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
56017
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
56018
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
56019
|
+
* array or by unrolling when bounds are known at compile time.
|
|
56020
|
+
*
|
|
56021
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
56022
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
56023
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
56024
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
56025
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
56026
|
+
* current behavior.
|
|
55012
56027
|
*/
|
|
55013
56028
|
static compileForLoop(args, target) {
|
|
55014
56029
|
if (!args[0]) throw new Error("Loop: no body");
|
|
55015
56030
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
55016
|
-
const
|
|
56031
|
+
const body = args[0];
|
|
56032
|
+
const elements = args.slice(1);
|
|
56033
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
56034
|
+
if (useComprehension) {
|
|
56035
|
+
const lang = target.language ?? "";
|
|
56036
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
56037
|
+
throw new Error(
|
|
56038
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
56039
|
+
);
|
|
56040
|
+
}
|
|
56041
|
+
const narrowedElements = [];
|
|
56042
|
+
for (let i = 0; i < elements.length; i++) {
|
|
56043
|
+
const elem = elements[i];
|
|
56044
|
+
if (!isFunction2(elem, "Element"))
|
|
56045
|
+
throw new Error(
|
|
56046
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
56047
|
+
);
|
|
56048
|
+
if (!isSymbol2(elem.ops[0]))
|
|
56049
|
+
throw new Error(
|
|
56050
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
56051
|
+
);
|
|
56052
|
+
narrowedElements.push(elem);
|
|
56053
|
+
}
|
|
56054
|
+
const loopVarSet = new Set(
|
|
56055
|
+
narrowedElements.map(
|
|
56056
|
+
(e) => e.ops[0].symbol
|
|
56057
|
+
)
|
|
56058
|
+
);
|
|
56059
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
56060
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
56061
|
+
...target,
|
|
56062
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
56063
|
+
} : target;
|
|
56064
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
56065
|
+
let inner = `result.push(${bodyCode});`;
|
|
56066
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
56067
|
+
const elem = narrowedElements[i];
|
|
56068
|
+
const name = elem.ops[0].symbol;
|
|
56069
|
+
const collExpr = elem.ops[1];
|
|
56070
|
+
let collection;
|
|
56071
|
+
if (isFunction2(collExpr, "Range")) {
|
|
56072
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
56073
|
+
} else {
|
|
56074
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
56075
|
+
}
|
|
56076
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
56077
|
+
}
|
|
56078
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
56079
|
+
}
|
|
56080
|
+
const indexing = elements[0];
|
|
55017
56081
|
if (!isFunction2(indexing, "Element"))
|
|
55018
56082
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
55019
56083
|
const indexExpr = indexing.ops[0];
|
|
@@ -55031,13 +56095,72 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
55031
56095
|
...target,
|
|
55032
56096
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
55033
56097
|
};
|
|
55034
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
56098
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
55035
56099
|
return `(() => {${target.ws(
|
|
55036
56100
|
"\n"
|
|
55037
56101
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
55038
56102
|
"\n"
|
|
55039
56103
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
55040
56104
|
}
|
|
56105
|
+
/**
|
|
56106
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
56107
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
56108
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
56109
|
+
*
|
|
56110
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
56111
|
+
* are not statically numeric we accept the Range (the historical
|
|
56112
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
56113
|
+
* left as a known limitation; callers can force the iterable path by
|
|
56114
|
+
* supplying an explicit step.
|
|
56115
|
+
*/
|
|
56116
|
+
static isLegacyCompatibleRange(coll) {
|
|
56117
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
56118
|
+
if (coll.ops.length >= 3) {
|
|
56119
|
+
const stepExpr = coll.ops[2];
|
|
56120
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
56121
|
+
}
|
|
56122
|
+
const lo = coll.ops[0];
|
|
56123
|
+
const hi = coll.ops[1];
|
|
56124
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
56125
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
56126
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
56127
|
+
return true;
|
|
56128
|
+
}
|
|
56129
|
+
/**
|
|
56130
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
56131
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
56132
|
+
* `library/collections.ts` Range:
|
|
56133
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
56134
|
+
* element = lo + step * k (0-indexed)
|
|
56135
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
56136
|
+
*
|
|
56137
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
56138
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
56139
|
+
*/
|
|
56140
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
56141
|
+
const loExpr = rangeExpr.ops[0];
|
|
56142
|
+
const hiExpr = rangeExpr.ops[1];
|
|
56143
|
+
const stepExpr = rangeExpr.ops[2];
|
|
56144
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
56145
|
+
const lo2 = loExpr.re;
|
|
56146
|
+
const hi2 = hiExpr.re;
|
|
56147
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
56148
|
+
if (step2 === 0) return "[]";
|
|
56149
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
56150
|
+
if (step2 === 1) {
|
|
56151
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
56152
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
56153
|
+
}
|
|
56154
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
56155
|
+
}
|
|
56156
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
56157
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
56158
|
+
if (stepExpr === void 0) {
|
|
56159
|
+
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})`;
|
|
56160
|
+
}
|
|
56161
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
56162
|
+
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})`;
|
|
56163
|
+
}
|
|
55041
56164
|
/**
|
|
55042
56165
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
55043
56166
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -59537,8 +60660,8 @@ function assumeInequality(proposition) {
|
|
|
59537
60660
|
}
|
|
59538
60661
|
if (effectiveOp === "greater" || effectiveOp === "greaterEqual") {
|
|
59539
60662
|
const isStrict = effectiveOp === "greater";
|
|
59540
|
-
if (bounds.
|
|
59541
|
-
const lowerVal = isNumber(bounds.
|
|
60663
|
+
if (bounds.lower !== void 0) {
|
|
60664
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59542
60665
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59543
60666
|
if (isStrict) {
|
|
59544
60667
|
if (lowerVal > k) return "tautology";
|
|
@@ -59550,8 +60673,8 @@ function assumeInequality(proposition) {
|
|
|
59550
60673
|
}
|
|
59551
60674
|
}
|
|
59552
60675
|
}
|
|
59553
|
-
if (bounds.
|
|
59554
|
-
const upperVal = isNumber(bounds.
|
|
60676
|
+
if (bounds.upper !== void 0) {
|
|
60677
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59555
60678
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59556
60679
|
if (isStrict) {
|
|
59557
60680
|
if (upperVal < k) return "contradiction";
|
|
@@ -59566,8 +60689,8 @@ function assumeInequality(proposition) {
|
|
|
59566
60689
|
}
|
|
59567
60690
|
} else {
|
|
59568
60691
|
const isStrict = effectiveOp === "less";
|
|
59569
|
-
if (bounds.
|
|
59570
|
-
const upperVal = isNumber(bounds.
|
|
60692
|
+
if (bounds.upper !== void 0) {
|
|
60693
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59571
60694
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59572
60695
|
if (isStrict) {
|
|
59573
60696
|
if (upperVal < k) return "tautology";
|
|
@@ -59578,8 +60701,8 @@ function assumeInequality(proposition) {
|
|
|
59578
60701
|
}
|
|
59579
60702
|
}
|
|
59580
60703
|
}
|
|
59581
|
-
if (bounds.
|
|
59582
|
-
const lowerVal = isNumber(bounds.
|
|
60704
|
+
if (bounds.lower !== void 0) {
|
|
60705
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59583
60706
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59584
60707
|
if (isStrict) {
|
|
59585
60708
|
if (lowerVal > k) return "contradiction";
|
|
@@ -59807,7 +60930,7 @@ function ask(ce, pattern) {
|
|
|
59807
60930
|
const patOp1B2 = pat.op1;
|
|
59808
60931
|
if (isSymbol2(patOp1B2)) {
|
|
59809
60932
|
const bounds = getInequalityBoundsFromAssumptions(ce, patOp1B2.symbol);
|
|
59810
|
-
const bound = isLower ? bounds.
|
|
60933
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59811
60934
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59812
60935
|
if (bound !== void 0 && (!isStrict || strictOk === true))
|
|
59813
60936
|
pushResult({ [boundWildcard]: bound });
|
|
@@ -59817,7 +60940,7 @@ function ask(ce, pattern) {
|
|
|
59817
60940
|
if (symbolWildcard && !symbolWildcard.startsWith("__")) {
|
|
59818
60941
|
for (const s of candidatesFromAssumptions()) {
|
|
59819
60942
|
const bounds = getInequalityBoundsFromAssumptions(ce, s);
|
|
59820
|
-
const bound = isLower ? bounds.
|
|
60943
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59821
60944
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59822
60945
|
if (bound === void 0 || isStrict && strictOk !== true)
|
|
59823
60946
|
continue;
|
|
@@ -60849,6 +61972,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
60849
61972
|
return `_SYS.cexp(${compile3(args[0])})`;
|
|
60850
61973
|
return `Math.exp(${compile3(args[0])})`;
|
|
60851
61974
|
},
|
|
61975
|
+
First: (args, compile3) => `${compile3(args[0])}[0]`,
|
|
60852
61976
|
Floor: (args, compile3) => {
|
|
60853
61977
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
60854
61978
|
return `Math.floor(${compile3(args[0])})`;
|
|
@@ -61007,7 +62131,20 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
61007
62131
|
if (nConst !== void 0) return `Math.pow(${compile3(arg)}, ${1 / nConst})`;
|
|
61008
62132
|
return `Math.pow(${compile3(arg)}, 1 / (${compile3(exp3)}))`;
|
|
61009
62133
|
},
|
|
61010
|
-
Random:
|
|
62134
|
+
Random: (args, compile3) => {
|
|
62135
|
+
if (args.length === 0) return "Math.random()";
|
|
62136
|
+
if (args.length === 2) {
|
|
62137
|
+
const m = compile3(args[0]);
|
|
62138
|
+
const n = compile3(args[1]);
|
|
62139
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
62140
|
+
}
|
|
62141
|
+
const arg = args[0];
|
|
62142
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
62143
|
+
return `Math.floor(Math.random() * (${compile3(arg)}))`;
|
|
62144
|
+
}
|
|
62145
|
+
const a = compile3(arg);
|
|
62146
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
62147
|
+
},
|
|
61011
62148
|
Round: (args, compile3) => {
|
|
61012
62149
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
61013
62150
|
return `Math.round(${compile3(args[0])})`;
|
|
@@ -61035,6 +62172,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
61035
62172
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile3(arg)})`;
|
|
61036
62173
|
return `1 / Math.cosh(${compile3(arg)})`;
|
|
61037
62174
|
},
|
|
62175
|
+
Second: (args, compile3) => `${compile3(args[0])}[1]`,
|
|
61038
62176
|
Heaviside: "_SYS.heaviside",
|
|
61039
62177
|
Sign: "Math.sign",
|
|
61040
62178
|
Sinc: "_SYS.sinc",
|
|
@@ -61067,6 +62205,7 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
61067
62205
|
return `_SYS.ctanh(${compile3(args[0])})`;
|
|
61068
62206
|
return `Math.tanh(${compile3(args[0])})`;
|
|
61069
62207
|
},
|
|
62208
|
+
Third: (args, compile3) => `${compile3(args[0])}[2]`,
|
|
61070
62209
|
Mod: ([a, b], compile3) => {
|
|
61071
62210
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
61072
62211
|
const ca = compile3(a);
|
|
@@ -62346,6 +63485,14 @@ var GPU_FUNCTIONS = {
|
|
|
62346
63485
|
return `exp(${compile3(args[0])})`;
|
|
62347
63486
|
},
|
|
62348
63487
|
Exp2: "exp2",
|
|
63488
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
63489
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
63490
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
63491
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
63492
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
63493
|
+
First: (args, compile3) => `${compile3(args[0])}.x`,
|
|
63494
|
+
Second: (args, compile3) => `${compile3(args[0])}.y`,
|
|
63495
|
+
Third: (args, compile3) => `${compile3(args[0])}.z`,
|
|
62349
63496
|
Floor: (args, compile3) => {
|
|
62350
63497
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
62351
63498
|
return `floor(${compile3(args[0])})`;
|
|
@@ -62823,6 +63970,39 @@ var GPU_FUNCTIONS = {
|
|
|
62823
63970
|
// Sum/Product — unrolled or for-loop
|
|
62824
63971
|
Sum: (args, compile3, target) => compileGPUSumProduct("Sum", args, compile3, target),
|
|
62825
63972
|
Product: (args, compile3, target) => compileGPUSumProduct("Product", args, compile3, target),
|
|
63973
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
63974
|
+
Range: (args, _compile2, target) => {
|
|
63975
|
+
if (args.length < 2 || args.length > 3) {
|
|
63976
|
+
throw new Error(
|
|
63977
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
63978
|
+
);
|
|
63979
|
+
}
|
|
63980
|
+
const lo = args[0].re;
|
|
63981
|
+
const hi = args[1].re;
|
|
63982
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
63983
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
63984
|
+
throw new Error(
|
|
63985
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
63986
|
+
);
|
|
63987
|
+
}
|
|
63988
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
63989
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
63990
|
+
if (count === 0) {
|
|
63991
|
+
throw new Error(
|
|
63992
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
63993
|
+
);
|
|
63994
|
+
}
|
|
63995
|
+
if (count > 256) {
|
|
63996
|
+
throw new Error(
|
|
63997
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
63998
|
+
);
|
|
63999
|
+
}
|
|
64000
|
+
const values = [];
|
|
64001
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
64002
|
+
const isWGSL = target.language === "wgsl";
|
|
64003
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
64004
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
64005
|
+
},
|
|
62826
64006
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
62827
64007
|
Loop: (args, _compile2, target) => {
|
|
62828
64008
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -62851,6 +64031,134 @@ var GPU_FUNCTIONS = {
|
|
|
62851
64031
|
${bodyCode};
|
|
62852
64032
|
}`;
|
|
62853
64033
|
},
|
|
64034
|
+
// Statistical functions
|
|
64035
|
+
/**
|
|
64036
|
+
* GCD of two scalar arguments.
|
|
64037
|
+
*
|
|
64038
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
64039
|
+
* Only two-argument form is supported in GPU targets.
|
|
64040
|
+
*/
|
|
64041
|
+
GCD: (args, compile3) => {
|
|
64042
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
64043
|
+
if (args.length > 2)
|
|
64044
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
64045
|
+
const a = args[0];
|
|
64046
|
+
const b = args[1];
|
|
64047
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
64048
|
+
return `_gpu_gcd(${compile3(a)}, ${compile3(b)})`;
|
|
64049
|
+
},
|
|
64050
|
+
/**
|
|
64051
|
+
* Variance of a compile-time-known list.
|
|
64052
|
+
*
|
|
64053
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64054
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
64055
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
64056
|
+
*/
|
|
64057
|
+
Variance: (args, compile3) => {
|
|
64058
|
+
let elems;
|
|
64059
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64060
|
+
elems = args[0].ops;
|
|
64061
|
+
} else if (args.length >= 2) {
|
|
64062
|
+
elems = args;
|
|
64063
|
+
} else {
|
|
64064
|
+
throw new Error(
|
|
64065
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
64066
|
+
);
|
|
64067
|
+
}
|
|
64068
|
+
const n = elems.length;
|
|
64069
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
64070
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64071
|
+
const sum = compiled.join(" + ");
|
|
64072
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
64073
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
64074
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
64075
|
+
},
|
|
64076
|
+
/**
|
|
64077
|
+
* Median of a compile-time-known list.
|
|
64078
|
+
*
|
|
64079
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64080
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
64081
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
64082
|
+
*
|
|
64083
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
64084
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
64085
|
+
*/
|
|
64086
|
+
Median: (args, compile3) => {
|
|
64087
|
+
let elems;
|
|
64088
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64089
|
+
elems = args[0].ops;
|
|
64090
|
+
} else if (args.length >= 1) {
|
|
64091
|
+
elems = args;
|
|
64092
|
+
} else {
|
|
64093
|
+
throw new Error(
|
|
64094
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
64095
|
+
);
|
|
64096
|
+
}
|
|
64097
|
+
const n = elems.length;
|
|
64098
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
64099
|
+
if (n > 8) {
|
|
64100
|
+
throw new Error(
|
|
64101
|
+
`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.`
|
|
64102
|
+
);
|
|
64103
|
+
}
|
|
64104
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64105
|
+
if (n === 1) return compiled[0];
|
|
64106
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
64107
|
+
},
|
|
64108
|
+
/**
|
|
64109
|
+
* Deterministic pseudorandom for GPU.
|
|
64110
|
+
*
|
|
64111
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
64112
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
64113
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
64114
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
64115
|
+
* integer-returning operators in this target.
|
|
64116
|
+
*
|
|
64117
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
64118
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
64119
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
64120
|
+
* caller must provide an explicit seed.
|
|
64121
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
64122
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
64123
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
64124
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
64125
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
64126
|
+
*
|
|
64127
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
64128
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
64129
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
64130
|
+
* `sin` differences.
|
|
64131
|
+
*/
|
|
64132
|
+
Random: (args, compile3, target) => {
|
|
64133
|
+
if (args.length === 0) {
|
|
64134
|
+
if (target.language === "wgsl") {
|
|
64135
|
+
throw new Error(
|
|
64136
|
+
"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."
|
|
64137
|
+
);
|
|
64138
|
+
}
|
|
64139
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64140
|
+
}
|
|
64141
|
+
if (args.length === 1) {
|
|
64142
|
+
const arg = args[0];
|
|
64143
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
64144
|
+
const compiled = compile3(arg);
|
|
64145
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
64146
|
+
}
|
|
64147
|
+
return `_gpu_random(${compile3(arg)})`;
|
|
64148
|
+
}
|
|
64149
|
+
if (args.length === 2) {
|
|
64150
|
+
if (target.language === "wgsl") {
|
|
64151
|
+
throw new Error(
|
|
64152
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
64153
|
+
);
|
|
64154
|
+
}
|
|
64155
|
+
const m = compile3(args[0]);
|
|
64156
|
+
const n = compile3(args[1]);
|
|
64157
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64158
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
64159
|
+
}
|
|
64160
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
64161
|
+
},
|
|
62854
64162
|
// Function (lambda) — not supported in GPU
|
|
62855
64163
|
Function: () => {
|
|
62856
64164
|
throw new Error(
|
|
@@ -63450,6 +64758,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
63450
64758
|
return 1.0;
|
|
63451
64759
|
}
|
|
63452
64760
|
`;
|
|
64761
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
64762
|
+
float _gpu_gcd(float a, float b) {
|
|
64763
|
+
a = abs(a); b = abs(b);
|
|
64764
|
+
for (int i = 0; i < 32; i++) {
|
|
64765
|
+
if (b < 0.5) break;
|
|
64766
|
+
float t = mod(a, b);
|
|
64767
|
+
a = b;
|
|
64768
|
+
b = t;
|
|
64769
|
+
}
|
|
64770
|
+
return a;
|
|
64771
|
+
}
|
|
64772
|
+
`;
|
|
64773
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
64774
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
64775
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
64776
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
64777
|
+
if (b < 0.5) { break; }
|
|
64778
|
+
let t = a % b;
|
|
64779
|
+
a = b;
|
|
64780
|
+
b = t;
|
|
64781
|
+
}
|
|
64782
|
+
return a;
|
|
64783
|
+
}
|
|
64784
|
+
`;
|
|
64785
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
64786
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64787
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64788
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64789
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64790
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64791
|
+
float _gpu_random(float seed) {
|
|
64792
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64793
|
+
}
|
|
64794
|
+
`;
|
|
64795
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
64796
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64797
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64798
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64799
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64800
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64801
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
64802
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64803
|
+
}
|
|
64804
|
+
`;
|
|
64805
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
64806
|
+
float _gpu_median_2(float a, float b) {
|
|
64807
|
+
return (a + b) * 0.5;
|
|
64808
|
+
}
|
|
64809
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
64810
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64811
|
+
}
|
|
64812
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
64813
|
+
float lo = max(min(a, b), min(c, d));
|
|
64814
|
+
float hi = min(max(a, b), max(c, d));
|
|
64815
|
+
return (lo + hi) * 0.5;
|
|
64816
|
+
}
|
|
64817
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
64818
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64819
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
64820
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64821
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64822
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64823
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64824
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64825
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64826
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64827
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64828
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64829
|
+
return v2;
|
|
64830
|
+
}
|
|
64831
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
64832
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
64833
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64834
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64835
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64836
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64837
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64838
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64839
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64840
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64841
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64842
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64843
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64844
|
+
return (v2 + v3) * 0.5;
|
|
64845
|
+
}
|
|
64846
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
64847
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
64848
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64849
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64850
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64851
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64852
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64853
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64854
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64855
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64856
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64857
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64858
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64859
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64860
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64861
|
+
return v3;
|
|
64862
|
+
}
|
|
64863
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
64864
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
64865
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64866
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64867
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64868
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
64869
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64870
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64871
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64872
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
64873
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64874
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64875
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64876
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
64877
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64878
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64879
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
64880
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64881
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64882
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64883
|
+
return (v3 + v4) * 0.5;
|
|
64884
|
+
}
|
|
64885
|
+
`;
|
|
64886
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
64887
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
64888
|
+
return (a + b) * 0.5;
|
|
64889
|
+
}
|
|
64890
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
64891
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64892
|
+
}
|
|
64893
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
64894
|
+
let lo = max(min(a, b), min(c, d));
|
|
64895
|
+
let hi = min(max(a, b), max(c, d));
|
|
64896
|
+
return (lo + hi) * 0.5;
|
|
64897
|
+
}
|
|
64898
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
64899
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64900
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
64901
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64902
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64903
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64904
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64905
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64906
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64907
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64908
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64909
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64910
|
+
return v2;
|
|
64911
|
+
}
|
|
64912
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
64913
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
64914
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64915
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64916
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64917
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64918
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64919
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64920
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64921
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64922
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64923
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64924
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64925
|
+
return (v2 + v3) * 0.5;
|
|
64926
|
+
}
|
|
64927
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
64928
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
64929
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64930
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64931
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64932
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64933
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64934
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64935
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64936
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64937
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64938
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64939
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64940
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64941
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64942
|
+
return v3;
|
|
64943
|
+
}
|
|
64944
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
64945
|
+
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;
|
|
64946
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64947
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64948
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64949
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
64950
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64951
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64952
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64953
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
64954
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64955
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64956
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64957
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
64958
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64959
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64960
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
64961
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64962
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64963
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64964
|
+
return (v3 + v4) * 0.5;
|
|
64965
|
+
}
|
|
64966
|
+
`;
|
|
63453
64967
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
63454
64968
|
float _gpu_srgb_to_linear(float c) {
|
|
63455
64969
|
if (c <= 0.04045) return c / 12.92;
|
|
@@ -64127,6 +65641,12 @@ var GPUShaderTarget = class {
|
|
|
64127
65641
|
if (code.includes("_fractal_")) {
|
|
64128
65642
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
64129
65643
|
}
|
|
65644
|
+
if (code.includes("_gpu_random"))
|
|
65645
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
65646
|
+
if (code.includes("_gpu_gcd"))
|
|
65647
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
65648
|
+
if (code.includes("_gpu_median_"))
|
|
65649
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
64130
65650
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
64131
65651
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
64132
65652
|
}
|
|
@@ -66352,6 +67872,7 @@ var EngineRuntimeState = class {
|
|
|
66352
67872
|
_timeLimit = 2e3;
|
|
66353
67873
|
_iterationLimit = 1024;
|
|
66354
67874
|
_recursionLimit = 1024;
|
|
67875
|
+
_maxCollectionSize = 1e4;
|
|
66355
67876
|
_deadline = void 0;
|
|
66356
67877
|
_isVerifying = false;
|
|
66357
67878
|
get timeLimit() {
|
|
@@ -66372,6 +67893,12 @@ var EngineRuntimeState = class {
|
|
|
66372
67893
|
set recursionLimit(value) {
|
|
66373
67894
|
this._recursionLimit = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
66374
67895
|
}
|
|
67896
|
+
get maxCollectionSize() {
|
|
67897
|
+
return this._maxCollectionSize;
|
|
67898
|
+
}
|
|
67899
|
+
set maxCollectionSize(value) {
|
|
67900
|
+
this._maxCollectionSize = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
67901
|
+
}
|
|
66375
67902
|
get deadline() {
|
|
66376
67903
|
return this._deadline;
|
|
66377
67904
|
}
|
|
@@ -68410,6 +69937,23 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68410
69937
|
set recursionLimit(t) {
|
|
68411
69938
|
this._runtimeState.recursionLimit = t;
|
|
68412
69939
|
}
|
|
69940
|
+
/** Maximum number of elements a collection may have when materialized
|
|
69941
|
+
* (converted from a lazy form to a `List`). Default: 10,000.
|
|
69942
|
+
*
|
|
69943
|
+
* When a materialization would exceed this size, the operation leaves
|
|
69944
|
+
* the expression in its lazy form. Consumers can detect oversize
|
|
69945
|
+
* collections via the symbolic form's `count`.
|
|
69946
|
+
*
|
|
69947
|
+
* Set to `Infinity` (or `0` / a negative number) to disable the cap.
|
|
69948
|
+
*
|
|
69949
|
+
* @experimental
|
|
69950
|
+
*/
|
|
69951
|
+
get maxCollectionSize() {
|
|
69952
|
+
return this._runtimeState.maxCollectionSize;
|
|
69953
|
+
}
|
|
69954
|
+
set maxCollectionSize(t) {
|
|
69955
|
+
this._runtimeState.maxCollectionSize = t;
|
|
69956
|
+
}
|
|
68413
69957
|
/**
|
|
68414
69958
|
* Flag to prevent infinite recursion in the verify/ask/equality checking cycle.
|
|
68415
69959
|
*
|
|
@@ -68686,6 +70230,36 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68686
70230
|
lookupDefinition(id) {
|
|
68687
70231
|
return lookupDefinition(this, id);
|
|
68688
70232
|
}
|
|
70233
|
+
normalizeIdentifier(latex) {
|
|
70234
|
+
if (!latex) return "";
|
|
70235
|
+
if (isValidSymbol(latex)) return latex;
|
|
70236
|
+
this.pushScope();
|
|
70237
|
+
try {
|
|
70238
|
+
const expr2 = this.parse(latex);
|
|
70239
|
+
if (isSymbol2(expr2)) return expr2.symbol;
|
|
70240
|
+
} finally {
|
|
70241
|
+
this.popScope();
|
|
70242
|
+
}
|
|
70243
|
+
return "";
|
|
70244
|
+
}
|
|
70245
|
+
operatorInfo(head) {
|
|
70246
|
+
const def = this.lookupDefinition(head);
|
|
70247
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
70248
|
+
const op = def.operator;
|
|
70249
|
+
return {
|
|
70250
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
70251
|
+
signature: op.signature
|
|
70252
|
+
};
|
|
70253
|
+
}
|
|
70254
|
+
symbolInfo(name) {
|
|
70255
|
+
const def = this.lookupDefinition(name);
|
|
70256
|
+
if (!def || !isValueDef(def)) return void 0;
|
|
70257
|
+
const v = def.value;
|
|
70258
|
+
return {
|
|
70259
|
+
kind: v.isConstant ? "constant" : "variable",
|
|
70260
|
+
type: v.type
|
|
70261
|
+
};
|
|
70262
|
+
}
|
|
68689
70263
|
/**
|
|
68690
70264
|
* Associate a new definition to a symbol in the current context.
|
|
68691
70265
|
*
|
|
@@ -68973,6 +70547,7 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68973
70547
|
const def = this.lookupDefinition(id);
|
|
68974
70548
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
68975
70549
|
},
|
|
70550
|
+
tolerance: this.tolerance,
|
|
68976
70551
|
...this._latexOptions,
|
|
68977
70552
|
...parseOpts
|
|
68978
70553
|
});
|
|
@@ -69137,7 +70712,7 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
69137
70712
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
69138
70713
|
|
|
69139
70714
|
// src/core.ts
|
|
69140
|
-
var version = "0.
|
|
70715
|
+
var version = "0.58.0";
|
|
69141
70716
|
export {
|
|
69142
70717
|
ComputeEngine,
|
|
69143
70718
|
N,
|