@cortex-js/compute-engine 0.57.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.
Files changed (259) hide show
  1. package/dist/compile.esm.js +690 -53
  2. package/dist/compile.min.esm.js +251 -51
  3. package/dist/compile.min.umd.cjs +251 -51
  4. package/dist/compile.umd.cjs +690 -53
  5. package/dist/compute-engine.esm.js +1079 -132
  6. package/dist/compute-engine.min.esm.js +271 -71
  7. package/dist/compute-engine.min.umd.cjs +270 -70
  8. package/dist/compute-engine.umd.cjs +1079 -132
  9. package/dist/core.esm.js +1078 -131
  10. package/dist/core.min.esm.js +269 -69
  11. package/dist/core.min.umd.cjs +269 -69
  12. package/dist/core.umd.cjs +1078 -131
  13. package/dist/interval.esm.js +132 -15
  14. package/dist/interval.min.esm.js +6 -6
  15. package/dist/interval.min.umd.cjs +6 -6
  16. package/dist/interval.umd.cjs +132 -15
  17. package/dist/latex-syntax.esm.js +132 -15
  18. package/dist/latex-syntax.min.esm.js +6 -6
  19. package/dist/latex-syntax.min.umd.cjs +6 -6
  20. package/dist/latex-syntax.umd.cjs +132 -15
  21. package/dist/math-json.esm.js +2 -2
  22. package/dist/math-json.min.esm.js +2 -2
  23. package/dist/math-json.min.umd.cjs +2 -2
  24. package/dist/math-json.umd.cjs +2 -2
  25. package/dist/numerics.esm.js +38 -3
  26. package/dist/numerics.min.esm.js +3 -3
  27. package/dist/numerics.min.umd.cjs +4 -4
  28. package/dist/numerics.umd.cjs +38 -3
  29. package/dist/types/big-decimal/big-decimal.d.ts +1 -1
  30. package/dist/types/big-decimal/index.d.ts +1 -1
  31. package/dist/types/big-decimal/transcendentals.d.ts +1 -1
  32. package/dist/types/big-decimal/utils.d.ts +1 -1
  33. package/dist/types/common/ansi-codes.d.ts +1 -1
  34. package/dist/types/common/configuration-change.d.ts +1 -1
  35. package/dist/types/common/fuzzy-string-match.d.ts +1 -1
  36. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  37. package/dist/types/common/interruptible.d.ts +1 -1
  38. package/dist/types/common/one-of.d.ts +1 -1
  39. package/dist/types/common/signals.d.ts +1 -1
  40. package/dist/types/common/type/ast-nodes.d.ts +1 -1
  41. package/dist/types/common/type/boxed-type.d.ts +1 -1
  42. package/dist/types/common/type/lexer.d.ts +1 -1
  43. package/dist/types/common/type/parse.d.ts +1 -1
  44. package/dist/types/common/type/parser.d.ts +1 -1
  45. package/dist/types/common/type/primitive.d.ts +1 -1
  46. package/dist/types/common/type/reduce.d.ts +1 -1
  47. package/dist/types/common/type/serialize.d.ts +1 -1
  48. package/dist/types/common/type/subtype.d.ts +1 -1
  49. package/dist/types/common/type/type-builder.d.ts +1 -1
  50. package/dist/types/common/type/types.d.ts +1 -1
  51. package/dist/types/common/type/utils.d.ts +1 -1
  52. package/dist/types/common/utils.d.ts +1 -1
  53. package/dist/types/compile.d.ts +1 -1
  54. package/dist/types/compute-engine/assume.d.ts +1 -1
  55. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +3 -1
  56. package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
  57. package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
  58. package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
  59. package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
  60. package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
  61. package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
  62. package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
  63. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
  64. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
  65. package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +7 -1
  66. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
  67. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
  68. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
  69. package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
  70. package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
  71. package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
  72. package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
  73. package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
  74. package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
  75. package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
  76. package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
  77. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  78. package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
  79. package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
  80. package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
  81. package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +22 -10
  82. package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
  83. package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
  84. package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
  85. package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
  86. package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
  87. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  88. package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
  89. package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
  90. package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
  91. package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
  92. package/dist/types/compute-engine/boxed-expression/rules.d.ts +1 -1
  93. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
  94. package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
  95. package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
  96. package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
  97. package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
  98. package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
  99. package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
  100. package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
  101. package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
  102. package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
  103. package/dist/types/compute-engine/collection-utils.d.ts +1 -1
  104. package/dist/types/compute-engine/compilation/base-compiler.d.ts +8 -1
  105. package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
  106. package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
  107. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  108. package/dist/types/compute-engine/compilation/gpu-target.d.ts +44 -1
  109. package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
  110. package/dist/types/compute-engine/compilation/javascript-target.d.ts +1 -1
  111. package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
  112. package/dist/types/compute-engine/compilation/types.d.ts +1 -1
  113. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  114. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  115. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-runtime-state.d.ts +4 -1
  126. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  131. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  132. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  133. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  134. package/dist/types/compute-engine/global-types.d.ts +1 -1
  135. package/dist/types/compute-engine/index.d.ts +17 -2
  136. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  142. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  143. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +1 -1
  144. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  145. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  146. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  147. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +1 -1
  148. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  149. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  150. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
  151. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  152. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  153. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
  154. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  155. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  156. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  157. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  158. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
  159. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
  160. package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +1 -1
  161. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
  162. package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
  163. package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
  164. package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
  165. package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
  166. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  167. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  168. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
  169. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  170. package/dist/types/compute-engine/latex-syntax/types.d.ts +1 -1
  171. package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
  172. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  173. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  174. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  175. package/dist/types/compute-engine/library/colors.d.ts +1 -1
  176. package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
  177. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  178. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  179. package/dist/types/compute-engine/library/core.d.ts +1 -1
  180. package/dist/types/compute-engine/library/fractals.d.ts +1 -1
  181. package/dist/types/compute-engine/library/library.d.ts +1 -1
  182. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  183. package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
  184. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  185. package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
  186. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  187. package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
  188. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  189. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  190. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  191. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  192. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  193. package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
  194. package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
  195. package/dist/types/compute-engine/library/units.d.ts +1 -1
  196. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  197. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
  198. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
  199. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
  200. package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
  201. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  202. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  203. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  204. package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
  205. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  206. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  207. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  208. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  209. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  210. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  211. package/dist/types/compute-engine/numerics/random.d.ts +23 -0
  212. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  213. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  214. package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
  215. package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
  216. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  217. package/dist/types/compute-engine/numerics/types.d.ts +1 -1
  218. package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
  219. package/dist/types/compute-engine/oeis.d.ts +1 -1
  220. package/dist/types/compute-engine/sequence.d.ts +1 -1
  221. package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
  222. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  223. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  224. package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
  225. package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
  226. package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
  227. package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
  228. package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
  229. package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
  230. package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
  231. package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
  232. package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
  233. package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
  234. package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
  235. package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
  236. package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
  237. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  238. package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
  239. package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
  240. package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
  241. package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
  242. package/dist/types/compute-engine/types-definitions.d.ts +1 -1
  243. package/dist/types/compute-engine/types-engine.d.ts +34 -1
  244. package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
  245. package/dist/types/compute-engine/types-expression.d.ts +69 -1
  246. package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
  247. package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
  248. package/dist/types/compute-engine/types-serialization.d.ts +1 -1
  249. package/dist/types/compute-engine/types.d.ts +1 -1
  250. package/dist/types/compute-engine.d.ts +1 -1
  251. package/dist/types/core.d.ts +1 -1
  252. package/dist/types/interval.d.ts +1 -1
  253. package/dist/types/latex-syntax.d.ts +2 -2
  254. package/dist/types/math-json/symbols.d.ts +1 -1
  255. package/dist/types/math-json/types.d.ts +1 -1
  256. package/dist/types/math-json/utils.d.ts +1 -1
  257. package/dist/types/math-json.d.ts +2 -2
  258. package/dist/types/numerics.d.ts +1 -1
  259. package/package.json +1 -1
package/dist/core.umd.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /** ComputeEngineCore 0.57.0 */
1
+ /** ComputeEngineCore 0.58.0 */
2
2
  (function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngineCore = {}));})(this, (function (exports) { 'use strict';
3
3
  var ComputeEngineCore = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -4315,7 +4315,42 @@ var ComputeEngineCore = (() => {
4315
4315
  if (b === "nothing") return a;
4316
4316
  if (isSubtype(a, b)) return b;
4317
4317
  if (isSubtype(b, a)) return a;
4318
- return superType(a, b);
4318
+ const sup = superType(a, b);
4319
+ if (LOSSY_SUPERTYPE.has(sup)) return unionTypes(a, b);
4320
+ return sup;
4321
+ }
4322
+ var LOSSY_SUPERTYPE = /* @__PURE__ */ new Set([
4323
+ "scalar",
4324
+ "value",
4325
+ "function",
4326
+ "expression",
4327
+ "collection",
4328
+ "indexed_collection",
4329
+ "list",
4330
+ "set",
4331
+ "tuple",
4332
+ "record",
4333
+ "dictionary",
4334
+ "map",
4335
+ "any"
4336
+ ]);
4337
+ function unionTypes(a, b) {
4338
+ const members = [];
4339
+ const push = (t) => {
4340
+ if (typeof t === "object" && t.kind === "union") {
4341
+ for (const m of t.types) push(m);
4342
+ return;
4343
+ }
4344
+ const key = typeof t === "string" ? t : JSON.stringify(t);
4345
+ if (!members.some(
4346
+ (m) => (typeof m === "string" ? m : JSON.stringify(m)) === key
4347
+ ))
4348
+ members.push(t);
4349
+ };
4350
+ push(a);
4351
+ push(b);
4352
+ if (members.length === 1) return members[0];
4353
+ return { kind: "union", types: members };
4319
4354
  }
4320
4355
  function narrow(...types) {
4321
4356
  if (types.length === 0) return "nothing";
@@ -4393,7 +4428,7 @@ var ComputeEngineCore = (() => {
4393
4428
  if (type2.kind === "set") return type2.elements;
4394
4429
  if (type2.kind === "tuple") return widen(...type2.elements.map((x) => x.type));
4395
4430
  if (type2.kind === "dictionary")
4396
- return parseType(`tuple<string, ${type2.values}>`);
4431
+ return parseType(`tuple<string, ${typeToString(type2.values)}>`);
4397
4432
  if (type2.kind === "record") {
4398
4433
  return parseType(
4399
4434
  `tuple<string, ${typeToString(widen(...Object.values(type2.elements)))}>`
@@ -5939,6 +5974,84 @@ var ComputeEngineCore = (() => {
5939
5974
  }
5940
5975
 
5941
5976
  // src/compute-engine/boxed-expression/inequality-bounds.ts
5977
+ function extractIntervalBounds(expr2, symbol2) {
5978
+ if (isFunction2(expr2, "When")) {
5979
+ const cond = expr2.op2;
5980
+ if (!cond) return void 0;
5981
+ return extractIntervalBounds(cond, symbol2);
5982
+ }
5983
+ if (isFunction2(expr2, "Multiply")) {
5984
+ const ops = expr2.ops;
5985
+ if (!ops) return void 0;
5986
+ const merged = {};
5987
+ for (const sub2 of ops) {
5988
+ if (isFunction2(sub2, "When")) {
5989
+ const sub_ = extractIntervalBounds(sub2, symbol2);
5990
+ if (sub_ !== void 0) _mergeBounds(merged, sub_);
5991
+ }
5992
+ }
5993
+ return _hasAnyBound(merged) ? merged : void 0;
5994
+ }
5995
+ const result = {};
5996
+ if (isFunction2(expr2, "And")) {
5997
+ const ops = expr2.ops;
5998
+ if (!ops) return void 0;
5999
+ for (const sub2 of ops) {
6000
+ const subBounds = extractIntervalBounds(sub2, symbol2);
6001
+ if (subBounds === void 0) continue;
6002
+ _mergeBounds(result, subBounds);
6003
+ }
6004
+ return _hasAnyBound(result) ? result : void 0;
6005
+ }
6006
+ const op = expr2.operator;
6007
+ if ((op === "Less" || op === "LessEqual" || op === "Greater" || op === "GreaterEqual") && isFunction2(expr2)) {
6008
+ const isStrict = op === "Less" || op === "Greater";
6009
+ const ops = expr2.ops;
6010
+ if (!ops || ops.length < 2) return void 0;
6011
+ const flipped = op === "Greater" || op === "GreaterEqual" ? [...ops].reverse() : ops;
6012
+ for (let i = 0; i < flipped.length; i++) {
6013
+ if (isSymbol2(flipped[i], symbol2)) {
6014
+ if (i > 0) {
6015
+ const candidate = flipped[i - 1];
6016
+ if (result.lower === void 0 || candidate.isGreater(result.lower) === true) {
6017
+ result.lower = candidate;
6018
+ result.lowerStrict = isStrict;
6019
+ }
6020
+ }
6021
+ if (i < flipped.length - 1) {
6022
+ const candidate = flipped[i + 1];
6023
+ if (result.upper === void 0 || candidate.isLess(result.upper) === true) {
6024
+ result.upper = candidate;
6025
+ result.upperStrict = isStrict;
6026
+ }
6027
+ }
6028
+ }
6029
+ }
6030
+ return _hasAnyBound(result) ? result : void 0;
6031
+ }
6032
+ return void 0;
6033
+ }
6034
+ function _mergeBounds(into, from) {
6035
+ if (from.lower !== void 0) {
6036
+ if (into.lower === void 0 || from.lower.isGreater(into.lower) === true) {
6037
+ into.lower = from.lower;
6038
+ into.lowerStrict = from.lowerStrict;
6039
+ } else if (from.lower.isSame(into.lower)) {
6040
+ into.lowerStrict = into.lowerStrict || from.lowerStrict;
6041
+ }
6042
+ }
6043
+ if (from.upper !== void 0) {
6044
+ if (into.upper === void 0 || from.upper.isLess(into.upper) === true) {
6045
+ into.upper = from.upper;
6046
+ into.upperStrict = from.upperStrict;
6047
+ } else if (from.upper.isSame(into.upper)) {
6048
+ into.upperStrict = into.upperStrict || from.upperStrict;
6049
+ }
6050
+ }
6051
+ }
6052
+ function _hasAnyBound(b) {
6053
+ return b.lower !== void 0 || b.upper !== void 0;
6054
+ }
5942
6055
  function getInequalityBoundsFromAssumptions(ce, symbol2) {
5943
6056
  const result = {};
5944
6057
  const assumptions = ce.context?.assumptions;
@@ -5955,8 +6068,8 @@ var ComputeEngineCore = (() => {
5955
6068
  const isStrict = op === "Less";
5956
6069
  if (isFunction2(lhs, "Negate") && isSymbol2(lhs.op1, symbol2)) {
5957
6070
  const bound = ce.Zero;
5958
- if (result.lowerBound === void 0 || bound.isGreater(result.lowerBound) === true) {
5959
- result.lowerBound = bound;
6071
+ if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
6072
+ result.lower = bound;
5960
6073
  result.lowerStrict = isStrict;
5961
6074
  }
5962
6075
  }
@@ -5975,16 +6088,16 @@ var ComputeEngineCore = (() => {
5975
6088
  }
5976
6089
  if (hasNegatedSymbol && constantSum !== 0) {
5977
6090
  const bound = ce.expr(constantSum);
5978
- if (result.lowerBound === void 0 || bound.isGreater(result.lowerBound) === true) {
5979
- result.lowerBound = bound;
6091
+ if (result.lower === void 0 || bound.isGreater(result.lower) === true) {
6092
+ result.lower = bound;
5980
6093
  result.lowerStrict = isStrict;
5981
6094
  }
5982
6095
  }
5983
6096
  }
5984
6097
  if (isSymbol2(lhs, symbol2)) {
5985
6098
  const bound = ce.Zero;
5986
- if (result.upperBound === void 0 || bound.isLess(result.upperBound) === true) {
5987
- result.upperBound = bound;
6099
+ if (result.upper === void 0 || bound.isLess(result.upper) === true) {
6100
+ result.upper = bound;
5988
6101
  result.upperStrict = isStrict;
5989
6102
  }
5990
6103
  }
@@ -6003,8 +6116,8 @@ var ComputeEngineCore = (() => {
6003
6116
  }
6004
6117
  if (hasSymbol && constantSum !== 0) {
6005
6118
  const bound = ce.expr(-constantSum);
6006
- if (result.upperBound === void 0 || bound.isLess(result.upperBound) === true) {
6007
- result.upperBound = bound;
6119
+ if (result.upper === void 0 || bound.isLess(result.upper) === true) {
6120
+ result.upper = bound;
6008
6121
  result.upperStrict = isStrict;
6009
6122
  }
6010
6123
  }
@@ -6224,8 +6337,8 @@ var ComputeEngineCore = (() => {
6224
6337
  const bounds = getInequalityBoundsFromAssumptions(a.engine, b.symbol);
6225
6338
  const aNum = typeof a.numericValue === "number" ? a.numericValue : a.numericValue.re;
6226
6339
  if (aNum !== void 0 && Number.isFinite(aNum)) {
6227
- if (bounds.lowerBound !== void 0) {
6228
- const lb = bounds.lowerBound;
6340
+ if (bounds.lower !== void 0) {
6341
+ const lb = bounds.lower;
6229
6342
  const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
6230
6343
  if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
6231
6344
  if (lowerNum > aNum) return "<";
@@ -6233,8 +6346,8 @@ var ComputeEngineCore = (() => {
6233
6346
  if (lowerNum === aNum && !bounds.lowerStrict) return "<=";
6234
6347
  }
6235
6348
  }
6236
- if (bounds.upperBound !== void 0) {
6237
- const ub = bounds.upperBound;
6349
+ if (bounds.upper !== void 0) {
6350
+ const ub = bounds.upper;
6238
6351
  const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
6239
6352
  if (upperNum !== void 0 && Number.isFinite(upperNum)) {
6240
6353
  if (upperNum < aNum) return ">";
@@ -6264,8 +6377,8 @@ var ComputeEngineCore = (() => {
6264
6377
  if (typeof b === "number") {
6265
6378
  if (isSymbol2(a)) {
6266
6379
  const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
6267
- if (bounds.lowerBound !== void 0) {
6268
- const lb = bounds.lowerBound;
6380
+ if (bounds.lower !== void 0) {
6381
+ const lb = bounds.lower;
6269
6382
  const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
6270
6383
  if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
6271
6384
  if (lowerNum > b) return ">";
@@ -6273,8 +6386,8 @@ var ComputeEngineCore = (() => {
6273
6386
  if (lowerNum === b && !bounds.lowerStrict) return ">=";
6274
6387
  }
6275
6388
  }
6276
- if (bounds.upperBound !== void 0) {
6277
- const ub = bounds.upperBound;
6389
+ if (bounds.upper !== void 0) {
6390
+ const ub = bounds.upper;
6278
6391
  const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
6279
6392
  if (upperNum !== void 0 && Number.isFinite(upperNum)) {
6280
6393
  if (upperNum < b) return "<";
@@ -6330,8 +6443,8 @@ var ComputeEngineCore = (() => {
6330
6443
  const bounds = getInequalityBoundsFromAssumptions(a.engine, a.symbol);
6331
6444
  const bNum = typeof b.numericValue === "number" ? b.numericValue : b.numericValue.re;
6332
6445
  if (bNum !== void 0 && Number.isFinite(bNum)) {
6333
- if (bounds.lowerBound !== void 0) {
6334
- const lb = bounds.lowerBound;
6446
+ if (bounds.lower !== void 0) {
6447
+ const lb = bounds.lower;
6335
6448
  const lowerNum = isNumber(lb) ? typeof lb.numericValue === "number" ? lb.numericValue : lb.numericValue.re : void 0;
6336
6449
  if (lowerNum !== void 0 && Number.isFinite(lowerNum)) {
6337
6450
  if (lowerNum > bNum) return ">";
@@ -6339,8 +6452,8 @@ var ComputeEngineCore = (() => {
6339
6452
  if (lowerNum === bNum && !bounds.lowerStrict) return ">=";
6340
6453
  }
6341
6454
  }
6342
- if (bounds.upperBound !== void 0) {
6343
- const ub = bounds.upperBound;
6455
+ if (bounds.upper !== void 0) {
6456
+ const ub = bounds.upper;
6344
6457
  const upperNum = isNumber(ub) ? typeof ub.numericValue === "number" ? ub.numericValue : ub.numericValue.re : void 0;
6345
6458
  if (upperNum !== void 0 && Number.isFinite(upperNum)) {
6346
6459
  if (upperNum < bNum) return "<";
@@ -6878,6 +6991,12 @@ var ComputeEngineCore = (() => {
6878
6991
  scoped = false;
6879
6992
  signature;
6880
6993
  inferredSignature = true;
6994
+ /** True if this operator definition was created from a user-defined
6995
+ * function literal (e.g. via `ce.assign('f', ce.parse('x \\mapsto x^2'))`).
6996
+ * Used to enable auto-broadcasting when applied to indexed collections.
6997
+ * @internal
6998
+ */
6999
+ _isLambda = false;
6881
7000
  type;
6882
7001
  sgn;
6883
7002
  eq;
@@ -7035,6 +7154,8 @@ var ComputeEngineCore = (() => {
7035
7154
  this.engine._typeResolver
7036
7155
  );
7037
7156
  }
7157
+ if (isFunction2(boxedFn) && boxedFn.operator === "Function")
7158
+ this._isLambda = true;
7038
7159
  const fn = applicable(boxedFn);
7039
7160
  evaluate2 = (xs, _options) => fn(xs);
7040
7161
  Object.defineProperty(evaluate2, "toString", {
@@ -8351,6 +8472,29 @@ var ComputeEngineCore = (() => {
8351
8472
  get isReal() {
8352
8473
  return void 0;
8353
8474
  }
8475
+ toSignedFunction() {
8476
+ const op = this.operator;
8477
+ if (op === void 0 || this.ops === void 0 || this.ops.length < 2) {
8478
+ return void 0;
8479
+ }
8480
+ const [lhs, rhs] = this.ops;
8481
+ const engine = this.engine;
8482
+ switch (op) {
8483
+ case "Equal":
8484
+ case "NotEqual":
8485
+ case "Less":
8486
+ case "LessEqual":
8487
+ return engine.function("Subtract", [lhs, rhs]);
8488
+ case "Greater":
8489
+ case "GreaterEqual":
8490
+ return engine.function("Subtract", [rhs, lhs]);
8491
+ default:
8492
+ return void 0;
8493
+ }
8494
+ }
8495
+ getInterval(symbol2) {
8496
+ return extractIntervalBounds(this, symbol2);
8497
+ }
8354
8498
  simplify(_options) {
8355
8499
  return this;
8356
8500
  }
@@ -10369,15 +10513,16 @@ var ComputeEngineCore = (() => {
10369
10513
  precedence: ASSIGNMENT_PRECEDENCE,
10370
10514
  parse: parseAssign
10371
10515
  },
10372
- // General colon operator (type annotation, mapping notation)
10373
- // Precedence below assignment (260) so `:=` takes priority,
10374
- // and below arrows (270) so `f: A \to B` parses as `Colon(f, To(A, B))`
10516
+ // General colon operator (type annotation, mapping notation, Desmos piecewise)
10517
+ // Precedence below comparisons (245) so `cond : val` (Desmos compact piecewise)
10518
+ // parses as `Colon(cond, val)`, and below arrows (270) so
10519
+ // `f: A \to B` parses as `Colon(f, To(A, B))`.
10375
10520
  {
10376
10521
  name: "Colon",
10377
10522
  latexTrigger: ":",
10378
10523
  kind: "infix",
10379
10524
  associativity: "right",
10380
- precedence: 250,
10525
+ precedence: 240,
10381
10526
  serialize: (serializer, expr2) => joinLatex([
10382
10527
  serializer.serialize(operand(expr2, 1)),
10383
10528
  "\\colon",
@@ -10388,7 +10533,7 @@ var ComputeEngineCore = (() => {
10388
10533
  latexTrigger: "\\colon",
10389
10534
  kind: "infix",
10390
10535
  associativity: "right",
10391
- precedence: 250,
10536
+ precedence: 240,
10392
10537
  parse: "Colon"
10393
10538
  },
10394
10539
  {
@@ -11958,7 +12103,10 @@ var ComputeEngineCore = (() => {
11958
12103
  p.skipVisualSpace();
11959
12104
  const isComma = p.peek === ",";
11960
12105
  p.index = saved;
11961
- return isComma;
12106
+ if (isComma) return true;
12107
+ if (peekKeyword(p, "where")) return true;
12108
+ if (peekKeyword(p, "with")) return true;
12109
+ return false;
11962
12110
  }
11963
12111
  };
11964
12112
  const elements = [];
@@ -11999,6 +12147,25 @@ var ComputeEngineCore = (() => {
11999
12147
  parser.skipVisualSpace();
12000
12148
  } while (parser.match(","));
12001
12149
  if (bindings.length === 0) return null;
12150
+ const forStart = parser.index;
12151
+ if (matchKeyword(parser, "for")) {
12152
+ const loop = parseForComprehension(parser, lhs, until);
12153
+ if (loop) {
12154
+ const block2 = [];
12155
+ for (const b of bindings) {
12156
+ const normalized = normalizeLocalAssign(b);
12157
+ if (operator(normalized) === "Assign") {
12158
+ block2.push(["Declare", operand(normalized, 1)]);
12159
+ block2.push(normalized);
12160
+ } else {
12161
+ block2.push(normalized);
12162
+ }
12163
+ }
12164
+ block2.push(loop);
12165
+ return ["Block", ...block2];
12166
+ }
12167
+ parser.index = forStart;
12168
+ }
12002
12169
  const block = [];
12003
12170
  for (const b of bindings) {
12004
12171
  const normalized = normalizeLocalAssign(b);
@@ -12212,6 +12379,17 @@ var ComputeEngineCore = (() => {
12212
12379
  const upperExpr = openRight ? ["Open", upper] : upper;
12213
12380
  return ["Interval", lowerExpr, upperExpr];
12214
12381
  }
12382
+ var COMPARISON_HEADS = /* @__PURE__ */ new Set([
12383
+ "Less",
12384
+ "LessEqual",
12385
+ "Greater",
12386
+ "GreaterEqual",
12387
+ "Equal",
12388
+ "NotEqual",
12389
+ "And",
12390
+ "Or",
12391
+ "Not"
12392
+ ]);
12215
12393
  var DEFINITIONS_SETS = [
12216
12394
  //
12217
12395
  // Constants
@@ -12470,18 +12648,58 @@ var ComputeEngineCore = (() => {
12470
12648
  closeTrigger: "}",
12471
12649
  parse: (_parser, body) => {
12472
12650
  if (isEmptySequence(body)) return "EmptySet";
12651
+ if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
12652
+ body = operand(body, 1);
12653
+ }
12473
12654
  const h = operator(body);
12474
- if (h === "Divides" || h === "Colon") {
12655
+ if (h === "Divides") {
12475
12656
  const expr2 = operand(body, 1);
12476
12657
  const condition = operand(body, 2);
12477
12658
  if (expr2 !== null && condition !== null)
12478
12659
  return ["Set", expr2, ["Condition", condition]];
12479
12660
  }
12480
- if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
12481
- body = operand(body, 1);
12661
+ if (h === "Colon") {
12662
+ const lhs = operand(body, 1);
12663
+ const rhs = operand(body, 2);
12664
+ if (lhs !== null && rhs !== null) {
12665
+ const lhsOp = operator(lhs);
12666
+ if (lhsOp !== null && COMPARISON_HEADS.has(lhsOp)) {
12667
+ return ["Which", lhs, rhs];
12668
+ }
12669
+ return ["Set", lhs, ["Condition", rhs]];
12670
+ }
12482
12671
  }
12483
- if (operator(body) !== "Sequence") return ["Set", body];
12484
- return ["Set", ...operands(body)];
12672
+ if (h === "Sequence") {
12673
+ const elements = operands(body);
12674
+ const colonElements = elements.filter((el) => operator(el) === "Colon");
12675
+ const allPiecewise = colonElements.length > 0 && colonElements.every((el) => {
12676
+ const lhs = operand(el, 1);
12677
+ const lhsOp = lhs !== null ? operator(lhs) : null;
12678
+ return lhsOp !== null && COMPARISON_HEADS.has(lhsOp);
12679
+ });
12680
+ if (allPiecewise) {
12681
+ const whichOps = [];
12682
+ for (let i = 0; i < elements.length; i++) {
12683
+ const el = elements[i];
12684
+ if (operator(el) === "Colon") {
12685
+ const cond = operand(el, 1);
12686
+ const val = operand(el, 2);
12687
+ if (cond === null || val === null) {
12688
+ return ["Set", ...elements];
12689
+ }
12690
+ whichOps.push(cond, val);
12691
+ } else {
12692
+ if (i !== elements.length - 1) {
12693
+ return ["Set", ...elements];
12694
+ }
12695
+ whichOps.push("True", el);
12696
+ }
12697
+ }
12698
+ return ["Which", ...whichOps];
12699
+ }
12700
+ return ["Set", ...elements];
12701
+ }
12702
+ return ["Set", body];
12485
12703
  },
12486
12704
  serialize: (serializer, expr2) => {
12487
12705
  if (nops(expr2) === 2 && operator(operand(expr2, 2)) === "Condition") {
@@ -14485,7 +14703,8 @@ var ComputeEngineCore = (() => {
14485
14703
  minPrec: MULTIPLICATION_PRECEDENCE,
14486
14704
  condition: (parser2) => trigCommands[parser2.peek] || (until?.condition?.(parser2) ?? false)
14487
14705
  });
14488
- const appliedFn = args === null ? fn : typeof fn === "string" ? [fn, ...args] : ["Apply", fn, ...args];
14706
+ const head = fn === "Arctan" && args?.length === 2 ? "Arctan2" : fn;
14707
+ const appliedFn = args === null ? fn : typeof head === "string" ? [head, ...args] : ["Apply", head, ...args];
14489
14708
  return sup === null ? appliedFn : ["Power", appliedFn, sup];
14490
14709
  };
14491
14710
  }
@@ -16701,10 +16920,17 @@ var ComputeEngineCore = (() => {
16701
16920
  // The capitalized library entries already exist; these are pure parse
16702
16921
  // aliases so the lowercase names don't land in `unsupported-operator`.
16703
16922
  // ---------------------------------------------------------------------------
16923
+ { latexTrigger: "\\operatorname{count}", parse: "Length" },
16704
16924
  { latexTrigger: "\\operatorname{random}", parse: "Random" },
16705
16925
  { latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
16706
16926
  { latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
16707
16927
  { latexTrigger: "\\operatorname{join}", parse: "Join" },
16928
+ { latexTrigger: "\\operatorname{range}", parse: "Range" },
16929
+ // Note: `\operatorname{with}` (Desmos's local-binding clause) is intentionally
16930
+ // NOT registered here. Use the math-notation equivalent `\operatorname{where}`
16931
+ // (with `\coloneq` for bindings), or register `with` as a custom dictionary
16932
+ // entry at the integration layer — see the "Desmos-Specific Syntax — Prefer
16933
+ // Custom LaTeX Dictionary" section in COMPUTE_ENGINE.md for a worked example.
16708
16934
  // ---------------------------------------------------------------------------
16709
16935
  // Geometric primitive heads. Registered as known typed heads so consumers
16710
16936
  // can branch on the operator name; CE itself doesn't render them. The
@@ -22546,6 +22772,15 @@ var ComputeEngineCore = (() => {
22546
22772
  }
22547
22773
  } else {
22548
22774
  for (const item of t) {
22775
+ const op = item.operator;
22776
+ if (op === "Tuple" || op === "Pair" || op === "Single" || op === "Triple" || op === "Quadruple" || op === "KeyValuePair" || op === "Dictionary" || op === "Set" || op === "Record") {
22777
+ valid = false;
22778
+ return;
22779
+ }
22780
+ if (item.type.type === "string") {
22781
+ valid = false;
22782
+ return;
22783
+ }
22549
22784
  dtype = getSupertype(dtype, getExpressionDatatype(item));
22550
22785
  }
22551
22786
  }
@@ -27581,6 +27816,15 @@ ${lines.join("\n")}`;
27581
27816
  return void 0;
27582
27817
  }
27583
27818
 
27819
+ // src/compute-engine/numerics/random.ts
27820
+ function deterministicRandom(seed) {
27821
+ const v = Math.sin(seed * 12.9898) * 43758.5453;
27822
+ return v - Math.floor(v);
27823
+ }
27824
+ function nextSeed(seed) {
27825
+ return seed + 0.6180339887498949;
27826
+ }
27827
+
27584
27828
  // src/compute-engine/boxed-expression/canonical-utils.ts
27585
27829
  function canonical(ce, xs, scope) {
27586
27830
  if (xs.every((x) => x.isCanonical)) return xs;
@@ -27630,6 +27874,19 @@ ${lines.join("\n")}`;
27630
27874
  indexWhere: void 0
27631
27875
  }
27632
27876
  },
27877
+ Length: {
27878
+ description: "Number of elements in a collection. Returns undefined for non-collections and for infinite collections.",
27879
+ complexity: 4e3,
27880
+ signature: "(any) -> integer",
27881
+ type: () => "integer",
27882
+ evaluate: ([xs], { engine }) => {
27883
+ if (!xs.isCollection) return void 0;
27884
+ if (xs.isEmptyCollection) return engine.Zero;
27885
+ const n = xs.count;
27886
+ if (n === void 0 || !isFinite(n)) return void 0;
27887
+ return engine.number(n);
27888
+ }
27889
+ },
27633
27890
  Tuple: {
27634
27891
  description: "A fixed number of heterogeneous elements",
27635
27892
  complexity: 8200,
@@ -27883,10 +28140,12 @@ ${lines.join("\n")}`;
27883
28140
  const upper = expr2.op2.re;
27884
28141
  let count = expr2.op3.re;
27885
28142
  if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
28143
+ count = Math.floor(count);
27886
28144
  if (!isFinite(lower) || !isFinite(upper)) return void 0;
27887
28145
  if (index < 1 || index > count) return void 0;
28146
+ if (count === 1) return expr2.engine.number(lower);
27888
28147
  return expr2.engine.number(
27889
- lower + (upper - lower) * (index - 1) / count
28148
+ lower + (upper - lower) * (index - 1) / (count - 1)
27890
28149
  );
27891
28150
  },
27892
28151
  iterator: (expr2) => {
@@ -27905,6 +28164,8 @@ ${lines.join("\n")}`;
27905
28164
  !isFinite(expr2.op3.re) ? DEFAULT_LINSPACE_COUNT : expr2.op3.re
27906
28165
  );
27907
28166
  }
28167
+ totalCount = Math.floor(totalCount);
28168
+ const denom = totalCount > 1 ? totalCount - 1 : 1;
27908
28169
  let index = 1;
27909
28170
  return {
27910
28171
  next: () => {
@@ -27913,7 +28174,7 @@ ${lines.join("\n")}`;
27913
28174
  index += 1;
27914
28175
  return {
27915
28176
  value: expr2.engine.number(
27916
- lower + (upper - lower) * (index - 1 - 1) / totalCount
28177
+ lower + (upper - lower) * (index - 1 - 1) / denom
27917
28178
  ),
27918
28179
  done: false
27919
28180
  };
@@ -27929,9 +28190,14 @@ ${lines.join("\n")}`;
27929
28190
  if (t < lower || t > upper) return false;
27930
28191
  let count = expr2.op3.re;
27931
28192
  if (!isFinite(count)) count = DEFAULT_LINSPACE_COUNT;
28193
+ count = Math.floor(count);
27932
28194
  if (count === 0) return false;
27933
- const step = (upper - lower) / count;
27934
- return (t - lower) % step === 0;
28195
+ if (count === 1) return t === lower;
28196
+ const step = (upper - lower) / (count - 1);
28197
+ const k = (t - lower) / step;
28198
+ const tol = expr2.engine.tolerance;
28199
+ const kRounded = Math.round(k);
28200
+ return kRounded >= 0 && kRounded <= count - 1 && Math.abs(k - kRounded) < tol;
27935
28201
  }
27936
28202
  }
27937
28203
  },
@@ -28256,10 +28522,12 @@ ${lines.join("\n")}`;
28256
28522
  description: [
28257
28523
  "Access an element of an indexed collection.",
28258
28524
  "If the index is negative, it is counted from the end.",
28259
- "Multiple indices can be provided to access nested collections (e.g., matrices)."
28525
+ "Multiple indices can be provided to access nested collections (e.g., matrices).",
28526
+ "If the index is a finite collection of booleans, returns the elements where the mask is True.",
28527
+ "If the index is a finite collection of integers, returns the elements at those indices."
28260
28528
  ],
28261
28529
  complexity: 8200,
28262
- signature: "(value: indexed_collection, index: (number|string)+) -> unknown",
28530
+ signature: "(value: indexed_collection, index: (number|string|indexed_collection)+) -> unknown",
28263
28531
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? collectionElementType(xs.type.type) ?? "any",
28264
28532
  evaluate: (ops, { engine: ce }) => {
28265
28533
  let expr2 = ops[0];
@@ -28270,12 +28538,39 @@ ${lines.join("\n")}`;
28270
28538
  if (!at) return void 0;
28271
28539
  const opAtIndex = ops[index];
28272
28540
  const s = isString(opAtIndex) ? opAtIndex.string : void 0;
28273
- if (s !== void 0) expr2 = at(expr2, s) ?? ce.Nothing;
28274
- else {
28275
- const i = ops[index].re;
28276
- if (!Number.isInteger(i)) return void 0;
28277
- expr2 = at(expr2, i) ?? ce.Nothing;
28541
+ if (s !== void 0) {
28542
+ expr2 = at(expr2, s) ?? ce.Nothing;
28543
+ index += 1;
28544
+ continue;
28545
+ }
28546
+ if (opAtIndex.isCollection && opAtIndex.isFiniteCollection) {
28547
+ const indices = Array.from(opAtIndex.each());
28548
+ const isMask = indices.every((m) => {
28549
+ const name = sym(m);
28550
+ return name === "True" || name === "False";
28551
+ });
28552
+ const picked = [];
28553
+ if (isMask) {
28554
+ indices.forEach((m, i2) => {
28555
+ if (sym(m) !== "True") return;
28556
+ const v = at(expr2, i2 + 1);
28557
+ if (v !== void 0) picked.push(v);
28558
+ });
28559
+ } else {
28560
+ for (const m of indices) {
28561
+ const k = m.re;
28562
+ if (!Number.isInteger(k)) return void 0;
28563
+ const v = at(expr2, k);
28564
+ if (v !== void 0) picked.push(v);
28565
+ }
28566
+ }
28567
+ expr2 = ce._fn("List", picked);
28568
+ index += 1;
28569
+ continue;
28278
28570
  }
28571
+ const i = opAtIndex.re;
28572
+ if (!Number.isInteger(i)) return void 0;
28573
+ expr2 = at(expr2, i) ?? ce.Nothing;
28279
28574
  index += 1;
28280
28575
  }
28281
28576
  return expr2;
@@ -28286,7 +28581,7 @@ ${lines.join("\n")}`;
28286
28581
  description: ["Return `n` elements from a collection."],
28287
28582
  complexity: 8200,
28288
28583
  signature: "(xs: indexed_collection, count: number) -> indexed_collection",
28289
- type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
28584
+ type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
28290
28585
  evaluate: (ops, { engine, materialization: eager }) => {
28291
28586
  if (!eager) return void 0;
28292
28587
  const takeExpr = engine._fn("Take", ops);
@@ -28333,7 +28628,7 @@ ${lines.join("\n")}`;
28333
28628
  description: ["Return the collection without the first n elements."],
28334
28629
  complexity: 8200,
28335
28630
  signature: "(xs: indexed_collection, count: number) -> indexed_collection",
28336
- type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
28631
+ type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
28337
28632
  collection: {
28338
28633
  isLazy: (_expr) => true,
28339
28634
  count: (expr2) => {
@@ -28529,7 +28824,9 @@ ${lines.join("\n")}`;
28529
28824
  ],
28530
28825
  complexity: 8200,
28531
28826
  signature: "(value: indexed_collection, start: number, end: number) -> list",
28532
- type: ([xs]) => parseType(`list<${collectionElementType(xs.type.type)}>`),
28827
+ type: ([xs]) => parseType(
28828
+ `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`
28829
+ ),
28533
28830
  collection: {
28534
28831
  isLazy: (_expr) => true,
28535
28832
  count: (expr2) => {
@@ -28861,16 +29158,26 @@ ${lines.join("\n")}`;
28861
29158
  },
28862
29159
  // Randomize the order of the elements in the collection.
28863
29160
  Shuffle: {
28864
- description: "Randomize the order of the elements in the collection.",
29161
+ description: "Randomize the order of the elements in the collection. With an optional `seed` argument, the shuffle is deterministic.",
28865
29162
  complexity: 8200,
28866
- signature: "(indexed_collection) -> indexed_collection",
29163
+ signature: "(indexed_collection, real?) -> indexed_collection",
28867
29164
  type: (ops) => ops[0].type,
28868
- evaluate: ([xs], { engine: ce }) => {
29165
+ evaluate: ([xs, seedOp], { engine: ce }) => {
28869
29166
  if (!xs.isFiniteCollection) return void 0;
28870
29167
  const data = Array.from(xs.each());
28871
- for (let i = data.length - 1; i > 0; i--) {
28872
- const j = Math.floor(Math.random() * (i + 1));
28873
- [data[i], data[j]] = [data[j], data[i]];
29168
+ const seed = seedOp?.re;
29169
+ if (seed !== void 0 && !Number.isNaN(seed)) {
29170
+ let s = seed;
29171
+ for (let i = data.length - 1; i > 0; i--) {
29172
+ const j = Math.floor(deterministicRandom(s) * (i + 1));
29173
+ [data[i], data[j]] = [data[j], data[i]];
29174
+ s = nextSeed(s);
29175
+ }
29176
+ } else {
29177
+ for (let i = data.length - 1; i > 0; i--) {
29178
+ const j = Math.floor(Math.random() * (i + 1));
29179
+ [data[i], data[j]] = [data[j], data[i]];
29180
+ }
28874
29181
  }
28875
29182
  return ce.function(xs.operator, data);
28876
29183
  }
@@ -28937,7 +29244,9 @@ ${lines.join("\n")}`;
28937
29244
  if (t === "string")
28938
29245
  return parseType(`tuple<list<string>, list<integer>>`);
28939
29246
  return parseType(
28940
- `tuple<list<${collectionElementType(t)}>, list<integer>>`
29247
+ `tuple<list<${typeToString(
29248
+ collectionElementType(t) ?? "any"
29249
+ )}>, list<integer>>`
28941
29250
  );
28942
29251
  },
28943
29252
  evaluate: (ops, { engine: ce }) => {
@@ -28953,7 +29262,7 @@ ${lines.join("\n")}`;
28953
29262
  description: "Return a list of the unique elements of the collection.",
28954
29263
  complexity: 8200,
28955
29264
  signature: "(collection) -> list",
28956
- type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
29265
+ type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
28957
29266
  evaluate: (ops, { engine: ce }) => {
28958
29267
  if (!ops[0].isFiniteCollection) return void 0;
28959
29268
  const [values, _counts] = tally(ops[0]);
@@ -28965,7 +29274,7 @@ ${lines.join("\n")}`;
28965
29274
  wikidata: "Q381060",
28966
29275
  complexity: 8200,
28967
29276
  signature: "(collection, integer | function) -> list",
28968
- type: ([xs]) => `list<${collectionElementType(xs.type.type)}>`,
29277
+ type: ([xs]) => `list<${typeToString(collectionElementType(xs.type.type) ?? "any")}>`,
28969
29278
  evaluate: ([xs, arg], { engine: ce }) => {
28970
29279
  if (!xs.isFiniteCollection) return void 0;
28971
29280
  const k = toInteger(arg);
@@ -29139,32 +29448,74 @@ ${lines.join("\n")}`;
29139
29448
  }
29140
29449
  }
29141
29450
  },
29142
- // Repeat(x) -> [x, x, ...]
29143
- // This is an infinite series. Can use Take(Repeat(x), n) to get a finite series
29144
- // x is evaluated once. Although could use Hold()?
29145
- // So that First(Repeat(Hold(Random(5))), 10) would return 10 random numbers...
29451
+ // Repeat(x) -> [x, x, ...] — infinite sequence
29452
+ // Repeat(x, n) -> [x, x, ..., x] — finite list of n copies
29146
29453
  Repeat: {
29147
- description: "Produce an infinite sequence by repeating a single value.",
29454
+ description: "Produce a sequence by repeating a single value. With 1 argument, returns an infinite sequence; with 2 arguments (value, count), returns a finite list of `count` copies.",
29148
29455
  complexity: 8200,
29149
- signature: "(value: any) -> list",
29456
+ signature: "(value: any, count: integer?) -> list",
29457
+ evaluate: (ops, { engine }) => {
29458
+ if (ops.length !== 2) return void 0;
29459
+ const raw = toInteger(ops[1]);
29460
+ if (raw === null) return void 0;
29461
+ const n = Math.max(0, raw);
29462
+ if (n > engine.maxCollectionSize) return void 0;
29463
+ return engine._fn("List", Array(n).fill(ops[0]));
29464
+ },
29150
29465
  collection: {
29151
- isLazy: (_expr) => true,
29152
- count: () => Infinity,
29153
- isEmpty: (_expr) => false,
29154
- // Never empty
29155
- isFinite: () => false,
29156
- // Infinite collection
29466
+ isLazy: (expr2) => isFunction2(expr2) && expr2.ops?.length === 1,
29467
+ count: (expr2) => {
29468
+ if (!isFunction2(expr2)) return void 0;
29469
+ if (expr2.ops?.length === 2) {
29470
+ const n = toInteger(expr2.op2);
29471
+ return n !== null ? Math.max(0, n) : void 0;
29472
+ }
29473
+ return Infinity;
29474
+ },
29475
+ isEmpty: (expr2) => {
29476
+ if (!isFunction2(expr2)) return void 0;
29477
+ if (expr2.ops?.length === 2) {
29478
+ const n = toInteger(expr2.op2);
29479
+ return n !== null ? n <= 0 : void 0;
29480
+ }
29481
+ return false;
29482
+ },
29483
+ isFinite: (expr2) => isFunction2(expr2) && expr2.ops?.length === 2,
29157
29484
  contains: (expr2, target) => {
29158
29485
  if (!isFunction2(expr2)) return false;
29486
+ if (expr2.ops?.length === 2) {
29487
+ const n = toInteger(expr2.op2);
29488
+ if (n !== null && n <= 0) return false;
29489
+ }
29159
29490
  return expr2.op1.isSame(target);
29160
29491
  },
29161
29492
  iterator: (expr2) => {
29162
29493
  if (!isFunction2(expr2))
29163
29494
  return { next: () => ({ value: void 0, done: true }) };
29495
+ if (expr2.ops?.length === 2) {
29496
+ const n = toInteger(expr2.op2);
29497
+ if (n === null) {
29498
+ return { next: () => ({ value: void 0, done: true }) };
29499
+ }
29500
+ const count = Math.max(0, n);
29501
+ let i = 0;
29502
+ return {
29503
+ next: () => i++ < count ? { value: expr2.op1, done: false } : { value: void 0, done: true }
29504
+ };
29505
+ }
29164
29506
  return { next: () => ({ value: expr2.op1, done: false }) };
29165
29507
  },
29166
- at: (expr2, _index) => {
29508
+ // at is 1-based (consistent with Range, Take, and other collection handlers)
29509
+ at: (expr2, index) => {
29167
29510
  if (!isFunction2(expr2)) return void 0;
29511
+ if (typeof index !== "number") return void 0;
29512
+ if (expr2.ops?.length === 2) {
29513
+ const n = toInteger(expr2.op2);
29514
+ const count = n !== null ? Math.max(0, n) : 0;
29515
+ if (index < 1 || index > count) return void 0;
29516
+ } else {
29517
+ if (index < 1) return void 0;
29518
+ }
29168
29519
  return expr2.op1;
29169
29520
  }
29170
29521
  }
@@ -31450,11 +31801,12 @@ ${lines.join("\n")}`;
31450
31801
  );
31451
31802
  }
31452
31803
  },
31453
- // Complex: {
31454
- // // This function is converted during boxing, so unlikely to encounter
31455
- // wikidata: 'Q11567',
31456
- // complexity: 500,
31457
- // },
31804
+ Complex: {
31805
+ description: 'Construct a complex number from real and imaginary parts. Converted directly to a BoxedNumber during boxing; this entry exists so `operatorInfo("Complex")` returns a signature.',
31806
+ wikidata: "Q11567",
31807
+ complexity: 500,
31808
+ signature: "(real: number, imaginary: number) -> complex"
31809
+ },
31458
31810
  Divide: {
31459
31811
  description: "Quotient of a numerator and one or more denominators.",
31460
31812
  wikidata: "Q1226939",
@@ -32804,48 +33156,83 @@ ${lines.join("\n")}`;
32804
33156
  }
32805
33157
  },
32806
33158
  Sum: {
32807
- description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`",
33159
+ description: "`Sum(f, [a, b])` computes the sum of `f` from `a` to `b`; `Sum(L)` sums the elements of a collection `L`",
32808
33160
  wikidata: "Q218005",
32809
33161
  complexity: 1e3,
32810
33162
  broadcastable: false,
32811
33163
  scoped: true,
32812
33164
  lazy: true,
32813
- signature: "((number) -> number, bounds:tuple+) -> number",
32814
- canonical: ([body, ...bounds], { scope }) => canonicalBigop("Sum", body, bounds, scope),
32815
- evaluate: ([body, ...indexes], { engine, numericApproximation: numericApproximation2 }) => {
33165
+ signature: "(any, tuple*) -> number",
33166
+ canonical: ([body, ...bounds], { scope, engine: ce }) => {
33167
+ if (bounds.length === 0) {
33168
+ const canon = body?.canonical;
33169
+ if (canon?.isCollection) return ce._fn("Sum", [canon]);
33170
+ }
33171
+ return canonicalBigop("Sum", body, bounds, scope);
33172
+ },
33173
+ evaluate: ([first, ...rest], { engine, numericApproximation: numericApproximation2 }) => {
33174
+ if (rest.length === 0 && first?.isCollection) {
33175
+ if (first.isFiniteCollection !== true) return void 0;
33176
+ const result2 = run(
33177
+ reduceCollection2(
33178
+ first,
33179
+ engine.Zero,
33180
+ (acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
33181
+ ),
33182
+ engine._timeRemaining
33183
+ );
33184
+ return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
33185
+ }
32816
33186
  const result = run(
32817
33187
  reduceBigOp(
32818
- body,
32819
- indexes,
33188
+ first,
33189
+ rest,
32820
33190
  (acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
32821
33191
  engine.Zero
32822
33192
  ),
32823
33193
  engine._timeRemaining
32824
33194
  );
32825
- if (result === NON_ENUMERABLE_DOMAIN) {
32826
- return void 0;
32827
- }
33195
+ if (result === NON_ENUMERABLE_DOMAIN) return void 0;
32828
33196
  return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
32829
33197
  },
32830
- evaluateAsync: async (xs, { engine, signal, numericApproximation: numericApproximation2 }) => {
33198
+ evaluateAsync: async ([first, ...rest], { engine, signal, numericApproximation: numericApproximation2 }) => {
33199
+ if (rest.length === 0 && first?.isCollection) {
33200
+ if (first.isFiniteCollection !== true) return void 0;
33201
+ const result2 = await runAsync(
33202
+ reduceCollection2(
33203
+ first,
33204
+ engine.Zero,
33205
+ (acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 }))
33206
+ ),
33207
+ engine._timeRemaining,
33208
+ signal
33209
+ );
33210
+ return result2?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
33211
+ }
32831
33212
  const result = await runAsync(
32832
33213
  reduceBigOp(
32833
- xs[0],
32834
- xs.slice(1),
33214
+ first,
33215
+ rest,
32835
33216
  (acc, x) => acc.add(x.evaluate({ numericApproximation: numericApproximation2 })),
32836
33217
  engine.Zero
32837
33218
  ),
32838
33219
  engine._timeRemaining,
32839
33220
  signal
32840
33221
  );
32841
- if (result === NON_ENUMERABLE_DOMAIN) {
32842
- return void 0;
32843
- }
33222
+ if (result === NON_ENUMERABLE_DOMAIN) return void 0;
32844
33223
  return result?.evaluate({ numericApproximation: numericApproximation2 }) ?? engine.NaN;
32845
33224
  }
32846
33225
  }
32847
33226
  }
32848
33227
  ];
33228
+ function* reduceCollection2(collection, init, combine) {
33229
+ let acc = init;
33230
+ for (const x of collection.each()) {
33231
+ acc = combine(acc, x);
33232
+ yield acc;
33233
+ }
33234
+ return acc;
33235
+ }
32849
33236
  function evaluateAbs(arg) {
32850
33237
  const ce = arg.engine;
32851
33238
  if (isNumber(arg)) {
@@ -43082,7 +43469,7 @@ ${e.message}
43082
43469
  var CONTROL_STRUCTURES_LIBRARY = [
43083
43470
  {
43084
43471
  Block: {
43085
- description: "Evaluate a sequence of expressions in a local scope.",
43472
+ description: "Evaluate a sequence of expressions in a local scope, **sequentially**. Each operand is evaluated in order; later operands observe side effects (`Assign`, `Declare`) of earlier operands. The block's value is the value of the last expression. Short-circuiting heads (`Return`, `Break`, `Continue`) terminate the sequence early.\n\nIMPORTANT \u2014 consumers translating *simultaneous* action tuples (e.g. Desmos `(a \u2192 1, b \u2192 a + 1)` where `b` reads the *pre-action* `a`) must rewrite to a snapshot-then-commit Block: bind each RHS to a fresh temp first, then assign the temps to the LHS symbols. See `docs/architecture/actions-and-randomness.md` for the canonical recipe.",
43086
43473
  lazy: true,
43087
43474
  scoped: true,
43088
43475
  signature: "(unknown*) -> unknown",
@@ -43144,7 +43531,7 @@ ${e.message}
43144
43531
  evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
43145
43532
  },
43146
43533
  When: {
43147
- description: "Conditional value: returns expr when cond holds, undefined otherwise.",
43534
+ description: 'Conditional/restriction value. `When(e, cond)` evaluates to:\n - `e` when `cond` evaluates to `True`\n - `Undefined` when `cond` evaluates to `False` (the "masking rule"; consumers like 2D plotters skip masked points)\n - `When(e, cond_simplified)` when `cond` is indeterminate (holds)\nStacked restrictions canonicalize: `When(When(e, c1), c2)` \u2192 `When(e, And(c1, c2))`.\nCompiles to ternary `(cond) ? (e) : NaN` in JS and GLSL.',
43148
43535
  lazy: true,
43149
43536
  signature: "(expression, boolean) -> any",
43150
43537
  type: ([expr2]) => expr2.type,
@@ -45003,7 +45390,7 @@ ${e.message}
45003
45390
  evaluate: (ops) => apply(ops[0], ops.slice(1))
45004
45391
  },
45005
45392
  Assign: {
45006
- description: "Assign a value to a symbol or define a sequence",
45393
+ description: "Assign a value to a symbol or define a sequence. The RHS is evaluated immediately and `ce.assign(name, val)` mutates the binding in the current scope chain. When used inside a `Block`, the assignment is visible to subsequent statements in the block (sequential semantics).",
45007
45394
  lazy: true,
45008
45395
  pure: false,
45009
45396
  signature: "(symbol | expression, any) -> any",
@@ -45134,7 +45521,12 @@ ${e.message}
45134
45521
  evaluate: (ops, { engine: ce }) => {
45135
45522
  const symbolName2 = sym(ops[0].evaluate());
45136
45523
  if (!symbolName2) return void 0;
45524
+ const currentScope = ce.context.lexicalScope;
45525
+ const existing = currentScope.bindings.get(symbolName2);
45526
+ const existingValueDef = existing && isValueDef(existing) ? existing : void 0;
45527
+ const isAutoDeclareHere = !!existingValueDef && existingValueDef.value.inferredType && existingValueDef.value.value === void 0;
45137
45528
  if (!ops[1]) {
45529
+ if (isAutoDeclareHere) return ce.Nothing;
45138
45530
  ce.declare(symbolName2, { inferred: true, type: "unknown" });
45139
45531
  return ce.Nothing;
45140
45532
  }
@@ -45143,6 +45535,11 @@ ${e.message}
45143
45535
  (isString(t) ? t.string : void 0) ?? sym(t) ?? void 0
45144
45536
  );
45145
45537
  if (!isValidType(type2)) return void 0;
45538
+ if (isAutoDeclareHere && existingValueDef) {
45539
+ existingValueDef.value.type = ce.type(type2);
45540
+ existingValueDef.value.inferredType = false;
45541
+ return ce.Nothing;
45542
+ }
45146
45543
  ce.declare(symbolName2, type2);
45147
45544
  return ce.Nothing;
45148
45545
  }
@@ -45260,33 +45657,41 @@ ${e.message}
45260
45657
  },
45261
45658
  Random: {
45262
45659
  description: [
45263
- "Random(): Return a random number between 0 and 1",
45264
- "Random(n): Return a random integer between 0 and n-1",
45265
- "Random(m, n): Return a random integer between m and n-1"
45660
+ "Random(): non-deterministic float in [0, 1)",
45661
+ "Random(seed: real): deterministic float in [0, 1) from a real seed",
45662
+ "Random(n: integer): non-deterministic integer in [0, n)",
45663
+ "Random(m: integer, n: integer): non-deterministic integer in [m, n)"
45266
45664
  ],
45267
45665
  pure: false,
45268
- signature: "(lower:integer?, upper:integer?) -> finite_number",
45269
- type: ([lower, upper]) => {
45270
- if (lower === void 0 && upper === void 0) return "finite_number";
45271
- return "finite_integer";
45666
+ // Signature accepts: nothing, one number, or two integers.
45667
+ // Use `number` (not `integer`) for the single-arg case so float seeds
45668
+ // type-check; runtime dispatch differentiates integer vs real.
45669
+ signature: "(number?, integer?) -> finite_number",
45670
+ type: ([first, second]) => {
45671
+ if (first === void 0) return "finite_number";
45672
+ if (second !== void 0) return "finite_integer";
45673
+ if (first.type.matches("integer")) return "finite_integer";
45674
+ return "finite_number";
45272
45675
  },
45273
45676
  sgn: () => "non-negative",
45274
45677
  evaluate: (ops, { engine: ce }) => {
45275
45678
  if (ops.length === 0) return ce.number(Math.random());
45276
- const [lowerOp, upperOp] = ops;
45277
- let lower;
45278
- let upper;
45279
- if (upperOp === void 0) {
45280
- lower = 0;
45281
- upper = Math.floor(lowerOp.re - 1);
45282
- if (isNaN(upper)) upper = 0;
45283
- } else {
45284
- lower = Math.floor(lowerOp.re);
45285
- upper = Math.floor(upperOp.re);
45679
+ const [firstOp, secondOp] = ops;
45680
+ if (secondOp !== void 0) {
45681
+ let lower = Math.floor(firstOp.re);
45682
+ let upper = Math.floor(secondOp.re);
45286
45683
  if (isNaN(lower)) lower = 0;
45287
45684
  if (isNaN(upper)) upper = 0;
45685
+ return ce.number(lower + Math.floor(Math.random() * (upper - lower)));
45686
+ }
45687
+ if (firstOp.type.matches("integer")) {
45688
+ let n = Math.floor(firstOp.re);
45689
+ if (isNaN(n)) n = 0;
45690
+ return ce.number(Math.floor(Math.random() * n));
45288
45691
  }
45289
- return ce.number(lower + Math.floor(Math.random() * (upper - lower)));
45692
+ const seed = firstOp.re;
45693
+ if (isNaN(seed)) return ce.number(0);
45694
+ return ce.number(deterministicRandom(seed));
45290
45695
  }
45291
45696
  },
45292
45697
  // @todo: need review
@@ -45742,6 +46147,14 @@ ${e.message}
45742
46147
  To: {
45743
46148
  description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
45744
46149
  signature: "(any, any) -> nothing"
46150
+ },
46151
+ Colon: {
46152
+ description: "Type annotation (`a : b`) \u2014 opaque typed head.",
46153
+ signature: "(any, any) -> expression"
46154
+ },
46155
+ Prime: {
46156
+ description: "Derivative or prime notation (`f'`, `f^{(n)}`) \u2014 opaque typed head until a derivative library handler runs.",
46157
+ signature: "(any, integer?) -> expression"
45745
46158
  }
45746
46159
  }
45747
46160
  ];
@@ -50782,18 +51195,28 @@ ${e.message}
50782
51195
  },
50783
51196
  {
50784
51197
  Sample: {
50785
- description: "Return a random sample of k elements from the collection, without replacement.",
51198
+ description: "Return a random sample of k elements from the collection, without replacement. With an optional `seed` argument, the sample is deterministic.",
50786
51199
  complexity: 8200,
50787
- signature: "(collection, integer) -> list",
50788
- evaluate: ([xs, nArg], { engine: ce }) => {
51200
+ signature: "(collection, integer, real?) -> list",
51201
+ evaluate: ([xs, nArg, seedArg], { engine: ce }) => {
50789
51202
  if (!xs.isFiniteCollection) return void 0;
50790
51203
  const k = toInteger(nArg);
50791
51204
  if (k === null || k < 0) return void 0;
50792
51205
  const data = Array.from(xs.each());
50793
51206
  if (k > data.length) return void 0;
50794
- for (let i = data.length - 1; i > 0; i--) {
50795
- const j = Math.floor(Math.random() * (i + 1));
50796
- [data[i], data[j]] = [data[j], data[i]];
51207
+ const seed = seedArg?.re;
51208
+ if (seed !== void 0 && !Number.isNaN(seed)) {
51209
+ let s = seed;
51210
+ for (let i = data.length - 1; i > 0; i--) {
51211
+ const j = Math.floor(deterministicRandom(s) * (i + 1));
51212
+ [data[i], data[j]] = [data[j], data[i]];
51213
+ s = nextSeed(s);
51214
+ }
51215
+ } else {
51216
+ for (let i = data.length - 1; i > 0; i--) {
51217
+ const j = Math.floor(Math.random() * (i + 1));
51218
+ [data[i], data[j]] = [data[j], data[i]];
51219
+ }
50797
51220
  }
50798
51221
  const sample = data.slice(0, k);
50799
51222
  return ce.function("List", sample);
@@ -53614,6 +54037,20 @@ Error in definition of "${name}"`,
53614
54037
  if (results.length === 1) return results[0];
53615
54038
  return this.engine._fn("List", results);
53616
54039
  }
54040
+ if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
54041
+ const items = zip(this._ops);
54042
+ if (items) {
54043
+ const results = [];
54044
+ while (true) {
54045
+ const { done, value } = items.next();
54046
+ if (done) break;
54047
+ results.push(
54048
+ this.engine._fn(this.operator, value).evaluate(options)
54049
+ );
54050
+ }
54051
+ return this.engine._fn("List", results);
54052
+ }
54053
+ }
53617
54054
  if (materialization !== false && !def.evaluate && this.isLazyCollection)
53618
54055
  return materialize(this, def, options);
53619
54056
  const tail = holdMap(this, (x) => x.evaluate(options));
@@ -53660,6 +54097,22 @@ Error in definition of "${name}"`,
53660
54097
  (resolved) => this.engine._fn("List", resolved)
53661
54098
  );
53662
54099
  }
54100
+ if (def instanceof _BoxedOperatorDefinition && def._isLambda && this.ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(def)) {
54101
+ const items = zip(this._ops);
54102
+ if (items) {
54103
+ const results = [];
54104
+ while (true) {
54105
+ const { done, value } = items.next();
54106
+ if (done) break;
54107
+ results.push(
54108
+ this.engine._fn(this.operator, value).evaluateAsync(options)
54109
+ );
54110
+ }
54111
+ return Promise.all(results).then(
54112
+ (resolved) => this.engine._fn("List", resolved)
54113
+ );
54114
+ }
54115
+ }
53663
54116
  const tail = await holdMapAsync(
53664
54117
  this,
53665
54118
  async (x) => await x.evaluateAsync(options)
@@ -53874,8 +54327,47 @@ Error in definition of "${name}"`,
53874
54327
  const ops = expr2.ops.map((x) => x.evaluate(options));
53875
54328
  if (!value || value.type.isUnknown)
53876
54329
  return expr2.engine.function(expr2.operator, ops);
54330
+ if (ops.some((x) => isFiniteIndexedCollection(x)) && paramsAreScalar(value.type.type)) {
54331
+ const items = zip(ops);
54332
+ if (items) {
54333
+ const results = [];
54334
+ while (true) {
54335
+ const { done, value: zipped } = items.next();
54336
+ if (done) break;
54337
+ results.push(apply(value, zipped).evaluate(options));
54338
+ }
54339
+ return expr2.engine._fn("List", results);
54340
+ }
54341
+ }
53877
54342
  return apply(value, ops);
53878
54343
  }
54344
+ function paramsAreScalar(source) {
54345
+ const sigType = isOperatorDefinition(source) ? source.signature?.type : source;
54346
+ if (!sigType || typeof sigType === "string") return true;
54347
+ if (sigType.kind !== "signature") return true;
54348
+ const args = [
54349
+ ...sigType.args ?? [],
54350
+ ...sigType.optArgs ?? [],
54351
+ ...sigType.variadicArg ? [sigType.variadicArg] : []
54352
+ ];
54353
+ return args.every((arg) => isScalarType(arg.type));
54354
+ }
54355
+ function isOperatorDefinition(source) {
54356
+ return typeof source === "object" && source !== null && "signature" in source;
54357
+ }
54358
+ function isScalarType(t) {
54359
+ if (typeof t === "string") {
54360
+ if (t === "collection" || t === "indexed_collection" || t === "list" || t === "tuple" || t === "set" || t === "dictionary" || t === "record" || t === "function")
54361
+ return false;
54362
+ return true;
54363
+ }
54364
+ if (t.kind === "collection" || t.kind === "indexed_collection" || t.kind === "list" || t.kind === "tuple" || t.kind === "set" || t.kind === "dictionary" || t.kind === "record" || t.kind === "signature")
54365
+ return false;
54366
+ if (t.kind === "union" || t.kind === "intersection")
54367
+ return t.types.every((x) => isScalarType(x));
54368
+ if (t.kind === "negation") return isScalarType(t.type);
54369
+ return true;
54370
+ }
53879
54371
  function materialize(expr2, def, options) {
53880
54372
  if (!expr2.isValid || options?.materialization === false) return expr2;
53881
54373
  let materialization = options?.materialization ?? false;
@@ -53883,6 +54375,11 @@ Error in definition of "${name}"`,
53883
54375
  materialization = DEFAULT_MATERIALIZATION;
53884
54376
  const isIndexed = expr2.isIndexedCollection;
53885
54377
  const isFinite2 = expr2.isFiniteCollection;
54378
+ if (isIndexed && isFinite2) {
54379
+ const count = expr2.count;
54380
+ if (count !== void 0 && count > expr2.engine.maxCollectionSize)
54381
+ return expr2;
54382
+ }
53886
54383
  const xs = [];
53887
54384
  if (!expr2.isEmptyCollection) {
53888
54385
  if (!isIndexed || !isFinite2) {
@@ -54110,7 +54607,7 @@ Error in definition of "${name}"`,
54110
54607
  const eltType = widen(
54111
54608
  ...Object.values(this._keyValues).map((op) => op.type.type)
54112
54609
  );
54113
- this._type = this.engine.type(`dictionary<${eltType}>`);
54610
+ this._type = new BoxedType({ kind: "dictionary", values: eltType });
54114
54611
  return this._type;
54115
54612
  }
54116
54613
  get isPure() {
@@ -54388,6 +54885,7 @@ Error in definition of "${name}"`,
54388
54885
  }
54389
54886
  if (typeof expr2 === "number" || expr2 instanceof BigDecimal || expr2 instanceof Complex)
54390
54887
  return ce.number(expr2);
54888
+ if (typeof expr2 === "boolean") return ce.symbol(expr2 ? "True" : "False");
54391
54889
  if (typeof expr2 === "string") {
54392
54890
  if (matchesSymbol(expr2)) {
54393
54891
  const sym2 = symbol(expr2);
@@ -55566,6 +56064,13 @@ Error in definition of "${name}"`,
55566
56064
  * GLSL (no dynamic arrays, no push). A compile-time error is thrown.
55567
56065
  * TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
55568
56066
  * array or by unrolling when bounds are known at compile time.
56067
+ *
56068
+ * Known issue (imperative form): the IIFE generated by form (1) has no
56069
+ * `return` statement, so `Loop(body, Element(i, Range(lo, hi)))` compiled
56070
+ * to JS evaluates to `undefined` at runtime, while CE evaluation returns a
56071
+ * `List` of body values. See `test/compute-engine/a1-c1-compile-parity.test.ts`
56072
+ * ("Loop compiles in JS") for the verify-only test that locks in the
56073
+ * current behavior.
55569
56074
  */
55570
56075
  static compileForLoop(args, target) {
55571
56076
  if (!args[0]) throw new Error("Loop: no body");
@@ -60202,8 +60707,8 @@ Error in definition of "${name}"`,
60202
60707
  }
60203
60708
  if (effectiveOp === "greater" || effectiveOp === "greaterEqual") {
60204
60709
  const isStrict = effectiveOp === "greater";
60205
- if (bounds.lowerBound !== void 0) {
60206
- const lowerVal = isNumber(bounds.lowerBound) ? bounds.lowerBound.numericValue : void 0;
60710
+ if (bounds.lower !== void 0) {
60711
+ const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
60207
60712
  if (typeof lowerVal === "number" && isFinite(lowerVal)) {
60208
60713
  if (isStrict) {
60209
60714
  if (lowerVal > k) return "tautology";
@@ -60215,8 +60720,8 @@ Error in definition of "${name}"`,
60215
60720
  }
60216
60721
  }
60217
60722
  }
60218
- if (bounds.upperBound !== void 0) {
60219
- const upperVal = isNumber(bounds.upperBound) ? bounds.upperBound.numericValue : void 0;
60723
+ if (bounds.upper !== void 0) {
60724
+ const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
60220
60725
  if (typeof upperVal === "number" && isFinite(upperVal)) {
60221
60726
  if (isStrict) {
60222
60727
  if (upperVal < k) return "contradiction";
@@ -60231,8 +60736,8 @@ Error in definition of "${name}"`,
60231
60736
  }
60232
60737
  } else {
60233
60738
  const isStrict = effectiveOp === "less";
60234
- if (bounds.upperBound !== void 0) {
60235
- const upperVal = isNumber(bounds.upperBound) ? bounds.upperBound.numericValue : void 0;
60739
+ if (bounds.upper !== void 0) {
60740
+ const upperVal = isNumber(bounds.upper) ? bounds.upper.numericValue : void 0;
60236
60741
  if (typeof upperVal === "number" && isFinite(upperVal)) {
60237
60742
  if (isStrict) {
60238
60743
  if (upperVal < k) return "tautology";
@@ -60243,8 +60748,8 @@ Error in definition of "${name}"`,
60243
60748
  }
60244
60749
  }
60245
60750
  }
60246
- if (bounds.lowerBound !== void 0) {
60247
- const lowerVal = isNumber(bounds.lowerBound) ? bounds.lowerBound.numericValue : void 0;
60751
+ if (bounds.lower !== void 0) {
60752
+ const lowerVal = isNumber(bounds.lower) ? bounds.lower.numericValue : void 0;
60248
60753
  if (typeof lowerVal === "number" && isFinite(lowerVal)) {
60249
60754
  if (isStrict) {
60250
60755
  if (lowerVal > k) return "contradiction";
@@ -60472,7 +60977,7 @@ Error in definition of "${name}"`,
60472
60977
  const patOp1B2 = pat.op1;
60473
60978
  if (isSymbol2(patOp1B2)) {
60474
60979
  const bounds = getInequalityBoundsFromAssumptions(ce, patOp1B2.symbol);
60475
- const bound = isLower ? bounds.lowerBound : bounds.upperBound;
60980
+ const bound = isLower ? bounds.lower : bounds.upper;
60476
60981
  const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
60477
60982
  if (bound !== void 0 && (!isStrict || strictOk === true))
60478
60983
  pushResult({ [boundWildcard]: bound });
@@ -60482,7 +60987,7 @@ Error in definition of "${name}"`,
60482
60987
  if (symbolWildcard && !symbolWildcard.startsWith("__")) {
60483
60988
  for (const s of candidatesFromAssumptions()) {
60484
60989
  const bounds = getInequalityBoundsFromAssumptions(ce, s);
60485
- const bound = isLower ? bounds.lowerBound : bounds.upperBound;
60990
+ const bound = isLower ? bounds.lower : bounds.upper;
60486
60991
  const strictOk = isLower ? bounds.lowerStrict : bounds.upperStrict;
60487
60992
  if (bound === void 0 || isStrict && strictOk !== true)
60488
60993
  continue;
@@ -61514,6 +62019,7 @@ Error in definition of "${name}"`,
61514
62019
  return `_SYS.cexp(${compile3(args[0])})`;
61515
62020
  return `Math.exp(${compile3(args[0])})`;
61516
62021
  },
62022
+ First: (args, compile3) => `${compile3(args[0])}[0]`,
61517
62023
  Floor: (args, compile3) => {
61518
62024
  if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
61519
62025
  return `Math.floor(${compile3(args[0])})`;
@@ -61672,7 +62178,20 @@ Error in definition of "${name}"`,
61672
62178
  if (nConst !== void 0) return `Math.pow(${compile3(arg)}, ${1 / nConst})`;
61673
62179
  return `Math.pow(${compile3(arg)}, 1 / (${compile3(exp3)}))`;
61674
62180
  },
61675
- Random: "Math.random",
62181
+ Random: (args, compile3) => {
62182
+ if (args.length === 0) return "Math.random()";
62183
+ if (args.length === 2) {
62184
+ const m = compile3(args[0]);
62185
+ const n = compile3(args[1]);
62186
+ return `((${m}) + Math.floor(Math.random() * ((${n}) - (${m}))))`;
62187
+ }
62188
+ const arg = args[0];
62189
+ if (BaseCompiler.isIntegerValued(arg)) {
62190
+ return `Math.floor(Math.random() * (${compile3(arg)}))`;
62191
+ }
62192
+ const a = compile3(arg);
62193
+ return `(() => { const _s = (${a}) * 12.9898; const _v = Math.sin(_s) * 43758.5453; return _v - Math.floor(_v); })()`;
62194
+ },
61676
62195
  Round: (args, compile3) => {
61677
62196
  if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
61678
62197
  return `Math.round(${compile3(args[0])})`;
@@ -61700,6 +62219,7 @@ Error in definition of "${name}"`,
61700
62219
  if (BaseCompiler.isComplexValued(arg)) return `_SYS.csech(${compile3(arg)})`;
61701
62220
  return `1 / Math.cosh(${compile3(arg)})`;
61702
62221
  },
62222
+ Second: (args, compile3) => `${compile3(args[0])}[1]`,
61703
62223
  Heaviside: "_SYS.heaviside",
61704
62224
  Sign: "Math.sign",
61705
62225
  Sinc: "_SYS.sinc",
@@ -61732,6 +62252,7 @@ Error in definition of "${name}"`,
61732
62252
  return `_SYS.ctanh(${compile3(args[0])})`;
61733
62253
  return `Math.tanh(${compile3(args[0])})`;
61734
62254
  },
62255
+ Third: (args, compile3) => `${compile3(args[0])}[2]`,
61735
62256
  Mod: ([a, b], compile3) => {
61736
62257
  if (a === null || b === null) throw new Error("Mod: missing argument");
61737
62258
  const ca = compile3(a);
@@ -63011,6 +63532,14 @@ Error in definition of "${name}"`,
63011
63532
  return `exp(${compile3(args[0])})`;
63012
63533
  },
63013
63534
  Exp2: "exp2",
63535
+ // Component access — assumes the argument compiles to a vec2/vec3/vec4
63536
+ // (the common case for 2D/3D points). For 5+-element tuples that compile
63537
+ // to `float[N]` arrays, swizzle access is invalid GLSL and the shader
63538
+ // will fail to compile; that's an edge case `First`/`Second`/`Third`
63539
+ // aren't designed for. Vec swizzles are identical between GLSL and WGSL.
63540
+ First: (args, compile3) => `${compile3(args[0])}.x`,
63541
+ Second: (args, compile3) => `${compile3(args[0])}.y`,
63542
+ Third: (args, compile3) => `${compile3(args[0])}.z`,
63014
63543
  Floor: (args, compile3) => {
63015
63544
  if (BaseCompiler.isIntegerValued(args[0])) return compile3(args[0]);
63016
63545
  return `floor(${compile3(args[0])})`;
@@ -63488,6 +64017,39 @@ Error in definition of "${name}"`,
63488
64017
  // Sum/Product — unrolled or for-loop
63489
64018
  Sum: (args, compile3, target) => compileGPUSumProduct("Sum", args, compile3, target),
63490
64019
  Product: (args, compile3, target) => compileGPUSumProduct("Product", args, compile3, target),
64020
+ // Range — inline constant array literal (bounds must be compile-time constants)
64021
+ Range: (args, _compile2, target) => {
64022
+ if (args.length < 2 || args.length > 3) {
64023
+ throw new Error(
64024
+ "Range: GPU compile expects 2 or 3 arguments (lo, hi, step?)"
64025
+ );
64026
+ }
64027
+ const lo = args[0].re;
64028
+ const hi = args[1].re;
64029
+ const step = args.length === 3 ? args[2].re : 1;
64030
+ if (!Number.isFinite(lo) || !Number.isFinite(hi) || !Number.isFinite(step)) {
64031
+ throw new Error(
64032
+ "Range: GPU compile requires constant numeric bounds (non-constant ranges must be materialized at JS host then uploaded as a uniform)"
64033
+ );
64034
+ }
64035
+ if (step === 0) throw new Error("Range: step cannot be zero");
64036
+ const count = Math.max(0, Math.floor((hi - lo) / step) + 1);
64037
+ if (count === 0) {
64038
+ throw new Error(
64039
+ "Range: empty range (lo > hi for positive step, or lo < hi for negative step)"
64040
+ );
64041
+ }
64042
+ if (count > 256) {
64043
+ throw new Error(
64044
+ `Range: GPU compile inlines ranges up to 256 elements (got ${count})`
64045
+ );
64046
+ }
64047
+ const values = [];
64048
+ for (let i = 0; i < count; i++) values.push(lo + i * step);
64049
+ const isWGSL = target.language === "wgsl";
64050
+ const arrayType = isWGSL ? `array<f32, ${count}>` : `float[${count}]`;
64051
+ return `${arrayType}(${values.map(formatGPUNumber).join(", ")})`;
64052
+ },
63491
64053
  // Loop — GPU for-loop (no IIFE, no let)
63492
64054
  Loop: (args, _compile2, target) => {
63493
64055
  if (!args[0]) throw new Error("Loop: no body");
@@ -63516,6 +64078,134 @@ Error in definition of "${name}"`,
63516
64078
  ${bodyCode};
63517
64079
  }`;
63518
64080
  },
64081
+ // Statistical functions
64082
+ /**
64083
+ * GCD of two scalar arguments.
64084
+ *
64085
+ * Uses a preamble helper `_gpu_gcd` (Euclidean algorithm via `mod`).
64086
+ * Only two-argument form is supported in GPU targets.
64087
+ */
64088
+ GCD: (args, compile3) => {
64089
+ if (args.length < 2) throw new Error("GCD: need at least two arguments");
64090
+ if (args.length > 2)
64091
+ throw new Error("GCD: GPU target supports only two-argument GCD");
64092
+ const a = args[0];
64093
+ const b = args[1];
64094
+ if (a === null || b === null) throw new Error("GCD: missing argument");
64095
+ return `_gpu_gcd(${compile3(a)}, ${compile3(b)})`;
64096
+ },
64097
+ /**
64098
+ * Variance of a compile-time-known list.
64099
+ *
64100
+ * Accepts either a single `List(...)` argument or N scalar arguments.
64101
+ * Generates fully inline code: computes mean then sum of squared deviations,
64102
+ * divided by (N-1) for sample variance (matches JS `_SYS.variance`).
64103
+ */
64104
+ Variance: (args, compile3) => {
64105
+ let elems;
64106
+ if (args.length === 1 && isFunction2(args[0], "List")) {
64107
+ elems = args[0].ops;
64108
+ } else if (args.length >= 2) {
64109
+ elems = args;
64110
+ } else {
64111
+ throw new Error(
64112
+ "Variance: GPU target requires a List argument or at least 2 scalar arguments"
64113
+ );
64114
+ }
64115
+ const n = elems.length;
64116
+ if (n < 2) throw new Error("Variance: need at least 2 elements");
64117
+ const compiled = elems.map((e) => compile3(e));
64118
+ const sum = compiled.join(" + ");
64119
+ const mean2 = `((${sum}) / ${formatGPUNumber(n)})`;
64120
+ const sqDiffs = compiled.map((c) => `(${c} - ${mean2}) * (${c} - ${mean2})`).join(" + ");
64121
+ return `((${sqDiffs}) / ${formatGPUNumber(n - 1)})`;
64122
+ },
64123
+ /**
64124
+ * Median of a compile-time-known list.
64125
+ *
64126
+ * Accepts either a single `List(...)` argument or N scalar arguments.
64127
+ * For N ≤ 8: generates a fully unrolled inline sorting network followed by
64128
+ * a middle-element pick. For larger N, throws (too large to inline cleanly).
64129
+ *
64130
+ * The sorting network uses the "odd-even merge sort" comparator pattern
64131
+ * inlined as `min`/`max` calls — no GPU statements required.
64132
+ */
64133
+ Median: (args, compile3) => {
64134
+ let elems;
64135
+ if (args.length === 1 && isFunction2(args[0], "List")) {
64136
+ elems = args[0].ops;
64137
+ } else if (args.length >= 1) {
64138
+ elems = args;
64139
+ } else {
64140
+ throw new Error(
64141
+ "Median: GPU target requires a List argument or at least 1 scalar argument"
64142
+ );
64143
+ }
64144
+ const n = elems.length;
64145
+ if (n === 0) throw new Error("Median: empty list");
64146
+ if (n > 8) {
64147
+ throw new Error(
64148
+ `Median: GPU target supports up to 8 elements via inline sorting network (got ${n}). For larger lists, compute on the CPU and pass the result as a uniform.`
64149
+ );
64150
+ }
64151
+ const compiled = elems.map((e) => compile3(e));
64152
+ if (n === 1) return compiled[0];
64153
+ return `_gpu_median_${n}(${compiled.join(", ")})`;
64154
+ },
64155
+ /**
64156
+ * Deterministic pseudorandom for GPU.
64157
+ *
64158
+ * All emitted forms return a GLSL `float` (or WGSL `f32`) so the result
64159
+ * composes with surrounding float arithmetic without explicit casts. The
64160
+ * "integer-bound" forms return an integer-valued float (the result of
64161
+ * `floor`), matching the convention used by `Floor` and other ostensibly
64162
+ * integer-returning operators in this target.
64163
+ *
64164
+ * - 0 args (GLSL only): fall back to a fragment-coord-derived seed.
64165
+ * Only meaningful in fragment shaders (gl_FragCoord is FS-only).
64166
+ * - 0 args (WGSL): throws — WGSL has no built-in fragment coordinate;
64167
+ * caller must provide an explicit seed.
64168
+ * - 1 arg, real-typed: `_gpu_random(seed)` — deterministic float in [0, 1)
64169
+ * - 1 arg, integer-typed: `floor(_gpu_random(float(n)) * float(n))` —
64170
+ * integer-valued float in {0, 1, ..., n-1}. The seed is derived from
64171
+ * `n` itself, so the result is per-pixel-and-n deterministic in GLSL.
64172
+ * - 2 args (integer m, n): float in [m, n), seeded from gl_FragCoord.
64173
+ *
64174
+ * JS-side `Random` has matching semantics (see `library/core.ts`'s
64175
+ * polymorphic dispatch). JS↔GLSL parity is approximate — same seed yields
64176
+ * a similar value, not bit-identical, due to fp64 vs fp32 and platform
64177
+ * `sin` differences.
64178
+ */
64179
+ Random: (args, compile3, target) => {
64180
+ if (args.length === 0) {
64181
+ if (target.language === "wgsl") {
64182
+ throw new Error(
64183
+ "Random(): WGSL compile requires an explicit seed argument. WGSL has no gl_FragCoord built-in outside fragment entry points, so the no-arg fallback used in GLSL is unavailable. Use Random(seed) where seed is a deterministic per-invocation value."
64184
+ );
64185
+ }
64186
+ return "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
64187
+ }
64188
+ if (args.length === 1) {
64189
+ const arg = args[0];
64190
+ if (BaseCompiler.isIntegerValued(arg)) {
64191
+ const compiled = compile3(arg);
64192
+ return `floor(_gpu_random(float(${compiled})) * float(${compiled}))`;
64193
+ }
64194
+ return `_gpu_random(${compile3(arg)})`;
64195
+ }
64196
+ if (args.length === 2) {
64197
+ if (target.language === "wgsl") {
64198
+ throw new Error(
64199
+ "Random(m, n): WGSL compile requires explicit seeding. Use a seeded variant or compute the integer range manually."
64200
+ );
64201
+ }
64202
+ const m = compile3(args[0]);
64203
+ const n = compile3(args[1]);
64204
+ const seed = "_gpu_random(gl_FragCoord.x + gl_FragCoord.y * 1024.0)";
64205
+ return `(float(${m}) + floor(${seed} * float((${n}) - (${m}))))`;
64206
+ }
64207
+ throw new Error("Random: GPU compile expects 0, 1, or 2 arguments");
64208
+ },
63519
64209
  // Function (lambda) — not supported in GPU
63520
64210
  Function: () => {
63521
64211
  throw new Error(
@@ -64114,6 +64804,212 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
64114
64804
  }
64115
64805
  return 1.0;
64116
64806
  }
64807
+ `;
64808
+ var GPU_GCD_PREAMBLE_GLSL = `
64809
+ float _gpu_gcd(float a, float b) {
64810
+ a = abs(a); b = abs(b);
64811
+ for (int i = 0; i < 32; i++) {
64812
+ if (b < 0.5) break;
64813
+ float t = mod(a, b);
64814
+ a = b;
64815
+ b = t;
64816
+ }
64817
+ return a;
64818
+ }
64819
+ `;
64820
+ var GPU_GCD_PREAMBLE_WGSL = `
64821
+ fn _gpu_gcd(a_in: f32, b_in: f32) -> f32 {
64822
+ var a = abs(a_in); var b = abs(b_in);
64823
+ for (var i: i32 = 0; i < 32; i++) {
64824
+ if (b < 0.5) { break; }
64825
+ let t = a % b;
64826
+ a = b;
64827
+ b = t;
64828
+ }
64829
+ return a;
64830
+ }
64831
+ `;
64832
+ var GPU_RANDOM_PREAMBLE_GLSL = `
64833
+ // Deterministic pseudorandom in [0, 1) from a float seed.
64834
+ // Standard fract-sin hash; reproducible across runs for the same seed.
64835
+ // Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
64836
+ // For high-quality shader random, callers should use a more robust hash
64837
+ // (e.g. PCG or xxHash) and pre-seed it appropriately.
64838
+ float _gpu_random(float seed) {
64839
+ return fract(sin(seed * 12.9898) * 43758.5453);
64840
+ }
64841
+ `;
64842
+ var GPU_RANDOM_PREAMBLE_WGSL = `
64843
+ // Deterministic pseudorandom in [0, 1) from a float seed.
64844
+ // Standard fract-sin hash; reproducible across runs for the same seed.
64845
+ // Note: this hash exhibits visible banding near seed \u2248 k\u03C0 for integer k.
64846
+ // For high-quality shader random, callers should use a more robust hash
64847
+ // (e.g. PCG or xxHash) and pre-seed it appropriately.
64848
+ fn _gpu_random(seed: f32) -> f32 {
64849
+ return fract(sin(seed * 12.9898) * 43758.5453);
64850
+ }
64851
+ `;
64852
+ var GPU_MEDIAN_PREAMBLE_GLSL = `
64853
+ float _gpu_median_2(float a, float b) {
64854
+ return (a + b) * 0.5;
64855
+ }
64856
+ float _gpu_median_3(float a, float b, float c) {
64857
+ return max(min(a, b), min(max(a, b), c));
64858
+ }
64859
+ float _gpu_median_4(float a, float b, float c, float d) {
64860
+ float lo = max(min(a, b), min(c, d));
64861
+ float hi = min(max(a, b), max(c, d));
64862
+ return (lo + hi) * 0.5;
64863
+ }
64864
+ float _gpu_median_5(float a, float b, float c, float d, float e) {
64865
+ // 9-comparator Bose-Nelson sort; v2 holds the median.
64866
+ float t; float v0=a,v1=b,v2=c,v3=d,v4=e;
64867
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64868
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64869
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64870
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64871
+ t=min(v0,v3); v3=max(v0,v3); v0=t;
64872
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64873
+ t=min(v1,v4); v4=max(v1,v4); v1=t;
64874
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64875
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64876
+ return v2;
64877
+ }
64878
+ float _gpu_median_6(float a, float b, float c, float d, float e, float f) {
64879
+ float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f;
64880
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64881
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64882
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64883
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64884
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64885
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
64886
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
64887
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64888
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64889
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
64890
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64891
+ return (v2 + v3) * 0.5;
64892
+ }
64893
+ float _gpu_median_7(float a, float b, float c, float d, float e, float f, float g) {
64894
+ float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g;
64895
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64896
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64897
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64898
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64899
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64900
+ t=min(v4,v6); v6=max(v4,v6); v4=t;
64901
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
64902
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
64903
+ t=min(v2,v6); v6=max(v2,v6); v2=t;
64904
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64905
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
64906
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64907
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64908
+ return v3;
64909
+ }
64910
+ float _gpu_median_8(float a, float b, float c, float d, float e, float f, float g, float h) {
64911
+ float t; float v0=a,v1=b,v2=c,v3=d,v4=e,v5=f,v6=g,v7=h;
64912
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64913
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64914
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64915
+ t=min(v6,v7); v7=max(v6,v7); v6=t;
64916
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64917
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64918
+ t=min(v4,v6); v6=max(v4,v6); v4=t;
64919
+ t=min(v5,v7); v7=max(v5,v7); v5=t;
64920
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
64921
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
64922
+ t=min(v2,v6); v6=max(v2,v6); v2=t;
64923
+ t=min(v3,v7); v7=max(v3,v7); v3=t;
64924
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64925
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64926
+ t=min(v5,v6); v6=max(v5,v6); v5=t;
64927
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
64928
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64929
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64930
+ return (v3 + v4) * 0.5;
64931
+ }
64932
+ `;
64933
+ var GPU_MEDIAN_PREAMBLE_WGSL = `
64934
+ fn _gpu_median_2(a: f32, b: f32) -> f32 {
64935
+ return (a + b) * 0.5;
64936
+ }
64937
+ fn _gpu_median_3(a: f32, b: f32, c: f32) -> f32 {
64938
+ return max(min(a, b), min(max(a, b), c));
64939
+ }
64940
+ fn _gpu_median_4(a: f32, b: f32, c: f32, d: f32) -> f32 {
64941
+ let lo = max(min(a, b), min(c, d));
64942
+ let hi = min(max(a, b), max(c, d));
64943
+ return (lo + hi) * 0.5;
64944
+ }
64945
+ fn _gpu_median_5(a: f32, b: f32, c: f32, d: f32, e: f32) -> f32 {
64946
+ // 9-comparator Bose-Nelson sort; v2 holds the median.
64947
+ var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var t: f32;
64948
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64949
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64950
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64951
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64952
+ t=min(v0,v3); v3=max(v0,v3); v0=t;
64953
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64954
+ t=min(v1,v4); v4=max(v1,v4); v1=t;
64955
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64956
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64957
+ return v2;
64958
+ }
64959
+ fn _gpu_median_6(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> f32 {
64960
+ var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var t: f32;
64961
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64962
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64963
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64964
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64965
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64966
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
64967
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
64968
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64969
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64970
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
64971
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64972
+ return (v2 + v3) * 0.5;
64973
+ }
64974
+ fn _gpu_median_7(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32) -> f32 {
64975
+ var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var t: f32;
64976
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64977
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64978
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64979
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64980
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64981
+ t=min(v4,v6); v6=max(v4,v6); v4=t;
64982
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
64983
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
64984
+ t=min(v2,v6); v6=max(v2,v6); v2=t;
64985
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
64986
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
64987
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
64988
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
64989
+ return v3;
64990
+ }
64991
+ fn _gpu_median_8(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32, g: f32, h: f32) -> f32 {
64992
+ var v0=a; var v1=b; var v2=c; var v3=d; var v4=e; var v5=f; var v6=g; var v7=h; var t: f32;
64993
+ t=min(v0,v1); v1=max(v0,v1); v0=t;
64994
+ t=min(v2,v3); v3=max(v2,v3); v2=t;
64995
+ t=min(v4,v5); v5=max(v4,v5); v4=t;
64996
+ t=min(v6,v7); v7=max(v6,v7); v6=t;
64997
+ t=min(v0,v2); v2=max(v0,v2); v0=t;
64998
+ t=min(v1,v3); v3=max(v1,v3); v1=t;
64999
+ t=min(v4,v6); v6=max(v4,v6); v4=t;
65000
+ t=min(v5,v7); v7=max(v5,v7); v5=t;
65001
+ t=min(v0,v4); v4=max(v0,v4); v0=t;
65002
+ t=min(v1,v5); v5=max(v1,v5); v1=t;
65003
+ t=min(v2,v6); v6=max(v2,v6); v2=t;
65004
+ t=min(v3,v7); v7=max(v3,v7); v3=t;
65005
+ t=min(v1,v2); v2=max(v1,v2); v1=t;
65006
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
65007
+ t=min(v5,v6); v6=max(v5,v6); v5=t;
65008
+ t=min(v3,v5); v5=max(v3,v5); v3=t;
65009
+ t=min(v2,v4); v4=max(v2,v4); v2=t;
65010
+ t=min(v3,v4); v4=max(v3,v4); v3=t;
65011
+ return (v3 + v4) * 0.5;
65012
+ }
64117
65013
  `;
64118
65014
  var GPU_COLOR_PREAMBLE_GLSL = `
64119
65015
  float _gpu_srgb_to_linear(float c) {
@@ -64792,6 +65688,12 @@ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
64792
65688
  if (code.includes("_fractal_")) {
64793
65689
  preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
64794
65690
  }
65691
+ if (code.includes("_gpu_random"))
65692
+ preamble += this.languageId === "wgsl" ? GPU_RANDOM_PREAMBLE_WGSL : GPU_RANDOM_PREAMBLE_GLSL;
65693
+ if (code.includes("_gpu_gcd"))
65694
+ preamble += this.languageId === "wgsl" ? GPU_GCD_PREAMBLE_WGSL : GPU_GCD_PREAMBLE_GLSL;
65695
+ if (code.includes("_gpu_median_"))
65696
+ preamble += this.languageId === "wgsl" ? GPU_MEDIAN_PREAMBLE_WGSL : GPU_MEDIAN_PREAMBLE_GLSL;
64795
65697
  if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
64796
65698
  preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
64797
65699
  }
@@ -67017,6 +67919,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
67017
67919
  _timeLimit = 2e3;
67018
67920
  _iterationLimit = 1024;
67019
67921
  _recursionLimit = 1024;
67922
+ _maxCollectionSize = 1e4;
67020
67923
  _deadline = void 0;
67021
67924
  _isVerifying = false;
67022
67925
  get timeLimit() {
@@ -67037,6 +67940,12 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
67037
67940
  set recursionLimit(value) {
67038
67941
  this._recursionLimit = value <= 0 ? Number.POSITIVE_INFINITY : value;
67039
67942
  }
67943
+ get maxCollectionSize() {
67944
+ return this._maxCollectionSize;
67945
+ }
67946
+ set maxCollectionSize(value) {
67947
+ this._maxCollectionSize = value <= 0 ? Number.POSITIVE_INFINITY : value;
67948
+ }
67040
67949
  get deadline() {
67041
67950
  return this._deadline;
67042
67951
  }
@@ -69075,6 +69984,23 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69075
69984
  set recursionLimit(t) {
69076
69985
  this._runtimeState.recursionLimit = t;
69077
69986
  }
69987
+ /** Maximum number of elements a collection may have when materialized
69988
+ * (converted from a lazy form to a `List`). Default: 10,000.
69989
+ *
69990
+ * When a materialization would exceed this size, the operation leaves
69991
+ * the expression in its lazy form. Consumers can detect oversize
69992
+ * collections via the symbolic form's `count`.
69993
+ *
69994
+ * Set to `Infinity` (or `0` / a negative number) to disable the cap.
69995
+ *
69996
+ * @experimental
69997
+ */
69998
+ get maxCollectionSize() {
69999
+ return this._runtimeState.maxCollectionSize;
70000
+ }
70001
+ set maxCollectionSize(t) {
70002
+ this._runtimeState.maxCollectionSize = t;
70003
+ }
69078
70004
  /**
69079
70005
  * Flag to prevent infinite recursion in the verify/ask/equality checking cycle.
69080
70006
  *
@@ -69351,6 +70277,18 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69351
70277
  lookupDefinition(id) {
69352
70278
  return lookupDefinition(this, id);
69353
70279
  }
70280
+ normalizeIdentifier(latex) {
70281
+ if (!latex) return "";
70282
+ if (isValidSymbol(latex)) return latex;
70283
+ this.pushScope();
70284
+ try {
70285
+ const expr2 = this.parse(latex);
70286
+ if (isSymbol2(expr2)) return expr2.symbol;
70287
+ } finally {
70288
+ this.popScope();
70289
+ }
70290
+ return "";
70291
+ }
69354
70292
  operatorInfo(head) {
69355
70293
  const def = this.lookupDefinition(head);
69356
70294
  if (!def || !isOperatorDef(def)) return void 0;
@@ -69360,6 +70298,15 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69360
70298
  signature: op.signature
69361
70299
  };
69362
70300
  }
70301
+ symbolInfo(name) {
70302
+ const def = this.lookupDefinition(name);
70303
+ if (!def || !isValueDef(def)) return void 0;
70304
+ const v = def.value;
70305
+ return {
70306
+ kind: v.isConstant ? "constant" : "variable",
70307
+ type: v.type
70308
+ };
70309
+ }
69363
70310
  /**
69364
70311
  * Associate a new definition to a symbol in the current context.
69365
70312
  *
@@ -69812,7 +70759,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69812
70759
  _setDefaultEngineFactory(() => new ComputeEngine());
69813
70760
 
69814
70761
  // src/core.ts
69815
- var version = "0.57.0";
70762
+ var version = "0.58.0";
69816
70763
  return __toCommonJS(core_exports);
69817
70764
  })();
69818
70765
  /*! Bundled license information: