@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.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** ComputeEngineCore 0.
|
|
1
|
+
/** ComputeEngineCore 0.58.0 */
|
|
2
2
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngineCore = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var ComputeEngineCore = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -4315,7 +4315,42 @@ var ComputeEngineCore = (() => {
|
|
|
4315
4315
|
if (b === "nothing") return a;
|
|
4316
4316
|
if (isSubtype(a, b)) return b;
|
|
4317
4317
|
if (isSubtype(b, a)) return a;
|
|
4318
|
-
|
|
4318
|
+
const sup = superType(a, b);
|
|
4319
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
4320
|
+
return sup;
|
|
4321
|
+
}
|
|
4322
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
4323
|
+
"scalar",
|
|
4324
|
+
"value",
|
|
4325
|
+
"function",
|
|
4326
|
+
"expression",
|
|
4327
|
+
"collection",
|
|
4328
|
+
"indexed_collection",
|
|
4329
|
+
"list",
|
|
4330
|
+
"set",
|
|
4331
|
+
"tuple",
|
|
4332
|
+
"record",
|
|
4333
|
+
"dictionary",
|
|
4334
|
+
"map",
|
|
4335
|
+
"any"
|
|
4336
|
+
]);
|
|
4337
|
+
function unionTypes(a, b) {
|
|
4338
|
+
const members = [];
|
|
4339
|
+
const push = (t) => {
|
|
4340
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
4341
|
+
for (const m of t.types) push(m);
|
|
4342
|
+
return;
|
|
4343
|
+
}
|
|
4344
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
4345
|
+
if (!members.some(
|
|
4346
|
+
(m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
|
|
4347
|
+
))
|
|
4348
|
+
members.push(t);
|
|
4349
|
+
};
|
|
4350
|
+
push(a);
|
|
4351
|
+
push(b);
|
|
4352
|
+
if (members.length === 1) return members[0];
|
|
4353
|
+
return { kind: "union", types: members };
|
|
4319
4354
|
}
|
|
4320
4355
|
function narrow(...types) {
|
|
4321
4356
|
if (types.length === 0) return "nothing";
|
|
@@ -4393,7 +4428,7 @@ var ComputeEngineCore = (() => {
|
|
|
4393
4428
|
if (type2.kind === "set") return type2.elements;
|
|
4394
4429
|
if (type2.kind === "tuple") return widen(...type2.elements.map((x) => x.type));
|
|
4395
4430
|
if (type2.kind === "dictionary")
|
|
4396
|
-
return parseType(`tuple<string, ${type2.values}>`);
|
|
4431
|
+
return parseType(`tuple<string, ${typeToString(type2.values)}>`);
|
|
4397
4432
|
if (type2.kind === "record") {
|
|
4398
4433
|
return parseType(
|
|
4399
4434
|
`tuple<string, ${typeToString(widen(...Object.values(type2.elements)))}>`
|
|
@@ -5939,6 +5974,84 @@ var ComputeEngineCore = (() => {
|
|
|
5939
5974
|
}
|
|
5940
5975
|
|
|
5941
5976
|
// src/compute-engine/boxed-expression/inequality-bounds.ts
|
|
5977
|
+
function extractIntervalBounds(expr2, symbol2) {
|
|
5978
|
+
if (isFunction2(expr2, "When")) {
|
|
5979
|
+
const cond = expr2.op2;
|
|
5980
|
+
if (!cond) return void 0;
|
|
5981
|
+
return extractIntervalBounds(cond, symbol2);
|
|
5982
|
+
}
|
|
5983
|
+
if (isFunction2(expr2, "Multiply")) {
|
|
5984
|
+
const ops = expr2.ops;
|
|
5985
|
+
if (!ops) return void 0;
|
|
5986
|
+
const merged = {};
|
|
5987
|
+
for (const sub2 of ops) {
|
|
5988
|
+
if (isFunction2(sub2, "When")) {
|
|
5989
|
+
const sub_ = extractIntervalBounds(sub2, symbol2);
|
|
5990
|
+
if (sub_ !== void 0) _mergeBounds(merged, sub_);
|
|
5991
|
+
}
|
|
5992
|
+
}
|
|
5993
|
+
return _hasAnyBound(merged) ? merged : void 0;
|
|
5994
|
+
}
|
|
5995
|
+
const result = {};
|
|
5996
|
+
if (isFunction2(expr2, "And")) {
|
|
5997
|
+
const ops = expr2.ops;
|
|
5998
|
+
if (!ops) return void 0;
|
|
5999
|
+
for (const sub2 of ops) {
|
|
6000
|
+
const subBounds = extractIntervalBounds(sub2, symbol2);
|
|
6001
|
+
if (subBounds === void 0) continue;
|
|
6002
|
+
_mergeBounds(result, subBounds);
|
|
6003
|
+
}
|
|
6004
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
6005
|
+
}
|
|
6006
|
+
const op = expr2.operator;
|
|
6007
|
+
if ((op === "Less" || op === "LessEqual" || op === "Greater" || op === "GreaterEqual") && isFunction2(expr2)) {
|
|
6008
|
+
const isStrict = op === "Less" || op === "Greater";
|
|
6009
|
+
const ops = expr2.ops;
|
|
6010
|
+
if (!ops || ops.length < 2) return void 0;
|
|
6011
|
+
const flipped = op === "Greater" || op === "GreaterEqual" ? [...ops].reverse() : ops;
|
|
6012
|
+
for (let i = 0; i < flipped.length; i++) {
|
|
6013
|
+
if (isSymbol2(flipped[i], symbol2)) {
|
|
6014
|
+
if (i > 0) {
|
|
6015
|
+
const candidate = flipped[i - 1];
|
|
6016
|
+
if (result.lower === void 0 || candidate.isGreater(result.lower) === true) {
|
|
6017
|
+
result.lower = candidate;
|
|
6018
|
+
result.lowerStrict = isStrict;
|
|
6019
|
+
}
|
|
6020
|
+
}
|
|
6021
|
+
if (i < flipped.length - 1) {
|
|
6022
|
+
const candidate = flipped[i + 1];
|
|
6023
|
+
if (result.upper === void 0 || candidate.isLess(result.upper) === true) {
|
|
6024
|
+
result.upper = candidate;
|
|
6025
|
+
result.upperStrict = isStrict;
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
6031
|
+
}
|
|
6032
|
+
return void 0;
|
|
6033
|
+
}
|
|
6034
|
+
function _mergeBounds(into, from) {
|
|
6035
|
+
if (from.lower !== void 0) {
|
|
6036
|
+
if (into.lower === void 0 || from.lower.isGreater(into.lower) === true) {
|
|
6037
|
+
into.lower = from.lower;
|
|
6038
|
+
into.lowerStrict = from.lowerStrict;
|
|
6039
|
+
} else if (from.lower.isSame(into.lower)) {
|
|
6040
|
+
into.lowerStrict = into.lowerStrict || from.lowerStrict;
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
if (from.upper !== void 0) {
|
|
6044
|
+
if (into.upper === void 0 || from.upper.isLess(into.upper) === true) {
|
|
6045
|
+
into.upper = from.upper;
|
|
6046
|
+
into.upperStrict = from.upperStrict;
|
|
6047
|
+
} else if (from.upper.isSame(into.upper)) {
|
|
6048
|
+
into.upperStrict = into.upperStrict || from.upperStrict;
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
function _hasAnyBound(b) {
|
|
6053
|
+
return b.lower !== void 0 || b.upper !== void 0;
|
|
6054
|
+
}
|
|
5942
6055
|
function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
5943
6056
|
const result = {};
|
|
5944
6057
|
const assumptions = ce.context?.assumptions;
|
|
@@ -5955,8 +6068,8 @@ var ComputeEngineCore = (() => {
|
|
|
5955
6068
|
const isStrict = op === "Less";
|
|
5956
6069
|
if (isFunction2(lhs, "Negate") && isSymbol2(lhs.op1, symbol2)) {
|
|
5957
6070
|
const bound = ce.Zero;
|
|
5958
|
-
if (result.
|
|
5959
|
-
result.
|
|
6071
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6072
|
+
result.lower = bound;
|
|
5960
6073
|
result.lowerStrict = isStrict;
|
|
5961
6074
|
}
|
|
5962
6075
|
}
|
|
@@ -5975,16 +6088,16 @@ var ComputeEngineCore = (() => {
|
|
|
5975
6088
|
}
|
|
5976
6089
|
if (hasNegatedSymbol && constantSum !== 0) {
|
|
5977
6090
|
const bound = ce.expr(constantSum);
|
|
5978
|
-
if (result.
|
|
5979
|
-
result.
|
|
6091
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6092
|
+
result.lower = bound;
|
|
5980
6093
|
result.lowerStrict = isStrict;
|
|
5981
6094
|
}
|
|
5982
6095
|
}
|
|
5983
6096
|
}
|
|
5984
6097
|
if (isSymbol2(lhs, symbol2)) {
|
|
5985
6098
|
const bound = ce.Zero;
|
|
5986
|
-
if (result.
|
|
5987
|
-
result.
|
|
6099
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6100
|
+
result.upper = bound;
|
|
5988
6101
|
result.upperStrict = isStrict;
|
|
5989
6102
|
}
|
|
5990
6103
|
}
|
|
@@ -6003,8 +6116,8 @@ var ComputeEngineCore = (() => {
|
|
|
6003
6116
|
}
|
|
6004
6117
|
if (hasSymbol && constantSum !== 0) {
|
|
6005
6118
|
const bound = ce.expr(-constantSum);
|
|
6006
|
-
if (result.
|
|
6007
|
-
result.
|
|
6119
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6120
|
+
result.upper = bound;
|
|
6008
6121
|
result.upperStrict = isStrict;
|
|
6009
6122
|
}
|
|
6010
6123
|
}
|
|
@@ -6224,8 +6337,8 @@ var ComputeEngineCore = (() => {
|
|
|
6224
6337
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, b.symbol);
|
|
6225
6338
|
const aNum = typeof a.numericValue === "number" ? a.numericValue : a.numericValue.re;
|
|
6226
6339
|
if (aNum !== void 0 && Number.isFinite(aNum)) {
|
|
6227
|
-
if (bounds.
|
|
6228
|
-
const lb = bounds.
|
|
6340
|
+
if (bounds.lower !== void 0) {
|
|
6341
|
+
const lb = bounds.lower;
|
|
6229
6342
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6230
6343
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6231
6344
|
if (lowerNum > aNum) return "<";
|
|
@@ -6233,8 +6346,8 @@ var ComputeEngineCore = (() => {
|
|
|
6233
6346
|
if (lowerNum === aNum && !bounds.lowerStrict) return "<=";
|
|
6234
6347
|
}
|
|
6235
6348
|
}
|
|
6236
|
-
if (bounds.
|
|
6237
|
-
const ub = bounds.
|
|
6349
|
+
if (bounds.upper !== void 0) {
|
|
6350
|
+
const ub = bounds.upper;
|
|
6238
6351
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6239
6352
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6240
6353
|
if (upperNum < aNum) return ">";
|
|
@@ -6264,8 +6377,8 @@ var ComputeEngineCore = (() => {
|
|
|
6264
6377
|
if (typeof b === "number") {
|
|
6265
6378
|
if (isSymbol2(a)) {
|
|
6266
6379
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6267
|
-
if (bounds.
|
|
6268
|
-
const lb = bounds.
|
|
6380
|
+
if (bounds.lower !== void 0) {
|
|
6381
|
+
const lb = bounds.lower;
|
|
6269
6382
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6270
6383
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6271
6384
|
if (lowerNum > b) return ">";
|
|
@@ -6273,8 +6386,8 @@ var ComputeEngineCore = (() => {
|
|
|
6273
6386
|
if (lowerNum === b && !bounds.lowerStrict) return ">=";
|
|
6274
6387
|
}
|
|
6275
6388
|
}
|
|
6276
|
-
if (bounds.
|
|
6277
|
-
const ub = bounds.
|
|
6389
|
+
if (bounds.upper !== void 0) {
|
|
6390
|
+
const ub = bounds.upper;
|
|
6278
6391
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6279
6392
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6280
6393
|
if (upperNum < b) return "<";
|
|
@@ -6330,8 +6443,8 @@ var ComputeEngineCore = (() => {
|
|
|
6330
6443
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6331
6444
|
const bNum = typeof b.numericValue === "number" ? b.numericValue : b.numericValue.re;
|
|
6332
6445
|
if (bNum !== void 0 && Number.isFinite(bNum)) {
|
|
6333
|
-
if (bounds.
|
|
6334
|
-
const lb = bounds.
|
|
6446
|
+
if (bounds.lower !== void 0) {
|
|
6447
|
+
const lb = bounds.lower;
|
|
6335
6448
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6336
6449
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6337
6450
|
if (lowerNum > bNum) return ">";
|
|
@@ -6339,8 +6452,8 @@ var ComputeEngineCore = (() => {
|
|
|
6339
6452
|
if (lowerNum === bNum && !bounds.lowerStrict) return ">=";
|
|
6340
6453
|
}
|
|
6341
6454
|
}
|
|
6342
|
-
if (bounds.
|
|
6343
|
-
const ub = bounds.
|
|
6455
|
+
if (bounds.upper !== void 0) {
|
|
6456
|
+
const ub = bounds.upper;
|
|
6344
6457
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6345
6458
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6346
6459
|
if (upperNum < bNum) return "<";
|
|
@@ -6878,6 +6991,12 @@ var ComputeEngineCore = (() => {
|
|
|
6878
6991
|
scoped = false;
|
|
6879
6992
|
signature;
|
|
6880
6993
|
inferredSignature = true;
|
|
6994
|
+
/** True if this operator definition was created from a user-defined
|
|
6995
|
+
* function literal (e.g. via `ce.assign('f', ce.parse('x \\mapsto x^2'))`).
|
|
6996
|
+
* Used to enable auto-broadcasting when applied to indexed collections.
|
|
6997
|
+
* @internal
|
|
6998
|
+
*/
|
|
6999
|
+
_isLambda = false;
|
|
6881
7000
|
type;
|
|
6882
7001
|
sgn;
|
|
6883
7002
|
eq;
|
|
@@ -7035,6 +7154,8 @@ var ComputeEngineCore = (() => {
|
|
|
7035
7154
|
this.engine._typeResolver
|
|
7036
7155
|
);
|
|
7037
7156
|
}
|
|
7157
|
+
if (isFunction2(boxedFn) && boxedFn.operator === "Function")
|
|
7158
|
+
this._isLambda = true;
|
|
7038
7159
|
const fn = applicable(boxedFn);
|
|
7039
7160
|
evaluate2 = (xs, _options) => fn(xs);
|
|
7040
7161
|
Object.defineProperty(evaluate2, "toString", {
|
|
@@ -7885,8 +8006,15 @@ var ComputeEngineCore = (() => {
|
|
|
7885
8006
|
*
|
|
7886
8007
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7887
8008
|
* (via `fractionalDigits: 'auto'`).
|
|
8009
|
+
*
|
|
8010
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
8011
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
8012
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
8013
|
+
* re-serialization if no verbatim is available.
|
|
7888
8014
|
*/
|
|
7889
8015
|
toLatex(options) {
|
|
8016
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
8017
|
+
return this.verbatimLatex;
|
|
7890
8018
|
if (this.isLazyCollection) {
|
|
7891
8019
|
const materialized = this.evaluate({
|
|
7892
8020
|
materialization: options?.materialization ?? true
|
|
@@ -8344,6 +8472,29 @@ var ComputeEngineCore = (() => {
|
|
|
8344
8472
|
get isReal() {
|
|
8345
8473
|
return void 0;
|
|
8346
8474
|
}
|
|
8475
|
+
toSignedFunction() {
|
|
8476
|
+
const op = this.operator;
|
|
8477
|
+
if (op === void 0 || this.ops === void 0 || this.ops.length < 2) {
|
|
8478
|
+
return void 0;
|
|
8479
|
+
}
|
|
8480
|
+
const [lhs, rhs] = this.ops;
|
|
8481
|
+
const engine = this.engine;
|
|
8482
|
+
switch (op) {
|
|
8483
|
+
case "Equal":
|
|
8484
|
+
case "NotEqual":
|
|
8485
|
+
case "Less":
|
|
8486
|
+
case "LessEqual":
|
|
8487
|
+
return engine.function("Subtract", [lhs, rhs]);
|
|
8488
|
+
case "Greater":
|
|
8489
|
+
case "GreaterEqual":
|
|
8490
|
+
return engine.function("Subtract", [rhs, lhs]);
|
|
8491
|
+
default:
|
|
8492
|
+
return void 0;
|
|
8493
|
+
}
|
|
8494
|
+
}
|
|
8495
|
+
getInterval(symbol2) {
|
|
8496
|
+
return extractIntervalBounds(this, symbol2);
|
|
8497
|
+
}
|
|
8347
8498
|
simplify(_options) {
|
|
8348
8499
|
return this;
|
|
8349
8500
|
}
|
|
@@ -10029,6 +10180,64 @@ var ComputeEngineCore = (() => {
|
|
|
10029
10180
|
}
|
|
10030
10181
|
|
|
10031
10182
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
10183
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
10184
|
+
x: "First",
|
|
10185
|
+
y: "Second",
|
|
10186
|
+
z: "Third",
|
|
10187
|
+
real: "Real",
|
|
10188
|
+
re: "Real",
|
|
10189
|
+
imag: "Imaginary",
|
|
10190
|
+
im: "Imaginary",
|
|
10191
|
+
count: "Length",
|
|
10192
|
+
total: "Sum",
|
|
10193
|
+
max: "Max",
|
|
10194
|
+
min: "Min"
|
|
10195
|
+
};
|
|
10196
|
+
function memberHead(name) {
|
|
10197
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10198
|
+
}
|
|
10199
|
+
function parseComponentAccess(parser, lhs) {
|
|
10200
|
+
parser.skipVisualSpace();
|
|
10201
|
+
if (parser.match("\\operatorname")) {
|
|
10202
|
+
const name = parser.parseStringGroup();
|
|
10203
|
+
if (name === null) return null;
|
|
10204
|
+
const head = memberHead(name.trim());
|
|
10205
|
+
if (head === null) return null;
|
|
10206
|
+
return [head, lhs];
|
|
10207
|
+
}
|
|
10208
|
+
const tok = parser.peek;
|
|
10209
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10210
|
+
const bare = tok.slice(1);
|
|
10211
|
+
const head = memberHead(bare);
|
|
10212
|
+
if (head !== null) {
|
|
10213
|
+
parser.nextToken();
|
|
10214
|
+
return [head, lhs];
|
|
10215
|
+
}
|
|
10216
|
+
return null;
|
|
10217
|
+
}
|
|
10218
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10219
|
+
const head = memberHead(tok);
|
|
10220
|
+
if (head === null) return null;
|
|
10221
|
+
parser.nextToken();
|
|
10222
|
+
return [head, lhs];
|
|
10223
|
+
}
|
|
10224
|
+
return null;
|
|
10225
|
+
}
|
|
10226
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10227
|
+
parser.addBoundary(close);
|
|
10228
|
+
parser.skipVisualSpace();
|
|
10229
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10230
|
+
if (cond === null) {
|
|
10231
|
+
parser.removeBoundary();
|
|
10232
|
+
return null;
|
|
10233
|
+
}
|
|
10234
|
+
parser.skipVisualSpace();
|
|
10235
|
+
if (!parser.matchBoundary()) {
|
|
10236
|
+
parser.removeBoundary();
|
|
10237
|
+
return null;
|
|
10238
|
+
}
|
|
10239
|
+
return ["When", lhs, cond];
|
|
10240
|
+
}
|
|
10032
10241
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
10033
10242
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
10034
10243
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10304,15 +10513,16 @@ var ComputeEngineCore = (() => {
|
|
|
10304
10513
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
10305
10514
|
parse: parseAssign
|
|
10306
10515
|
},
|
|
10307
|
-
// General colon operator (type annotation, mapping notation)
|
|
10308
|
-
// Precedence below
|
|
10309
|
-
// and below arrows (270) so
|
|
10516
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
10517
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
10518
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
10519
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
10310
10520
|
{
|
|
10311
10521
|
name: "Colon",
|
|
10312
10522
|
latexTrigger: ":",
|
|
10313
10523
|
kind: "infix",
|
|
10314
10524
|
associativity: "right",
|
|
10315
|
-
precedence:
|
|
10525
|
+
precedence: 240,
|
|
10316
10526
|
serialize: (serializer, expr2) => joinLatex([
|
|
10317
10527
|
serializer.serialize(operand(expr2, 1)),
|
|
10318
10528
|
"\\colon",
|
|
@@ -10323,7 +10533,7 @@ var ComputeEngineCore = (() => {
|
|
|
10323
10533
|
latexTrigger: "\\colon",
|
|
10324
10534
|
kind: "infix",
|
|
10325
10535
|
associativity: "right",
|
|
10326
|
-
precedence:
|
|
10536
|
+
precedence: 240,
|
|
10327
10537
|
parse: "Colon"
|
|
10328
10538
|
},
|
|
10329
10539
|
{
|
|
@@ -10500,6 +10710,15 @@ var ComputeEngineCore = (() => {
|
|
|
10500
10710
|
}
|
|
10501
10711
|
},
|
|
10502
10712
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10713
|
+
// Component-access postfix: expr.member (C3)
|
|
10714
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10715
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10716
|
+
{
|
|
10717
|
+
kind: "postfix",
|
|
10718
|
+
precedence: 850,
|
|
10719
|
+
latexTrigger: ["."],
|
|
10720
|
+
parse: parseComponentAccess
|
|
10721
|
+
},
|
|
10503
10722
|
{
|
|
10504
10723
|
name: "At",
|
|
10505
10724
|
kind: "postfix",
|
|
@@ -10520,6 +10739,29 @@ var ComputeEngineCore = (() => {
|
|
|
10520
10739
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10521
10740
|
parse: parseAt("\\right", "\\rbrack")
|
|
10522
10741
|
},
|
|
10742
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10743
|
+
{
|
|
10744
|
+
name: "When",
|
|
10745
|
+
kind: "postfix",
|
|
10746
|
+
precedence: 800,
|
|
10747
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10748
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10749
|
+
serialize: (serializer, expr2) => {
|
|
10750
|
+
const e = operand(expr2, 1);
|
|
10751
|
+
const cond = operand(expr2, 2);
|
|
10752
|
+
if (!e || !cond) return "";
|
|
10753
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10754
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10755
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10756
|
+
}
|
|
10757
|
+
},
|
|
10758
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10759
|
+
{
|
|
10760
|
+
kind: "postfix",
|
|
10761
|
+
precedence: 800,
|
|
10762
|
+
latexTrigger: ["\\{"],
|
|
10763
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10764
|
+
},
|
|
10523
10765
|
{
|
|
10524
10766
|
kind: "postfix",
|
|
10525
10767
|
latexTrigger: ["_"],
|
|
@@ -10602,6 +10844,29 @@ var ComputeEngineCore = (() => {
|
|
|
10602
10844
|
return "";
|
|
10603
10845
|
}
|
|
10604
10846
|
},
|
|
10847
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10848
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10849
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10850
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10851
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10852
|
+
{
|
|
10853
|
+
latexTrigger: [".", ".", "."],
|
|
10854
|
+
kind: "infix",
|
|
10855
|
+
precedence: 800,
|
|
10856
|
+
parse: parseRange
|
|
10857
|
+
},
|
|
10858
|
+
{
|
|
10859
|
+
latexTrigger: ["\\ldots"],
|
|
10860
|
+
kind: "infix",
|
|
10861
|
+
precedence: 800,
|
|
10862
|
+
parse: parseRange
|
|
10863
|
+
},
|
|
10864
|
+
{
|
|
10865
|
+
latexTrigger: ["\\dots"],
|
|
10866
|
+
kind: "infix",
|
|
10867
|
+
precedence: 800,
|
|
10868
|
+
parse: parseRange
|
|
10869
|
+
},
|
|
10605
10870
|
{
|
|
10606
10871
|
latexTrigger: [";"],
|
|
10607
10872
|
kind: "infix",
|
|
@@ -10786,13 +11051,24 @@ var ComputeEngineCore = (() => {
|
|
|
10786
11051
|
const args = operands(expr2);
|
|
10787
11052
|
if (!args || args.length < 2) return "";
|
|
10788
11053
|
const body = args[0];
|
|
10789
|
-
const
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
11054
|
+
const elements = args.slice(1);
|
|
11055
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
11056
|
+
if (!allElements) {
|
|
11057
|
+
return joinLatex([
|
|
11058
|
+
"\\operatorname{Loop}(",
|
|
11059
|
+
serializer.serialize(body),
|
|
11060
|
+
", ",
|
|
11061
|
+
serializer.serialize(elements[0]),
|
|
11062
|
+
")"
|
|
11063
|
+
]);
|
|
11064
|
+
}
|
|
11065
|
+
if (elements.length === 1) {
|
|
11066
|
+
const elem = elements[0];
|
|
11067
|
+
const index = operand(elem, 1);
|
|
11068
|
+
const coll = operand(elem, 2);
|
|
11069
|
+
if (operator(coll) === "Range") {
|
|
11070
|
+
const lo = operand(coll, 1);
|
|
11071
|
+
const hi = operand(coll, 2);
|
|
10796
11072
|
return joinLatex([
|
|
10797
11073
|
"\\text{for }",
|
|
10798
11074
|
serializer.serialize(index),
|
|
@@ -10804,13 +11080,27 @@ var ComputeEngineCore = (() => {
|
|
|
10804
11080
|
serializer.serialize(body)
|
|
10805
11081
|
]);
|
|
10806
11082
|
}
|
|
11083
|
+
return joinLatex([
|
|
11084
|
+
serializer.serialize(body),
|
|
11085
|
+
" \\operatorname{for} ",
|
|
11086
|
+
serializer.serialize(index),
|
|
11087
|
+
" = ",
|
|
11088
|
+
serializer.serialize(coll)
|
|
11089
|
+
]);
|
|
10807
11090
|
}
|
|
11091
|
+
const bindings = elements.map((elem) => {
|
|
11092
|
+
const name = operand(elem, 1);
|
|
11093
|
+
const coll = operand(elem, 2);
|
|
11094
|
+
return joinLatex([
|
|
11095
|
+
serializer.serialize(name),
|
|
11096
|
+
" = ",
|
|
11097
|
+
serializer.serialize(coll)
|
|
11098
|
+
]);
|
|
11099
|
+
}).join(", ");
|
|
10808
11100
|
return joinLatex([
|
|
10809
|
-
"\\operatorname{Loop}(",
|
|
10810
11101
|
serializer.serialize(body),
|
|
10811
|
-
"
|
|
10812
|
-
|
|
10813
|
-
")"
|
|
11102
|
+
" \\operatorname{for} ",
|
|
11103
|
+
bindings
|
|
10814
11104
|
]);
|
|
10815
11105
|
}
|
|
10816
11106
|
},
|
|
@@ -10843,6 +11133,18 @@ var ComputeEngineCore = (() => {
|
|
|
10843
11133
|
precedence: 245,
|
|
10844
11134
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10845
11135
|
},
|
|
11136
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
11137
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
11138
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
11139
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
11140
|
+
// bindings can be comma-separated below us.
|
|
11141
|
+
{
|
|
11142
|
+
symbolTrigger: "for",
|
|
11143
|
+
kind: "infix",
|
|
11144
|
+
associativity: "none",
|
|
11145
|
+
precedence: 19,
|
|
11146
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
11147
|
+
},
|
|
10846
11148
|
// \operatorname{break}
|
|
10847
11149
|
{
|
|
10848
11150
|
symbolTrigger: "break",
|
|
@@ -11047,7 +11349,10 @@ var ComputeEngineCore = (() => {
|
|
|
11047
11349
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
11048
11350
|
parser.addBoundary([")"]);
|
|
11049
11351
|
const expr2 = parser.parseExpression(until);
|
|
11050
|
-
if (!parser.matchBoundary())
|
|
11352
|
+
if (!parser.matchBoundary()) {
|
|
11353
|
+
parser.removeBoundary();
|
|
11354
|
+
return null;
|
|
11355
|
+
}
|
|
11051
11356
|
if (!parser.match("<}>")) return null;
|
|
11052
11357
|
return ["Derivative", lhs, expr2];
|
|
11053
11358
|
}
|
|
@@ -11488,7 +11793,12 @@ var ComputeEngineCore = (() => {
|
|
|
11488
11793
|
if (isEmptySequence(body)) return ["List"];
|
|
11489
11794
|
const h = operator(body);
|
|
11490
11795
|
if (h === "Range" || h === "Linspace") return body;
|
|
11491
|
-
if (h === "Sequence")
|
|
11796
|
+
if (h === "Sequence") {
|
|
11797
|
+
const elems = operands(body);
|
|
11798
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11799
|
+
if (inferred) return inferred;
|
|
11800
|
+
return ["List", ...elems];
|
|
11801
|
+
}
|
|
11492
11802
|
if (h === "Delimiter") {
|
|
11493
11803
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11494
11804
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11501,12 +11811,37 @@ var ComputeEngineCore = (() => {
|
|
|
11501
11811
|
}
|
|
11502
11812
|
if (delim === "," || delim === ".,.") {
|
|
11503
11813
|
body = operand(body, 1);
|
|
11504
|
-
if (operator(body) === "Sequence")
|
|
11814
|
+
if (operator(body) === "Sequence") {
|
|
11815
|
+
const elems = operands(body);
|
|
11816
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11817
|
+
if (inferred) return inferred;
|
|
11818
|
+
return ["List", ...elems];
|
|
11819
|
+
}
|
|
11505
11820
|
return ["List", body ?? "Nothing"];
|
|
11506
11821
|
}
|
|
11507
11822
|
}
|
|
11508
11823
|
return ["List", body];
|
|
11509
11824
|
}
|
|
11825
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11826
|
+
if (elems.length < 4) return null;
|
|
11827
|
+
const penultimate = elems[elems.length - 2];
|
|
11828
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11829
|
+
const samples = elems.slice(0, -2);
|
|
11830
|
+
const endExpr = elems[elems.length - 1];
|
|
11831
|
+
if (samples.length < 2) return null;
|
|
11832
|
+
const sampleNums = samples.map(machineValue);
|
|
11833
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11834
|
+
const nums = sampleNums;
|
|
11835
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11836
|
+
const tol = parser.options.tolerance;
|
|
11837
|
+
if (Math.abs(step) < tol)
|
|
11838
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11839
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11840
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11841
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11842
|
+
}
|
|
11843
|
+
return ["Range", nums[0], endExpr, step];
|
|
11844
|
+
}
|
|
11510
11845
|
function serializeList(serializer, expr2) {
|
|
11511
11846
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11512
11847
|
const op = operator(x);
|
|
@@ -11758,6 +12093,38 @@ var ComputeEngineCore = (() => {
|
|
|
11758
12093
|
["Element", index, ["Range", lower, upper]]
|
|
11759
12094
|
];
|
|
11760
12095
|
}
|
|
12096
|
+
function parseForComprehension(parser, lhs, until) {
|
|
12097
|
+
const bindingTerminator = {
|
|
12098
|
+
minPrec: 21,
|
|
12099
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
12100
|
+
condition: (p) => {
|
|
12101
|
+
if (until?.condition?.(p)) return true;
|
|
12102
|
+
const saved = p.index;
|
|
12103
|
+
p.skipVisualSpace();
|
|
12104
|
+
const isComma = p.peek === ",";
|
|
12105
|
+
p.index = saved;
|
|
12106
|
+
if (isComma) return true;
|
|
12107
|
+
if (peekKeyword(p, "where")) return true;
|
|
12108
|
+
if (peekKeyword(p, "with")) return true;
|
|
12109
|
+
return false;
|
|
12110
|
+
}
|
|
12111
|
+
};
|
|
12112
|
+
const elements = [];
|
|
12113
|
+
do {
|
|
12114
|
+
parser.skipVisualSpace();
|
|
12115
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
12116
|
+
if (binding === null) break;
|
|
12117
|
+
const op = operator(binding);
|
|
12118
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
12119
|
+
const name = operand(binding, 1);
|
|
12120
|
+
const list = operand(binding, 2);
|
|
12121
|
+
if (!name || !list) return null;
|
|
12122
|
+
elements.push(["Element", name, list]);
|
|
12123
|
+
parser.skipVisualSpace();
|
|
12124
|
+
} while (parser.match(","));
|
|
12125
|
+
if (elements.length === 0) return null;
|
|
12126
|
+
return ["Loop", lhs, ...elements];
|
|
12127
|
+
}
|
|
11761
12128
|
function parseWhereExpression(parser, lhs, until) {
|
|
11762
12129
|
const bindingTerminator = {
|
|
11763
12130
|
minPrec: 21,
|
|
@@ -11780,6 +12147,25 @@ var ComputeEngineCore = (() => {
|
|
|
11780
12147
|
parser.skipVisualSpace();
|
|
11781
12148
|
} while (parser.match(","));
|
|
11782
12149
|
if (bindings.length === 0) return null;
|
|
12150
|
+
const forStart = parser.index;
|
|
12151
|
+
if (matchKeyword(parser, "for")) {
|
|
12152
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
12153
|
+
if (loop) {
|
|
12154
|
+
const block2 = [];
|
|
12155
|
+
for (const b of bindings) {
|
|
12156
|
+
const normalized = normalizeLocalAssign(b);
|
|
12157
|
+
if (operator(normalized) === "Assign") {
|
|
12158
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
12159
|
+
block2.push(normalized);
|
|
12160
|
+
} else {
|
|
12161
|
+
block2.push(normalized);
|
|
12162
|
+
}
|
|
12163
|
+
}
|
|
12164
|
+
block2.push(loop);
|
|
12165
|
+
return ["Block", ...block2];
|
|
12166
|
+
}
|
|
12167
|
+
parser.index = forStart;
|
|
12168
|
+
}
|
|
11783
12169
|
const block = [];
|
|
11784
12170
|
for (const b of bindings) {
|
|
11785
12171
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -11993,6 +12379,17 @@ var ComputeEngineCore = (() => {
|
|
|
11993
12379
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
11994
12380
|
return ["Interval", lowerExpr, upperExpr];
|
|
11995
12381
|
}
|
|
12382
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
12383
|
+
"Less",
|
|
12384
|
+
"LessEqual",
|
|
12385
|
+
"Greater",
|
|
12386
|
+
"GreaterEqual",
|
|
12387
|
+
"Equal",
|
|
12388
|
+
"NotEqual",
|
|
12389
|
+
"And",
|
|
12390
|
+
"Or",
|
|
12391
|
+
"Not"
|
|
12392
|
+
]);
|
|
11996
12393
|
var DEFINITIONS_SETS = [
|
|
11997
12394
|
//
|
|
11998
12395
|
// Constants
|
|
@@ -12251,18 +12648,58 @@ var ComputeEngineCore = (() => {
|
|
|
12251
12648
|
closeTrigger: "}",
|
|
12252
12649
|
parse: (_parser, body) => {
|
|
12253
12650
|
if (isEmptySequence(body)) return "EmptySet";
|
|
12651
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
12652
|
+
body = operand(body, 1);
|
|
12653
|
+
}
|
|
12254
12654
|
const h = operator(body);
|
|
12255
|
-
if (h === "Divides"
|
|
12655
|
+
if (h === "Divides") {
|
|
12256
12656
|
const expr2 = operand(body, 1);
|
|
12257
12657
|
const condition = operand(body, 2);
|
|
12258
12658
|
if (expr2 !== null && condition !== null)
|
|
12259
12659
|
return ["Set", expr2, ["Condition", condition]];
|
|
12260
12660
|
}
|
|
12261
|
-
if (
|
|
12262
|
-
|
|
12661
|
+
if (h === "Colon") {
|
|
12662
|
+
const lhs = operand(body, 1);
|
|
12663
|
+
const rhs = operand(body, 2);
|
|
12664
|
+
if (lhs !== null && rhs !== null) {
|
|
12665
|
+
const lhsOp = operator(lhs);
|
|
12666
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
12667
|
+
return ["Which", lhs, rhs];
|
|
12668
|
+
}
|
|
12669
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
12670
|
+
}
|
|
12263
12671
|
}
|
|
12264
|
-
if (
|
|
12265
|
-
|
|
12672
|
+
if (h === "Sequence") {
|
|
12673
|
+
const elements = operands(body);
|
|
12674
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
12675
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
12676
|
+
const lhs = operand(el, 1);
|
|
12677
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
12678
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
12679
|
+
});
|
|
12680
|
+
if (allPiecewise) {
|
|
12681
|
+
const whichOps = [];
|
|
12682
|
+
for (let i = 0; i < elements.length; i++) {
|
|
12683
|
+
const el = elements[i];
|
|
12684
|
+
if (operator(el) === "Colon") {
|
|
12685
|
+
const cond = operand(el, 1);
|
|
12686
|
+
const val = operand(el, 2);
|
|
12687
|
+
if (cond === null || val === null) {
|
|
12688
|
+
return ["Set", ...elements];
|
|
12689
|
+
}
|
|
12690
|
+
whichOps.push(cond, val);
|
|
12691
|
+
} else {
|
|
12692
|
+
if (i !== elements.length - 1) {
|
|
12693
|
+
return ["Set", ...elements];
|
|
12694
|
+
}
|
|
12695
|
+
whichOps.push("True", el);
|
|
12696
|
+
}
|
|
12697
|
+
}
|
|
12698
|
+
return ["Which", ...whichOps];
|
|
12699
|
+
}
|
|
12700
|
+
return ["Set", ...elements];
|
|
12701
|
+
}
|
|
12702
|
+
return ["Set", body];
|
|
12266
12703
|
},
|
|
12267
12704
|
serialize: (serializer, expr2) => {
|
|
12268
12705
|
if (nops(expr2) === 2 && operator(operand(expr2, 2)) === "Condition") {
|
|
@@ -14266,7 +14703,8 @@ var ComputeEngineCore = (() => {
|
|
|
14266
14703
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
14267
14704
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
14268
14705
|
});
|
|
14269
|
-
const
|
|
14706
|
+
const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
|
|
14707
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
14270
14708
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
14271
14709
|
};
|
|
14272
14710
|
}
|
|
@@ -16482,10 +16920,17 @@ var ComputeEngineCore = (() => {
|
|
|
16482
16920
|
// The capitalized library entries already exist; these are pure parse
|
|
16483
16921
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16484
16922
|
// ---------------------------------------------------------------------------
|
|
16923
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
16485
16924
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16486
16925
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16487
16926
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16488
16927
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16928
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
16929
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
16930
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
16931
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
16932
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
16933
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
16489
16934
|
// ---------------------------------------------------------------------------
|
|
16490
16935
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16491
16936
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -19529,6 +19974,19 @@ var ComputeEngineCore = (() => {
|
|
|
19529
19974
|
} while (postfix !== null);
|
|
19530
19975
|
}
|
|
19531
19976
|
if (result !== null) result = this.parseSupsub(result);
|
|
19977
|
+
if (result !== null) {
|
|
19978
|
+
let postfix = null;
|
|
19979
|
+
let index = this.index;
|
|
19980
|
+
do {
|
|
19981
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
19982
|
+
result = postfix ?? result;
|
|
19983
|
+
if (this.index === index && postfix !== null) {
|
|
19984
|
+
console.assert(this.index !== index, "No token consumed");
|
|
19985
|
+
break;
|
|
19986
|
+
}
|
|
19987
|
+
index = this.index;
|
|
19988
|
+
} while (postfix !== null);
|
|
19989
|
+
}
|
|
19532
19990
|
if (result === null) {
|
|
19533
19991
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19534
19992
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -20037,6 +20495,28 @@ var ComputeEngineCore = (() => {
|
|
|
20037
20495
|
}
|
|
20038
20496
|
|
|
20039
20497
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20498
|
+
var DOT_NOTATION_MAP = {
|
|
20499
|
+
First: ".x",
|
|
20500
|
+
Second: ".y",
|
|
20501
|
+
Third: ".z",
|
|
20502
|
+
Real: ".\\operatorname{real}",
|
|
20503
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20504
|
+
Length: ".\\operatorname{count}",
|
|
20505
|
+
Sum: ".\\operatorname{total}",
|
|
20506
|
+
Max: ".\\max",
|
|
20507
|
+
Min: ".\\min"
|
|
20508
|
+
};
|
|
20509
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20510
|
+
if (!serializer.options.dotNotation) return null;
|
|
20511
|
+
const ops = operands(expr2);
|
|
20512
|
+
if (!ops || ops.length !== 1) return null;
|
|
20513
|
+
const head = operator(expr2);
|
|
20514
|
+
if (!head) return null;
|
|
20515
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20516
|
+
if (suffix === void 0) return null;
|
|
20517
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20518
|
+
return `${lhs}${suffix}`;
|
|
20519
|
+
}
|
|
20040
20520
|
var ACCENT_MODIFIERS = {
|
|
20041
20521
|
deg: (s) => `${s}\\degree`,
|
|
20042
20522
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -20080,6 +20560,7 @@ var ComputeEngineCore = (() => {
|
|
|
20080
20560
|
constructor(dictionary, options) {
|
|
20081
20561
|
this.dictionary = dictionary;
|
|
20082
20562
|
this.options = {
|
|
20563
|
+
dotNotation: false,
|
|
20083
20564
|
dmsFormat: false,
|
|
20084
20565
|
angleNormalization: "none",
|
|
20085
20566
|
...options
|
|
@@ -20178,6 +20659,8 @@ var ComputeEngineCore = (() => {
|
|
|
20178
20659
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
20179
20660
|
}
|
|
20180
20661
|
serializeFunction(expr2, def) {
|
|
20662
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20663
|
+
if (dotResult !== null) return dotResult;
|
|
20181
20664
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
20182
20665
|
const h = operator(expr2);
|
|
20183
20666
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20420,6 +20903,8 @@ var ComputeEngineCore = (() => {
|
|
|
20420
20903
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20421
20904
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20422
20905
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20906
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20907
|
+
tolerance: 1e-7,
|
|
20423
20908
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20424
20909
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20425
20910
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20452,6 +20937,7 @@ var ComputeEngineCore = (() => {
|
|
|
20452
20937
|
invisiblePlus: "",
|
|
20453
20938
|
multiply: "\\times",
|
|
20454
20939
|
missingSymbol: "\\blacksquare",
|
|
20940
|
+
dotNotation: false,
|
|
20455
20941
|
dmsFormat: false,
|
|
20456
20942
|
angleNormalization: "none",
|
|
20457
20943
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -22286,6 +22772,15 @@ var ComputeEngineCore = (() => {
|
|
|
22286
22772
|
}
|
|
22287
22773
|
} else {
|
|
22288
22774
|
for (const item of t) {
|
|
22775
|
+
const op = item.operator;
|
|
22776
|
+
if (op === "Tuple" || op === "Pair" || op === "Single" || op === "Triple" || op === "Quadruple" || op === "KeyValuePair" || op === "Dictionary" || op === "Set" || op === "Record") {
|
|
22777
|
+
valid = false;
|
|
22778
|
+
return;
|
|
22779
|
+
}
|
|
22780
|
+
if (item.type.type === "string") {
|
|
22781
|
+
valid = false;
|
|
22782
|
+
return;
|
|
22783
|
+
}
|
|
22289
22784
|
dtype = getSupertype(dtype, getExpressionDatatype(item));
|
|
22290
22785
|
}
|
|
22291
22786
|
}
|
|
@@ -27321,6 +27816,15 @@ ${lines.join("\n")}`;
|
|
|
27321
27816
|
return void 0;
|
|
27322
27817
|
}
|
|
27323
27818
|
|
|
27819
|
+
// src/compute-engine/numerics/random.ts
|
|
27820
|
+
function deterministicRandom(seed) {
|
|
27821
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
27822
|
+
return v - Math.floor(v);
|
|
27823
|
+
}
|
|
27824
|
+
function nextSeed(seed) {
|
|
27825
|
+
return seed + 0.6180339887498949;
|
|
27826
|
+
}
|
|
27827
|
+
|
|
27324
27828
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
27325
27829
|
function canonical(ce, xs, scope) {
|
|
27326
27830
|
if (xs.every((x) => x.isCanonical)) return xs;
|
|
@@ -27370,6 +27874,19 @@ ${lines.join("\n")}`;
|
|
|
27370
27874
|
indexWhere: void 0
|
|
27371
27875
|
}
|
|
27372
27876
|
},
|
|
27877
|
+
Length: {
|
|
27878
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
27879
|
+
complexity: 4e3,
|
|
27880
|
+
signature: "(any) -> integer",
|
|
27881
|
+
type: () => "integer",
|
|
27882
|
+
evaluate: ([xs], { engine }) => {
|
|
27883
|
+
if (!xs.isCollection) return void 0;
|
|
27884
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
27885
|
+
const n = xs.count;
|
|
27886
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
27887
|
+
return engine.number(n);
|
|
27888
|
+
}
|
|
27889
|
+
},
|
|
27373
27890
|
Tuple: {
|
|
27374
27891
|
description: "A fixed number of heterogeneous elements",
|
|
27375
27892
|
complexity: 8200,
|
|
@@ -27422,7 +27939,11 @@ ${lines.join("\n")}`;
|
|
|
27422
27939
|
//
|
|
27423
27940
|
Range: {
|
|
27424
27941
|
complexity: 8200,
|
|
27425
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27942
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27943
|
+
type: (ops) => {
|
|
27944
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27945
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27946
|
+
},
|
|
27426
27947
|
canonical: (ops, { engine: ce }) => {
|
|
27427
27948
|
if (ops.length === 0) return null;
|
|
27428
27949
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27446,19 +27967,26 @@ ${lines.join("\n")}`;
|
|
|
27446
27967
|
const [lower, upper, step] = range(expr2);
|
|
27447
27968
|
if (step === 0) return 0;
|
|
27448
27969
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27449
|
-
return
|
|
27970
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27450
27971
|
},
|
|
27451
27972
|
contains: (expr2, target) => {
|
|
27452
|
-
if (!target.type.matches("integer")) return false;
|
|
27453
27973
|
const t = target.re;
|
|
27974
|
+
if (!isFinite(t)) return false;
|
|
27454
27975
|
const [lower, upper, step] = range(expr2);
|
|
27455
27976
|
if (step === 0) return false;
|
|
27456
|
-
if (step > 0)
|
|
27457
|
-
|
|
27977
|
+
if (step > 0) {
|
|
27978
|
+
if (t < lower || t > upper) return false;
|
|
27979
|
+
} else {
|
|
27980
|
+
if (t > lower || t < upper) return false;
|
|
27981
|
+
}
|
|
27982
|
+
const k = (t - lower) / step;
|
|
27983
|
+
const tol = expr2.engine.tolerance;
|
|
27984
|
+
const kRounded = Math.round(k);
|
|
27985
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27458
27986
|
},
|
|
27459
27987
|
iterator: (expr2) => {
|
|
27460
27988
|
const [lower, upper, step] = range(expr2);
|
|
27461
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
27989
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27462
27990
|
let index = 1;
|
|
27463
27991
|
return {
|
|
27464
27992
|
next: () => {
|
|
@@ -27476,7 +28004,9 @@ ${lines.join("\n")}`;
|
|
|
27476
28004
|
at: (expr2, index) => {
|
|
27477
28005
|
if (typeof index !== "number") return void 0;
|
|
27478
28006
|
const [lower, upper, step] = range(expr2);
|
|
27479
|
-
if (
|
|
28007
|
+
if (step === 0) return void 0;
|
|
28008
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
28009
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27480
28010
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27481
28011
|
},
|
|
27482
28012
|
indexWhere: void 0,
|
|
@@ -27501,7 +28031,13 @@ ${lines.join("\n")}`;
|
|
|
27501
28031
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27502
28032
|
return lower >= upper ? "positive" : "negative";
|
|
27503
28033
|
},
|
|
27504
|
-
elttype: (
|
|
28034
|
+
elttype: (expr2) => {
|
|
28035
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
28036
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
28037
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
28038
|
+
}
|
|
28039
|
+
return "finite_integer";
|
|
28040
|
+
}
|
|
27505
28041
|
}
|
|
27506
28042
|
},
|
|
27507
28043
|
Interval: {
|
|
@@ -27604,10 +28140,12 @@ ${lines.join("\n")}`;
|
|
|
27604
28140
|
const upper = expr2.op2.re;
|
|
27605
28141
|
let count = expr2.op3.re;
|
|
27606
28142
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28143
|
+
count = Math.floor(count);
|
|
27607
28144
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
27608
28145
|
if (index < 1 || index > count) return void 0;
|
|
28146
|
+
if (count === 1) return expr2.engine.number(lower);
|
|
27609
28147
|
return expr2.engine.number(
|
|
27610
|
-
lower + (upper - lower) * (index - 1) / count
|
|
28148
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
27611
28149
|
);
|
|
27612
28150
|
},
|
|
27613
28151
|
iterator: (expr2) => {
|
|
@@ -27626,6 +28164,8 @@ ${lines.join("\n")}`;
|
|
|
27626
28164
|
!isFinite(expr2.op3.re) ? DEFAULT_LINSPACE_COUNT : expr2.op3.re
|
|
27627
28165
|
);
|
|
27628
28166
|
}
|
|
28167
|
+
totalCount = Math.floor(totalCount);
|
|
28168
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
27629
28169
|
let index = 1;
|
|
27630
28170
|
return {
|
|
27631
28171
|
next: () => {
|
|
@@ -27634,7 +28174,7 @@ ${lines.join("\n")}`;
|
|
|
27634
28174
|
index += 1;
|
|
27635
28175
|
return {
|
|
27636
28176
|
value: expr2.engine.number(
|
|
27637
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
28177
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
27638
28178
|
),
|
|
27639
28179
|
done: false
|
|
27640
28180
|
};
|
|
@@ -27650,9 +28190,14 @@ ${lines.join("\n")}`;
|
|
|
27650
28190
|
if (t < lower || t > upper) return false;
|
|
27651
28191
|
let count = expr2.op3.re;
|
|
27652
28192
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28193
|
+
count = Math.floor(count);
|
|
27653
28194
|
if (count === 0) return false;
|
|
27654
|
-
|
|
27655
|
-
|
|
28195
|
+
if (count === 1) return t === lower;
|
|
28196
|
+
const step = (upper - lower) / (count - 1);
|
|
28197
|
+
const k = (t - lower) / step;
|
|
28198
|
+
const tol = expr2.engine.tolerance;
|
|
28199
|
+
const kRounded = Math.round(k);
|
|
28200
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
27656
28201
|
}
|
|
27657
28202
|
}
|
|
27658
28203
|
},
|
|
@@ -27977,10 +28522,12 @@ ${lines.join("\n")}`;
|
|
|
27977
28522
|
description: [
|
|
27978
28523
|
"Access an element of an indexed collection.",
|
|
27979
28524
|
"If the index is negative, it is counted from the end.",
|
|
27980
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
28525
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
28526
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
28527
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
27981
28528
|
],
|
|
27982
28529
|
complexity: 8200,
|
|
27983
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
28530
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
27984
28531
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
27985
28532
|
evaluate: (ops, { engine: ce }) => {
|
|
27986
28533
|
let expr2 = ops[0];
|
|
@@ -27991,12 +28538,39 @@ ${lines.join("\n")}`;
|
|
|
27991
28538
|
if (!at) return void 0;
|
|
27992
28539
|
const opAtIndex = ops[index];
|
|
27993
28540
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
27994
|
-
if (s !== void 0)
|
|
27995
|
-
|
|
27996
|
-
|
|
27997
|
-
|
|
27998
|
-
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
28541
|
+
if (s !== void 0) {
|
|
28542
|
+
expr2 = at(expr2, s) ?? ce.Nothing;
|
|
28543
|
+
index += 1;
|
|
28544
|
+
continue;
|
|
27999
28545
|
}
|
|
28546
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
28547
|
+
const indices = Array.from(opAtIndex.each());
|
|
28548
|
+
const isMask = indices.every((m) => {
|
|
28549
|
+
const name = sym(m);
|
|
28550
|
+
return name === "True" || name === "False";
|
|
28551
|
+
});
|
|
28552
|
+
const picked = [];
|
|
28553
|
+
if (isMask) {
|
|
28554
|
+
indices.forEach((m, i2) => {
|
|
28555
|
+
if (sym(m) !== "True") return;
|
|
28556
|
+
const v = at(expr2, i2 + 1);
|
|
28557
|
+
if (v !== void 0) picked.push(v);
|
|
28558
|
+
});
|
|
28559
|
+
} else {
|
|
28560
|
+
for (const m of indices) {
|
|
28561
|
+
const k = m.re;
|
|
28562
|
+
if (!Number.isInteger(k)) return void 0;
|
|
28563
|
+
const v = at(expr2, k);
|
|
28564
|
+
if (v !== void 0) picked.push(v);
|
|
28565
|
+
}
|
|
28566
|
+
}
|
|
28567
|
+
expr2 = ce._fn("List", picked);
|
|
28568
|
+
index += 1;
|
|
28569
|
+
continue;
|
|
28570
|
+
}
|
|
28571
|
+
const i = opAtIndex.re;
|
|
28572
|
+
if (!Number.isInteger(i)) return void 0;
|
|
28573
|
+
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
28000
28574
|
index += 1;
|
|
28001
28575
|
}
|
|
28002
28576
|
return expr2;
|
|
@@ -28007,7 +28581,7 @@ ${lines.join("\n")}`;
|
|
|
28007
28581
|
description: ["Return `n` elements from a collection."],
|
|
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
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
28012
28586
|
if (!eager) return void 0;
|
|
28013
28587
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -28054,7 +28628,7 @@ ${lines.join("\n")}`;
|
|
|
28054
28628
|
description: ["Return the collection without the first n elements."],
|
|
28055
28629
|
complexity: 8200,
|
|
28056
28630
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
28057
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
28631
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28058
28632
|
collection: {
|
|
28059
28633
|
isLazy: (_expr) => true,
|
|
28060
28634
|
count: (expr2) => {
|
|
@@ -28099,15 +28673,45 @@ ${lines.join("\n")}`;
|
|
|
28099
28673
|
},
|
|
28100
28674
|
First: {
|
|
28101
28675
|
complexity: 8200,
|
|
28102
|
-
signature: "(
|
|
28676
|
+
signature: "(any) -> any",
|
|
28103
28677
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28104
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28678
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28679
|
+
if (!xs.isCollection)
|
|
28680
|
+
return ce.error([
|
|
28681
|
+
"incompatible-type",
|
|
28682
|
+
`'collection'`,
|
|
28683
|
+
xs.type.toString()
|
|
28684
|
+
]);
|
|
28685
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28686
|
+
}
|
|
28105
28687
|
},
|
|
28106
28688
|
Second: {
|
|
28107
28689
|
complexity: 8200,
|
|
28108
|
-
signature: "(
|
|
28690
|
+
signature: "(any) -> any",
|
|
28109
28691
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28110
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28692
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28693
|
+
if (!xs.isCollection)
|
|
28694
|
+
return ce.error([
|
|
28695
|
+
"incompatible-type",
|
|
28696
|
+
`'collection'`,
|
|
28697
|
+
xs.type.toString()
|
|
28698
|
+
]);
|
|
28699
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28700
|
+
}
|
|
28701
|
+
},
|
|
28702
|
+
Third: {
|
|
28703
|
+
complexity: 8200,
|
|
28704
|
+
signature: "(any) -> any",
|
|
28705
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28706
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28707
|
+
if (!xs.isCollection)
|
|
28708
|
+
return ce.error([
|
|
28709
|
+
"incompatible-type",
|
|
28710
|
+
`'collection'`,
|
|
28711
|
+
xs.type.toString()
|
|
28712
|
+
]);
|
|
28713
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28714
|
+
}
|
|
28111
28715
|
},
|
|
28112
28716
|
Last: {
|
|
28113
28717
|
complexity: 8200,
|
|
@@ -28220,7 +28824,9 @@ ${lines.join("\n")}`;
|
|
|
28220
28824
|
],
|
|
28221
28825
|
complexity: 8200,
|
|
28222
28826
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
28223
|
-
type: ([xs]) => parseType(
|
|
28827
|
+
type: ([xs]) => parseType(
|
|
28828
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
28829
|
+
),
|
|
28224
28830
|
collection: {
|
|
28225
28831
|
isLazy: (_expr) => true,
|
|
28226
28832
|
count: (expr2) => {
|
|
@@ -28552,16 +29158,26 @@ ${lines.join("\n")}`;
|
|
|
28552
29158
|
},
|
|
28553
29159
|
// Randomize the order of the elements in the collection.
|
|
28554
29160
|
Shuffle: {
|
|
28555
|
-
description: "Randomize the order of the elements in the collection.",
|
|
29161
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
28556
29162
|
complexity: 8200,
|
|
28557
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
29163
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
28558
29164
|
type: (ops) => ops[0].type,
|
|
28559
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
29165
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
28560
29166
|
if (!xs.isFiniteCollection) return void 0;
|
|
28561
29167
|
const data = Array.from(xs.each());
|
|
28562
|
-
|
|
28563
|
-
|
|
28564
|
-
|
|
29168
|
+
const seed = seedOp?.re;
|
|
29169
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
29170
|
+
let s = seed;
|
|
29171
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29172
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
29173
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29174
|
+
s = nextSeed(s);
|
|
29175
|
+
}
|
|
29176
|
+
} else {
|
|
29177
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29178
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
29179
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29180
|
+
}
|
|
28565
29181
|
}
|
|
28566
29182
|
return ce.function(xs.operator, data);
|
|
28567
29183
|
}
|
|
@@ -28628,7 +29244,9 @@ ${lines.join("\n")}`;
|
|
|
28628
29244
|
if (t === "string")
|
|
28629
29245
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
28630
29246
|
return parseType(
|
|
28631
|
-
`tuple<list<${
|
|
29247
|
+
`tuple<list<${typeToString(
|
|
29248
|
+
collectionElementType(t) ?? "any"
|
|
29249
|
+
)}>, list<integer>>`
|
|
28632
29250
|
);
|
|
28633
29251
|
},
|
|
28634
29252
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -28644,7 +29262,7 @@ ${lines.join("\n")}`;
|
|
|
28644
29262
|
description: "Return a list of the unique elements of the collection.",
|
|
28645
29263
|
complexity: 8200,
|
|
28646
29264
|
signature: "(collection) -> list",
|
|
28647
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29265
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28648
29266
|
evaluate: (ops, { engine: ce }) => {
|
|
28649
29267
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
28650
29268
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -28656,7 +29274,7 @@ ${lines.join("\n")}`;
|
|
|
28656
29274
|
wikidata: "Q381060",
|
|
28657
29275
|
complexity: 8200,
|
|
28658
29276
|
signature: "(collection, integer | function) -> list",
|
|
28659
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29277
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28660
29278
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
28661
29279
|
if (!xs.isFiniteCollection) return void 0;
|
|
28662
29280
|
const k = toInteger(arg);
|
|
@@ -28830,32 +29448,74 @@ ${lines.join("\n")}`;
|
|
|
28830
29448
|
}
|
|
28831
29449
|
}
|
|
28832
29450
|
},
|
|
28833
|
-
// Repeat(x) -> [x, x, ...]
|
|
28834
|
-
//
|
|
28835
|
-
// x is evaluated once. Although could use Hold()?
|
|
28836
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
29451
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
29452
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
28837
29453
|
Repeat: {
|
|
28838
|
-
description: "Produce
|
|
29454
|
+
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.",
|
|
28839
29455
|
complexity: 8200,
|
|
28840
|
-
signature: "(value: any) -> list",
|
|
29456
|
+
signature: "(value: any, count: integer?) -> list",
|
|
29457
|
+
evaluate: (ops, { engine }) => {
|
|
29458
|
+
if (ops.length !== 2) return void 0;
|
|
29459
|
+
const raw = toInteger(ops[1]);
|
|
29460
|
+
if (raw === null) return void 0;
|
|
29461
|
+
const n = Math.max(0, raw);
|
|
29462
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
29463
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
29464
|
+
},
|
|
28841
29465
|
collection: {
|
|
28842
|
-
isLazy: (
|
|
28843
|
-
count: () =>
|
|
28844
|
-
|
|
28845
|
-
|
|
28846
|
-
|
|
28847
|
-
|
|
29466
|
+
isLazy: (expr2) => isFunction2(expr2) && expr2.ops?.length === 1,
|
|
29467
|
+
count: (expr2) => {
|
|
29468
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29469
|
+
if (expr2.ops?.length === 2) {
|
|
29470
|
+
const n = toInteger(expr2.op2);
|
|
29471
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
29472
|
+
}
|
|
29473
|
+
return Infinity;
|
|
29474
|
+
},
|
|
29475
|
+
isEmpty: (expr2) => {
|
|
29476
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29477
|
+
if (expr2.ops?.length === 2) {
|
|
29478
|
+
const n = toInteger(expr2.op2);
|
|
29479
|
+
return n !== null ? n <= 0 : void 0;
|
|
29480
|
+
}
|
|
29481
|
+
return false;
|
|
29482
|
+
},
|
|
29483
|
+
isFinite: (expr2) => isFunction2(expr2) && expr2.ops?.length === 2,
|
|
28848
29484
|
contains: (expr2, target) => {
|
|
28849
29485
|
if (!isFunction2(expr2)) return false;
|
|
29486
|
+
if (expr2.ops?.length === 2) {
|
|
29487
|
+
const n = toInteger(expr2.op2);
|
|
29488
|
+
if (n !== null && n <= 0) return false;
|
|
29489
|
+
}
|
|
28850
29490
|
return expr2.op1.isSame(target);
|
|
28851
29491
|
},
|
|
28852
29492
|
iterator: (expr2) => {
|
|
28853
29493
|
if (!isFunction2(expr2))
|
|
28854
29494
|
return { next: () => ({ value: void 0, done: true }) };
|
|
29495
|
+
if (expr2.ops?.length === 2) {
|
|
29496
|
+
const n = toInteger(expr2.op2);
|
|
29497
|
+
if (n === null) {
|
|
29498
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
29499
|
+
}
|
|
29500
|
+
const count = Math.max(0, n);
|
|
29501
|
+
let i = 0;
|
|
29502
|
+
return {
|
|
29503
|
+
next: () => i++ < count ? { value: expr2.op1, done: false } : { value: void 0, done: true }
|
|
29504
|
+
};
|
|
29505
|
+
}
|
|
28855
29506
|
return { next: () => ({ value: expr2.op1, done: false }) };
|
|
28856
29507
|
},
|
|
28857
|
-
at
|
|
29508
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
29509
|
+
at: (expr2, index) => {
|
|
28858
29510
|
if (!isFunction2(expr2)) return void 0;
|
|
29511
|
+
if (typeof index !== "number") return void 0;
|
|
29512
|
+
if (expr2.ops?.length === 2) {
|
|
29513
|
+
const n = toInteger(expr2.op2);
|
|
29514
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
29515
|
+
if (index < 1 || index > count) return void 0;
|
|
29516
|
+
} else {
|
|
29517
|
+
if (index < 1) return void 0;
|
|
29518
|
+
}
|
|
28859
29519
|
return expr2.op1;
|
|
28860
29520
|
}
|
|
28861
29521
|
}
|
|
@@ -29086,17 +29746,14 @@ ${lines.join("\n")}`;
|
|
|
29086
29746
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
29087
29747
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
29088
29748
|
let op1 = expr2.op1.re;
|
|
29089
|
-
if (!isFinite(op1)) op1 = 1;
|
|
29090
|
-
else op1 = Math.round(op1);
|
|
29749
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
29091
29750
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
29092
29751
|
let op2 = expr2.op2.re;
|
|
29093
29752
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
29094
|
-
|
|
29095
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29753
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
29096
29754
|
let op3 = expr2.op3.re;
|
|
29097
|
-
if (!isFinite(op3)) op3 = 1;
|
|
29098
|
-
|
|
29099
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29755
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29756
|
+
return [op1, op2, op3];
|
|
29100
29757
|
}
|
|
29101
29758
|
function rangeLast(r) {
|
|
29102
29759
|
const [lower, upper, step] = r;
|
|
@@ -31144,11 +31801,12 @@ ${lines.join("\n")}`;
|
|
|
31144
31801
|
);
|
|
31145
31802
|
}
|
|
31146
31803
|
},
|
|
31147
|
-
|
|
31148
|
-
|
|
31149
|
-
|
|
31150
|
-
|
|
31151
|
-
|
|
31804
|
+
Complex: {
|
|
31805
|
+
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.',
|
|
31806
|
+
wikidata: "Q11567",
|
|
31807
|
+
complexity: 500,
|
|
31808
|
+
signature: "(real: number, imaginary: number) -> complex"
|
|
31809
|
+
},
|
|
31152
31810
|
Divide: {
|
|
31153
31811
|
description: "Quotient of a numerator and one or more denominators.",
|
|
31154
31812
|
wikidata: "Q1226939",
|
|
@@ -32498,48 +33156,83 @@ ${lines.join("\n")}`;
|
|
|
32498
33156
|
}
|
|
32499
33157
|
},
|
|
32500
33158
|
Sum: {
|
|
32501
|
-
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`",
|
|
33159
|
+
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`; `Sum(L)` sums the elements of a collection `L`",
|
|
32502
33160
|
wikidata: "Q218005",
|
|
32503
33161
|
complexity: 1e3,
|
|
32504
33162
|
broadcastable: false,
|
|
32505
33163
|
scoped: true,
|
|
32506
33164
|
lazy: true,
|
|
32507
|
-
signature: "(
|
|
32508
|
-
canonical: ([body, ...bounds], { scope }) =>
|
|
32509
|
-
|
|
33165
|
+
signature: "(any, tuple*) -> number",
|
|
33166
|
+
canonical: ([body, ...bounds], { scope, engine: ce }) => {
|
|
33167
|
+
if (bounds.length === 0) {
|
|
33168
|
+
const canon = body?.canonical;
|
|
33169
|
+
if (canon?.isCollection) return ce._fn("Sum", [canon]);
|
|
33170
|
+
}
|
|
33171
|
+
return canonicalBigop("Sum", body, bounds, scope);
|
|
33172
|
+
},
|
|
33173
|
+
evaluate: ([first, ...rest], { engine, numericApproximation: numericApproximation2 }) => {
|
|
33174
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33175
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33176
|
+
const result2 = run(
|
|
33177
|
+
reduceCollection2(
|
|
33178
|
+
first,
|
|
33179
|
+
engine.Zero,
|
|
33180
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33181
|
+
),
|
|
33182
|
+
engine._timeRemaining
|
|
33183
|
+
);
|
|
33184
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33185
|
+
}
|
|
32510
33186
|
const result = run(
|
|
32511
33187
|
reduceBigOp(
|
|
32512
|
-
|
|
32513
|
-
|
|
33188
|
+
first,
|
|
33189
|
+
rest,
|
|
32514
33190
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32515
33191
|
engine.Zero
|
|
32516
33192
|
),
|
|
32517
33193
|
engine._timeRemaining
|
|
32518
33194
|
);
|
|
32519
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32520
|
-
return void 0;
|
|
32521
|
-
}
|
|
33195
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32522
33196
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32523
33197
|
},
|
|
32524
|
-
evaluateAsync: async (
|
|
33198
|
+
evaluateAsync: async ([first, ...rest], { engine, signal, numericApproximation: numericApproximation2 }) => {
|
|
33199
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33200
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33201
|
+
const result2 = await runAsync(
|
|
33202
|
+
reduceCollection2(
|
|
33203
|
+
first,
|
|
33204
|
+
engine.Zero,
|
|
33205
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33206
|
+
),
|
|
33207
|
+
engine._timeRemaining,
|
|
33208
|
+
signal
|
|
33209
|
+
);
|
|
33210
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33211
|
+
}
|
|
32525
33212
|
const result = await runAsync(
|
|
32526
33213
|
reduceBigOp(
|
|
32527
|
-
|
|
32528
|
-
|
|
33214
|
+
first,
|
|
33215
|
+
rest,
|
|
32529
33216
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32530
33217
|
engine.Zero
|
|
32531
33218
|
),
|
|
32532
33219
|
engine._timeRemaining,
|
|
32533
33220
|
signal
|
|
32534
33221
|
);
|
|
32535
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32536
|
-
return void 0;
|
|
32537
|
-
}
|
|
33222
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32538
33223
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32539
33224
|
}
|
|
32540
33225
|
}
|
|
32541
33226
|
}
|
|
32542
33227
|
];
|
|
33228
|
+
function* reduceCollection2(collection, init, combine) {
|
|
33229
|
+
let acc = init;
|
|
33230
|
+
for (const x of collection.each()) {
|
|
33231
|
+
acc = combine(acc, x);
|
|
33232
|
+
yield acc;
|
|
33233
|
+
}
|
|
33234
|
+
return acc;
|
|
33235
|
+
}
|
|
32543
33236
|
function evaluateAbs(arg) {
|
|
32544
33237
|
const ce = arg.engine;
|
|
32545
33238
|
if (isNumber(arg)) {
|
|
@@ -42776,7 +43469,7 @@ ${e.message}
|
|
|
42776
43469
|
var CONTROL_STRUCTURES_LIBRARY = [
|
|
42777
43470
|
{
|
|
42778
43471
|
Block: {
|
|
42779
|
-
description: "Evaluate a sequence of expressions in a local scope.",
|
|
43472
|
+
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.",
|
|
42780
43473
|
lazy: true,
|
|
42781
43474
|
scoped: true,
|
|
42782
43475
|
signature: "(unknown*) -> unknown",
|
|
@@ -42826,12 +43519,42 @@ ${e.message}
|
|
|
42826
43519
|
}
|
|
42827
43520
|
},
|
|
42828
43521
|
Loop: {
|
|
42829
|
-
description: "Evaluate a body expression over
|
|
43522
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
42830
43523
|
lazy: true,
|
|
42831
|
-
signature: "(body:expression,
|
|
42832
|
-
type: ([body]) =>
|
|
42833
|
-
|
|
42834
|
-
|
|
43524
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43525
|
+
type: ([body]) => {
|
|
43526
|
+
if (!body) return "nothing";
|
|
43527
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43528
|
+
},
|
|
43529
|
+
canonical: canonicalLoop,
|
|
43530
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43531
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43532
|
+
},
|
|
43533
|
+
When: {
|
|
43534
|
+
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.',
|
|
43535
|
+
lazy: true,
|
|
43536
|
+
signature: "(expression, boolean) -> any",
|
|
43537
|
+
type: ([expr2]) => expr2.type,
|
|
43538
|
+
canonical: (args, { engine: ce }) => {
|
|
43539
|
+
if (args.length !== 2) return null;
|
|
43540
|
+
const [expr2, cond] = args;
|
|
43541
|
+
if (isFunction2(expr2, "When")) {
|
|
43542
|
+
const inner = expr2.op1.canonical;
|
|
43543
|
+
const innerCond = expr2.op2.canonical;
|
|
43544
|
+
return ce._fn("When", [
|
|
43545
|
+
inner,
|
|
43546
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43547
|
+
]);
|
|
43548
|
+
}
|
|
43549
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43550
|
+
},
|
|
43551
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43552
|
+
const c = cond.evaluate();
|
|
43553
|
+
const cs = sym(c);
|
|
43554
|
+
if (cs === "True") return expr2.evaluate();
|
|
43555
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43556
|
+
return ce._fn("When", [expr2, c]);
|
|
43557
|
+
}
|
|
42835
43558
|
},
|
|
42836
43559
|
Which: {
|
|
42837
43560
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42891,9 +43614,141 @@ ${e.message}
|
|
|
42891
43614
|
);
|
|
42892
43615
|
return result;
|
|
42893
43616
|
}
|
|
42894
|
-
function
|
|
43617
|
+
function canonicalLoop(ops, options) {
|
|
43618
|
+
const { engine: ce, scope } = options;
|
|
43619
|
+
if (ops.length === 0) return null;
|
|
43620
|
+
if (ops.length === 1) {
|
|
43621
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43622
|
+
}
|
|
43623
|
+
const body = ops[0];
|
|
43624
|
+
const iterators = ops.slice(1);
|
|
43625
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43626
|
+
if (!allElement) {
|
|
43627
|
+
return ce._fn(
|
|
43628
|
+
"Loop",
|
|
43629
|
+
ops.map((op) => op.canonical)
|
|
43630
|
+
);
|
|
43631
|
+
}
|
|
43632
|
+
const loopScope = scope ?? {
|
|
43633
|
+
parent: ce.context.lexicalScope,
|
|
43634
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43635
|
+
};
|
|
43636
|
+
loopScope.noAutoDeclare = true;
|
|
43637
|
+
ce.pushScope(loopScope);
|
|
43638
|
+
let canonicalIterators;
|
|
43639
|
+
let canonicalBody;
|
|
43640
|
+
try {
|
|
43641
|
+
canonicalIterators = iterators.map((it) => {
|
|
43642
|
+
if (!isFunction2(it, "Element")) {
|
|
43643
|
+
return ce._fn("Element", [
|
|
43644
|
+
ce.error("missing").canonical,
|
|
43645
|
+
ce.error("missing").canonical
|
|
43646
|
+
]);
|
|
43647
|
+
}
|
|
43648
|
+
const indexExpr = it.ops[0];
|
|
43649
|
+
const collExpr = it.ops[1];
|
|
43650
|
+
if (!indexExpr || !collExpr) {
|
|
43651
|
+
return ce._fn("Element", [
|
|
43652
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43653
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43654
|
+
]);
|
|
43655
|
+
}
|
|
43656
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43657
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43658
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43659
|
+
}
|
|
43660
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43661
|
+
});
|
|
43662
|
+
canonicalBody = body.canonical;
|
|
43663
|
+
} finally {
|
|
43664
|
+
ce.popScope();
|
|
43665
|
+
loopScope.noAutoDeclare = false;
|
|
43666
|
+
}
|
|
43667
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43668
|
+
scope: loopScope
|
|
43669
|
+
});
|
|
43670
|
+
}
|
|
43671
|
+
function* runLoop(body, elements, ce) {
|
|
42895
43672
|
body ??= ce.Nothing;
|
|
42896
43673
|
if (sym(body) === "Nothing") return body;
|
|
43674
|
+
if (elements.length === 0) {
|
|
43675
|
+
const result = body.evaluate();
|
|
43676
|
+
yield result;
|
|
43677
|
+
return result;
|
|
43678
|
+
}
|
|
43679
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43680
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43681
|
+
}
|
|
43682
|
+
const results = [];
|
|
43683
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43684
|
+
const freshScope = {
|
|
43685
|
+
parent: ce.context.lexicalScope,
|
|
43686
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43687
|
+
};
|
|
43688
|
+
ce._pushEvalContext(freshScope);
|
|
43689
|
+
try {
|
|
43690
|
+
for (const elem of elements) {
|
|
43691
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43692
|
+
const idx = elem.ops[0];
|
|
43693
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43694
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43695
|
+
ce.declare(idx.symbol, "unknown");
|
|
43696
|
+
}
|
|
43697
|
+
}
|
|
43698
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43699
|
+
} finally {
|
|
43700
|
+
ce._popEvalContext();
|
|
43701
|
+
}
|
|
43702
|
+
if (state.stopped && state.value !== void 0) {
|
|
43703
|
+
if (!state.broke) return state.value;
|
|
43704
|
+
return state.value;
|
|
43705
|
+
}
|
|
43706
|
+
return ce.function("List", results);
|
|
43707
|
+
}
|
|
43708
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43709
|
+
if (state.stopped) return;
|
|
43710
|
+
if (index === elements.length) {
|
|
43711
|
+
const result = body.evaluate();
|
|
43712
|
+
state.count += 1;
|
|
43713
|
+
if (state.count > ce.iterationLimit)
|
|
43714
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43715
|
+
if (isFunction2(result, "Break")) {
|
|
43716
|
+
state.stopped = true;
|
|
43717
|
+
state.broke = true;
|
|
43718
|
+
state.value = result.op1;
|
|
43719
|
+
return;
|
|
43720
|
+
}
|
|
43721
|
+
if (result.operator === "Return") {
|
|
43722
|
+
state.stopped = true;
|
|
43723
|
+
state.value = result;
|
|
43724
|
+
return;
|
|
43725
|
+
}
|
|
43726
|
+
results.push(result);
|
|
43727
|
+
yield result;
|
|
43728
|
+
return;
|
|
43729
|
+
}
|
|
43730
|
+
const elem = elements[index];
|
|
43731
|
+
if (!isFunction2(elem, "Element")) {
|
|
43732
|
+
return;
|
|
43733
|
+
}
|
|
43734
|
+
const indexExpr = elem.ops[0];
|
|
43735
|
+
const collExpr = elem.ops[1];
|
|
43736
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43737
|
+
return;
|
|
43738
|
+
}
|
|
43739
|
+
const name = indexExpr.symbol;
|
|
43740
|
+
const collection = collExpr.evaluate();
|
|
43741
|
+
if (!collection?.isCollection) {
|
|
43742
|
+
return;
|
|
43743
|
+
}
|
|
43744
|
+
const skipAssign = name === "Nothing";
|
|
43745
|
+
for (const value of collection.each()) {
|
|
43746
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43747
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43748
|
+
if (state.stopped) return;
|
|
43749
|
+
}
|
|
43750
|
+
}
|
|
43751
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42897
43752
|
if (collection?.isCollection) {
|
|
42898
43753
|
let result = void 0;
|
|
42899
43754
|
const fn = applicable(body);
|
|
@@ -44535,7 +45390,7 @@ ${e.message}
|
|
|
44535
45390
|
evaluate: (ops) => apply(ops[0], ops.slice(1))
|
|
44536
45391
|
},
|
|
44537
45392
|
Assign: {
|
|
44538
|
-
description: "Assign a value to a symbol or define a sequence",
|
|
45393
|
+
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).",
|
|
44539
45394
|
lazy: true,
|
|
44540
45395
|
pure: false,
|
|
44541
45396
|
signature: "(symbol | expression, any) -> any",
|
|
@@ -44666,7 +45521,12 @@ ${e.message}
|
|
|
44666
45521
|
evaluate: (ops, { engine: ce }) => {
|
|
44667
45522
|
const symbolName2 = sym(ops[0].evaluate());
|
|
44668
45523
|
if (!symbolName2) return void 0;
|
|
45524
|
+
const currentScope = ce.context.lexicalScope;
|
|
45525
|
+
const existing = currentScope.bindings.get(symbolName2);
|
|
45526
|
+
const existingValueDef = existing && isValueDef(existing) ? existing : void 0;
|
|
45527
|
+
const isAutoDeclareHere = !!existingValueDef && existingValueDef.value.inferredType && existingValueDef.value.value === void 0;
|
|
44669
45528
|
if (!ops[1]) {
|
|
45529
|
+
if (isAutoDeclareHere) return ce.Nothing;
|
|
44670
45530
|
ce.declare(symbolName2, { inferred: true, type: "unknown" });
|
|
44671
45531
|
return ce.Nothing;
|
|
44672
45532
|
}
|
|
@@ -44675,6 +45535,11 @@ ${e.message}
|
|
|
44675
45535
|
(isString(t) ? t.string : void 0) ?? sym(t) ?? void 0
|
|
44676
45536
|
);
|
|
44677
45537
|
if (!isValidType(type2)) return void 0;
|
|
45538
|
+
if (isAutoDeclareHere && existingValueDef) {
|
|
45539
|
+
existingValueDef.value.type = ce.type(type2);
|
|
45540
|
+
existingValueDef.value.inferredType = false;
|
|
45541
|
+
return ce.Nothing;
|
|
45542
|
+
}
|
|
44678
45543
|
ce.declare(symbolName2, type2);
|
|
44679
45544
|
return ce.Nothing;
|
|
44680
45545
|
}
|
|
@@ -44792,33 +45657,41 @@ ${e.message}
|
|
|
44792
45657
|
},
|
|
44793
45658
|
Random: {
|
|
44794
45659
|
description: [
|
|
44795
|
-
"Random():
|
|
44796
|
-
"Random(
|
|
44797
|
-
"Random(
|
|
45660
|
+
"Random(): non-deterministic float in [0, 1)",
|
|
45661
|
+
"Random(seed: real): deterministic float in [0, 1) from a real seed",
|
|
45662
|
+
"Random(n: integer): non-deterministic integer in [0, n)",
|
|
45663
|
+
"Random(m: integer, n: integer): non-deterministic integer in [m, n)"
|
|
44798
45664
|
],
|
|
44799
45665
|
pure: false,
|
|
44800
|
-
|
|
44801
|
-
|
|
44802
|
-
|
|
44803
|
-
|
|
45666
|
+
// Signature accepts: nothing, one number, or two integers.
|
|
45667
|
+
// Use `number` (not `integer`) for the single-arg case so float seeds
|
|
45668
|
+
// type-check; runtime dispatch differentiates integer vs real.
|
|
45669
|
+
signature: "(number?, integer?) -> finite_number",
|
|
45670
|
+
type: ([first, second]) => {
|
|
45671
|
+
if (first === void 0) return "finite_number";
|
|
45672
|
+
if (second !== void 0) return "finite_integer";
|
|
45673
|
+
if (first.type.matches("integer")) return "finite_integer";
|
|
45674
|
+
return "finite_number";
|
|
44804
45675
|
},
|
|
44805
45676
|
sgn: () => "non-negative",
|
|
44806
45677
|
evaluate: (ops, { engine: ce }) => {
|
|
44807
45678
|
if (ops.length === 0) return ce.number(Math.random());
|
|
44808
|
-
const [
|
|
44809
|
-
|
|
44810
|
-
|
|
44811
|
-
|
|
44812
|
-
lower = 0;
|
|
44813
|
-
upper = Math.floor(lowerOp.re - 1);
|
|
44814
|
-
if (isNaN(upper)) upper = 0;
|
|
44815
|
-
} else {
|
|
44816
|
-
lower = Math.floor(lowerOp.re);
|
|
44817
|
-
upper = Math.floor(upperOp.re);
|
|
45679
|
+
const [firstOp, secondOp] = ops;
|
|
45680
|
+
if (secondOp !== void 0) {
|
|
45681
|
+
let lower = Math.floor(firstOp.re);
|
|
45682
|
+
let upper = Math.floor(secondOp.re);
|
|
44818
45683
|
if (isNaN(lower)) lower = 0;
|
|
44819
45684
|
if (isNaN(upper)) upper = 0;
|
|
45685
|
+
return ce.number(lower + Math.floor(Math.random() * (upper - lower)));
|
|
45686
|
+
}
|
|
45687
|
+
if (firstOp.type.matches("integer")) {
|
|
45688
|
+
let n = Math.floor(firstOp.re);
|
|
45689
|
+
if (isNaN(n)) n = 0;
|
|
45690
|
+
return ce.number(Math.floor(Math.random() * n));
|
|
44820
45691
|
}
|
|
44821
|
-
|
|
45692
|
+
const seed = firstOp.re;
|
|
45693
|
+
if (isNaN(seed)) return ce.number(0);
|
|
45694
|
+
return ce.number(deterministicRandom(seed));
|
|
44822
45695
|
}
|
|
44823
45696
|
},
|
|
44824
45697
|
// @todo: need review
|
|
@@ -45274,6 +46147,14 @@ ${e.message}
|
|
|
45274
46147
|
To: {
|
|
45275
46148
|
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45276
46149
|
signature: "(any, any) -> nothing"
|
|
46150
|
+
},
|
|
46151
|
+
Colon: {
|
|
46152
|
+
description: "Type annotation (`a : b`) \u2014 opaque typed head.",
|
|
46153
|
+
signature: "(any, any) -> expression"
|
|
46154
|
+
},
|
|
46155
|
+
Prime: {
|
|
46156
|
+
description: "Derivative or prime notation (`f'`, `f^{(n)}`) \u2014 opaque typed head until a derivative library handler runs.",
|
|
46157
|
+
signature: "(any, integer?) -> expression"
|
|
45277
46158
|
}
|
|
45278
46159
|
}
|
|
45279
46160
|
];
|
|
@@ -50314,18 +51195,28 @@ ${e.message}
|
|
|
50314
51195
|
},
|
|
50315
51196
|
{
|
|
50316
51197
|
Sample: {
|
|
50317
|
-
description: "Return a random sample of k elements from the collection, without replacement.",
|
|
51198
|
+
description: "Return a random sample of k elements from the collection, without replacement. With an optional `seed` argument, the sample is deterministic.",
|
|
50318
51199
|
complexity: 8200,
|
|
50319
|
-
signature: "(collection, integer) -> list",
|
|
50320
|
-
evaluate: ([xs, nArg], { engine: ce }) => {
|
|
51200
|
+
signature: "(collection, integer, real?) -> list",
|
|
51201
|
+
evaluate: ([xs, nArg, seedArg], { engine: ce }) => {
|
|
50321
51202
|
if (!xs.isFiniteCollection) return void 0;
|
|
50322
51203
|
const k = toInteger(nArg);
|
|
50323
51204
|
if (k === null || k < 0) return void 0;
|
|
50324
51205
|
const data = Array.from(xs.each());
|
|
50325
51206
|
if (k > data.length) return void 0;
|
|
50326
|
-
|
|
50327
|
-
|
|
50328
|
-
|
|
51207
|
+
const seed = seedArg?.re;
|
|
51208
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
51209
|
+
let s = seed;
|
|
51210
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51211
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
51212
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51213
|
+
s = nextSeed(s);
|
|
51214
|
+
}
|
|
51215
|
+
} else {
|
|
51216
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51217
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
51218
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51219
|
+
}
|
|
50329
51220
|
}
|
|
50330
51221
|
const sample = data.slice(0, k);
|
|
50331
51222
|
return ce.function("List", sample);
|
|
@@ -53146,6 +54037,20 @@ Error in definition of "${name}"`,
|
|
|
53146
54037
|
if (results.length === 1) return results[0];
|
|
53147
54038
|
return this.engine._fn("List", results);
|
|
53148
54039
|
}
|
|
54040
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
54041
|
+
const items = zip(this._ops);
|
|
54042
|
+
if (items) {
|
|
54043
|
+
const results = [];
|
|
54044
|
+
while (true) {
|
|
54045
|
+
const { done, value } = items.next();
|
|
54046
|
+
if (done) break;
|
|
54047
|
+
results.push(
|
|
54048
|
+
this.engine._fn(this.operator, value).evaluate(options)
|
|
54049
|
+
);
|
|
54050
|
+
}
|
|
54051
|
+
return this.engine._fn("List", results);
|
|
54052
|
+
}
|
|
54053
|
+
}
|
|
53149
54054
|
if (materialization !== false && !def.evaluate && this.isLazyCollection)
|
|
53150
54055
|
return materialize(this, def, options);
|
|
53151
54056
|
const tail = holdMap(this, (x) => x.evaluate(options));
|
|
@@ -53192,6 +54097,22 @@ Error in definition of "${name}"`,
|
|
|
53192
54097
|
(resolved) => this.engine._fn("List", resolved)
|
|
53193
54098
|
);
|
|
53194
54099
|
}
|
|
54100
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
54101
|
+
const items = zip(this._ops);
|
|
54102
|
+
if (items) {
|
|
54103
|
+
const results = [];
|
|
54104
|
+
while (true) {
|
|
54105
|
+
const { done, value } = items.next();
|
|
54106
|
+
if (done) break;
|
|
54107
|
+
results.push(
|
|
54108
|
+
this.engine._fn(this.operator, value).evaluateAsync(options)
|
|
54109
|
+
);
|
|
54110
|
+
}
|
|
54111
|
+
return Promise.all(results).then(
|
|
54112
|
+
(resolved) => this.engine._fn("List", resolved)
|
|
54113
|
+
);
|
|
54114
|
+
}
|
|
54115
|
+
}
|
|
53195
54116
|
const tail = await holdMapAsync(
|
|
53196
54117
|
this,
|
|
53197
54118
|
async (x) => await x.evaluateAsync(options)
|
|
@@ -53406,8 +54327,47 @@ Error in definition of "${name}"`,
|
|
|
53406
54327
|
const ops = expr2.ops.map((x) => x.evaluate(options));
|
|
53407
54328
|
if (!value || value.type.isUnknown)
|
|
53408
54329
|
return expr2.engine.function(expr2.operator, ops);
|
|
54330
|
+
if (ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(value.type.type)) {
|
|
54331
|
+
const items = zip(ops);
|
|
54332
|
+
if (items) {
|
|
54333
|
+
const results = [];
|
|
54334
|
+
while (true) {
|
|
54335
|
+
const { done, value: zipped } = items.next();
|
|
54336
|
+
if (done) break;
|
|
54337
|
+
results.push(apply(value, zipped).evaluate(options));
|
|
54338
|
+
}
|
|
54339
|
+
return expr2.engine._fn("List", results);
|
|
54340
|
+
}
|
|
54341
|
+
}
|
|
53409
54342
|
return apply(value, ops);
|
|
53410
54343
|
}
|
|
54344
|
+
function paramsAreScalar(source) {
|
|
54345
|
+
const sigType = isOperatorDefinition(source) ? source.signature?.type : source;
|
|
54346
|
+
if (!sigType || typeof sigType === "string") return true;
|
|
54347
|
+
if (sigType.kind !== "signature") return true;
|
|
54348
|
+
const args = [
|
|
54349
|
+
...sigType.args ?? [],
|
|
54350
|
+
...sigType.optArgs ?? [],
|
|
54351
|
+
...sigType.variadicArg ? [sigType.variadicArg] : []
|
|
54352
|
+
];
|
|
54353
|
+
return args.every((arg) => isScalarType(arg.type));
|
|
54354
|
+
}
|
|
54355
|
+
function isOperatorDefinition(source) {
|
|
54356
|
+
return typeof source === "object" && source !== null && "signature" in source;
|
|
54357
|
+
}
|
|
54358
|
+
function isScalarType(t) {
|
|
54359
|
+
if (typeof t === "string") {
|
|
54360
|
+
if (t === "collection" || t === "indexed_collection" || t === "list" || t === "tuple" || t === "set" || t === "dictionary" || t === "record" || t === "function")
|
|
54361
|
+
return false;
|
|
54362
|
+
return true;
|
|
54363
|
+
}
|
|
54364
|
+
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")
|
|
54365
|
+
return false;
|
|
54366
|
+
if (t.kind === "union" || t.kind === "intersection")
|
|
54367
|
+
return t.types.every((x) => isScalarType(x));
|
|
54368
|
+
if (t.kind === "negation") return isScalarType(t.type);
|
|
54369
|
+
return true;
|
|
54370
|
+
}
|
|
53411
54371
|
function materialize(expr2, def, options) {
|
|
53412
54372
|
if (!expr2.isValid || options?.materialization === false) return expr2;
|
|
53413
54373
|
let materialization = options?.materialization ?? false;
|
|
@@ -53415,6 +54375,11 @@ Error in definition of "${name}"`,
|
|
|
53415
54375
|
materialization = DEFAULT_MATERIALIZATION;
|
|
53416
54376
|
const isIndexed = expr2.isIndexedCollection;
|
|
53417
54377
|
const isFinite2 = expr2.isFiniteCollection;
|
|
54378
|
+
if (isIndexed && isFinite2) {
|
|
54379
|
+
const count = expr2.count;
|
|
54380
|
+
if (count !== void 0 && count > expr2.engine.maxCollectionSize)
|
|
54381
|
+
return expr2;
|
|
54382
|
+
}
|
|
53418
54383
|
const xs = [];
|
|
53419
54384
|
if (!expr2.isEmptyCollection) {
|
|
53420
54385
|
if (!isIndexed || !isFinite2) {
|
|
@@ -53642,7 +54607,7 @@ Error in definition of "${name}"`,
|
|
|
53642
54607
|
const eltType = widen(
|
|
53643
54608
|
...Object.values(this._keyValues).map((op) => op.type.type)
|
|
53644
54609
|
);
|
|
53645
|
-
this._type =
|
|
54610
|
+
this._type = new BoxedType({ kind: "dictionary", values: eltType });
|
|
53646
54611
|
return this._type;
|
|
53647
54612
|
}
|
|
53648
54613
|
get isPure() {
|
|
@@ -53920,6 +54885,7 @@ Error in definition of "${name}"`,
|
|
|
53920
54885
|
}
|
|
53921
54886
|
if (typeof expr2 === "number" || expr2 instanceof BigDecimal || expr2 instanceof Complex)
|
|
53922
54887
|
return ce.number(expr2);
|
|
54888
|
+
if (typeof expr2 === "boolean") return ce.symbol(expr2 ? "True" : "False");
|
|
53923
54889
|
if (typeof expr2 === "string") {
|
|
53924
54890
|
if (matchesSymbol(expr2)) {
|
|
53925
54891
|
const sym2 = symbol(expr2);
|
|
@@ -54976,6 +55942,23 @@ Error in definition of "${name}"`,
|
|
|
54976
55942
|
};
|
|
54977
55943
|
return compilePair(0);
|
|
54978
55944
|
}
|
|
55945
|
+
if (h === "When") {
|
|
55946
|
+
if (args.length !== 2)
|
|
55947
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55948
|
+
const fn2 = target.functions?.(h);
|
|
55949
|
+
if (fn2) {
|
|
55950
|
+
if (typeof fn2 === "function") {
|
|
55951
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55952
|
+
}
|
|
55953
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55954
|
+
}
|
|
55955
|
+
if (isSymbol2(args[1], "True"))
|
|
55956
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55957
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55958
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55959
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55960
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55961
|
+
}
|
|
54979
55962
|
if (h === "Block") {
|
|
54980
55963
|
return _BaseCompiler.compileBlock(args, target);
|
|
54981
55964
|
}
|
|
@@ -55050,17 +56033,98 @@ Error in definition of "${name}"`,
|
|
|
55050
56033
|
)}${target.ws("\n")}})()`;
|
|
55051
56034
|
}
|
|
55052
56035
|
/**
|
|
55053
|
-
* Compile a Loop expression
|
|
55054
|
-
*
|
|
56036
|
+
* Compile a Loop expression.
|
|
56037
|
+
*
|
|
56038
|
+
* Two forms are supported:
|
|
56039
|
+
*
|
|
56040
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
56041
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
56042
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
56043
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
56044
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
56045
|
+
* references to the loop index inside the body are re-wrapped via
|
|
56046
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
55055
56047
|
*
|
|
55056
|
-
*
|
|
55057
|
-
*
|
|
55058
|
-
*
|
|
56048
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
56049
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
56050
|
+
* When two or more `Element` clauses are present — or when the single
|
|
56051
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
56052
|
+
* comprehension that collects results into an array. Each clause
|
|
56053
|
+
* produces a `for (const name of collection)` loop, nested
|
|
56054
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
56055
|
+
*
|
|
56056
|
+
* Example output (JS):
|
|
56057
|
+
* ```js
|
|
56058
|
+
* (() => { const result = [];
|
|
56059
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
56060
|
+
* return result; })()
|
|
56061
|
+
* ```
|
|
56062
|
+
*
|
|
56063
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
56064
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
56065
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
56066
|
+
* array or by unrolling when bounds are known at compile time.
|
|
56067
|
+
*
|
|
56068
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
56069
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
56070
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
56071
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
56072
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
56073
|
+
* current behavior.
|
|
55059
56074
|
*/
|
|
55060
56075
|
static compileForLoop(args, target) {
|
|
55061
56076
|
if (!args[0]) throw new Error("Loop: no body");
|
|
55062
56077
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
55063
|
-
const
|
|
56078
|
+
const body = args[0];
|
|
56079
|
+
const elements = args.slice(1);
|
|
56080
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
56081
|
+
if (useComprehension) {
|
|
56082
|
+
const lang = target.language ?? "";
|
|
56083
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
56084
|
+
throw new Error(
|
|
56085
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
56086
|
+
);
|
|
56087
|
+
}
|
|
56088
|
+
const narrowedElements = [];
|
|
56089
|
+
for (let i = 0; i < elements.length; i++) {
|
|
56090
|
+
const elem = elements[i];
|
|
56091
|
+
if (!isFunction2(elem, "Element"))
|
|
56092
|
+
throw new Error(
|
|
56093
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
56094
|
+
);
|
|
56095
|
+
if (!isSymbol2(elem.ops[0]))
|
|
56096
|
+
throw new Error(
|
|
56097
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
56098
|
+
);
|
|
56099
|
+
narrowedElements.push(elem);
|
|
56100
|
+
}
|
|
56101
|
+
const loopVarSet = new Set(
|
|
56102
|
+
narrowedElements.map(
|
|
56103
|
+
(e) => e.ops[0].symbol
|
|
56104
|
+
)
|
|
56105
|
+
);
|
|
56106
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
56107
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
56108
|
+
...target,
|
|
56109
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
56110
|
+
} : target;
|
|
56111
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
56112
|
+
let inner = `result.push(${bodyCode});`;
|
|
56113
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
56114
|
+
const elem = narrowedElements[i];
|
|
56115
|
+
const name = elem.ops[0].symbol;
|
|
56116
|
+
const collExpr = elem.ops[1];
|
|
56117
|
+
let collection;
|
|
56118
|
+
if (isFunction2(collExpr, "Range")) {
|
|
56119
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
56120
|
+
} else {
|
|
56121
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
56122
|
+
}
|
|
56123
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
56124
|
+
}
|
|
56125
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
56126
|
+
}
|
|
56127
|
+
const indexing = elements[0];
|
|
55064
56128
|
if (!isFunction2(indexing, "Element"))
|
|
55065
56129
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
55066
56130
|
const indexExpr = indexing.ops[0];
|
|
@@ -55078,13 +56142,72 @@ Error in definition of "${name}"`,
|
|
|
55078
56142
|
...target,
|
|
55079
56143
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
55080
56144
|
};
|
|
55081
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
56145
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
55082
56146
|
return `(() => {${target.ws(
|
|
55083
56147
|
"\n"
|
|
55084
56148
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
55085
56149
|
"\n"
|
|
55086
56150
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
55087
56151
|
}
|
|
56152
|
+
/**
|
|
56153
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
56154
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
56155
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
56156
|
+
*
|
|
56157
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
56158
|
+
* are not statically numeric we accept the Range (the historical
|
|
56159
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
56160
|
+
* left as a known limitation; callers can force the iterable path by
|
|
56161
|
+
* supplying an explicit step.
|
|
56162
|
+
*/
|
|
56163
|
+
static isLegacyCompatibleRange(coll) {
|
|
56164
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
56165
|
+
if (coll.ops.length >= 3) {
|
|
56166
|
+
const stepExpr = coll.ops[2];
|
|
56167
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
56168
|
+
}
|
|
56169
|
+
const lo = coll.ops[0];
|
|
56170
|
+
const hi = coll.ops[1];
|
|
56171
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
56172
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
56173
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
56174
|
+
return true;
|
|
56175
|
+
}
|
|
56176
|
+
/**
|
|
56177
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
56178
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
56179
|
+
* `library/collections.ts` Range:
|
|
56180
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
56181
|
+
* element = lo + step * k (0-indexed)
|
|
56182
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
56183
|
+
*
|
|
56184
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
56185
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
56186
|
+
*/
|
|
56187
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
56188
|
+
const loExpr = rangeExpr.ops[0];
|
|
56189
|
+
const hiExpr = rangeExpr.ops[1];
|
|
56190
|
+
const stepExpr = rangeExpr.ops[2];
|
|
56191
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
56192
|
+
const lo2 = loExpr.re;
|
|
56193
|
+
const hi2 = hiExpr.re;
|
|
56194
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
56195
|
+
if (step2 === 0) return "[]";
|
|
56196
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
56197
|
+
if (step2 === 1) {
|
|
56198
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
56199
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
56200
|
+
}
|
|
56201
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
56202
|
+
}
|
|
56203
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
56204
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
56205
|
+
if (stepExpr === void 0) {
|
|
56206
|
+
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})`;
|
|
56207
|
+
}
|
|
56208
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
56209
|
+
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})`;
|
|
56210
|
+
}
|
|
55088
56211
|
/**
|
|
55089
56212
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
55090
56213
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -59584,8 +60707,8 @@ Error in definition of "${name}"`,
|
|
|
59584
60707
|
}
|
|
59585
60708
|
if (effectiveOp === "greater" || effectiveOp === "greaterEqual") {
|
|
59586
60709
|
const isStrict = effectiveOp === "greater";
|
|
59587
|
-
if (bounds.
|
|
59588
|
-
const lowerVal = isNumber(bounds.
|
|
60710
|
+
if (bounds.lower !== void 0) {
|
|
60711
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59589
60712
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59590
60713
|
if (isStrict) {
|
|
59591
60714
|
if (lowerVal > k) return "tautology";
|
|
@@ -59597,8 +60720,8 @@ Error in definition of "${name}"`,
|
|
|
59597
60720
|
}
|
|
59598
60721
|
}
|
|
59599
60722
|
}
|
|
59600
|
-
if (bounds.
|
|
59601
|
-
const upperVal = isNumber(bounds.
|
|
60723
|
+
if (bounds.upper !== void 0) {
|
|
60724
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59602
60725
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59603
60726
|
if (isStrict) {
|
|
59604
60727
|
if (upperVal < k) return "contradiction";
|
|
@@ -59613,8 +60736,8 @@ Error in definition of "${name}"`,
|
|
|
59613
60736
|
}
|
|
59614
60737
|
} else {
|
|
59615
60738
|
const isStrict = effectiveOp === "less";
|
|
59616
|
-
if (bounds.
|
|
59617
|
-
const upperVal = isNumber(bounds.
|
|
60739
|
+
if (bounds.upper !== void 0) {
|
|
60740
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59618
60741
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59619
60742
|
if (isStrict) {
|
|
59620
60743
|
if (upperVal < k) return "tautology";
|
|
@@ -59625,8 +60748,8 @@ Error in definition of "${name}"`,
|
|
|
59625
60748
|
}
|
|
59626
60749
|
}
|
|
59627
60750
|
}
|
|
59628
|
-
if (bounds.
|
|
59629
|
-
const lowerVal = isNumber(bounds.
|
|
60751
|
+
if (bounds.lower !== void 0) {
|
|
60752
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59630
60753
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59631
60754
|
if (isStrict) {
|
|
59632
60755
|
if (lowerVal > k) return "contradiction";
|
|
@@ -59854,7 +60977,7 @@ Error in definition of "${name}"`,
|
|
|
59854
60977
|
const patOp1B2 = pat.op1;
|
|
59855
60978
|
if (isSymbol2(patOp1B2)) {
|
|
59856
60979
|
const bounds = getInequalityBoundsFromAssumptions(ce, patOp1B2.symbol);
|
|
59857
|
-
const bound = isLower ? bounds.
|
|
60980
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59858
60981
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59859
60982
|
if (bound !== void 0 && (!isStrict || strictOk === true))
|
|
59860
60983
|
pushResult({ [boundWildcard]: bound });
|
|
@@ -59864,7 +60987,7 @@ Error in definition of "${name}"`,
|
|
|
59864
60987
|
if (symbolWildcard && !symbolWildcard.startsWith("__")) {
|
|
59865
60988
|
for (const s of candidatesFromAssumptions()) {
|
|
59866
60989
|
const bounds = getInequalityBoundsFromAssumptions(ce, s);
|
|
59867
|
-
const bound = isLower ? bounds.
|
|
60990
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59868
60991
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59869
60992
|
if (bound === void 0 || isStrict && strictOk !== true)
|
|
59870
60993
|
continue;
|
|
@@ -60896,6 +62019,7 @@ Error in definition of "${name}"`,
|
|
|
60896
62019
|
return `_SYS.cexp(${compile3(args[0])})`;
|
|
60897
62020
|
return `Math.exp(${compile3(args[0])})`;
|
|
60898
62021
|
},
|
|
62022
|
+
First: (args, compile3) => `${compile3(args[0])}[0]`,
|
|
60899
62023
|
Floor: (args, compile3) => {
|
|
60900
62024
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
60901
62025
|
return `Math.floor(${compile3(args[0])})`;
|
|
@@ -61054,7 +62178,20 @@ Error in definition of "${name}"`,
|
|
|
61054
62178
|
if (nConst !== void 0) return `Math.pow(${compile3(arg)}, ${1 / nConst})`;
|
|
61055
62179
|
return `Math.pow(${compile3(arg)}, 1 / (${compile3(exp3)}))`;
|
|
61056
62180
|
},
|
|
61057
|
-
Random:
|
|
62181
|
+
Random: (args, compile3) => {
|
|
62182
|
+
if (args.length === 0) return "Math.random()";
|
|
62183
|
+
if (args.length === 2) {
|
|
62184
|
+
const m = compile3(args[0]);
|
|
62185
|
+
const n = compile3(args[1]);
|
|
62186
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
62187
|
+
}
|
|
62188
|
+
const arg = args[0];
|
|
62189
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
62190
|
+
return `Math.floor(Math.random() * (${compile3(arg)}))`;
|
|
62191
|
+
}
|
|
62192
|
+
const a = compile3(arg);
|
|
62193
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
62194
|
+
},
|
|
61058
62195
|
Round: (args, compile3) => {
|
|
61059
62196
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
61060
62197
|
return `Math.round(${compile3(args[0])})`;
|
|
@@ -61082,6 +62219,7 @@ Error in definition of "${name}"`,
|
|
|
61082
62219
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile3(arg)})`;
|
|
61083
62220
|
return `1 / Math.cosh(${compile3(arg)})`;
|
|
61084
62221
|
},
|
|
62222
|
+
Second: (args, compile3) => `${compile3(args[0])}[1]`,
|
|
61085
62223
|
Heaviside: "_SYS.heaviside",
|
|
61086
62224
|
Sign: "Math.sign",
|
|
61087
62225
|
Sinc: "_SYS.sinc",
|
|
@@ -61114,6 +62252,7 @@ Error in definition of "${name}"`,
|
|
|
61114
62252
|
return `_SYS.ctanh(${compile3(args[0])})`;
|
|
61115
62253
|
return `Math.tanh(${compile3(args[0])})`;
|
|
61116
62254
|
},
|
|
62255
|
+
Third: (args, compile3) => `${compile3(args[0])}[2]`,
|
|
61117
62256
|
Mod: ([a, b], compile3) => {
|
|
61118
62257
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
61119
62258
|
const ca = compile3(a);
|
|
@@ -62393,6 +63532,14 @@ Error in definition of "${name}"`,
|
|
|
62393
63532
|
return `exp(${compile3(args[0])})`;
|
|
62394
63533
|
},
|
|
62395
63534
|
Exp2: "exp2",
|
|
63535
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
63536
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
63537
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
63538
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
63539
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
63540
|
+
First: (args, compile3) => `${compile3(args[0])}.x`,
|
|
63541
|
+
Second: (args, compile3) => `${compile3(args[0])}.y`,
|
|
63542
|
+
Third: (args, compile3) => `${compile3(args[0])}.z`,
|
|
62396
63543
|
Floor: (args, compile3) => {
|
|
62397
63544
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
62398
63545
|
return `floor(${compile3(args[0])})`;
|
|
@@ -62870,6 +64017,39 @@ Error in definition of "${name}"`,
|
|
|
62870
64017
|
// Sum/Product — unrolled or for-loop
|
|
62871
64018
|
Sum: (args, compile3, target) => compileGPUSumProduct("Sum", args, compile3, target),
|
|
62872
64019
|
Product: (args, compile3, target) => compileGPUSumProduct("Product", args, compile3, target),
|
|
64020
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
64021
|
+
Range: (args, _compile2, target) => {
|
|
64022
|
+
if (args.length < 2 || args.length > 3) {
|
|
64023
|
+
throw new Error(
|
|
64024
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
64025
|
+
);
|
|
64026
|
+
}
|
|
64027
|
+
const lo = args[0].re;
|
|
64028
|
+
const hi = args[1].re;
|
|
64029
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
64030
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
64031
|
+
throw new Error(
|
|
64032
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
64033
|
+
);
|
|
64034
|
+
}
|
|
64035
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
64036
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
64037
|
+
if (count === 0) {
|
|
64038
|
+
throw new Error(
|
|
64039
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
64040
|
+
);
|
|
64041
|
+
}
|
|
64042
|
+
if (count > 256) {
|
|
64043
|
+
throw new Error(
|
|
64044
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
64045
|
+
);
|
|
64046
|
+
}
|
|
64047
|
+
const values = [];
|
|
64048
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
64049
|
+
const isWGSL = target.language === "wgsl";
|
|
64050
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
64051
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
64052
|
+
},
|
|
62873
64053
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
62874
64054
|
Loop: (args, _compile2, target) => {
|
|
62875
64055
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -62898,6 +64078,134 @@ Error in definition of "${name}"`,
|
|
|
62898
64078
|
${bodyCode};
|
|
62899
64079
|
}`;
|
|
62900
64080
|
},
|
|
64081
|
+
// Statistical functions
|
|
64082
|
+
/**
|
|
64083
|
+
* GCD of two scalar arguments.
|
|
64084
|
+
*
|
|
64085
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
64086
|
+
* Only two-argument form is supported in GPU targets.
|
|
64087
|
+
*/
|
|
64088
|
+
GCD: (args, compile3) => {
|
|
64089
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
64090
|
+
if (args.length > 2)
|
|
64091
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
64092
|
+
const a = args[0];
|
|
64093
|
+
const b = args[1];
|
|
64094
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
64095
|
+
return `_gpu_gcd(${compile3(a)}, ${compile3(b)})`;
|
|
64096
|
+
},
|
|
64097
|
+
/**
|
|
64098
|
+
* Variance of a compile-time-known list.
|
|
64099
|
+
*
|
|
64100
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64101
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
64102
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
64103
|
+
*/
|
|
64104
|
+
Variance: (args, compile3) => {
|
|
64105
|
+
let elems;
|
|
64106
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64107
|
+
elems = args[0].ops;
|
|
64108
|
+
} else if (args.length >= 2) {
|
|
64109
|
+
elems = args;
|
|
64110
|
+
} else {
|
|
64111
|
+
throw new Error(
|
|
64112
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
64113
|
+
);
|
|
64114
|
+
}
|
|
64115
|
+
const n = elems.length;
|
|
64116
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
64117
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64118
|
+
const sum = compiled.join(" + ");
|
|
64119
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
64120
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
64121
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
64122
|
+
},
|
|
64123
|
+
/**
|
|
64124
|
+
* Median of a compile-time-known list.
|
|
64125
|
+
*
|
|
64126
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64127
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
64128
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
64129
|
+
*
|
|
64130
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
64131
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
64132
|
+
*/
|
|
64133
|
+
Median: (args, compile3) => {
|
|
64134
|
+
let elems;
|
|
64135
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64136
|
+
elems = args[0].ops;
|
|
64137
|
+
} else if (args.length >= 1) {
|
|
64138
|
+
elems = args;
|
|
64139
|
+
} else {
|
|
64140
|
+
throw new Error(
|
|
64141
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
64142
|
+
);
|
|
64143
|
+
}
|
|
64144
|
+
const n = elems.length;
|
|
64145
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
64146
|
+
if (n > 8) {
|
|
64147
|
+
throw new Error(
|
|
64148
|
+
`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.`
|
|
64149
|
+
);
|
|
64150
|
+
}
|
|
64151
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64152
|
+
if (n === 1) return compiled[0];
|
|
64153
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
64154
|
+
},
|
|
64155
|
+
/**
|
|
64156
|
+
* Deterministic pseudorandom for GPU.
|
|
64157
|
+
*
|
|
64158
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
64159
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
64160
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
64161
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
64162
|
+
* integer-returning operators in this target.
|
|
64163
|
+
*
|
|
64164
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
64165
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
64166
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
64167
|
+
* caller must provide an explicit seed.
|
|
64168
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
64169
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
64170
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
64171
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
64172
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
64173
|
+
*
|
|
64174
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
64175
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
64176
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
64177
|
+
* `sin` differences.
|
|
64178
|
+
*/
|
|
64179
|
+
Random: (args, compile3, target) => {
|
|
64180
|
+
if (args.length === 0) {
|
|
64181
|
+
if (target.language === "wgsl") {
|
|
64182
|
+
throw new Error(
|
|
64183
|
+
"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."
|
|
64184
|
+
);
|
|
64185
|
+
}
|
|
64186
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64187
|
+
}
|
|
64188
|
+
if (args.length === 1) {
|
|
64189
|
+
const arg = args[0];
|
|
64190
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
64191
|
+
const compiled = compile3(arg);
|
|
64192
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
64193
|
+
}
|
|
64194
|
+
return `_gpu_random(${compile3(arg)})`;
|
|
64195
|
+
}
|
|
64196
|
+
if (args.length === 2) {
|
|
64197
|
+
if (target.language === "wgsl") {
|
|
64198
|
+
throw new Error(
|
|
64199
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
64200
|
+
);
|
|
64201
|
+
}
|
|
64202
|
+
const m = compile3(args[0]);
|
|
64203
|
+
const n = compile3(args[1]);
|
|
64204
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64205
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
64206
|
+
}
|
|
64207
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
64208
|
+
},
|
|
62901
64209
|
// Function (lambda) — not supported in GPU
|
|
62902
64210
|
Function: () => {
|
|
62903
64211
|
throw new Error(
|
|
@@ -63496,6 +64804,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
63496
64804
|
}
|
|
63497
64805
|
return 1.0;
|
|
63498
64806
|
}
|
|
64807
|
+
`;
|
|
64808
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
64809
|
+
float _gpu_gcd(float a, float b) {
|
|
64810
|
+
a = abs(a); b = abs(b);
|
|
64811
|
+
for (int i = 0; i < 32; i++) {
|
|
64812
|
+
if (b < 0.5) break;
|
|
64813
|
+
float t = mod(a, b);
|
|
64814
|
+
a = b;
|
|
64815
|
+
b = t;
|
|
64816
|
+
}
|
|
64817
|
+
return a;
|
|
64818
|
+
}
|
|
64819
|
+
`;
|
|
64820
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
64821
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
64822
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
64823
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
64824
|
+
if (b < 0.5) { break; }
|
|
64825
|
+
let t = a % b;
|
|
64826
|
+
a = b;
|
|
64827
|
+
b = t;
|
|
64828
|
+
}
|
|
64829
|
+
return a;
|
|
64830
|
+
}
|
|
64831
|
+
`;
|
|
64832
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
64833
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64834
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64835
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64836
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64837
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64838
|
+
float _gpu_random(float seed) {
|
|
64839
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64840
|
+
}
|
|
64841
|
+
`;
|
|
64842
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
64843
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64844
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64845
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64846
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64847
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64848
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
64849
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64850
|
+
}
|
|
64851
|
+
`;
|
|
64852
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
64853
|
+
float _gpu_median_2(float a, float b) {
|
|
64854
|
+
return (a + b) * 0.5;
|
|
64855
|
+
}
|
|
64856
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
64857
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64858
|
+
}
|
|
64859
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
64860
|
+
float lo = max(min(a, b), min(c, d));
|
|
64861
|
+
float hi = min(max(a, b), max(c, d));
|
|
64862
|
+
return (lo + hi) * 0.5;
|
|
64863
|
+
}
|
|
64864
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
64865
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64866
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
64867
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64868
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64869
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64870
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64871
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64872
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64873
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64874
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64875
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64876
|
+
return v2;
|
|
64877
|
+
}
|
|
64878
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
64879
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
64880
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64881
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64882
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64883
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64884
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64885
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64886
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64887
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64888
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64889
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64890
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64891
|
+
return (v2 + v3) * 0.5;
|
|
64892
|
+
}
|
|
64893
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
64894
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
64895
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64896
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64897
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64898
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64899
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64900
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64901
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64902
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64903
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64904
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64905
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64906
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64907
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64908
|
+
return v3;
|
|
64909
|
+
}
|
|
64910
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
64911
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
64912
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64913
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64914
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64915
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
64916
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64917
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64918
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64919
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
64920
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64921
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64922
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64923
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
64924
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64925
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64926
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
64927
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64928
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64929
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64930
|
+
return (v3 + v4) * 0.5;
|
|
64931
|
+
}
|
|
64932
|
+
`;
|
|
64933
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
64934
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
64935
|
+
return (a + b) * 0.5;
|
|
64936
|
+
}
|
|
64937
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
64938
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64939
|
+
}
|
|
64940
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
64941
|
+
let lo = max(min(a, b), min(c, d));
|
|
64942
|
+
let hi = min(max(a, b), max(c, d));
|
|
64943
|
+
return (lo + hi) * 0.5;
|
|
64944
|
+
}
|
|
64945
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
64946
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64947
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
64948
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64949
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64950
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64951
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64952
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64953
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64954
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64955
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64956
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64957
|
+
return v2;
|
|
64958
|
+
}
|
|
64959
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
64960
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
64961
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64962
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64963
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64964
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64965
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64966
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64967
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64968
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64969
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64970
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64971
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64972
|
+
return (v2 + v3) * 0.5;
|
|
64973
|
+
}
|
|
64974
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
64975
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
64976
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64977
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64978
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64979
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64980
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64981
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64982
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64983
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64984
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64985
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64986
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64987
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64988
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64989
|
+
return v3;
|
|
64990
|
+
}
|
|
64991
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
64992
|
+
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;
|
|
64993
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64994
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64995
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64996
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
64997
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64998
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64999
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
65000
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
65001
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
65002
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
65003
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
65004
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
65005
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
65006
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65007
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
65008
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
65009
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
65010
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65011
|
+
return (v3 + v4) * 0.5;
|
|
65012
|
+
}
|
|
63499
65013
|
`;
|
|
63500
65014
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
63501
65015
|
float _gpu_srgb_to_linear(float c) {
|
|
@@ -64174,6 +65688,12 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
|
64174
65688
|
if (code.includes("_fractal_")) {
|
|
64175
65689
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
64176
65690
|
}
|
|
65691
|
+
if (code.includes("_gpu_random"))
|
|
65692
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
65693
|
+
if (code.includes("_gpu_gcd"))
|
|
65694
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
65695
|
+
if (code.includes("_gpu_median_"))
|
|
65696
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
64177
65697
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
64178
65698
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
64179
65699
|
}
|
|
@@ -66399,6 +67919,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
66399
67919
|
_timeLimit = 2e3;
|
|
66400
67920
|
_iterationLimit = 1024;
|
|
66401
67921
|
_recursionLimit = 1024;
|
|
67922
|
+
_maxCollectionSize = 1e4;
|
|
66402
67923
|
_deadline = void 0;
|
|
66403
67924
|
_isVerifying = false;
|
|
66404
67925
|
get timeLimit() {
|
|
@@ -66419,6 +67940,12 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
66419
67940
|
set recursionLimit(value) {
|
|
66420
67941
|
this._recursionLimit = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
66421
67942
|
}
|
|
67943
|
+
get maxCollectionSize() {
|
|
67944
|
+
return this._maxCollectionSize;
|
|
67945
|
+
}
|
|
67946
|
+
set maxCollectionSize(value) {
|
|
67947
|
+
this._maxCollectionSize = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
67948
|
+
}
|
|
66422
67949
|
get deadline() {
|
|
66423
67950
|
return this._deadline;
|
|
66424
67951
|
}
|
|
@@ -68457,6 +69984,23 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
68457
69984
|
set recursionLimit(t) {
|
|
68458
69985
|
this._runtimeState.recursionLimit = t;
|
|
68459
69986
|
}
|
|
69987
|
+
/** Maximum number of elements a collection may have when materialized
|
|
69988
|
+
* (converted from a lazy form to a `List`). Default: 10,000.
|
|
69989
|
+
*
|
|
69990
|
+
* When a materialization would exceed this size, the operation leaves
|
|
69991
|
+
* the expression in its lazy form. Consumers can detect oversize
|
|
69992
|
+
* collections via the symbolic form's `count`.
|
|
69993
|
+
*
|
|
69994
|
+
* Set to `Infinity` (or `0` / a negative number) to disable the cap.
|
|
69995
|
+
*
|
|
69996
|
+
* @experimental
|
|
69997
|
+
*/
|
|
69998
|
+
get maxCollectionSize() {
|
|
69999
|
+
return this._runtimeState.maxCollectionSize;
|
|
70000
|
+
}
|
|
70001
|
+
set maxCollectionSize(t) {
|
|
70002
|
+
this._runtimeState.maxCollectionSize = t;
|
|
70003
|
+
}
|
|
68460
70004
|
/**
|
|
68461
70005
|
* Flag to prevent infinite recursion in the verify/ask/equality checking cycle.
|
|
68462
70006
|
*
|
|
@@ -68733,6 +70277,36 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
68733
70277
|
lookupDefinition(id) {
|
|
68734
70278
|
return lookupDefinition(this, id);
|
|
68735
70279
|
}
|
|
70280
|
+
normalizeIdentifier(latex) {
|
|
70281
|
+
if (!latex) return "";
|
|
70282
|
+
if (isValidSymbol(latex)) return latex;
|
|
70283
|
+
this.pushScope();
|
|
70284
|
+
try {
|
|
70285
|
+
const expr2 = this.parse(latex);
|
|
70286
|
+
if (isSymbol2(expr2)) return expr2.symbol;
|
|
70287
|
+
} finally {
|
|
70288
|
+
this.popScope();
|
|
70289
|
+
}
|
|
70290
|
+
return "";
|
|
70291
|
+
}
|
|
70292
|
+
operatorInfo(head) {
|
|
70293
|
+
const def = this.lookupDefinition(head);
|
|
70294
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
70295
|
+
const op = def.operator;
|
|
70296
|
+
return {
|
|
70297
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
70298
|
+
signature: op.signature
|
|
70299
|
+
};
|
|
70300
|
+
}
|
|
70301
|
+
symbolInfo(name) {
|
|
70302
|
+
const def = this.lookupDefinition(name);
|
|
70303
|
+
if (!def || !isValueDef(def)) return void 0;
|
|
70304
|
+
const v = def.value;
|
|
70305
|
+
return {
|
|
70306
|
+
kind: v.isConstant ? "constant" : "variable",
|
|
70307
|
+
type: v.type
|
|
70308
|
+
};
|
|
70309
|
+
}
|
|
68736
70310
|
/**
|
|
68737
70311
|
* Associate a new definition to a symbol in the current context.
|
|
68738
70312
|
*
|
|
@@ -69020,6 +70594,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
69020
70594
|
const def = this.lookupDefinition(id);
|
|
69021
70595
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
69022
70596
|
},
|
|
70597
|
+
tolerance: this.tolerance,
|
|
69023
70598
|
...this._latexOptions,
|
|
69024
70599
|
...parseOpts
|
|
69025
70600
|
});
|
|
@@ -69184,7 +70759,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
69184
70759
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
69185
70760
|
|
|
69186
70761
|
// src/core.ts
|
|
69187
|
-
var version = "0.
|
|
70762
|
+
var version = "0.58.0";
|
|
69188
70763
|
return __toCommonJS(core_exports);
|
|
69189
70764
|
})();
|
|
69190
70765
|
/*! Bundled license information:
|