@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 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.ComputeEngine = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var ComputeEngine = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -4344,7 +4344,42 @@ var ComputeEngine = (() => {
|
|
|
4344
4344
|
if (b === "nothing") return a;
|
|
4345
4345
|
if (isSubtype(a, b)) return b;
|
|
4346
4346
|
if (isSubtype(b, a)) return a;
|
|
4347
|
-
|
|
4347
|
+
const sup = superType(a, b);
|
|
4348
|
+
if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
|
|
4349
|
+
return sup;
|
|
4350
|
+
}
|
|
4351
|
+
var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
|
|
4352
|
+
"scalar",
|
|
4353
|
+
"value",
|
|
4354
|
+
"function",
|
|
4355
|
+
"expression",
|
|
4356
|
+
"collection",
|
|
4357
|
+
"indexed_collection",
|
|
4358
|
+
"list",
|
|
4359
|
+
"set",
|
|
4360
|
+
"tuple",
|
|
4361
|
+
"record",
|
|
4362
|
+
"dictionary",
|
|
4363
|
+
"map",
|
|
4364
|
+
"any"
|
|
4365
|
+
]);
|
|
4366
|
+
function unionTypes(a, b) {
|
|
4367
|
+
const members = [];
|
|
4368
|
+
const push = (t) => {
|
|
4369
|
+
if (typeof t === "object" && t.kind === "union") {
|
|
4370
|
+
for (const m of t.types) push(m);
|
|
4371
|
+
return;
|
|
4372
|
+
}
|
|
4373
|
+
const key = typeof t === "string" ? t : JSON.stringify(t);
|
|
4374
|
+
if (!members.some(
|
|
4375
|
+
(m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
|
|
4376
|
+
))
|
|
4377
|
+
members.push(t);
|
|
4378
|
+
};
|
|
4379
|
+
push(a);
|
|
4380
|
+
push(b);
|
|
4381
|
+
if (members.length === 1) return members[0];
|
|
4382
|
+
return { kind: "union", types: members };
|
|
4348
4383
|
}
|
|
4349
4384
|
function narrow(...types) {
|
|
4350
4385
|
if (types.length === 0) return "nothing";
|
|
@@ -4422,7 +4457,7 @@ var ComputeEngine = (() => {
|
|
|
4422
4457
|
if (type2.kind === "set") return type2.elements;
|
|
4423
4458
|
if (type2.kind === "tuple") return widen(...type2.elements.map((x) => x.type));
|
|
4424
4459
|
if (type2.kind === "dictionary")
|
|
4425
|
-
return parseType(`tuple<string, ${type2.values}>`);
|
|
4460
|
+
return parseType(`tuple<string, ${typeToString(type2.values)}>`);
|
|
4426
4461
|
if (type2.kind === "record") {
|
|
4427
4462
|
return parseType(
|
|
4428
4463
|
`tuple<string, ${typeToString(widen(...Object.values(type2.elements)))}>`
|
|
@@ -5968,6 +6003,84 @@ var ComputeEngine = (() => {
|
|
|
5968
6003
|
}
|
|
5969
6004
|
|
|
5970
6005
|
// src/compute-engine/boxed-expression/inequality-bounds.ts
|
|
6006
|
+
function extractIntervalBounds(expr2, symbol2) {
|
|
6007
|
+
if (isFunction2(expr2, "When")) {
|
|
6008
|
+
const cond = expr2.op2;
|
|
6009
|
+
if (!cond) return void 0;
|
|
6010
|
+
return extractIntervalBounds(cond, symbol2);
|
|
6011
|
+
}
|
|
6012
|
+
if (isFunction2(expr2, "Multiply")) {
|
|
6013
|
+
const ops = expr2.ops;
|
|
6014
|
+
if (!ops) return void 0;
|
|
6015
|
+
const merged = {};
|
|
6016
|
+
for (const sub2 of ops) {
|
|
6017
|
+
if (isFunction2(sub2, "When")) {
|
|
6018
|
+
const sub_ = extractIntervalBounds(sub2, symbol2);
|
|
6019
|
+
if (sub_ !== void 0) _mergeBounds(merged, sub_);
|
|
6020
|
+
}
|
|
6021
|
+
}
|
|
6022
|
+
return _hasAnyBound(merged) ? merged : void 0;
|
|
6023
|
+
}
|
|
6024
|
+
const result = {};
|
|
6025
|
+
if (isFunction2(expr2, "And")) {
|
|
6026
|
+
const ops = expr2.ops;
|
|
6027
|
+
if (!ops) return void 0;
|
|
6028
|
+
for (const sub2 of ops) {
|
|
6029
|
+
const subBounds = extractIntervalBounds(sub2, symbol2);
|
|
6030
|
+
if (subBounds === void 0) continue;
|
|
6031
|
+
_mergeBounds(result, subBounds);
|
|
6032
|
+
}
|
|
6033
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
6034
|
+
}
|
|
6035
|
+
const op = expr2.operator;
|
|
6036
|
+
if ((op === "Less" || op === "LessEqual" || op === "Greater" || op === "GreaterEqual") && isFunction2(expr2)) {
|
|
6037
|
+
const isStrict = op === "Less" || op === "Greater";
|
|
6038
|
+
const ops = expr2.ops;
|
|
6039
|
+
if (!ops || ops.length < 2) return void 0;
|
|
6040
|
+
const flipped = op === "Greater" || op === "GreaterEqual" ? [...ops].reverse() : ops;
|
|
6041
|
+
for (let i = 0; i < flipped.length; i++) {
|
|
6042
|
+
if (isSymbol2(flipped[i], symbol2)) {
|
|
6043
|
+
if (i > 0) {
|
|
6044
|
+
const candidate = flipped[i - 1];
|
|
6045
|
+
if (result.lower === void 0 || candidate.isGreater(result.lower) === true) {
|
|
6046
|
+
result.lower = candidate;
|
|
6047
|
+
result.lowerStrict = isStrict;
|
|
6048
|
+
}
|
|
6049
|
+
}
|
|
6050
|
+
if (i < flipped.length - 1) {
|
|
6051
|
+
const candidate = flipped[i + 1];
|
|
6052
|
+
if (result.upper === void 0 || candidate.isLess(result.upper) === true) {
|
|
6053
|
+
result.upper = candidate;
|
|
6054
|
+
result.upperStrict = isStrict;
|
|
6055
|
+
}
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
return _hasAnyBound(result) ? result : void 0;
|
|
6060
|
+
}
|
|
6061
|
+
return void 0;
|
|
6062
|
+
}
|
|
6063
|
+
function _mergeBounds(into, from) {
|
|
6064
|
+
if (from.lower !== void 0) {
|
|
6065
|
+
if (into.lower === void 0 || from.lower.isGreater(into.lower) === true) {
|
|
6066
|
+
into.lower = from.lower;
|
|
6067
|
+
into.lowerStrict = from.lowerStrict;
|
|
6068
|
+
} else if (from.lower.isSame(into.lower)) {
|
|
6069
|
+
into.lowerStrict = into.lowerStrict || from.lowerStrict;
|
|
6070
|
+
}
|
|
6071
|
+
}
|
|
6072
|
+
if (from.upper !== void 0) {
|
|
6073
|
+
if (into.upper === void 0 || from.upper.isLess(into.upper) === true) {
|
|
6074
|
+
into.upper = from.upper;
|
|
6075
|
+
into.upperStrict = from.upperStrict;
|
|
6076
|
+
} else if (from.upper.isSame(into.upper)) {
|
|
6077
|
+
into.upperStrict = into.upperStrict || from.upperStrict;
|
|
6078
|
+
}
|
|
6079
|
+
}
|
|
6080
|
+
}
|
|
6081
|
+
function _hasAnyBound(b) {
|
|
6082
|
+
return b.lower !== void 0 || b.upper !== void 0;
|
|
6083
|
+
}
|
|
5971
6084
|
function getInequalityBoundsFromAssumptions(ce, symbol2) {
|
|
5972
6085
|
const result = {};
|
|
5973
6086
|
const assumptions = ce.context?.assumptions;
|
|
@@ -5984,8 +6097,8 @@ var ComputeEngine = (() => {
|
|
|
5984
6097
|
const isStrict = op === "Less";
|
|
5985
6098
|
if (isFunction2(lhs, "Negate") && isSymbol2(lhs.op1, symbol2)) {
|
|
5986
6099
|
const bound = ce.Zero;
|
|
5987
|
-
if (result.
|
|
5988
|
-
result.
|
|
6100
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6101
|
+
result.lower = bound;
|
|
5989
6102
|
result.lowerStrict = isStrict;
|
|
5990
6103
|
}
|
|
5991
6104
|
}
|
|
@@ -6004,16 +6117,16 @@ var ComputeEngine = (() => {
|
|
|
6004
6117
|
}
|
|
6005
6118
|
if (hasNegatedSymbol && constantSum !== 0) {
|
|
6006
6119
|
const bound = ce.expr(constantSum);
|
|
6007
|
-
if (result.
|
|
6008
|
-
result.
|
|
6120
|
+
if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
|
|
6121
|
+
result.lower = bound;
|
|
6009
6122
|
result.lowerStrict = isStrict;
|
|
6010
6123
|
}
|
|
6011
6124
|
}
|
|
6012
6125
|
}
|
|
6013
6126
|
if (isSymbol2(lhs, symbol2)) {
|
|
6014
6127
|
const bound = ce.Zero;
|
|
6015
|
-
if (result.
|
|
6016
|
-
result.
|
|
6128
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6129
|
+
result.upper = bound;
|
|
6017
6130
|
result.upperStrict = isStrict;
|
|
6018
6131
|
}
|
|
6019
6132
|
}
|
|
@@ -6032,8 +6145,8 @@ var ComputeEngine = (() => {
|
|
|
6032
6145
|
}
|
|
6033
6146
|
if (hasSymbol && constantSum !== 0) {
|
|
6034
6147
|
const bound = ce.expr(-constantSum);
|
|
6035
|
-
if (result.
|
|
6036
|
-
result.
|
|
6148
|
+
if (result.upper === void 0 || bound.isLess(result.upper) === true) {
|
|
6149
|
+
result.upper = bound;
|
|
6037
6150
|
result.upperStrict = isStrict;
|
|
6038
6151
|
}
|
|
6039
6152
|
}
|
|
@@ -6253,8 +6366,8 @@ var ComputeEngine = (() => {
|
|
|
6253
6366
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, b.symbol);
|
|
6254
6367
|
const aNum = typeof a.numericValue === "number" ? a.numericValue : a.numericValue.re;
|
|
6255
6368
|
if (aNum !== void 0 && Number.isFinite(aNum)) {
|
|
6256
|
-
if (bounds.
|
|
6257
|
-
const lb = bounds.
|
|
6369
|
+
if (bounds.lower !== void 0) {
|
|
6370
|
+
const lb = bounds.lower;
|
|
6258
6371
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6259
6372
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6260
6373
|
if (lowerNum > aNum) return "<";
|
|
@@ -6262,8 +6375,8 @@ var ComputeEngine = (() => {
|
|
|
6262
6375
|
if (lowerNum === aNum && !bounds.lowerStrict) return "<=";
|
|
6263
6376
|
}
|
|
6264
6377
|
}
|
|
6265
|
-
if (bounds.
|
|
6266
|
-
const ub = bounds.
|
|
6378
|
+
if (bounds.upper !== void 0) {
|
|
6379
|
+
const ub = bounds.upper;
|
|
6267
6380
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6268
6381
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6269
6382
|
if (upperNum < aNum) return ">";
|
|
@@ -6293,8 +6406,8 @@ var ComputeEngine = (() => {
|
|
|
6293
6406
|
if (typeof b === "number") {
|
|
6294
6407
|
if (isSymbol2(a)) {
|
|
6295
6408
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6296
|
-
if (bounds.
|
|
6297
|
-
const lb = bounds.
|
|
6409
|
+
if (bounds.lower !== void 0) {
|
|
6410
|
+
const lb = bounds.lower;
|
|
6298
6411
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6299
6412
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6300
6413
|
if (lowerNum > b) return ">";
|
|
@@ -6302,8 +6415,8 @@ var ComputeEngine = (() => {
|
|
|
6302
6415
|
if (lowerNum === b && !bounds.lowerStrict) return ">=";
|
|
6303
6416
|
}
|
|
6304
6417
|
}
|
|
6305
|
-
if (bounds.
|
|
6306
|
-
const ub = bounds.
|
|
6418
|
+
if (bounds.upper !== void 0) {
|
|
6419
|
+
const ub = bounds.upper;
|
|
6307
6420
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6308
6421
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6309
6422
|
if (upperNum < b) return "<";
|
|
@@ -6359,8 +6472,8 @@ var ComputeEngine = (() => {
|
|
|
6359
6472
|
const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
|
|
6360
6473
|
const bNum = typeof b.numericValue === "number" ? b.numericValue : b.numericValue.re;
|
|
6361
6474
|
if (bNum !== void 0 && Number.isFinite(bNum)) {
|
|
6362
|
-
if (bounds.
|
|
6363
|
-
const lb = bounds.
|
|
6475
|
+
if (bounds.lower !== void 0) {
|
|
6476
|
+
const lb = bounds.lower;
|
|
6364
6477
|
const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
|
|
6365
6478
|
if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
|
|
6366
6479
|
if (lowerNum > bNum) return ">";
|
|
@@ -6368,8 +6481,8 @@ var ComputeEngine = (() => {
|
|
|
6368
6481
|
if (lowerNum === bNum && !bounds.lowerStrict) return ">=";
|
|
6369
6482
|
}
|
|
6370
6483
|
}
|
|
6371
|
-
if (bounds.
|
|
6372
|
-
const ub = bounds.
|
|
6484
|
+
if (bounds.upper !== void 0) {
|
|
6485
|
+
const ub = bounds.upper;
|
|
6373
6486
|
const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
|
|
6374
6487
|
if (upperNum !== void 0 && Number.isFinite(upperNum)) {
|
|
6375
6488
|
if (upperNum < bNum) return "<";
|
|
@@ -6907,6 +7020,12 @@ var ComputeEngine = (() => {
|
|
|
6907
7020
|
scoped = false;
|
|
6908
7021
|
signature;
|
|
6909
7022
|
inferredSignature = true;
|
|
7023
|
+
/** True if this operator definition was created from a user-defined
|
|
7024
|
+
* function literal (e.g. via `ce.assign('f', ce.parse('x \\mapsto x^2'))`).
|
|
7025
|
+
* Used to enable auto-broadcasting when applied to indexed collections.
|
|
7026
|
+
* @internal
|
|
7027
|
+
*/
|
|
7028
|
+
_isLambda = false;
|
|
6910
7029
|
type;
|
|
6911
7030
|
sgn;
|
|
6912
7031
|
eq;
|
|
@@ -7064,6 +7183,8 @@ var ComputeEngine = (() => {
|
|
|
7064
7183
|
this.engine._typeResolver
|
|
7065
7184
|
);
|
|
7066
7185
|
}
|
|
7186
|
+
if (isFunction2(boxedFn) && boxedFn.operator === "Function")
|
|
7187
|
+
this._isLambda = true;
|
|
7067
7188
|
const fn = applicable(boxedFn);
|
|
7068
7189
|
evaluate2 = (xs, _options) => fn(xs);
|
|
7069
7190
|
Object.defineProperty(evaluate2, "toString", {
|
|
@@ -7914,8 +8035,15 @@ var ComputeEngine = (() => {
|
|
|
7914
8035
|
*
|
|
7915
8036
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7916
8037
|
* (via `fractionalDigits: 'auto'`).
|
|
8038
|
+
*
|
|
8039
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
8040
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
8041
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
8042
|
+
* re-serialization if no verbatim is available.
|
|
7917
8043
|
*/
|
|
7918
8044
|
toLatex(options) {
|
|
8045
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
8046
|
+
return this.verbatimLatex;
|
|
7919
8047
|
if (this.isLazyCollection) {
|
|
7920
8048
|
const materialized = this.evaluate({
|
|
7921
8049
|
materialization: options?.materialization ?? true
|
|
@@ -8373,6 +8501,29 @@ var ComputeEngine = (() => {
|
|
|
8373
8501
|
get isReal() {
|
|
8374
8502
|
return void 0;
|
|
8375
8503
|
}
|
|
8504
|
+
toSignedFunction() {
|
|
8505
|
+
const op = this.operator;
|
|
8506
|
+
if (op === void 0 || this.ops === void 0 || this.ops.length < 2) {
|
|
8507
|
+
return void 0;
|
|
8508
|
+
}
|
|
8509
|
+
const [lhs, rhs] = this.ops;
|
|
8510
|
+
const engine = this.engine;
|
|
8511
|
+
switch (op) {
|
|
8512
|
+
case "Equal":
|
|
8513
|
+
case "NotEqual":
|
|
8514
|
+
case "Less":
|
|
8515
|
+
case "LessEqual":
|
|
8516
|
+
return engine.function("Subtract", [lhs, rhs]);
|
|
8517
|
+
case "Greater":
|
|
8518
|
+
case "GreaterEqual":
|
|
8519
|
+
return engine.function("Subtract", [rhs, lhs]);
|
|
8520
|
+
default:
|
|
8521
|
+
return void 0;
|
|
8522
|
+
}
|
|
8523
|
+
}
|
|
8524
|
+
getInterval(symbol2) {
|
|
8525
|
+
return extractIntervalBounds(this, symbol2);
|
|
8526
|
+
}
|
|
8376
8527
|
simplify(_options) {
|
|
8377
8528
|
return this;
|
|
8378
8529
|
}
|
|
@@ -10058,6 +10209,64 @@ var ComputeEngine = (() => {
|
|
|
10058
10209
|
}
|
|
10059
10210
|
|
|
10060
10211
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
10212
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
10213
|
+
x: "First",
|
|
10214
|
+
y: "Second",
|
|
10215
|
+
z: "Third",
|
|
10216
|
+
real: "Real",
|
|
10217
|
+
re: "Real",
|
|
10218
|
+
imag: "Imaginary",
|
|
10219
|
+
im: "Imaginary",
|
|
10220
|
+
count: "Length",
|
|
10221
|
+
total: "Sum",
|
|
10222
|
+
max: "Max",
|
|
10223
|
+
min: "Min"
|
|
10224
|
+
};
|
|
10225
|
+
function memberHead(name) {
|
|
10226
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10227
|
+
}
|
|
10228
|
+
function parseComponentAccess(parser, lhs) {
|
|
10229
|
+
parser.skipVisualSpace();
|
|
10230
|
+
if (parser.match("\\operatorname")) {
|
|
10231
|
+
const name = parser.parseStringGroup();
|
|
10232
|
+
if (name === null) return null;
|
|
10233
|
+
const head = memberHead(name.trim());
|
|
10234
|
+
if (head === null) return null;
|
|
10235
|
+
return [head, lhs];
|
|
10236
|
+
}
|
|
10237
|
+
const tok = parser.peek;
|
|
10238
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10239
|
+
const bare = tok.slice(1);
|
|
10240
|
+
const head = memberHead(bare);
|
|
10241
|
+
if (head !== null) {
|
|
10242
|
+
parser.nextToken();
|
|
10243
|
+
return [head, lhs];
|
|
10244
|
+
}
|
|
10245
|
+
return null;
|
|
10246
|
+
}
|
|
10247
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10248
|
+
const head = memberHead(tok);
|
|
10249
|
+
if (head === null) return null;
|
|
10250
|
+
parser.nextToken();
|
|
10251
|
+
return [head, lhs];
|
|
10252
|
+
}
|
|
10253
|
+
return null;
|
|
10254
|
+
}
|
|
10255
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10256
|
+
parser.addBoundary(close);
|
|
10257
|
+
parser.skipVisualSpace();
|
|
10258
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10259
|
+
if (cond === null) {
|
|
10260
|
+
parser.removeBoundary();
|
|
10261
|
+
return null;
|
|
10262
|
+
}
|
|
10263
|
+
parser.skipVisualSpace();
|
|
10264
|
+
if (!parser.matchBoundary()) {
|
|
10265
|
+
parser.removeBoundary();
|
|
10266
|
+
return null;
|
|
10267
|
+
}
|
|
10268
|
+
return ["When", lhs, cond];
|
|
10269
|
+
}
|
|
10061
10270
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
10062
10271
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
10063
10272
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10333,15 +10542,16 @@ var ComputeEngine = (() => {
|
|
|
10333
10542
|
precedence: ASSIGNMENT_PRECEDENCE,
|
|
10334
10543
|
parse: parseAssign
|
|
10335
10544
|
},
|
|
10336
|
-
// General colon operator (type annotation, mapping notation)
|
|
10337
|
-
// Precedence below
|
|
10338
|
-
// and below arrows (270) so
|
|
10545
|
+
// General colon operator (type annotation, mapping notation, Desmos piecewise)
|
|
10546
|
+
// Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
|
|
10547
|
+
// parses as `Colon(cond, val)`, and below arrows (270) so
|
|
10548
|
+
// `f: A \to B` parses as `Colon(f, To(A, B))`.
|
|
10339
10549
|
{
|
|
10340
10550
|
name: "Colon",
|
|
10341
10551
|
latexTrigger: ":",
|
|
10342
10552
|
kind: "infix",
|
|
10343
10553
|
associativity: "right",
|
|
10344
|
-
precedence:
|
|
10554
|
+
precedence: 240,
|
|
10345
10555
|
serialize: (serializer, expr2) => joinLatex([
|
|
10346
10556
|
serializer.serialize(operand(expr2, 1)),
|
|
10347
10557
|
"\\colon",
|
|
@@ -10352,7 +10562,7 @@ var ComputeEngine = (() => {
|
|
|
10352
10562
|
latexTrigger: "\\colon",
|
|
10353
10563
|
kind: "infix",
|
|
10354
10564
|
associativity: "right",
|
|
10355
|
-
precedence:
|
|
10565
|
+
precedence: 240,
|
|
10356
10566
|
parse: "Colon"
|
|
10357
10567
|
},
|
|
10358
10568
|
{
|
|
@@ -10529,6 +10739,15 @@ var ComputeEngine = (() => {
|
|
|
10529
10739
|
}
|
|
10530
10740
|
},
|
|
10531
10741
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10742
|
+
// Component-access postfix: expr.member (C3)
|
|
10743
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10744
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10745
|
+
{
|
|
10746
|
+
kind: "postfix",
|
|
10747
|
+
precedence: 850,
|
|
10748
|
+
latexTrigger: ["."],
|
|
10749
|
+
parse: parseComponentAccess
|
|
10750
|
+
},
|
|
10532
10751
|
{
|
|
10533
10752
|
name: "At",
|
|
10534
10753
|
kind: "postfix",
|
|
@@ -10549,6 +10768,29 @@ var ComputeEngine = (() => {
|
|
|
10549
10768
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10550
10769
|
parse: parseAt("\\right", "\\rbrack")
|
|
10551
10770
|
},
|
|
10771
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10772
|
+
{
|
|
10773
|
+
name: "When",
|
|
10774
|
+
kind: "postfix",
|
|
10775
|
+
precedence: 800,
|
|
10776
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10777
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10778
|
+
serialize: (serializer, expr2) => {
|
|
10779
|
+
const e = operand(expr2, 1);
|
|
10780
|
+
const cond = operand(expr2, 2);
|
|
10781
|
+
if (!e || !cond) return "";
|
|
10782
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10783
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10784
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10785
|
+
}
|
|
10786
|
+
},
|
|
10787
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10788
|
+
{
|
|
10789
|
+
kind: "postfix",
|
|
10790
|
+
precedence: 800,
|
|
10791
|
+
latexTrigger: ["\\{"],
|
|
10792
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10793
|
+
},
|
|
10552
10794
|
{
|
|
10553
10795
|
kind: "postfix",
|
|
10554
10796
|
latexTrigger: ["_"],
|
|
@@ -10631,6 +10873,29 @@ var ComputeEngine = (() => {
|
|
|
10631
10873
|
return "";
|
|
10632
10874
|
}
|
|
10633
10875
|
},
|
|
10876
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10877
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10878
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10879
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10880
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10881
|
+
{
|
|
10882
|
+
latexTrigger: [".", ".", "."],
|
|
10883
|
+
kind: "infix",
|
|
10884
|
+
precedence: 800,
|
|
10885
|
+
parse: parseRange
|
|
10886
|
+
},
|
|
10887
|
+
{
|
|
10888
|
+
latexTrigger: ["\\ldots"],
|
|
10889
|
+
kind: "infix",
|
|
10890
|
+
precedence: 800,
|
|
10891
|
+
parse: parseRange
|
|
10892
|
+
},
|
|
10893
|
+
{
|
|
10894
|
+
latexTrigger: ["\\dots"],
|
|
10895
|
+
kind: "infix",
|
|
10896
|
+
precedence: 800,
|
|
10897
|
+
parse: parseRange
|
|
10898
|
+
},
|
|
10634
10899
|
{
|
|
10635
10900
|
latexTrigger: [";"],
|
|
10636
10901
|
kind: "infix",
|
|
@@ -10815,13 +11080,24 @@ var ComputeEngine = (() => {
|
|
|
10815
11080
|
const args = operands(expr2);
|
|
10816
11081
|
if (!args || args.length < 2) return "";
|
|
10817
11082
|
const body = args[0];
|
|
10818
|
-
const
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
11083
|
+
const elements = args.slice(1);
|
|
11084
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
11085
|
+
if (!allElements) {
|
|
11086
|
+
return joinLatex([
|
|
11087
|
+
"\\operatorname{Loop}(",
|
|
11088
|
+
serializer.serialize(body),
|
|
11089
|
+
", ",
|
|
11090
|
+
serializer.serialize(elements[0]),
|
|
11091
|
+
")"
|
|
11092
|
+
]);
|
|
11093
|
+
}
|
|
11094
|
+
if (elements.length === 1) {
|
|
11095
|
+
const elem = elements[0];
|
|
11096
|
+
const index = operand(elem, 1);
|
|
11097
|
+
const coll = operand(elem, 2);
|
|
11098
|
+
if (operator(coll) === "Range") {
|
|
11099
|
+
const lo = operand(coll, 1);
|
|
11100
|
+
const hi = operand(coll, 2);
|
|
10825
11101
|
return joinLatex([
|
|
10826
11102
|
"\\text{for }",
|
|
10827
11103
|
serializer.serialize(index),
|
|
@@ -10833,13 +11109,27 @@ var ComputeEngine = (() => {
|
|
|
10833
11109
|
serializer.serialize(body)
|
|
10834
11110
|
]);
|
|
10835
11111
|
}
|
|
11112
|
+
return joinLatex([
|
|
11113
|
+
serializer.serialize(body),
|
|
11114
|
+
" \\operatorname{for} ",
|
|
11115
|
+
serializer.serialize(index),
|
|
11116
|
+
" = ",
|
|
11117
|
+
serializer.serialize(coll)
|
|
11118
|
+
]);
|
|
10836
11119
|
}
|
|
11120
|
+
const bindings = elements.map((elem) => {
|
|
11121
|
+
const name = operand(elem, 1);
|
|
11122
|
+
const coll = operand(elem, 2);
|
|
11123
|
+
return joinLatex([
|
|
11124
|
+
serializer.serialize(name),
|
|
11125
|
+
" = ",
|
|
11126
|
+
serializer.serialize(coll)
|
|
11127
|
+
]);
|
|
11128
|
+
}).join(", ");
|
|
10837
11129
|
return joinLatex([
|
|
10838
|
-
"\\operatorname{Loop}(",
|
|
10839
11130
|
serializer.serialize(body),
|
|
10840
|
-
"
|
|
10841
|
-
|
|
10842
|
-
")"
|
|
11131
|
+
" \\operatorname{for} ",
|
|
11132
|
+
bindings
|
|
10843
11133
|
]);
|
|
10844
11134
|
}
|
|
10845
11135
|
},
|
|
@@ -10872,6 +11162,18 @@ var ComputeEngine = (() => {
|
|
|
10872
11162
|
precedence: 245,
|
|
10873
11163
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10874
11164
|
},
|
|
11165
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
11166
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
11167
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
11168
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
11169
|
+
// bindings can be comma-separated below us.
|
|
11170
|
+
{
|
|
11171
|
+
symbolTrigger: "for",
|
|
11172
|
+
kind: "infix",
|
|
11173
|
+
associativity: "none",
|
|
11174
|
+
precedence: 19,
|
|
11175
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
11176
|
+
},
|
|
10875
11177
|
// \operatorname{break}
|
|
10876
11178
|
{
|
|
10877
11179
|
symbolTrigger: "break",
|
|
@@ -11076,7 +11378,10 @@ var ComputeEngine = (() => {
|
|
|
11076
11378
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
11077
11379
|
parser.addBoundary([")"]);
|
|
11078
11380
|
const expr2 = parser.parseExpression(until);
|
|
11079
|
-
if (!parser.matchBoundary())
|
|
11381
|
+
if (!parser.matchBoundary()) {
|
|
11382
|
+
parser.removeBoundary();
|
|
11383
|
+
return null;
|
|
11384
|
+
}
|
|
11080
11385
|
if (!parser.match("<}>")) return null;
|
|
11081
11386
|
return ["Derivative", lhs, expr2];
|
|
11082
11387
|
}
|
|
@@ -11517,7 +11822,12 @@ var ComputeEngine = (() => {
|
|
|
11517
11822
|
if (isEmptySequence(body)) return ["List"];
|
|
11518
11823
|
const h = operator(body);
|
|
11519
11824
|
if (h === "Range" || h === "Linspace") return body;
|
|
11520
|
-
if (h === "Sequence")
|
|
11825
|
+
if (h === "Sequence") {
|
|
11826
|
+
const elems = operands(body);
|
|
11827
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11828
|
+
if (inferred) return inferred;
|
|
11829
|
+
return ["List", ...elems];
|
|
11830
|
+
}
|
|
11521
11831
|
if (h === "Delimiter") {
|
|
11522
11832
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11523
11833
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11530,12 +11840,37 @@ var ComputeEngine = (() => {
|
|
|
11530
11840
|
}
|
|
11531
11841
|
if (delim === "," || delim === ".,.") {
|
|
11532
11842
|
body = operand(body, 1);
|
|
11533
|
-
if (operator(body) === "Sequence")
|
|
11843
|
+
if (operator(body) === "Sequence") {
|
|
11844
|
+
const elems = operands(body);
|
|
11845
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11846
|
+
if (inferred) return inferred;
|
|
11847
|
+
return ["List", ...elems];
|
|
11848
|
+
}
|
|
11534
11849
|
return ["List", body ?? "Nothing"];
|
|
11535
11850
|
}
|
|
11536
11851
|
}
|
|
11537
11852
|
return ["List", body];
|
|
11538
11853
|
}
|
|
11854
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11855
|
+
if (elems.length < 4) return null;
|
|
11856
|
+
const penultimate = elems[elems.length - 2];
|
|
11857
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11858
|
+
const samples = elems.slice(0, -2);
|
|
11859
|
+
const endExpr = elems[elems.length - 1];
|
|
11860
|
+
if (samples.length < 2) return null;
|
|
11861
|
+
const sampleNums = samples.map(machineValue);
|
|
11862
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11863
|
+
const nums = sampleNums;
|
|
11864
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11865
|
+
const tol = parser.options.tolerance;
|
|
11866
|
+
if (Math.abs(step) < tol)
|
|
11867
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11868
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11869
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11870
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11871
|
+
}
|
|
11872
|
+
return ["Range", nums[0], endExpr, step];
|
|
11873
|
+
}
|
|
11539
11874
|
function serializeList(serializer, expr2) {
|
|
11540
11875
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11541
11876
|
const op = operator(x);
|
|
@@ -11787,6 +12122,38 @@ var ComputeEngine = (() => {
|
|
|
11787
12122
|
["Element", index, ["Range", lower, upper]]
|
|
11788
12123
|
];
|
|
11789
12124
|
}
|
|
12125
|
+
function parseForComprehension(parser, lhs, until) {
|
|
12126
|
+
const bindingTerminator = {
|
|
12127
|
+
minPrec: 21,
|
|
12128
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
12129
|
+
condition: (p) => {
|
|
12130
|
+
if (until?.condition?.(p)) return true;
|
|
12131
|
+
const saved = p.index;
|
|
12132
|
+
p.skipVisualSpace();
|
|
12133
|
+
const isComma = p.peek === ",";
|
|
12134
|
+
p.index = saved;
|
|
12135
|
+
if (isComma) return true;
|
|
12136
|
+
if (peekKeyword(p, "where")) return true;
|
|
12137
|
+
if (peekKeyword(p, "with")) return true;
|
|
12138
|
+
return false;
|
|
12139
|
+
}
|
|
12140
|
+
};
|
|
12141
|
+
const elements = [];
|
|
12142
|
+
do {
|
|
12143
|
+
parser.skipVisualSpace();
|
|
12144
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
12145
|
+
if (binding === null) break;
|
|
12146
|
+
const op = operator(binding);
|
|
12147
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
12148
|
+
const name = operand(binding, 1);
|
|
12149
|
+
const list = operand(binding, 2);
|
|
12150
|
+
if (!name || !list) return null;
|
|
12151
|
+
elements.push(["Element", name, list]);
|
|
12152
|
+
parser.skipVisualSpace();
|
|
12153
|
+
} while (parser.match(","));
|
|
12154
|
+
if (elements.length === 0) return null;
|
|
12155
|
+
return ["Loop", lhs, ...elements];
|
|
12156
|
+
}
|
|
11790
12157
|
function parseWhereExpression(parser, lhs, until) {
|
|
11791
12158
|
const bindingTerminator = {
|
|
11792
12159
|
minPrec: 21,
|
|
@@ -11809,6 +12176,25 @@ var ComputeEngine = (() => {
|
|
|
11809
12176
|
parser.skipVisualSpace();
|
|
11810
12177
|
} while (parser.match(","));
|
|
11811
12178
|
if (bindings.length === 0) return null;
|
|
12179
|
+
const forStart = parser.index;
|
|
12180
|
+
if (matchKeyword(parser, "for")) {
|
|
12181
|
+
const loop = parseForComprehension(parser, lhs, until);
|
|
12182
|
+
if (loop) {
|
|
12183
|
+
const block2 = [];
|
|
12184
|
+
for (const b of bindings) {
|
|
12185
|
+
const normalized = normalizeLocalAssign(b);
|
|
12186
|
+
if (operator(normalized) === "Assign") {
|
|
12187
|
+
block2.push(["Declare", operand(normalized, 1)]);
|
|
12188
|
+
block2.push(normalized);
|
|
12189
|
+
} else {
|
|
12190
|
+
block2.push(normalized);
|
|
12191
|
+
}
|
|
12192
|
+
}
|
|
12193
|
+
block2.push(loop);
|
|
12194
|
+
return ["Block", ...block2];
|
|
12195
|
+
}
|
|
12196
|
+
parser.index = forStart;
|
|
12197
|
+
}
|
|
11812
12198
|
const block = [];
|
|
11813
12199
|
for (const b of bindings) {
|
|
11814
12200
|
const normalized = normalizeLocalAssign(b);
|
|
@@ -12022,6 +12408,17 @@ var ComputeEngine = (() => {
|
|
|
12022
12408
|
const upperExpr = openRight ? ["Open", upper] : upper;
|
|
12023
12409
|
return ["Interval", lowerExpr, upperExpr];
|
|
12024
12410
|
}
|
|
12411
|
+
var COMPARISON_HEADS = /* @__PURE__ */ new Set([
|
|
12412
|
+
"Less",
|
|
12413
|
+
"LessEqual",
|
|
12414
|
+
"Greater",
|
|
12415
|
+
"GreaterEqual",
|
|
12416
|
+
"Equal",
|
|
12417
|
+
"NotEqual",
|
|
12418
|
+
"And",
|
|
12419
|
+
"Or",
|
|
12420
|
+
"Not"
|
|
12421
|
+
]);
|
|
12025
12422
|
var DEFINITIONS_SETS = [
|
|
12026
12423
|
//
|
|
12027
12424
|
// Constants
|
|
@@ -12280,18 +12677,58 @@ var ComputeEngine = (() => {
|
|
|
12280
12677
|
closeTrigger: "}",
|
|
12281
12678
|
parse: (_parser, body) => {
|
|
12282
12679
|
if (isEmptySequence(body)) return "EmptySet";
|
|
12680
|
+
if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
|
|
12681
|
+
body = operand(body, 1);
|
|
12682
|
+
}
|
|
12283
12683
|
const h = operator(body);
|
|
12284
|
-
if (h === "Divides"
|
|
12684
|
+
if (h === "Divides") {
|
|
12285
12685
|
const expr2 = operand(body, 1);
|
|
12286
12686
|
const condition = operand(body, 2);
|
|
12287
12687
|
if (expr2 !== null && condition !== null)
|
|
12288
12688
|
return ["Set", expr2, ["Condition", condition]];
|
|
12289
12689
|
}
|
|
12290
|
-
if (
|
|
12291
|
-
|
|
12690
|
+
if (h === "Colon") {
|
|
12691
|
+
const lhs = operand(body, 1);
|
|
12692
|
+
const rhs = operand(body, 2);
|
|
12693
|
+
if (lhs !== null && rhs !== null) {
|
|
12694
|
+
const lhsOp = operator(lhs);
|
|
12695
|
+
if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
|
|
12696
|
+
return ["Which", lhs, rhs];
|
|
12697
|
+
}
|
|
12698
|
+
return ["Set", lhs, ["Condition", rhs]];
|
|
12699
|
+
}
|
|
12292
12700
|
}
|
|
12293
|
-
if (
|
|
12294
|
-
|
|
12701
|
+
if (h === "Sequence") {
|
|
12702
|
+
const elements = operands(body);
|
|
12703
|
+
const colonElements = elements.filter((el) => operator(el) === "Colon");
|
|
12704
|
+
const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
|
|
12705
|
+
const lhs = operand(el, 1);
|
|
12706
|
+
const lhsOp = lhs !== null ? operator(lhs) : null;
|
|
12707
|
+
return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
|
|
12708
|
+
});
|
|
12709
|
+
if (allPiecewise) {
|
|
12710
|
+
const whichOps = [];
|
|
12711
|
+
for (let i = 0; i < elements.length; i++) {
|
|
12712
|
+
const el = elements[i];
|
|
12713
|
+
if (operator(el) === "Colon") {
|
|
12714
|
+
const cond = operand(el, 1);
|
|
12715
|
+
const val = operand(el, 2);
|
|
12716
|
+
if (cond === null || val === null) {
|
|
12717
|
+
return ["Set", ...elements];
|
|
12718
|
+
}
|
|
12719
|
+
whichOps.push(cond, val);
|
|
12720
|
+
} else {
|
|
12721
|
+
if (i !== elements.length - 1) {
|
|
12722
|
+
return ["Set", ...elements];
|
|
12723
|
+
}
|
|
12724
|
+
whichOps.push("True", el);
|
|
12725
|
+
}
|
|
12726
|
+
}
|
|
12727
|
+
return ["Which", ...whichOps];
|
|
12728
|
+
}
|
|
12729
|
+
return ["Set", ...elements];
|
|
12730
|
+
}
|
|
12731
|
+
return ["Set", body];
|
|
12295
12732
|
},
|
|
12296
12733
|
serialize: (serializer, expr2) => {
|
|
12297
12734
|
if (nops(expr2) === 2 && operator(operand(expr2, 2)) === "Condition") {
|
|
@@ -14295,7 +14732,8 @@ var ComputeEngine = (() => {
|
|
|
14295
14732
|
minPrec: MULTIPLICATION_PRECEDENCE,
|
|
14296
14733
|
condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
|
|
14297
14734
|
});
|
|
14298
|
-
const
|
|
14735
|
+
const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
|
|
14736
|
+
const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
|
|
14299
14737
|
return sup === null ? appliedFn : ["Power", appliedFn, sup];
|
|
14300
14738
|
};
|
|
14301
14739
|
}
|
|
@@ -16511,10 +16949,17 @@ var ComputeEngine = (() => {
|
|
|
16511
16949
|
// The capitalized library entries already exist; these are pure parse
|
|
16512
16950
|
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16513
16951
|
// ---------------------------------------------------------------------------
|
|
16952
|
+
{ latexTrigger: "\\operatorname{count}", parse: "Length" },
|
|
16514
16953
|
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16515
16954
|
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16516
16955
|
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16517
16956
|
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16957
|
+
{ latexTrigger: "\\operatorname{range}", parse: "Range" },
|
|
16958
|
+
// Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
|
|
16959
|
+
// NOT registered here. Use the math-notation equivalent `\operatorname{where}`
|
|
16960
|
+
// (with `\coloneq` for bindings), or register `with` as a custom dictionary
|
|
16961
|
+
// entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
|
|
16962
|
+
// Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
|
|
16518
16963
|
// ---------------------------------------------------------------------------
|
|
16519
16964
|
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16520
16965
|
// can branch on the operator name; CE itself doesn't render them. The
|
|
@@ -19558,6 +20003,19 @@ var ComputeEngine = (() => {
|
|
|
19558
20003
|
} while (postfix !== null);
|
|
19559
20004
|
}
|
|
19560
20005
|
if (result !== null) result = this.parseSupsub(result);
|
|
20006
|
+
if (result !== null) {
|
|
20007
|
+
let postfix = null;
|
|
20008
|
+
let index = this.index;
|
|
20009
|
+
do {
|
|
20010
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
20011
|
+
result = postfix ?? result;
|
|
20012
|
+
if (this.index === index && postfix !== null) {
|
|
20013
|
+
console.assert(this.index !== index, "No token consumed");
|
|
20014
|
+
break;
|
|
20015
|
+
}
|
|
20016
|
+
index = this.index;
|
|
20017
|
+
} while (postfix !== null);
|
|
20018
|
+
}
|
|
19561
20019
|
if (result === null) {
|
|
19562
20020
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19563
20021
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -20066,6 +20524,28 @@ var ComputeEngine = (() => {
|
|
|
20066
20524
|
}
|
|
20067
20525
|
|
|
20068
20526
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20527
|
+
var DOT_NOTATION_MAP = {
|
|
20528
|
+
First: ".x",
|
|
20529
|
+
Second: ".y",
|
|
20530
|
+
Third: ".z",
|
|
20531
|
+
Real: ".\\operatorname{real}",
|
|
20532
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20533
|
+
Length: ".\\operatorname{count}",
|
|
20534
|
+
Sum: ".\\operatorname{total}",
|
|
20535
|
+
Max: ".\\max",
|
|
20536
|
+
Min: ".\\min"
|
|
20537
|
+
};
|
|
20538
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20539
|
+
if (!serializer.options.dotNotation) return null;
|
|
20540
|
+
const ops = operands(expr2);
|
|
20541
|
+
if (!ops || ops.length !== 1) return null;
|
|
20542
|
+
const head = operator(expr2);
|
|
20543
|
+
if (!head) return null;
|
|
20544
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20545
|
+
if (suffix === void 0) return null;
|
|
20546
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20547
|
+
return `${lhs}${suffix}`;
|
|
20548
|
+
}
|
|
20069
20549
|
var ACCENT_MODIFIERS = {
|
|
20070
20550
|
deg: (s) => `${s}\\degree`,
|
|
20071
20551
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -20109,6 +20589,7 @@ var ComputeEngine = (() => {
|
|
|
20109
20589
|
constructor(dictionary, options) {
|
|
20110
20590
|
this.dictionary = dictionary;
|
|
20111
20591
|
this.options = {
|
|
20592
|
+
dotNotation: false,
|
|
20112
20593
|
dmsFormat: false,
|
|
20113
20594
|
angleNormalization: "none",
|
|
20114
20595
|
...options
|
|
@@ -20207,6 +20688,8 @@ var ComputeEngine = (() => {
|
|
|
20207
20688
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
20208
20689
|
}
|
|
20209
20690
|
serializeFunction(expr2, def) {
|
|
20691
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20692
|
+
if (dotResult !== null) return dotResult;
|
|
20210
20693
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
20211
20694
|
const h = operator(expr2);
|
|
20212
20695
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20449,6 +20932,8 @@ var ComputeEngine = (() => {
|
|
|
20449
20932
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20450
20933
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20451
20934
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20935
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20936
|
+
tolerance: 1e-7,
|
|
20452
20937
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20453
20938
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20454
20939
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20481,6 +20966,7 @@ var ComputeEngine = (() => {
|
|
|
20481
20966
|
invisiblePlus: "",
|
|
20482
20967
|
multiply: "\\times",
|
|
20483
20968
|
missingSymbol: "\\blacksquare",
|
|
20969
|
+
dotNotation: false,
|
|
20484
20970
|
dmsFormat: false,
|
|
20485
20971
|
angleNormalization: "none",
|
|
20486
20972
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -22315,6 +22801,15 @@ var ComputeEngine = (() => {
|
|
|
22315
22801
|
}
|
|
22316
22802
|
} else {
|
|
22317
22803
|
for (const item of t) {
|
|
22804
|
+
const op = item.operator;
|
|
22805
|
+
if (op === "Tuple" || op === "Pair" || op === "Single" || op === "Triple" || op === "Quadruple" || op === "KeyValuePair" || op === "Dictionary" || op === "Set" || op === "Record") {
|
|
22806
|
+
valid = false;
|
|
22807
|
+
return;
|
|
22808
|
+
}
|
|
22809
|
+
if (item.type.type === "string") {
|
|
22810
|
+
valid = false;
|
|
22811
|
+
return;
|
|
22812
|
+
}
|
|
22318
22813
|
dtype = getSupertype(dtype, getExpressionDatatype(item));
|
|
22319
22814
|
}
|
|
22320
22815
|
}
|
|
@@ -27350,6 +27845,15 @@ ${lines.join("\n")}`;
|
|
|
27350
27845
|
return void 0;
|
|
27351
27846
|
}
|
|
27352
27847
|
|
|
27848
|
+
// src/compute-engine/numerics/random.ts
|
|
27849
|
+
function deterministicRandom(seed) {
|
|
27850
|
+
const v = Math.sin(seed * 12.9898) * 43758.5453;
|
|
27851
|
+
return v - Math.floor(v);
|
|
27852
|
+
}
|
|
27853
|
+
function nextSeed(seed) {
|
|
27854
|
+
return seed + 0.6180339887498949;
|
|
27855
|
+
}
|
|
27856
|
+
|
|
27353
27857
|
// src/compute-engine/boxed-expression/canonical-utils.ts
|
|
27354
27858
|
function canonical(ce, xs, scope) {
|
|
27355
27859
|
if (xs.every((x) => x.isCanonical)) return xs;
|
|
@@ -27399,6 +27903,19 @@ ${lines.join("\n")}`;
|
|
|
27399
27903
|
indexWhere: void 0
|
|
27400
27904
|
}
|
|
27401
27905
|
},
|
|
27906
|
+
Length: {
|
|
27907
|
+
description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
|
|
27908
|
+
complexity: 4e3,
|
|
27909
|
+
signature: "(any) -> integer",
|
|
27910
|
+
type: () => "integer",
|
|
27911
|
+
evaluate: ([xs], { engine }) => {
|
|
27912
|
+
if (!xs.isCollection) return void 0;
|
|
27913
|
+
if (xs.isEmptyCollection) return engine.Zero;
|
|
27914
|
+
const n = xs.count;
|
|
27915
|
+
if (n === void 0 || !isFinite(n)) return void 0;
|
|
27916
|
+
return engine.number(n);
|
|
27917
|
+
}
|
|
27918
|
+
},
|
|
27402
27919
|
Tuple: {
|
|
27403
27920
|
description: "A fixed number of heterogeneous elements",
|
|
27404
27921
|
complexity: 8200,
|
|
@@ -27451,7 +27968,11 @@ ${lines.join("\n")}`;
|
|
|
27451
27968
|
//
|
|
27452
27969
|
Range: {
|
|
27453
27970
|
complexity: 8200,
|
|
27454
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27971
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27972
|
+
type: (ops) => {
|
|
27973
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27974
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27975
|
+
},
|
|
27455
27976
|
canonical: (ops, { engine: ce }) => {
|
|
27456
27977
|
if (ops.length === 0) return null;
|
|
27457
27978
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27475,19 +27996,26 @@ ${lines.join("\n")}`;
|
|
|
27475
27996
|
const [lower, upper, step] = range(expr2);
|
|
27476
27997
|
if (step === 0) return 0;
|
|
27477
27998
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27478
|
-
return
|
|
27999
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27479
28000
|
},
|
|
27480
28001
|
contains: (expr2, target) => {
|
|
27481
|
-
if (!target.type.matches("integer")) return false;
|
|
27482
28002
|
const t = target.re;
|
|
28003
|
+
if (!isFinite(t)) return false;
|
|
27483
28004
|
const [lower, upper, step] = range(expr2);
|
|
27484
28005
|
if (step === 0) return false;
|
|
27485
|
-
if (step > 0)
|
|
27486
|
-
|
|
28006
|
+
if (step > 0) {
|
|
28007
|
+
if (t < lower || t > upper) return false;
|
|
28008
|
+
} else {
|
|
28009
|
+
if (t > lower || t < upper) return false;
|
|
28010
|
+
}
|
|
28011
|
+
const k = (t - lower) / step;
|
|
28012
|
+
const tol = expr2.engine.tolerance;
|
|
28013
|
+
const kRounded = Math.round(k);
|
|
28014
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27487
28015
|
},
|
|
27488
28016
|
iterator: (expr2) => {
|
|
27489
28017
|
const [lower, upper, step] = range(expr2);
|
|
27490
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
28018
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27491
28019
|
let index = 1;
|
|
27492
28020
|
return {
|
|
27493
28021
|
next: () => {
|
|
@@ -27505,7 +28033,9 @@ ${lines.join("\n")}`;
|
|
|
27505
28033
|
at: (expr2, index) => {
|
|
27506
28034
|
if (typeof index !== "number") return void 0;
|
|
27507
28035
|
const [lower, upper, step] = range(expr2);
|
|
27508
|
-
if (
|
|
28036
|
+
if (step === 0) return void 0;
|
|
28037
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
28038
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27509
28039
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27510
28040
|
},
|
|
27511
28041
|
indexWhere: void 0,
|
|
@@ -27530,7 +28060,13 @@ ${lines.join("\n")}`;
|
|
|
27530
28060
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27531
28061
|
return lower >= upper ? "positive" : "negative";
|
|
27532
28062
|
},
|
|
27533
|
-
elttype: (
|
|
28063
|
+
elttype: (expr2) => {
|
|
28064
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
28065
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
28066
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
28067
|
+
}
|
|
28068
|
+
return "finite_integer";
|
|
28069
|
+
}
|
|
27534
28070
|
}
|
|
27535
28071
|
},
|
|
27536
28072
|
Interval: {
|
|
@@ -27633,10 +28169,12 @@ ${lines.join("\n")}`;
|
|
|
27633
28169
|
const upper = expr2.op2.re;
|
|
27634
28170
|
let count = expr2.op3.re;
|
|
27635
28171
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28172
|
+
count = Math.floor(count);
|
|
27636
28173
|
if (!isFinite(lower) || !isFinite(upper)) return void 0;
|
|
27637
28174
|
if (index < 1 || index > count) return void 0;
|
|
28175
|
+
if (count === 1) return expr2.engine.number(lower);
|
|
27638
28176
|
return expr2.engine.number(
|
|
27639
|
-
lower + (upper - lower) * (index - 1) / count
|
|
28177
|
+
lower + (upper - lower) * (index - 1) / (count - 1)
|
|
27640
28178
|
);
|
|
27641
28179
|
},
|
|
27642
28180
|
iterator: (expr2) => {
|
|
@@ -27655,6 +28193,8 @@ ${lines.join("\n")}`;
|
|
|
27655
28193
|
!isFinite(expr2.op3.re) ? DEFAULT_LINSPACE_COUNT : expr2.op3.re
|
|
27656
28194
|
);
|
|
27657
28195
|
}
|
|
28196
|
+
totalCount = Math.floor(totalCount);
|
|
28197
|
+
const denom = totalCount > 1 ? totalCount - 1 : 1;
|
|
27658
28198
|
let index = 1;
|
|
27659
28199
|
return {
|
|
27660
28200
|
next: () => {
|
|
@@ -27663,7 +28203,7 @@ ${lines.join("\n")}`;
|
|
|
27663
28203
|
index += 1;
|
|
27664
28204
|
return {
|
|
27665
28205
|
value: expr2.engine.number(
|
|
27666
|
-
lower + (upper - lower) * (index - 1 - 1) /
|
|
28206
|
+
lower + (upper - lower) * (index - 1 - 1) / denom
|
|
27667
28207
|
),
|
|
27668
28208
|
done: false
|
|
27669
28209
|
};
|
|
@@ -27679,9 +28219,14 @@ ${lines.join("\n")}`;
|
|
|
27679
28219
|
if (t < lower || t > upper) return false;
|
|
27680
28220
|
let count = expr2.op3.re;
|
|
27681
28221
|
if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
|
|
28222
|
+
count = Math.floor(count);
|
|
27682
28223
|
if (count === 0) return false;
|
|
27683
|
-
|
|
27684
|
-
|
|
28224
|
+
if (count === 1) return t === lower;
|
|
28225
|
+
const step = (upper - lower) / (count - 1);
|
|
28226
|
+
const k = (t - lower) / step;
|
|
28227
|
+
const tol = expr2.engine.tolerance;
|
|
28228
|
+
const kRounded = Math.round(k);
|
|
28229
|
+
return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
|
|
27685
28230
|
}
|
|
27686
28231
|
}
|
|
27687
28232
|
},
|
|
@@ -28006,10 +28551,12 @@ ${lines.join("\n")}`;
|
|
|
28006
28551
|
description: [
|
|
28007
28552
|
"Access an element of an indexed collection.",
|
|
28008
28553
|
"If the index is negative, it is counted from the end.",
|
|
28009
|
-
"Multiple indices can be provided to access nested collections (e.g., matrices)."
|
|
28554
|
+
"Multiple indices can be provided to access nested collections (e.g., matrices).",
|
|
28555
|
+
"If the index is a finite collection of booleans, returns the elements where the mask is True.",
|
|
28556
|
+
"If the index is a finite collection of integers, returns the elements at those indices."
|
|
28010
28557
|
],
|
|
28011
28558
|
complexity: 8200,
|
|
28012
|
-
signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
|
|
28559
|
+
signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
|
|
28013
28560
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
|
|
28014
28561
|
evaluate: (ops, { engine: ce }) => {
|
|
28015
28562
|
let expr2 = ops[0];
|
|
@@ -28020,12 +28567,39 @@ ${lines.join("\n")}`;
|
|
|
28020
28567
|
if (!at) return void 0;
|
|
28021
28568
|
const opAtIndex = ops[index];
|
|
28022
28569
|
const s = isString(opAtIndex) ? opAtIndex.string : void 0;
|
|
28023
|
-
if (s !== void 0)
|
|
28024
|
-
|
|
28025
|
-
|
|
28026
|
-
|
|
28027
|
-
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
28570
|
+
if (s !== void 0) {
|
|
28571
|
+
expr2 = at(expr2, s) ?? ce.Nothing;
|
|
28572
|
+
index += 1;
|
|
28573
|
+
continue;
|
|
28028
28574
|
}
|
|
28575
|
+
if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
|
|
28576
|
+
const indices = Array.from(opAtIndex.each());
|
|
28577
|
+
const isMask = indices.every((m) => {
|
|
28578
|
+
const name = sym(m);
|
|
28579
|
+
return name === "True" || name === "False";
|
|
28580
|
+
});
|
|
28581
|
+
const picked = [];
|
|
28582
|
+
if (isMask) {
|
|
28583
|
+
indices.forEach((m, i2) => {
|
|
28584
|
+
if (sym(m) !== "True") return;
|
|
28585
|
+
const v = at(expr2, i2 + 1);
|
|
28586
|
+
if (v !== void 0) picked.push(v);
|
|
28587
|
+
});
|
|
28588
|
+
} else {
|
|
28589
|
+
for (const m of indices) {
|
|
28590
|
+
const k = m.re;
|
|
28591
|
+
if (!Number.isInteger(k)) return void 0;
|
|
28592
|
+
const v = at(expr2, k);
|
|
28593
|
+
if (v !== void 0) picked.push(v);
|
|
28594
|
+
}
|
|
28595
|
+
}
|
|
28596
|
+
expr2 = ce._fn("List", picked);
|
|
28597
|
+
index += 1;
|
|
28598
|
+
continue;
|
|
28599
|
+
}
|
|
28600
|
+
const i = opAtIndex.re;
|
|
28601
|
+
if (!Number.isInteger(i)) return void 0;
|
|
28602
|
+
expr2 = at(expr2, i) ?? ce.Nothing;
|
|
28029
28603
|
index += 1;
|
|
28030
28604
|
}
|
|
28031
28605
|
return expr2;
|
|
@@ -28036,7 +28610,7 @@ ${lines.join("\n")}`;
|
|
|
28036
28610
|
description: ["Return `n` elements from a collection."],
|
|
28037
28611
|
complexity: 8200,
|
|
28038
28612
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
28039
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
28613
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28040
28614
|
evaluate: (ops, { engine, materialization: eager }) => {
|
|
28041
28615
|
if (!eager) return void 0;
|
|
28042
28616
|
const takeExpr = engine._fn("Take", ops);
|
|
@@ -28083,7 +28657,7 @@ ${lines.join("\n")}`;
|
|
|
28083
28657
|
description: ["Return the collection without the first n elements."],
|
|
28084
28658
|
complexity: 8200,
|
|
28085
28659
|
signature: "(xs: indexed_collection, count: number) -> indexed_collection",
|
|
28086
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
28660
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28087
28661
|
collection: {
|
|
28088
28662
|
isLazy: (_expr) => true,
|
|
28089
28663
|
count: (expr2) => {
|
|
@@ -28128,15 +28702,45 @@ ${lines.join("\n")}`;
|
|
|
28128
28702
|
},
|
|
28129
28703
|
First: {
|
|
28130
28704
|
complexity: 8200,
|
|
28131
|
-
signature: "(
|
|
28705
|
+
signature: "(any) -> any",
|
|
28132
28706
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28133
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28707
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28708
|
+
if (!xs.isCollection)
|
|
28709
|
+
return ce.error([
|
|
28710
|
+
"incompatible-type",
|
|
28711
|
+
`'collection'`,
|
|
28712
|
+
xs.type.toString()
|
|
28713
|
+
]);
|
|
28714
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28715
|
+
}
|
|
28134
28716
|
},
|
|
28135
28717
|
Second: {
|
|
28136
28718
|
complexity: 8200,
|
|
28137
|
-
signature: "(
|
|
28719
|
+
signature: "(any) -> any",
|
|
28138
28720
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28139
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28721
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28722
|
+
if (!xs.isCollection)
|
|
28723
|
+
return ce.error([
|
|
28724
|
+
"incompatible-type",
|
|
28725
|
+
`'collection'`,
|
|
28726
|
+
xs.type.toString()
|
|
28727
|
+
]);
|
|
28728
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28729
|
+
}
|
|
28730
|
+
},
|
|
28731
|
+
Third: {
|
|
28732
|
+
complexity: 8200,
|
|
28733
|
+
signature: "(any) -> any",
|
|
28734
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28735
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28736
|
+
if (!xs.isCollection)
|
|
28737
|
+
return ce.error([
|
|
28738
|
+
"incompatible-type",
|
|
28739
|
+
`'collection'`,
|
|
28740
|
+
xs.type.toString()
|
|
28741
|
+
]);
|
|
28742
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28743
|
+
}
|
|
28140
28744
|
},
|
|
28141
28745
|
Last: {
|
|
28142
28746
|
complexity: 8200,
|
|
@@ -28249,7 +28853,9 @@ ${lines.join("\n")}`;
|
|
|
28249
28853
|
],
|
|
28250
28854
|
complexity: 8200,
|
|
28251
28855
|
signature: "(value: indexed_collection, start: number, end: number) -> list",
|
|
28252
|
-
type: ([xs]) => parseType(
|
|
28856
|
+
type: ([xs]) => parseType(
|
|
28857
|
+
`list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
|
|
28858
|
+
),
|
|
28253
28859
|
collection: {
|
|
28254
28860
|
isLazy: (_expr) => true,
|
|
28255
28861
|
count: (expr2) => {
|
|
@@ -28581,16 +29187,26 @@ ${lines.join("\n")}`;
|
|
|
28581
29187
|
},
|
|
28582
29188
|
// Randomize the order of the elements in the collection.
|
|
28583
29189
|
Shuffle: {
|
|
28584
|
-
description: "Randomize the order of the elements in the collection.",
|
|
29190
|
+
description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
|
|
28585
29191
|
complexity: 8200,
|
|
28586
|
-
signature: "(indexed_collection) -> indexed_collection",
|
|
29192
|
+
signature: "(indexed_collection, real?) -> indexed_collection",
|
|
28587
29193
|
type: (ops) => ops[0].type,
|
|
28588
|
-
evaluate: ([xs], { engine: ce }) => {
|
|
29194
|
+
evaluate: ([xs, seedOp], { engine: ce }) => {
|
|
28589
29195
|
if (!xs.isFiniteCollection) return void 0;
|
|
28590
29196
|
const data = Array.from(xs.each());
|
|
28591
|
-
|
|
28592
|
-
|
|
28593
|
-
|
|
29197
|
+
const seed = seedOp?.re;
|
|
29198
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
29199
|
+
let s = seed;
|
|
29200
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29201
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
29202
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29203
|
+
s = nextSeed(s);
|
|
29204
|
+
}
|
|
29205
|
+
} else {
|
|
29206
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
29207
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
29208
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
29209
|
+
}
|
|
28594
29210
|
}
|
|
28595
29211
|
return ce.function(xs.operator, data);
|
|
28596
29212
|
}
|
|
@@ -28657,7 +29273,9 @@ ${lines.join("\n")}`;
|
|
|
28657
29273
|
if (t === "string")
|
|
28658
29274
|
return parseType(`tuple<list<string>, list<integer>>`);
|
|
28659
29275
|
return parseType(
|
|
28660
|
-
`tuple<list<${
|
|
29276
|
+
`tuple<list<${typeToString(
|
|
29277
|
+
collectionElementType(t) ?? "any"
|
|
29278
|
+
)}>, list<integer>>`
|
|
28661
29279
|
);
|
|
28662
29280
|
},
|
|
28663
29281
|
evaluate: (ops, { engine: ce }) => {
|
|
@@ -28673,7 +29291,7 @@ ${lines.join("\n")}`;
|
|
|
28673
29291
|
description: "Return a list of the unique elements of the collection.",
|
|
28674
29292
|
complexity: 8200,
|
|
28675
29293
|
signature: "(collection) -> list",
|
|
28676
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29294
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28677
29295
|
evaluate: (ops, { engine: ce }) => {
|
|
28678
29296
|
if (!ops[0].isFiniteCollection) return void 0;
|
|
28679
29297
|
const [values, _counts] = tally(ops[0]);
|
|
@@ -28685,7 +29303,7 @@ ${lines.join("\n")}`;
|
|
|
28685
29303
|
wikidata: "Q381060",
|
|
28686
29304
|
complexity: 8200,
|
|
28687
29305
|
signature: "(collection, integer | function) -> list",
|
|
28688
|
-
type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
|
|
29306
|
+
type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
|
|
28689
29307
|
evaluate: ([xs, arg], { engine: ce }) => {
|
|
28690
29308
|
if (!xs.isFiniteCollection) return void 0;
|
|
28691
29309
|
const k = toInteger(arg);
|
|
@@ -28859,32 +29477,74 @@ ${lines.join("\n")}`;
|
|
|
28859
29477
|
}
|
|
28860
29478
|
}
|
|
28861
29479
|
},
|
|
28862
|
-
// Repeat(x) -> [x, x, ...]
|
|
28863
|
-
//
|
|
28864
|
-
// x is evaluated once. Although could use Hold()?
|
|
28865
|
-
// So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
|
|
29480
|
+
// Repeat(x) -> [x, x, ...] — infinite sequence
|
|
29481
|
+
// Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
|
|
28866
29482
|
Repeat: {
|
|
28867
|
-
description: "Produce
|
|
29483
|
+
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.",
|
|
28868
29484
|
complexity: 8200,
|
|
28869
|
-
signature: "(value: any) -> list",
|
|
29485
|
+
signature: "(value: any, count: integer?) -> list",
|
|
29486
|
+
evaluate: (ops, { engine }) => {
|
|
29487
|
+
if (ops.length !== 2) return void 0;
|
|
29488
|
+
const raw = toInteger(ops[1]);
|
|
29489
|
+
if (raw === null) return void 0;
|
|
29490
|
+
const n = Math.max(0, raw);
|
|
29491
|
+
if (n > engine.maxCollectionSize) return void 0;
|
|
29492
|
+
return engine._fn("List", Array(n).fill(ops[0]));
|
|
29493
|
+
},
|
|
28870
29494
|
collection: {
|
|
28871
|
-
isLazy: (
|
|
28872
|
-
count: () =>
|
|
28873
|
-
|
|
28874
|
-
|
|
28875
|
-
|
|
28876
|
-
|
|
29495
|
+
isLazy: (expr2) => isFunction2(expr2) && expr2.ops?.length === 1,
|
|
29496
|
+
count: (expr2) => {
|
|
29497
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29498
|
+
if (expr2.ops?.length === 2) {
|
|
29499
|
+
const n = toInteger(expr2.op2);
|
|
29500
|
+
return n !== null ? Math.max(0, n) : void 0;
|
|
29501
|
+
}
|
|
29502
|
+
return Infinity;
|
|
29503
|
+
},
|
|
29504
|
+
isEmpty: (expr2) => {
|
|
29505
|
+
if (!isFunction2(expr2)) return void 0;
|
|
29506
|
+
if (expr2.ops?.length === 2) {
|
|
29507
|
+
const n = toInteger(expr2.op2);
|
|
29508
|
+
return n !== null ? n <= 0 : void 0;
|
|
29509
|
+
}
|
|
29510
|
+
return false;
|
|
29511
|
+
},
|
|
29512
|
+
isFinite: (expr2) => isFunction2(expr2) && expr2.ops?.length === 2,
|
|
28877
29513
|
contains: (expr2, target) => {
|
|
28878
29514
|
if (!isFunction2(expr2)) return false;
|
|
29515
|
+
if (expr2.ops?.length === 2) {
|
|
29516
|
+
const n = toInteger(expr2.op2);
|
|
29517
|
+
if (n !== null && n <= 0) return false;
|
|
29518
|
+
}
|
|
28879
29519
|
return expr2.op1.isSame(target);
|
|
28880
29520
|
},
|
|
28881
29521
|
iterator: (expr2) => {
|
|
28882
29522
|
if (!isFunction2(expr2))
|
|
28883
29523
|
return { next: () => ({ value: void 0, done: true }) };
|
|
29524
|
+
if (expr2.ops?.length === 2) {
|
|
29525
|
+
const n = toInteger(expr2.op2);
|
|
29526
|
+
if (n === null) {
|
|
29527
|
+
return { next: () => ({ value: void 0, done: true }) };
|
|
29528
|
+
}
|
|
29529
|
+
const count = Math.max(0, n);
|
|
29530
|
+
let i = 0;
|
|
29531
|
+
return {
|
|
29532
|
+
next: () => i++ < count ? { value: expr2.op1, done: false } : { value: void 0, done: true }
|
|
29533
|
+
};
|
|
29534
|
+
}
|
|
28884
29535
|
return { next: () => ({ value: expr2.op1, done: false }) };
|
|
28885
29536
|
},
|
|
28886
|
-
at
|
|
29537
|
+
// at is 1-based (consistent with Range, Take, and other collection handlers)
|
|
29538
|
+
at: (expr2, index) => {
|
|
28887
29539
|
if (!isFunction2(expr2)) return void 0;
|
|
29540
|
+
if (typeof index !== "number") return void 0;
|
|
29541
|
+
if (expr2.ops?.length === 2) {
|
|
29542
|
+
const n = toInteger(expr2.op2);
|
|
29543
|
+
const count = n !== null ? Math.max(0, n) : 0;
|
|
29544
|
+
if (index < 1 || index > count) return void 0;
|
|
29545
|
+
} else {
|
|
29546
|
+
if (index < 1) return void 0;
|
|
29547
|
+
}
|
|
28888
29548
|
return expr2.op1;
|
|
28889
29549
|
}
|
|
28890
29550
|
}
|
|
@@ -29115,17 +29775,14 @@ ${lines.join("\n")}`;
|
|
|
29115
29775
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
29116
29776
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
29117
29777
|
let op1 = expr2.op1.re;
|
|
29118
|
-
if (!isFinite(op1)) op1 = 1;
|
|
29119
|
-
else op1 = Math.round(op1);
|
|
29778
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
29120
29779
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
29121
29780
|
let op2 = expr2.op2.re;
|
|
29122
29781
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
29123
|
-
|
|
29124
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29782
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
29125
29783
|
let op3 = expr2.op3.re;
|
|
29126
|
-
if (!isFinite(op3)) op3 = 1;
|
|
29127
|
-
|
|
29128
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29784
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29785
|
+
return [op1, op2, op3];
|
|
29129
29786
|
}
|
|
29130
29787
|
function rangeLast(r) {
|
|
29131
29788
|
const [lower, upper, step] = r;
|
|
@@ -31173,11 +31830,12 @@ ${lines.join("\n")}`;
|
|
|
31173
31830
|
);
|
|
31174
31831
|
}
|
|
31175
31832
|
},
|
|
31176
|
-
|
|
31177
|
-
|
|
31178
|
-
|
|
31179
|
-
|
|
31180
|
-
|
|
31833
|
+
Complex: {
|
|
31834
|
+
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.',
|
|
31835
|
+
wikidata: "Q11567",
|
|
31836
|
+
complexity: 500,
|
|
31837
|
+
signature: "(real: number, imaginary: number) -> complex"
|
|
31838
|
+
},
|
|
31181
31839
|
Divide: {
|
|
31182
31840
|
description: "Quotient of a numerator and one or more denominators.",
|
|
31183
31841
|
wikidata: "Q1226939",
|
|
@@ -32527,48 +33185,83 @@ ${lines.join("\n")}`;
|
|
|
32527
33185
|
}
|
|
32528
33186
|
},
|
|
32529
33187
|
Sum: {
|
|
32530
|
-
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`",
|
|
33188
|
+
description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`; `Sum(L)` sums the elements of a collection `L`",
|
|
32531
33189
|
wikidata: "Q218005",
|
|
32532
33190
|
complexity: 1e3,
|
|
32533
33191
|
broadcastable: false,
|
|
32534
33192
|
scoped: true,
|
|
32535
33193
|
lazy: true,
|
|
32536
|
-
signature: "(
|
|
32537
|
-
canonical: ([body, ...bounds], { scope }) =>
|
|
32538
|
-
|
|
33194
|
+
signature: "(any, tuple*) -> number",
|
|
33195
|
+
canonical: ([body, ...bounds], { scope, engine: ce }) => {
|
|
33196
|
+
if (bounds.length === 0) {
|
|
33197
|
+
const canon = body?.canonical;
|
|
33198
|
+
if (canon?.isCollection) return ce._fn("Sum", [canon]);
|
|
33199
|
+
}
|
|
33200
|
+
return canonicalBigop("Sum", body, bounds, scope);
|
|
33201
|
+
},
|
|
33202
|
+
evaluate: ([first, ...rest], { engine, numericApproximation: numericApproximation2 }) => {
|
|
33203
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33204
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33205
|
+
const result2 = run(
|
|
33206
|
+
reduceCollection2(
|
|
33207
|
+
first,
|
|
33208
|
+
engine.Zero,
|
|
33209
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33210
|
+
),
|
|
33211
|
+
engine._timeRemaining
|
|
33212
|
+
);
|
|
33213
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33214
|
+
}
|
|
32539
33215
|
const result = run(
|
|
32540
33216
|
reduceBigOp(
|
|
32541
|
-
|
|
32542
|
-
|
|
33217
|
+
first,
|
|
33218
|
+
rest,
|
|
32543
33219
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32544
33220
|
engine.Zero
|
|
32545
33221
|
),
|
|
32546
33222
|
engine._timeRemaining
|
|
32547
33223
|
);
|
|
32548
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32549
|
-
return void 0;
|
|
32550
|
-
}
|
|
33224
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32551
33225
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32552
33226
|
},
|
|
32553
|
-
evaluateAsync: async (
|
|
33227
|
+
evaluateAsync: async ([first, ...rest], { engine, signal, numericApproximation: numericApproximation2 }) => {
|
|
33228
|
+
if (rest.length === 0 && first?.isCollection) {
|
|
33229
|
+
if (first.isFiniteCollection !== true) return void 0;
|
|
33230
|
+
const result2 = await runAsync(
|
|
33231
|
+
reduceCollection2(
|
|
33232
|
+
first,
|
|
33233
|
+
engine.Zero,
|
|
33234
|
+
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
|
|
33235
|
+
),
|
|
33236
|
+
engine._timeRemaining,
|
|
33237
|
+
signal
|
|
33238
|
+
);
|
|
33239
|
+
return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
33240
|
+
}
|
|
32554
33241
|
const result = await runAsync(
|
|
32555
33242
|
reduceBigOp(
|
|
32556
|
-
|
|
32557
|
-
|
|
33243
|
+
first,
|
|
33244
|
+
rest,
|
|
32558
33245
|
(acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
|
|
32559
33246
|
engine.Zero
|
|
32560
33247
|
),
|
|
32561
33248
|
engine._timeRemaining,
|
|
32562
33249
|
signal
|
|
32563
33250
|
);
|
|
32564
|
-
if (result === NON_ENUMERABLE_DOMAIN)
|
|
32565
|
-
return void 0;
|
|
32566
|
-
}
|
|
33251
|
+
if (result === NON_ENUMERABLE_DOMAIN) return void 0;
|
|
32567
33252
|
return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
|
|
32568
33253
|
}
|
|
32569
33254
|
}
|
|
32570
33255
|
}
|
|
32571
33256
|
];
|
|
33257
|
+
function* reduceCollection2(collection, init, combine) {
|
|
33258
|
+
let acc = init;
|
|
33259
|
+
for (const x of collection.each()) {
|
|
33260
|
+
acc = combine(acc, x);
|
|
33261
|
+
yield acc;
|
|
33262
|
+
}
|
|
33263
|
+
return acc;
|
|
33264
|
+
}
|
|
32572
33265
|
function evaluateAbs(arg) {
|
|
32573
33266
|
const ce = arg.engine;
|
|
32574
33267
|
if (isNumber(arg)) {
|
|
@@ -42805,7 +43498,7 @@ ${e.message}
|
|
|
42805
43498
|
var CONTROL_STRUCTURES_LIBRARY = [
|
|
42806
43499
|
{
|
|
42807
43500
|
Block: {
|
|
42808
|
-
description: "Evaluate a sequence of expressions in a local scope.",
|
|
43501
|
+
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.",
|
|
42809
43502
|
lazy: true,
|
|
42810
43503
|
scoped: true,
|
|
42811
43504
|
signature: "(unknown*) -> unknown",
|
|
@@ -42855,12 +43548,42 @@ ${e.message}
|
|
|
42855
43548
|
}
|
|
42856
43549
|
},
|
|
42857
43550
|
Loop: {
|
|
42858
|
-
description: "Evaluate a body expression over
|
|
43551
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
42859
43552
|
lazy: true,
|
|
42860
|
-
signature: "(body:expression,
|
|
42861
|
-
type: ([body]) =>
|
|
42862
|
-
|
|
42863
|
-
|
|
43553
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43554
|
+
type: ([body]) => {
|
|
43555
|
+
if (!body) return "nothing";
|
|
43556
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43557
|
+
},
|
|
43558
|
+
canonical: canonicalLoop,
|
|
43559
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43560
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43561
|
+
},
|
|
43562
|
+
When: {
|
|
43563
|
+
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.',
|
|
43564
|
+
lazy: true,
|
|
43565
|
+
signature: "(expression, boolean) -> any",
|
|
43566
|
+
type: ([expr2]) => expr2.type,
|
|
43567
|
+
canonical: (args, { engine: ce }) => {
|
|
43568
|
+
if (args.length !== 2) return null;
|
|
43569
|
+
const [expr2, cond] = args;
|
|
43570
|
+
if (isFunction2(expr2, "When")) {
|
|
43571
|
+
const inner = expr2.op1.canonical;
|
|
43572
|
+
const innerCond = expr2.op2.canonical;
|
|
43573
|
+
return ce._fn("When", [
|
|
43574
|
+
inner,
|
|
43575
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43576
|
+
]);
|
|
43577
|
+
}
|
|
43578
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43579
|
+
},
|
|
43580
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43581
|
+
const c = cond.evaluate();
|
|
43582
|
+
const cs = sym(c);
|
|
43583
|
+
if (cs === "True") return expr2.evaluate();
|
|
43584
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43585
|
+
return ce._fn("When", [expr2, c]);
|
|
43586
|
+
}
|
|
42864
43587
|
},
|
|
42865
43588
|
Which: {
|
|
42866
43589
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42920,9 +43643,141 @@ ${e.message}
|
|
|
42920
43643
|
);
|
|
42921
43644
|
return result;
|
|
42922
43645
|
}
|
|
42923
|
-
function
|
|
43646
|
+
function canonicalLoop(ops, options) {
|
|
43647
|
+
const { engine: ce, scope } = options;
|
|
43648
|
+
if (ops.length === 0) return null;
|
|
43649
|
+
if (ops.length === 1) {
|
|
43650
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43651
|
+
}
|
|
43652
|
+
const body = ops[0];
|
|
43653
|
+
const iterators = ops.slice(1);
|
|
43654
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43655
|
+
if (!allElement) {
|
|
43656
|
+
return ce._fn(
|
|
43657
|
+
"Loop",
|
|
43658
|
+
ops.map((op) => op.canonical)
|
|
43659
|
+
);
|
|
43660
|
+
}
|
|
43661
|
+
const loopScope = scope ?? {
|
|
43662
|
+
parent: ce.context.lexicalScope,
|
|
43663
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43664
|
+
};
|
|
43665
|
+
loopScope.noAutoDeclare = true;
|
|
43666
|
+
ce.pushScope(loopScope);
|
|
43667
|
+
let canonicalIterators;
|
|
43668
|
+
let canonicalBody;
|
|
43669
|
+
try {
|
|
43670
|
+
canonicalIterators = iterators.map((it) => {
|
|
43671
|
+
if (!isFunction2(it, "Element")) {
|
|
43672
|
+
return ce._fn("Element", [
|
|
43673
|
+
ce.error("missing").canonical,
|
|
43674
|
+
ce.error("missing").canonical
|
|
43675
|
+
]);
|
|
43676
|
+
}
|
|
43677
|
+
const indexExpr = it.ops[0];
|
|
43678
|
+
const collExpr = it.ops[1];
|
|
43679
|
+
if (!indexExpr || !collExpr) {
|
|
43680
|
+
return ce._fn("Element", [
|
|
43681
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43682
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43683
|
+
]);
|
|
43684
|
+
}
|
|
43685
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43686
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43687
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43688
|
+
}
|
|
43689
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43690
|
+
});
|
|
43691
|
+
canonicalBody = body.canonical;
|
|
43692
|
+
} finally {
|
|
43693
|
+
ce.popScope();
|
|
43694
|
+
loopScope.noAutoDeclare = false;
|
|
43695
|
+
}
|
|
43696
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43697
|
+
scope: loopScope
|
|
43698
|
+
});
|
|
43699
|
+
}
|
|
43700
|
+
function* runLoop(body, elements, ce) {
|
|
42924
43701
|
body ??= ce.Nothing;
|
|
42925
43702
|
if (sym(body) === "Nothing") return body;
|
|
43703
|
+
if (elements.length === 0) {
|
|
43704
|
+
const result = body.evaluate();
|
|
43705
|
+
yield result;
|
|
43706
|
+
return result;
|
|
43707
|
+
}
|
|
43708
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43709
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43710
|
+
}
|
|
43711
|
+
const results = [];
|
|
43712
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43713
|
+
const freshScope = {
|
|
43714
|
+
parent: ce.context.lexicalScope,
|
|
43715
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43716
|
+
};
|
|
43717
|
+
ce._pushEvalContext(freshScope);
|
|
43718
|
+
try {
|
|
43719
|
+
for (const elem of elements) {
|
|
43720
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43721
|
+
const idx = elem.ops[0];
|
|
43722
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43723
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43724
|
+
ce.declare(idx.symbol, "unknown");
|
|
43725
|
+
}
|
|
43726
|
+
}
|
|
43727
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43728
|
+
} finally {
|
|
43729
|
+
ce._popEvalContext();
|
|
43730
|
+
}
|
|
43731
|
+
if (state.stopped && state.value !== void 0) {
|
|
43732
|
+
if (!state.broke) return state.value;
|
|
43733
|
+
return state.value;
|
|
43734
|
+
}
|
|
43735
|
+
return ce.function("List", results);
|
|
43736
|
+
}
|
|
43737
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43738
|
+
if (state.stopped) return;
|
|
43739
|
+
if (index === elements.length) {
|
|
43740
|
+
const result = body.evaluate();
|
|
43741
|
+
state.count += 1;
|
|
43742
|
+
if (state.count > ce.iterationLimit)
|
|
43743
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43744
|
+
if (isFunction2(result, "Break")) {
|
|
43745
|
+
state.stopped = true;
|
|
43746
|
+
state.broke = true;
|
|
43747
|
+
state.value = result.op1;
|
|
43748
|
+
return;
|
|
43749
|
+
}
|
|
43750
|
+
if (result.operator === "Return") {
|
|
43751
|
+
state.stopped = true;
|
|
43752
|
+
state.value = result;
|
|
43753
|
+
return;
|
|
43754
|
+
}
|
|
43755
|
+
results.push(result);
|
|
43756
|
+
yield result;
|
|
43757
|
+
return;
|
|
43758
|
+
}
|
|
43759
|
+
const elem = elements[index];
|
|
43760
|
+
if (!isFunction2(elem, "Element")) {
|
|
43761
|
+
return;
|
|
43762
|
+
}
|
|
43763
|
+
const indexExpr = elem.ops[0];
|
|
43764
|
+
const collExpr = elem.ops[1];
|
|
43765
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43766
|
+
return;
|
|
43767
|
+
}
|
|
43768
|
+
const name = indexExpr.symbol;
|
|
43769
|
+
const collection = collExpr.evaluate();
|
|
43770
|
+
if (!collection?.isCollection) {
|
|
43771
|
+
return;
|
|
43772
|
+
}
|
|
43773
|
+
const skipAssign = name === "Nothing";
|
|
43774
|
+
for (const value of collection.each()) {
|
|
43775
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43776
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43777
|
+
if (state.stopped) return;
|
|
43778
|
+
}
|
|
43779
|
+
}
|
|
43780
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42926
43781
|
if (collection?.isCollection) {
|
|
42927
43782
|
let result = void 0;
|
|
42928
43783
|
const fn = applicable(body);
|
|
@@ -44564,7 +45419,7 @@ ${e.message}
|
|
|
44564
45419
|
evaluate: (ops) => apply(ops[0], ops.slice(1))
|
|
44565
45420
|
},
|
|
44566
45421
|
Assign: {
|
|
44567
|
-
description: "Assign a value to a symbol or define a sequence",
|
|
45422
|
+
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).",
|
|
44568
45423
|
lazy: true,
|
|
44569
45424
|
pure: false,
|
|
44570
45425
|
signature: "(symbol | expression, any) -> any",
|
|
@@ -44695,7 +45550,12 @@ ${e.message}
|
|
|
44695
45550
|
evaluate: (ops, { engine: ce }) => {
|
|
44696
45551
|
const symbolName2 = sym(ops[0].evaluate());
|
|
44697
45552
|
if (!symbolName2) return void 0;
|
|
45553
|
+
const currentScope = ce.context.lexicalScope;
|
|
45554
|
+
const existing = currentScope.bindings.get(symbolName2);
|
|
45555
|
+
const existingValueDef = existing && isValueDef(existing) ? existing : void 0;
|
|
45556
|
+
const isAutoDeclareHere = !!existingValueDef && existingValueDef.value.inferredType && existingValueDef.value.value === void 0;
|
|
44698
45557
|
if (!ops[1]) {
|
|
45558
|
+
if (isAutoDeclareHere) return ce.Nothing;
|
|
44699
45559
|
ce.declare(symbolName2, { inferred: true, type: "unknown" });
|
|
44700
45560
|
return ce.Nothing;
|
|
44701
45561
|
}
|
|
@@ -44704,6 +45564,11 @@ ${e.message}
|
|
|
44704
45564
|
(isString(t) ? t.string : void 0) ?? sym(t) ?? void 0
|
|
44705
45565
|
);
|
|
44706
45566
|
if (!isValidType(type2)) return void 0;
|
|
45567
|
+
if (isAutoDeclareHere && existingValueDef) {
|
|
45568
|
+
existingValueDef.value.type = ce.type(type2);
|
|
45569
|
+
existingValueDef.value.inferredType = false;
|
|
45570
|
+
return ce.Nothing;
|
|
45571
|
+
}
|
|
44707
45572
|
ce.declare(symbolName2, type2);
|
|
44708
45573
|
return ce.Nothing;
|
|
44709
45574
|
}
|
|
@@ -44821,33 +45686,41 @@ ${e.message}
|
|
|
44821
45686
|
},
|
|
44822
45687
|
Random: {
|
|
44823
45688
|
description: [
|
|
44824
|
-
"Random():
|
|
44825
|
-
"Random(
|
|
44826
|
-
"Random(
|
|
45689
|
+
"Random(): non-deterministic float in [0, 1)",
|
|
45690
|
+
"Random(seed: real): deterministic float in [0, 1) from a real seed",
|
|
45691
|
+
"Random(n: integer): non-deterministic integer in [0, n)",
|
|
45692
|
+
"Random(m: integer, n: integer): non-deterministic integer in [m, n)"
|
|
44827
45693
|
],
|
|
44828
45694
|
pure: false,
|
|
44829
|
-
|
|
44830
|
-
|
|
44831
|
-
|
|
44832
|
-
|
|
45695
|
+
// Signature accepts: nothing, one number, or two integers.
|
|
45696
|
+
// Use `number` (not `integer`) for the single-arg case so float seeds
|
|
45697
|
+
// type-check; runtime dispatch differentiates integer vs real.
|
|
45698
|
+
signature: "(number?, integer?) -> finite_number",
|
|
45699
|
+
type: ([first, second]) => {
|
|
45700
|
+
if (first === void 0) return "finite_number";
|
|
45701
|
+
if (second !== void 0) return "finite_integer";
|
|
45702
|
+
if (first.type.matches("integer")) return "finite_integer";
|
|
45703
|
+
return "finite_number";
|
|
44833
45704
|
},
|
|
44834
45705
|
sgn: () => "non-negative",
|
|
44835
45706
|
evaluate: (ops, { engine: ce }) => {
|
|
44836
45707
|
if (ops.length === 0) return ce.number(Math.random());
|
|
44837
|
-
const [
|
|
44838
|
-
|
|
44839
|
-
|
|
44840
|
-
|
|
44841
|
-
lower = 0;
|
|
44842
|
-
upper = Math.floor(lowerOp.re - 1);
|
|
44843
|
-
if (isNaN(upper)) upper = 0;
|
|
44844
|
-
} else {
|
|
44845
|
-
lower = Math.floor(lowerOp.re);
|
|
44846
|
-
upper = Math.floor(upperOp.re);
|
|
45708
|
+
const [firstOp, secondOp] = ops;
|
|
45709
|
+
if (secondOp !== void 0) {
|
|
45710
|
+
let lower = Math.floor(firstOp.re);
|
|
45711
|
+
let upper = Math.floor(secondOp.re);
|
|
44847
45712
|
if (isNaN(lower)) lower = 0;
|
|
44848
45713
|
if (isNaN(upper)) upper = 0;
|
|
45714
|
+
return ce.number(lower + Math.floor(Math.random() * (upper - lower)));
|
|
45715
|
+
}
|
|
45716
|
+
if (firstOp.type.matches("integer")) {
|
|
45717
|
+
let n = Math.floor(firstOp.re);
|
|
45718
|
+
if (isNaN(n)) n = 0;
|
|
45719
|
+
return ce.number(Math.floor(Math.random() * n));
|
|
44849
45720
|
}
|
|
44850
|
-
|
|
45721
|
+
const seed = firstOp.re;
|
|
45722
|
+
if (isNaN(seed)) return ce.number(0);
|
|
45723
|
+
return ce.number(deterministicRandom(seed));
|
|
44851
45724
|
}
|
|
44852
45725
|
},
|
|
44853
45726
|
// @todo: need review
|
|
@@ -45303,6 +46176,14 @@ ${e.message}
|
|
|
45303
46176
|
To: {
|
|
45304
46177
|
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45305
46178
|
signature: "(any, any) -> nothing"
|
|
46179
|
+
},
|
|
46180
|
+
Colon: {
|
|
46181
|
+
description: "Type annotation (`a : b`) \u2014 opaque typed head.",
|
|
46182
|
+
signature: "(any, any) -> expression"
|
|
46183
|
+
},
|
|
46184
|
+
Prime: {
|
|
46185
|
+
description: "Derivative or prime notation (`f'`, `f^{(n)}`) \u2014 opaque typed head until a derivative library handler runs.",
|
|
46186
|
+
signature: "(any, integer?) -> expression"
|
|
45306
46187
|
}
|
|
45307
46188
|
}
|
|
45308
46189
|
];
|
|
@@ -50343,18 +51224,28 @@ ${e.message}
|
|
|
50343
51224
|
},
|
|
50344
51225
|
{
|
|
50345
51226
|
Sample: {
|
|
50346
|
-
description: "Return a random sample of k elements from the collection, without replacement.",
|
|
51227
|
+
description: "Return a random sample of k elements from the collection, without replacement. With an optional `seed` argument, the sample is deterministic.",
|
|
50347
51228
|
complexity: 8200,
|
|
50348
|
-
signature: "(collection, integer) -> list",
|
|
50349
|
-
evaluate: ([xs, nArg], { engine: ce }) => {
|
|
51229
|
+
signature: "(collection, integer, real?) -> list",
|
|
51230
|
+
evaluate: ([xs, nArg, seedArg], { engine: ce }) => {
|
|
50350
51231
|
if (!xs.isFiniteCollection) return void 0;
|
|
50351
51232
|
const k = toInteger(nArg);
|
|
50352
51233
|
if (k === null || k < 0) return void 0;
|
|
50353
51234
|
const data = Array.from(xs.each());
|
|
50354
51235
|
if (k > data.length) return void 0;
|
|
50355
|
-
|
|
50356
|
-
|
|
50357
|
-
|
|
51236
|
+
const seed = seedArg?.re;
|
|
51237
|
+
if (seed !== void 0 && !Number.isNaN(seed)) {
|
|
51238
|
+
let s = seed;
|
|
51239
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51240
|
+
const j = Math.floor(deterministicRandom(s) * (i + 1));
|
|
51241
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51242
|
+
s = nextSeed(s);
|
|
51243
|
+
}
|
|
51244
|
+
} else {
|
|
51245
|
+
for (let i = data.length - 1; i > 0; i--) {
|
|
51246
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
51247
|
+
[data[i], data[j]] = [data[j], data[i]];
|
|
51248
|
+
}
|
|
50358
51249
|
}
|
|
50359
51250
|
const sample = data.slice(0, k);
|
|
50360
51251
|
return ce.function("List", sample);
|
|
@@ -53175,6 +54066,20 @@ Error in definition of "${name}"`,
|
|
|
53175
54066
|
if (results.length === 1) return results[0];
|
|
53176
54067
|
return this.engine._fn("List", results);
|
|
53177
54068
|
}
|
|
54069
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
54070
|
+
const items = zip(this._ops);
|
|
54071
|
+
if (items) {
|
|
54072
|
+
const results = [];
|
|
54073
|
+
while (true) {
|
|
54074
|
+
const { done, value } = items.next();
|
|
54075
|
+
if (done) break;
|
|
54076
|
+
results.push(
|
|
54077
|
+
this.engine._fn(this.operator, value).evaluate(options)
|
|
54078
|
+
);
|
|
54079
|
+
}
|
|
54080
|
+
return this.engine._fn("List", results);
|
|
54081
|
+
}
|
|
54082
|
+
}
|
|
53178
54083
|
if (materialization !== false && !def.evaluate && this.isLazyCollection)
|
|
53179
54084
|
return materialize(this, def, options);
|
|
53180
54085
|
const tail = holdMap(this, (x) => x.evaluate(options));
|
|
@@ -53221,6 +54126,22 @@ Error in definition of "${name}"`,
|
|
|
53221
54126
|
(resolved) => this.engine._fn("List", resolved)
|
|
53222
54127
|
);
|
|
53223
54128
|
}
|
|
54129
|
+
if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
|
|
54130
|
+
const items = zip(this._ops);
|
|
54131
|
+
if (items) {
|
|
54132
|
+
const results = [];
|
|
54133
|
+
while (true) {
|
|
54134
|
+
const { done, value } = items.next();
|
|
54135
|
+
if (done) break;
|
|
54136
|
+
results.push(
|
|
54137
|
+
this.engine._fn(this.operator, value).evaluateAsync(options)
|
|
54138
|
+
);
|
|
54139
|
+
}
|
|
54140
|
+
return Promise.all(results).then(
|
|
54141
|
+
(resolved) => this.engine._fn("List", resolved)
|
|
54142
|
+
);
|
|
54143
|
+
}
|
|
54144
|
+
}
|
|
53224
54145
|
const tail = await holdMapAsync(
|
|
53225
54146
|
this,
|
|
53226
54147
|
async (x) => await x.evaluateAsync(options)
|
|
@@ -53435,8 +54356,47 @@ Error in definition of "${name}"`,
|
|
|
53435
54356
|
const ops = expr2.ops.map((x) => x.evaluate(options));
|
|
53436
54357
|
if (!value || value.type.isUnknown)
|
|
53437
54358
|
return expr2.engine.function(expr2.operator, ops);
|
|
54359
|
+
if (ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(value.type.type)) {
|
|
54360
|
+
const items = zip(ops);
|
|
54361
|
+
if (items) {
|
|
54362
|
+
const results = [];
|
|
54363
|
+
while (true) {
|
|
54364
|
+
const { done, value: zipped } = items.next();
|
|
54365
|
+
if (done) break;
|
|
54366
|
+
results.push(apply(value, zipped).evaluate(options));
|
|
54367
|
+
}
|
|
54368
|
+
return expr2.engine._fn("List", results);
|
|
54369
|
+
}
|
|
54370
|
+
}
|
|
53438
54371
|
return apply(value, ops);
|
|
53439
54372
|
}
|
|
54373
|
+
function paramsAreScalar(source) {
|
|
54374
|
+
const sigType = isOperatorDefinition(source) ? source.signature?.type : source;
|
|
54375
|
+
if (!sigType || typeof sigType === "string") return true;
|
|
54376
|
+
if (sigType.kind !== "signature") return true;
|
|
54377
|
+
const args = [
|
|
54378
|
+
...sigType.args ?? [],
|
|
54379
|
+
...sigType.optArgs ?? [],
|
|
54380
|
+
...sigType.variadicArg ? [sigType.variadicArg] : []
|
|
54381
|
+
];
|
|
54382
|
+
return args.every((arg) => isScalarType(arg.type));
|
|
54383
|
+
}
|
|
54384
|
+
function isOperatorDefinition(source) {
|
|
54385
|
+
return typeof source === "object" && source !== null && "signature" in source;
|
|
54386
|
+
}
|
|
54387
|
+
function isScalarType(t) {
|
|
54388
|
+
if (typeof t === "string") {
|
|
54389
|
+
if (t === "collection" || t === "indexed_collection" || t === "list" || t === "tuple" || t === "set" || t === "dictionary" || t === "record" || t === "function")
|
|
54390
|
+
return false;
|
|
54391
|
+
return true;
|
|
54392
|
+
}
|
|
54393
|
+
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")
|
|
54394
|
+
return false;
|
|
54395
|
+
if (t.kind === "union" || t.kind === "intersection")
|
|
54396
|
+
return t.types.every((x) => isScalarType(x));
|
|
54397
|
+
if (t.kind === "negation") return isScalarType(t.type);
|
|
54398
|
+
return true;
|
|
54399
|
+
}
|
|
53440
54400
|
function materialize(expr2, def, options) {
|
|
53441
54401
|
if (!expr2.isValid || options?.materialization === false) return expr2;
|
|
53442
54402
|
let materialization = options?.materialization ?? false;
|
|
@@ -53444,6 +54404,11 @@ Error in definition of "${name}"`,
|
|
|
53444
54404
|
materialization = DEFAULT_MATERIALIZATION;
|
|
53445
54405
|
const isIndexed = expr2.isIndexedCollection;
|
|
53446
54406
|
const isFinite2 = expr2.isFiniteCollection;
|
|
54407
|
+
if (isIndexed && isFinite2) {
|
|
54408
|
+
const count = expr2.count;
|
|
54409
|
+
if (count !== void 0 && count > expr2.engine.maxCollectionSize)
|
|
54410
|
+
return expr2;
|
|
54411
|
+
}
|
|
53447
54412
|
const xs = [];
|
|
53448
54413
|
if (!expr2.isEmptyCollection) {
|
|
53449
54414
|
if (!isIndexed || !isFinite2) {
|
|
@@ -53671,7 +54636,7 @@ Error in definition of "${name}"`,
|
|
|
53671
54636
|
const eltType = widen(
|
|
53672
54637
|
...Object.values(this._keyValues).map((op) => op.type.type)
|
|
53673
54638
|
);
|
|
53674
|
-
this._type =
|
|
54639
|
+
this._type = new BoxedType({ kind: "dictionary", values: eltType });
|
|
53675
54640
|
return this._type;
|
|
53676
54641
|
}
|
|
53677
54642
|
get isPure() {
|
|
@@ -53949,6 +54914,7 @@ Error in definition of "${name}"`,
|
|
|
53949
54914
|
}
|
|
53950
54915
|
if (typeof expr2 === "number" || expr2 instanceof BigDecimal || expr2 instanceof Complex)
|
|
53951
54916
|
return ce.number(expr2);
|
|
54917
|
+
if (typeof expr2 === "boolean") return ce.symbol(expr2 ? "True" : "False");
|
|
53952
54918
|
if (typeof expr2 === "string") {
|
|
53953
54919
|
if (matchesSymbol(expr2)) {
|
|
53954
54920
|
const sym2 = symbol(expr2);
|
|
@@ -55005,6 +55971,23 @@ Error in definition of "${name}"`,
|
|
|
55005
55971
|
};
|
|
55006
55972
|
return compilePair(0);
|
|
55007
55973
|
}
|
|
55974
|
+
if (h === "When") {
|
|
55975
|
+
if (args.length !== 2)
|
|
55976
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55977
|
+
const fn2 = target.functions?.(h);
|
|
55978
|
+
if (fn2) {
|
|
55979
|
+
if (typeof fn2 === "function") {
|
|
55980
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55981
|
+
}
|
|
55982
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55983
|
+
}
|
|
55984
|
+
if (isSymbol2(args[1], "True"))
|
|
55985
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55986
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55987
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55988
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55989
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55990
|
+
}
|
|
55008
55991
|
if (h === "Block") {
|
|
55009
55992
|
return _BaseCompiler.compileBlock(args, target);
|
|
55010
55993
|
}
|
|
@@ -55079,17 +56062,98 @@ Error in definition of "${name}"`,
|
|
|
55079
56062
|
)}${target.ws("\n")}})()`;
|
|
55080
56063
|
}
|
|
55081
56064
|
/**
|
|
55082
|
-
* Compile a Loop expression
|
|
55083
|
-
*
|
|
56065
|
+
* Compile a Loop expression.
|
|
56066
|
+
*
|
|
56067
|
+
* Two forms are supported:
|
|
56068
|
+
*
|
|
56069
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
56070
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
56071
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
56072
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
56073
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
56074
|
+
* references to the loop index inside the body are re-wrapped via
|
|
56075
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
55084
56076
|
*
|
|
55085
|
-
*
|
|
55086
|
-
*
|
|
55087
|
-
*
|
|
56077
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
56078
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
56079
|
+
* When two or more `Element` clauses are present — or when the single
|
|
56080
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
56081
|
+
* comprehension that collects results into an array. Each clause
|
|
56082
|
+
* produces a `for (const name of collection)` loop, nested
|
|
56083
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
56084
|
+
*
|
|
56085
|
+
* Example output (JS):
|
|
56086
|
+
* ```js
|
|
56087
|
+
* (() => { const result = [];
|
|
56088
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
56089
|
+
* return result; })()
|
|
56090
|
+
* ```
|
|
56091
|
+
*
|
|
56092
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
56093
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
56094
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
56095
|
+
* array or by unrolling when bounds are known at compile time.
|
|
56096
|
+
*
|
|
56097
|
+
* Known issue (imperative form): the IIFE generated by form (1) has no
|
|
56098
|
+
* `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
|
|
56099
|
+
* to JS evaluates to `undefined` at runtime, while CE evaluation returns a
|
|
56100
|
+
* `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
|
|
56101
|
+
* ("Loop compiles in JS") for the verify-only test that locks in the
|
|
56102
|
+
* current behavior.
|
|
55088
56103
|
*/
|
|
55089
56104
|
static compileForLoop(args, target) {
|
|
55090
56105
|
if (!args[0]) throw new Error("Loop: no body");
|
|
55091
56106
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
55092
|
-
const
|
|
56107
|
+
const body = args[0];
|
|
56108
|
+
const elements = args.slice(1);
|
|
56109
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
56110
|
+
if (useComprehension) {
|
|
56111
|
+
const lang = target.language ?? "";
|
|
56112
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
56113
|
+
throw new Error(
|
|
56114
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
56115
|
+
);
|
|
56116
|
+
}
|
|
56117
|
+
const narrowedElements = [];
|
|
56118
|
+
for (let i = 0; i < elements.length; i++) {
|
|
56119
|
+
const elem = elements[i];
|
|
56120
|
+
if (!isFunction2(elem, "Element"))
|
|
56121
|
+
throw new Error(
|
|
56122
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
56123
|
+
);
|
|
56124
|
+
if (!isSymbol2(elem.ops[0]))
|
|
56125
|
+
throw new Error(
|
|
56126
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
56127
|
+
);
|
|
56128
|
+
narrowedElements.push(elem);
|
|
56129
|
+
}
|
|
56130
|
+
const loopVarSet = new Set(
|
|
56131
|
+
narrowedElements.map(
|
|
56132
|
+
(e) => e.ops[0].symbol
|
|
56133
|
+
)
|
|
56134
|
+
);
|
|
56135
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
56136
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
56137
|
+
...target,
|
|
56138
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
56139
|
+
} : target;
|
|
56140
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
56141
|
+
let inner = `result.push(${bodyCode});`;
|
|
56142
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
56143
|
+
const elem = narrowedElements[i];
|
|
56144
|
+
const name = elem.ops[0].symbol;
|
|
56145
|
+
const collExpr = elem.ops[1];
|
|
56146
|
+
let collection;
|
|
56147
|
+
if (isFunction2(collExpr, "Range")) {
|
|
56148
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
56149
|
+
} else {
|
|
56150
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
56151
|
+
}
|
|
56152
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
56153
|
+
}
|
|
56154
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
56155
|
+
}
|
|
56156
|
+
const indexing = elements[0];
|
|
55093
56157
|
if (!isFunction2(indexing, "Element"))
|
|
55094
56158
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
55095
56159
|
const indexExpr = indexing.ops[0];
|
|
@@ -55107,13 +56171,72 @@ Error in definition of "${name}"`,
|
|
|
55107
56171
|
...target,
|
|
55108
56172
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
55109
56173
|
};
|
|
55110
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
56174
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
55111
56175
|
return `(() => {${target.ws(
|
|
55112
56176
|
"\n"
|
|
55113
56177
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
55114
56178
|
"\n"
|
|
55115
56179
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
55116
56180
|
}
|
|
56181
|
+
/**
|
|
56182
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
56183
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
56184
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
56185
|
+
*
|
|
56186
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
56187
|
+
* are not statically numeric we accept the Range (the historical
|
|
56188
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
56189
|
+
* left as a known limitation; callers can force the iterable path by
|
|
56190
|
+
* supplying an explicit step.
|
|
56191
|
+
*/
|
|
56192
|
+
static isLegacyCompatibleRange(coll) {
|
|
56193
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
56194
|
+
if (coll.ops.length >= 3) {
|
|
56195
|
+
const stepExpr = coll.ops[2];
|
|
56196
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
56197
|
+
}
|
|
56198
|
+
const lo = coll.ops[0];
|
|
56199
|
+
const hi = coll.ops[1];
|
|
56200
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
56201
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
56202
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
56203
|
+
return true;
|
|
56204
|
+
}
|
|
56205
|
+
/**
|
|
56206
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
56207
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
56208
|
+
* `library/collections.ts` Range:
|
|
56209
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
56210
|
+
* element = lo + step * k (0-indexed)
|
|
56211
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
56212
|
+
*
|
|
56213
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
56214
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
56215
|
+
*/
|
|
56216
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
56217
|
+
const loExpr = rangeExpr.ops[0];
|
|
56218
|
+
const hiExpr = rangeExpr.ops[1];
|
|
56219
|
+
const stepExpr = rangeExpr.ops[2];
|
|
56220
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
56221
|
+
const lo2 = loExpr.re;
|
|
56222
|
+
const hi2 = hiExpr.re;
|
|
56223
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
56224
|
+
if (step2 === 0) return "[]";
|
|
56225
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
56226
|
+
if (step2 === 1) {
|
|
56227
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
56228
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
56229
|
+
}
|
|
56230
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
56231
|
+
}
|
|
56232
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
56233
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
56234
|
+
if (stepExpr === void 0) {
|
|
56235
|
+
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})`;
|
|
56236
|
+
}
|
|
56237
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
56238
|
+
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})`;
|
|
56239
|
+
}
|
|
55117
56240
|
/**
|
|
55118
56241
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
55119
56242
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -59613,8 +60736,8 @@ Error in definition of "${name}"`,
|
|
|
59613
60736
|
}
|
|
59614
60737
|
if (effectiveOp === "greater" || effectiveOp === "greaterEqual") {
|
|
59615
60738
|
const isStrict = effectiveOp === "greater";
|
|
59616
|
-
if (bounds.
|
|
59617
|
-
const lowerVal = isNumber(bounds.
|
|
60739
|
+
if (bounds.lower !== void 0) {
|
|
60740
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59618
60741
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59619
60742
|
if (isStrict) {
|
|
59620
60743
|
if (lowerVal > k) return "tautology";
|
|
@@ -59626,8 +60749,8 @@ Error in definition of "${name}"`,
|
|
|
59626
60749
|
}
|
|
59627
60750
|
}
|
|
59628
60751
|
}
|
|
59629
|
-
if (bounds.
|
|
59630
|
-
const upperVal = isNumber(bounds.
|
|
60752
|
+
if (bounds.upper !== void 0) {
|
|
60753
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59631
60754
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59632
60755
|
if (isStrict) {
|
|
59633
60756
|
if (upperVal < k) return "contradiction";
|
|
@@ -59642,8 +60765,8 @@ Error in definition of "${name}"`,
|
|
|
59642
60765
|
}
|
|
59643
60766
|
} else {
|
|
59644
60767
|
const isStrict = effectiveOp === "less";
|
|
59645
|
-
if (bounds.
|
|
59646
|
-
const upperVal = isNumber(bounds.
|
|
60768
|
+
if (bounds.upper !== void 0) {
|
|
60769
|
+
const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
|
|
59647
60770
|
if (typeof upperVal === "number" && isFinite(upperVal)) {
|
|
59648
60771
|
if (isStrict) {
|
|
59649
60772
|
if (upperVal < k) return "tautology";
|
|
@@ -59654,8 +60777,8 @@ Error in definition of "${name}"`,
|
|
|
59654
60777
|
}
|
|
59655
60778
|
}
|
|
59656
60779
|
}
|
|
59657
|
-
if (bounds.
|
|
59658
|
-
const lowerVal = isNumber(bounds.
|
|
60780
|
+
if (bounds.lower !== void 0) {
|
|
60781
|
+
const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
|
|
59659
60782
|
if (typeof lowerVal === "number" && isFinite(lowerVal)) {
|
|
59660
60783
|
if (isStrict) {
|
|
59661
60784
|
if (lowerVal > k) return "contradiction";
|
|
@@ -59883,7 +61006,7 @@ Error in definition of "${name}"`,
|
|
|
59883
61006
|
const patOp1B2 = pat.op1;
|
|
59884
61007
|
if (isSymbol2(patOp1B2)) {
|
|
59885
61008
|
const bounds = getInequalityBoundsFromAssumptions(ce, patOp1B2.symbol);
|
|
59886
|
-
const bound = isLower ? bounds.
|
|
61009
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59887
61010
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59888
61011
|
if (bound !== void 0 && (!isStrict || strictOk === true))
|
|
59889
61012
|
pushResult({ [boundWildcard]: bound });
|
|
@@ -59893,7 +61016,7 @@ Error in definition of "${name}"`,
|
|
|
59893
61016
|
if (symbolWildcard && !symbolWildcard.startsWith("__")) {
|
|
59894
61017
|
for (const s of candidatesFromAssumptions()) {
|
|
59895
61018
|
const bounds = getInequalityBoundsFromAssumptions(ce, s);
|
|
59896
|
-
const bound = isLower ? bounds.
|
|
61019
|
+
const bound = isLower ? bounds.lower : bounds.upper;
|
|
59897
61020
|
const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
|
|
59898
61021
|
if (bound === void 0 || isStrict && strictOk !== true)
|
|
59899
61022
|
continue;
|
|
@@ -60925,6 +62048,7 @@ Error in definition of "${name}"`,
|
|
|
60925
62048
|
return `_SYS.cexp(${compile3(args[0])})`;
|
|
60926
62049
|
return `Math.exp(${compile3(args[0])})`;
|
|
60927
62050
|
},
|
|
62051
|
+
First: (args, compile3) => `${compile3(args[0])}[0]`,
|
|
60928
62052
|
Floor: (args, compile3) => {
|
|
60929
62053
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
60930
62054
|
return `Math.floor(${compile3(args[0])})`;
|
|
@@ -61083,7 +62207,20 @@ Error in definition of "${name}"`,
|
|
|
61083
62207
|
if (nConst !== void 0) return `Math.pow(${compile3(arg)}, ${1 / nConst})`;
|
|
61084
62208
|
return `Math.pow(${compile3(arg)}, 1 / (${compile3(exp3)}))`;
|
|
61085
62209
|
},
|
|
61086
|
-
Random:
|
|
62210
|
+
Random: (args, compile3) => {
|
|
62211
|
+
if (args.length === 0) return "Math.random()";
|
|
62212
|
+
if (args.length === 2) {
|
|
62213
|
+
const m = compile3(args[0]);
|
|
62214
|
+
const n = compile3(args[1]);
|
|
62215
|
+
return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
|
|
62216
|
+
}
|
|
62217
|
+
const arg = args[0];
|
|
62218
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
62219
|
+
return `Math.floor(Math.random() * (${compile3(arg)}))`;
|
|
62220
|
+
}
|
|
62221
|
+
const a = compile3(arg);
|
|
62222
|
+
return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
|
|
62223
|
+
},
|
|
61087
62224
|
Round: (args, compile3) => {
|
|
61088
62225
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
61089
62226
|
return `Math.round(${compile3(args[0])})`;
|
|
@@ -61111,6 +62248,7 @@ Error in definition of "${name}"`,
|
|
|
61111
62248
|
if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile3(arg)})`;
|
|
61112
62249
|
return `1 / Math.cosh(${compile3(arg)})`;
|
|
61113
62250
|
},
|
|
62251
|
+
Second: (args, compile3) => `${compile3(args[0])}[1]`,
|
|
61114
62252
|
Heaviside: "_SYS.heaviside",
|
|
61115
62253
|
Sign: "Math.sign",
|
|
61116
62254
|
Sinc: "_SYS.sinc",
|
|
@@ -61143,6 +62281,7 @@ Error in definition of "${name}"`,
|
|
|
61143
62281
|
return `_SYS.ctanh(${compile3(args[0])})`;
|
|
61144
62282
|
return `Math.tanh(${compile3(args[0])})`;
|
|
61145
62283
|
},
|
|
62284
|
+
Third: (args, compile3) => `${compile3(args[0])}[2]`,
|
|
61146
62285
|
Mod: ([a, b], compile3) => {
|
|
61147
62286
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
61148
62287
|
const ca = compile3(a);
|
|
@@ -62422,6 +63561,14 @@ Error in definition of "${name}"`,
|
|
|
62422
63561
|
return `exp(${compile3(args[0])})`;
|
|
62423
63562
|
},
|
|
62424
63563
|
Exp2: "exp2",
|
|
63564
|
+
// Component access — assumes the argument compiles to a vec2/vec3/vec4
|
|
63565
|
+
// (the common case for 2D/3D points). For 5+-element tuples that compile
|
|
63566
|
+
// to `float[N]` arrays, swizzle access is invalid GLSL and the shader
|
|
63567
|
+
// will fail to compile; that's an edge case `First`/`Second`/`Third`
|
|
63568
|
+
// aren't designed for. Vec swizzles are identical between GLSL and WGSL.
|
|
63569
|
+
First: (args, compile3) => `${compile3(args[0])}.x`,
|
|
63570
|
+
Second: (args, compile3) => `${compile3(args[0])}.y`,
|
|
63571
|
+
Third: (args, compile3) => `${compile3(args[0])}.z`,
|
|
62425
63572
|
Floor: (args, compile3) => {
|
|
62426
63573
|
if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
|
|
62427
63574
|
return `floor(${compile3(args[0])})`;
|
|
@@ -62899,6 +64046,39 @@ Error in definition of "${name}"`,
|
|
|
62899
64046
|
// Sum/Product — unrolled or for-loop
|
|
62900
64047
|
Sum: (args, compile3, target) => compileGPUSumProduct("Sum", args, compile3, target),
|
|
62901
64048
|
Product: (args, compile3, target) => compileGPUSumProduct("Product", args, compile3, target),
|
|
64049
|
+
// Range — inline constant array literal (bounds must be compile-time constants)
|
|
64050
|
+
Range: (args, _compile2, target) => {
|
|
64051
|
+
if (args.length < 2 || args.length > 3) {
|
|
64052
|
+
throw new Error(
|
|
64053
|
+
"Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
|
|
64054
|
+
);
|
|
64055
|
+
}
|
|
64056
|
+
const lo = args[0].re;
|
|
64057
|
+
const hi = args[1].re;
|
|
64058
|
+
const step = args.length === 3 ? args[2].re : 1;
|
|
64059
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
|
|
64060
|
+
throw new Error(
|
|
64061
|
+
"Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
|
|
64062
|
+
);
|
|
64063
|
+
}
|
|
64064
|
+
if (step === 0) throw new Error("Range: step cannot be zero");
|
|
64065
|
+
const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
|
|
64066
|
+
if (count === 0) {
|
|
64067
|
+
throw new Error(
|
|
64068
|
+
"Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
|
|
64069
|
+
);
|
|
64070
|
+
}
|
|
64071
|
+
if (count > 256) {
|
|
64072
|
+
throw new Error(
|
|
64073
|
+
`Range: GPU compile inlines ranges up to 256 elements (got ${count})`
|
|
64074
|
+
);
|
|
64075
|
+
}
|
|
64076
|
+
const values = [];
|
|
64077
|
+
for (let i = 0; i < count; i++) values.push(lo + i * step);
|
|
64078
|
+
const isWGSL = target.language === "wgsl";
|
|
64079
|
+
const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
|
|
64080
|
+
return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
|
|
64081
|
+
},
|
|
62902
64082
|
// Loop — GPU for-loop (no IIFE, no let)
|
|
62903
64083
|
Loop: (args, _compile2, target) => {
|
|
62904
64084
|
if (!args[0]) throw new Error("Loop: no body");
|
|
@@ -62927,6 +64107,134 @@ Error in definition of "${name}"`,
|
|
|
62927
64107
|
${bodyCode};
|
|
62928
64108
|
}`;
|
|
62929
64109
|
},
|
|
64110
|
+
// Statistical functions
|
|
64111
|
+
/**
|
|
64112
|
+
* GCD of two scalar arguments.
|
|
64113
|
+
*
|
|
64114
|
+
* Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
|
|
64115
|
+
* Only two-argument form is supported in GPU targets.
|
|
64116
|
+
*/
|
|
64117
|
+
GCD: (args, compile3) => {
|
|
64118
|
+
if (args.length < 2) throw new Error("GCD: need at least two arguments");
|
|
64119
|
+
if (args.length > 2)
|
|
64120
|
+
throw new Error("GCD: GPU target supports only two-argument GCD");
|
|
64121
|
+
const a = args[0];
|
|
64122
|
+
const b = args[1];
|
|
64123
|
+
if (a === null || b === null) throw new Error("GCD: missing argument");
|
|
64124
|
+
return `_gpu_gcd(${compile3(a)}, ${compile3(b)})`;
|
|
64125
|
+
},
|
|
64126
|
+
/**
|
|
64127
|
+
* Variance of a compile-time-known list.
|
|
64128
|
+
*
|
|
64129
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64130
|
+
* Generates fully inline code: computes mean then sum of squared deviations,
|
|
64131
|
+
* divided by (N-1) for sample variance (matches JS `_SYS.variance`).
|
|
64132
|
+
*/
|
|
64133
|
+
Variance: (args, compile3) => {
|
|
64134
|
+
let elems;
|
|
64135
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64136
|
+
elems = args[0].ops;
|
|
64137
|
+
} else if (args.length >= 2) {
|
|
64138
|
+
elems = args;
|
|
64139
|
+
} else {
|
|
64140
|
+
throw new Error(
|
|
64141
|
+
"Variance: GPU target requires a List argument or at least 2 scalar arguments"
|
|
64142
|
+
);
|
|
64143
|
+
}
|
|
64144
|
+
const n = elems.length;
|
|
64145
|
+
if (n < 2) throw new Error("Variance: need at least 2 elements");
|
|
64146
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64147
|
+
const sum = compiled.join(" + ");
|
|
64148
|
+
const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
|
|
64149
|
+
const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
|
|
64150
|
+
return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
|
|
64151
|
+
},
|
|
64152
|
+
/**
|
|
64153
|
+
* Median of a compile-time-known list.
|
|
64154
|
+
*
|
|
64155
|
+
* Accepts either a single `List(...)` argument or N scalar arguments.
|
|
64156
|
+
* For N ≤ 8: generates a fully unrolled inline sorting network followed by
|
|
64157
|
+
* a middle-element pick. For larger N, throws (too large to inline cleanly).
|
|
64158
|
+
*
|
|
64159
|
+
* The sorting network uses the "odd-even merge sort" comparator pattern
|
|
64160
|
+
* inlined as `min`/`max` calls — no GPU statements required.
|
|
64161
|
+
*/
|
|
64162
|
+
Median: (args, compile3) => {
|
|
64163
|
+
let elems;
|
|
64164
|
+
if (args.length === 1 && isFunction2(args[0], "List")) {
|
|
64165
|
+
elems = args[0].ops;
|
|
64166
|
+
} else if (args.length >= 1) {
|
|
64167
|
+
elems = args;
|
|
64168
|
+
} else {
|
|
64169
|
+
throw new Error(
|
|
64170
|
+
"Median: GPU target requires a List argument or at least 1 scalar argument"
|
|
64171
|
+
);
|
|
64172
|
+
}
|
|
64173
|
+
const n = elems.length;
|
|
64174
|
+
if (n === 0) throw new Error("Median: empty list");
|
|
64175
|
+
if (n > 8) {
|
|
64176
|
+
throw new Error(
|
|
64177
|
+
`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.`
|
|
64178
|
+
);
|
|
64179
|
+
}
|
|
64180
|
+
const compiled = elems.map((e) => compile3(e));
|
|
64181
|
+
if (n === 1) return compiled[0];
|
|
64182
|
+
return `_gpu_median_${n}(${compiled.join(", ")})`;
|
|
64183
|
+
},
|
|
64184
|
+
/**
|
|
64185
|
+
* Deterministic pseudorandom for GPU.
|
|
64186
|
+
*
|
|
64187
|
+
* All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
|
|
64188
|
+
* composes with surrounding float arithmetic without explicit casts. The
|
|
64189
|
+
* "integer-bound" forms return an integer-valued float (the result of
|
|
64190
|
+
* `floor`), matching the convention used by `Floor` and other ostensibly
|
|
64191
|
+
* integer-returning operators in this target.
|
|
64192
|
+
*
|
|
64193
|
+
* - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
|
|
64194
|
+
* Only meaningful in fragment shaders (gl_FragCoord is FS-only).
|
|
64195
|
+
* - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
|
|
64196
|
+
* caller must provide an explicit seed.
|
|
64197
|
+
* - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
|
|
64198
|
+
* - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
|
|
64199
|
+
* integer-valued float in {0, 1, ..., n-1}. The seed is derived from
|
|
64200
|
+
* `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
|
|
64201
|
+
* - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
|
|
64202
|
+
*
|
|
64203
|
+
* JS-side `Random` has matching semantics (see `library/core.ts`'s
|
|
64204
|
+
* polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
|
|
64205
|
+
* a similar value, not bit-identical, due to fp64 vs fp32 and platform
|
|
64206
|
+
* `sin` differences.
|
|
64207
|
+
*/
|
|
64208
|
+
Random: (args, compile3, target) => {
|
|
64209
|
+
if (args.length === 0) {
|
|
64210
|
+
if (target.language === "wgsl") {
|
|
64211
|
+
throw new Error(
|
|
64212
|
+
"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."
|
|
64213
|
+
);
|
|
64214
|
+
}
|
|
64215
|
+
return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64216
|
+
}
|
|
64217
|
+
if (args.length === 1) {
|
|
64218
|
+
const arg = args[0];
|
|
64219
|
+
if (BaseCompiler.isIntegerValued(arg)) {
|
|
64220
|
+
const compiled = compile3(arg);
|
|
64221
|
+
return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
|
|
64222
|
+
}
|
|
64223
|
+
return `_gpu_random(${compile3(arg)})`;
|
|
64224
|
+
}
|
|
64225
|
+
if (args.length === 2) {
|
|
64226
|
+
if (target.language === "wgsl") {
|
|
64227
|
+
throw new Error(
|
|
64228
|
+
"Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
|
|
64229
|
+
);
|
|
64230
|
+
}
|
|
64231
|
+
const m = compile3(args[0]);
|
|
64232
|
+
const n = compile3(args[1]);
|
|
64233
|
+
const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
|
|
64234
|
+
return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
|
|
64235
|
+
}
|
|
64236
|
+
throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
|
|
64237
|
+
},
|
|
62930
64238
|
// Function (lambda) — not supported in GPU
|
|
62931
64239
|
Function: () => {
|
|
62932
64240
|
throw new Error(
|
|
@@ -63525,6 +64833,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
63525
64833
|
}
|
|
63526
64834
|
return 1.0;
|
|
63527
64835
|
}
|
|
64836
|
+
`;
|
|
64837
|
+
var GPU_GCD_PREAMBLE_GLSL = `
|
|
64838
|
+
float _gpu_gcd(float a, float b) {
|
|
64839
|
+
a = abs(a); b = abs(b);
|
|
64840
|
+
for (int i = 0; i < 32; i++) {
|
|
64841
|
+
if (b < 0.5) break;
|
|
64842
|
+
float t = mod(a, b);
|
|
64843
|
+
a = b;
|
|
64844
|
+
b = t;
|
|
64845
|
+
}
|
|
64846
|
+
return a;
|
|
64847
|
+
}
|
|
64848
|
+
`;
|
|
64849
|
+
var GPU_GCD_PREAMBLE_WGSL = `
|
|
64850
|
+
fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
|
|
64851
|
+
var a = abs(a_in); var b = abs(b_in);
|
|
64852
|
+
for (var i: i32 = 0; i < 32; i++) {
|
|
64853
|
+
if (b < 0.5) { break; }
|
|
64854
|
+
let t = a % b;
|
|
64855
|
+
a = b;
|
|
64856
|
+
b = t;
|
|
64857
|
+
}
|
|
64858
|
+
return a;
|
|
64859
|
+
}
|
|
64860
|
+
`;
|
|
64861
|
+
var GPU_RANDOM_PREAMBLE_GLSL = `
|
|
64862
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64863
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64864
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64865
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64866
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64867
|
+
float _gpu_random(float seed) {
|
|
64868
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64869
|
+
}
|
|
64870
|
+
`;
|
|
64871
|
+
var GPU_RANDOM_PREAMBLE_WGSL = `
|
|
64872
|
+
// Deterministic pseudorandom in [0, 1) from a float seed.
|
|
64873
|
+
// Standard fract-sin hash; reproducible across runs for the same seed.
|
|
64874
|
+
// Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
|
|
64875
|
+
// For high-quality shader random, callers should use a more robust hash
|
|
64876
|
+
// (e.g. PCG or xxHash) and pre-seed it appropriately.
|
|
64877
|
+
fn _gpu_random(seed: f32) -> f32 {
|
|
64878
|
+
return fract(sin(seed * 12.9898) * 43758.5453);
|
|
64879
|
+
}
|
|
64880
|
+
`;
|
|
64881
|
+
var GPU_MEDIAN_PREAMBLE_GLSL = `
|
|
64882
|
+
float _gpu_median_2(float a, float b) {
|
|
64883
|
+
return (a + b) * 0.5;
|
|
64884
|
+
}
|
|
64885
|
+
float _gpu_median_3(float a, float b, float c) {
|
|
64886
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64887
|
+
}
|
|
64888
|
+
float _gpu_median_4(float a, float b, float c, float d) {
|
|
64889
|
+
float lo = max(min(a, b), min(c, d));
|
|
64890
|
+
float hi = min(max(a, b), max(c, d));
|
|
64891
|
+
return (lo + hi) * 0.5;
|
|
64892
|
+
}
|
|
64893
|
+
float _gpu_median_5(float a, float b, float c, float d, float e) {
|
|
64894
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64895
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
|
|
64896
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64897
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64898
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64899
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64900
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64901
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64902
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64903
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64904
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64905
|
+
return v2;
|
|
64906
|
+
}
|
|
64907
|
+
float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
|
|
64908
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
|
|
64909
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64910
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64911
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64912
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64913
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64914
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64915
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64916
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64917
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64918
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64919
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64920
|
+
return (v2 + v3) * 0.5;
|
|
64921
|
+
}
|
|
64922
|
+
float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
|
|
64923
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
|
|
64924
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64925
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64926
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64927
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64928
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64929
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64930
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64931
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64932
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64933
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64934
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64935
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64936
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64937
|
+
return v3;
|
|
64938
|
+
}
|
|
64939
|
+
float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
|
|
64940
|
+
float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
|
|
64941
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64942
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64943
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64944
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
64945
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64946
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64947
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
64948
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
64949
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64950
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64951
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
64952
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
64953
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64954
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64955
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
64956
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
64957
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64958
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64959
|
+
return (v3 + v4) * 0.5;
|
|
64960
|
+
}
|
|
64961
|
+
`;
|
|
64962
|
+
var GPU_MEDIAN_PREAMBLE_WGSL = `
|
|
64963
|
+
fn _gpu_median_2(a: f32, b: f32) -> f32 {
|
|
64964
|
+
return (a + b) * 0.5;
|
|
64965
|
+
}
|
|
64966
|
+
fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
|
|
64967
|
+
return max(min(a, b), min(max(a, b), c));
|
|
64968
|
+
}
|
|
64969
|
+
fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
|
|
64970
|
+
let lo = max(min(a, b), min(c, d));
|
|
64971
|
+
let hi = min(max(a, b), max(c, d));
|
|
64972
|
+
return (lo + hi) * 0.5;
|
|
64973
|
+
}
|
|
64974
|
+
fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
|
|
64975
|
+
// 9-comparator Bose-Nelson sort; v2 holds the median.
|
|
64976
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
|
|
64977
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64978
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
64979
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64980
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64981
|
+
t=min(v0,v3); v3=max(v0,v3); v0=t;
|
|
64982
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64983
|
+
t=min(v1,v4); v4=max(v1,v4); v1=t;
|
|
64984
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64985
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64986
|
+
return v2;
|
|
64987
|
+
}
|
|
64988
|
+
fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
|
|
64989
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
|
|
64990
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
64991
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
64992
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
64993
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
64994
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
64995
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
64996
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
64997
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
64998
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
64999
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
65000
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65001
|
+
return (v2 + v3) * 0.5;
|
|
65002
|
+
}
|
|
65003
|
+
fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
|
|
65004
|
+
var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
|
|
65005
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
65006
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
65007
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
65008
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
65009
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
65010
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
65011
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
65012
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
65013
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
65014
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
65015
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
65016
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
65017
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65018
|
+
return v3;
|
|
65019
|
+
}
|
|
65020
|
+
fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
|
|
65021
|
+
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;
|
|
65022
|
+
t=min(v0,v1); v1=max(v0,v1); v0=t;
|
|
65023
|
+
t=min(v2,v3); v3=max(v2,v3); v2=t;
|
|
65024
|
+
t=min(v4,v5); v5=max(v4,v5); v4=t;
|
|
65025
|
+
t=min(v6,v7); v7=max(v6,v7); v6=t;
|
|
65026
|
+
t=min(v0,v2); v2=max(v0,v2); v0=t;
|
|
65027
|
+
t=min(v1,v3); v3=max(v1,v3); v1=t;
|
|
65028
|
+
t=min(v4,v6); v6=max(v4,v6); v4=t;
|
|
65029
|
+
t=min(v5,v7); v7=max(v5,v7); v5=t;
|
|
65030
|
+
t=min(v0,v4); v4=max(v0,v4); v0=t;
|
|
65031
|
+
t=min(v1,v5); v5=max(v1,v5); v1=t;
|
|
65032
|
+
t=min(v2,v6); v6=max(v2,v6); v2=t;
|
|
65033
|
+
t=min(v3,v7); v7=max(v3,v7); v3=t;
|
|
65034
|
+
t=min(v1,v2); v2=max(v1,v2); v1=t;
|
|
65035
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65036
|
+
t=min(v5,v6); v6=max(v5,v6); v5=t;
|
|
65037
|
+
t=min(v3,v5); v5=max(v3,v5); v3=t;
|
|
65038
|
+
t=min(v2,v4); v4=max(v2,v4); v2=t;
|
|
65039
|
+
t=min(v3,v4); v4=max(v3,v4); v3=t;
|
|
65040
|
+
return (v3 + v4) * 0.5;
|
|
65041
|
+
}
|
|
63528
65042
|
`;
|
|
63529
65043
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
63530
65044
|
float _gpu_srgb_to_linear(float c) {
|
|
@@ -64203,6 +65717,12 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
|
64203
65717
|
if (code.includes("_fractal_")) {
|
|
64204
65718
|
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
64205
65719
|
}
|
|
65720
|
+
if (code.includes("_gpu_random"))
|
|
65721
|
+
preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
|
|
65722
|
+
if (code.includes("_gpu_gcd"))
|
|
65723
|
+
preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
|
|
65724
|
+
if (code.includes("_gpu_median_"))
|
|
65725
|
+
preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
|
|
64206
65726
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
64207
65727
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
64208
65728
|
}
|
|
@@ -66428,6 +67948,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
66428
67948
|
_timeLimit = 2e3;
|
|
66429
67949
|
_iterationLimit = 1024;
|
|
66430
67950
|
_recursionLimit = 1024;
|
|
67951
|
+
_maxCollectionSize = 1e4;
|
|
66431
67952
|
_deadline = void 0;
|
|
66432
67953
|
_isVerifying = false;
|
|
66433
67954
|
get timeLimit() {
|
|
@@ -66448,6 +67969,12 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
66448
67969
|
set recursionLimit(value) {
|
|
66449
67970
|
this._recursionLimit = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
66450
67971
|
}
|
|
67972
|
+
get maxCollectionSize() {
|
|
67973
|
+
return this._maxCollectionSize;
|
|
67974
|
+
}
|
|
67975
|
+
set maxCollectionSize(value) {
|
|
67976
|
+
this._maxCollectionSize = value <= 0 ? Number.POSITIVE_INFINITY : value;
|
|
67977
|
+
}
|
|
66451
67978
|
get deadline() {
|
|
66452
67979
|
return this._deadline;
|
|
66453
67980
|
}
|
|
@@ -68908,6 +70435,23 @@ ${code}`;
|
|
|
68908
70435
|
set recursionLimit(t) {
|
|
68909
70436
|
this._runtimeState.recursionLimit = t;
|
|
68910
70437
|
}
|
|
70438
|
+
/** Maximum number of elements a collection may have when materialized
|
|
70439
|
+
* (converted from a lazy form to a `List`). Default: 10,000.
|
|
70440
|
+
*
|
|
70441
|
+
* When a materialization would exceed this size, the operation leaves
|
|
70442
|
+
* the expression in its lazy form. Consumers can detect oversize
|
|
70443
|
+
* collections via the symbolic form's `count`.
|
|
70444
|
+
*
|
|
70445
|
+
* Set to `Infinity` (or `0` / a negative number) to disable the cap.
|
|
70446
|
+
*
|
|
70447
|
+
* @experimental
|
|
70448
|
+
*/
|
|
70449
|
+
get maxCollectionSize() {
|
|
70450
|
+
return this._runtimeState.maxCollectionSize;
|
|
70451
|
+
}
|
|
70452
|
+
set maxCollectionSize(t) {
|
|
70453
|
+
this._runtimeState.maxCollectionSize = t;
|
|
70454
|
+
}
|
|
68911
70455
|
/**
|
|
68912
70456
|
* Flag to prevent infinite recursion in the verify/ask/equality checking cycle.
|
|
68913
70457
|
*
|
|
@@ -69184,6 +70728,36 @@ ${code}`;
|
|
|
69184
70728
|
lookupDefinition(id) {
|
|
69185
70729
|
return lookupDefinition(this, id);
|
|
69186
70730
|
}
|
|
70731
|
+
normalizeIdentifier(latex) {
|
|
70732
|
+
if (!latex) return "";
|
|
70733
|
+
if (isValidSymbol(latex)) return latex;
|
|
70734
|
+
this.pushScope();
|
|
70735
|
+
try {
|
|
70736
|
+
const expr2 = this.parse(latex);
|
|
70737
|
+
if (isSymbol2(expr2)) return expr2.symbol;
|
|
70738
|
+
} finally {
|
|
70739
|
+
this.popScope();
|
|
70740
|
+
}
|
|
70741
|
+
return "";
|
|
70742
|
+
}
|
|
70743
|
+
operatorInfo(head) {
|
|
70744
|
+
const def = this.lookupDefinition(head);
|
|
70745
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
70746
|
+
const op = def.operator;
|
|
70747
|
+
return {
|
|
70748
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
70749
|
+
signature: op.signature
|
|
70750
|
+
};
|
|
70751
|
+
}
|
|
70752
|
+
symbolInfo(name) {
|
|
70753
|
+
const def = this.lookupDefinition(name);
|
|
70754
|
+
if (!def || !isValueDef(def)) return void 0;
|
|
70755
|
+
const v = def.value;
|
|
70756
|
+
return {
|
|
70757
|
+
kind: v.isConstant ? "constant" : "variable",
|
|
70758
|
+
type: v.type
|
|
70759
|
+
};
|
|
70760
|
+
}
|
|
69187
70761
|
/**
|
|
69188
70762
|
* Associate a new definition to a symbol in the current context.
|
|
69189
70763
|
*
|
|
@@ -69471,6 +71045,7 @@ ${code}`;
|
|
|
69471
71045
|
const def = this.lookupDefinition(id);
|
|
69472
71046
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
69473
71047
|
},
|
|
71048
|
+
tolerance: this.tolerance,
|
|
69474
71049
|
...this._latexOptions,
|
|
69475
71050
|
...parseOpts
|
|
69476
71051
|
});
|
|
@@ -69635,14 +71210,14 @@ ${code}`;
|
|
|
69635
71210
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
69636
71211
|
|
|
69637
71212
|
// src/compute-engine.ts
|
|
69638
|
-
var version = "0.
|
|
71213
|
+
var version = "0.58.0";
|
|
69639
71214
|
ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
|
|
69640
71215
|
_setDefaultEngineFactory(
|
|
69641
71216
|
() => new ComputeEngine({ latexSyntax: new LatexSyntax() })
|
|
69642
71217
|
);
|
|
69643
71218
|
globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
|
|
69644
71219
|
ComputeEngine: ComputeEngine.prototype.constructor,
|
|
69645
|
-
version: "0.
|
|
71220
|
+
version: "0.58.0"
|
|
69646
71221
|
};
|
|
69647
71222
|
return __toCommonJS(compute_engine_exports);
|
|
69648
71223
|
})();
|