@cortex-js/compute-engine 0.56.0 → 0.57.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 (258) hide show
  1. package/dist/compile.esm.js +450 -42
  2. package/dist/compile.min.esm.js +57 -57
  3. package/dist/compile.min.umd.cjs +58 -58
  4. package/dist/compile.umd.cjs +450 -42
  5. package/dist/compute-engine.esm.js +677 -49
  6. package/dist/compute-engine.min.esm.js +62 -62
  7. package/dist/compute-engine.min.umd.cjs +62 -62
  8. package/dist/compute-engine.umd.cjs +677 -49
  9. package/dist/core.esm.js +676 -48
  10. package/dist/core.min.esm.js +61 -61
  11. package/dist/core.min.umd.cjs +61 -61
  12. package/dist/core.umd.cjs +676 -48
  13. package/dist/interval.esm.js +228 -16
  14. package/dist/interval.min.esm.js +6 -6
  15. package/dist/interval.min.umd.cjs +6 -6
  16. package/dist/interval.umd.cjs +228 -16
  17. package/dist/latex-syntax.esm.js +269 -16
  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 +269 -16
  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 +2 -2
  26. package/dist/numerics.min.esm.js +2 -2
  27. package/dist/numerics.min.umd.cjs +2 -2
  28. package/dist/numerics.umd.cjs +2 -2
  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 +6 -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 +1 -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 +1 -1
  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 +55 -6
  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 +1 -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 +1 -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 +3 -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 +40 -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 +5 -3
  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/rationals.d.ts +1 -1
  212. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  213. package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
  214. package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
  215. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  216. package/dist/types/compute-engine/numerics/types.d.ts +1 -1
  217. package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
  218. package/dist/types/compute-engine/oeis.d.ts +1 -1
  219. package/dist/types/compute-engine/sequence.d.ts +1 -1
  220. package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
  221. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  222. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  223. package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
  224. package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
  225. package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
  226. package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
  227. package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
  228. package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
  229. package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
  230. package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
  231. package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
  232. package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
  233. package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
  234. package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
  235. package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
  236. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  237. package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
  238. package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
  239. package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
  240. package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
  241. package/dist/types/compute-engine/types-definitions.d.ts +1 -1
  242. package/dist/types/compute-engine/types-engine.d.ts +18 -1
  243. package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
  244. package/dist/types/compute-engine/types-expression.d.ts +1 -1
  245. package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
  246. package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
  247. package/dist/types/compute-engine/types-serialization.d.ts +1 -1
  248. package/dist/types/compute-engine/types.d.ts +1 -1
  249. package/dist/types/compute-engine.d.ts +1 -1
  250. package/dist/types/core.d.ts +1 -1
  251. package/dist/types/interval.d.ts +1 -1
  252. package/dist/types/latex-syntax.d.ts +2 -2
  253. package/dist/types/math-json/symbols.d.ts +1 -1
  254. package/dist/types/math-json/types.d.ts +1 -1
  255. package/dist/types/math-json/utils.d.ts +1 -1
  256. package/dist/types/math-json.d.ts +2 -2
  257. package/dist/types/numerics.d.ts +1 -1
  258. package/package.json +1 -1
package/dist/core.umd.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /** ComputeEngineCore 0.56.0 */
1
+ /** ComputeEngineCore 0.57.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;
@@ -7885,8 +7885,15 @@ var ComputeEngineCore = (() => {
7885
7885
  *
7886
7886
  * Numeric values are rounded to `ce.precision` significant digits
7887
7887
  * (via `fractionalDigits: 'auto'`).
7888
+ *
7889
+ * If `options.verbatim` is `true` and `verbatimLatex` is set on this
7890
+ * expression (i.e. it was parsed with `preserveLatex: true`), return
7891
+ * the verbatim source instead of re-serializing. Falls through to
7892
+ * re-serialization if no verbatim is available.
7888
7893
  */
7889
7894
  toLatex(options) {
7895
+ if (options?.verbatim === true && this.verbatimLatex !== void 0)
7896
+ return this.verbatimLatex;
7890
7897
  if (this.isLazyCollection) {
7891
7898
  const materialized = this.evaluate({
7892
7899
  materialization: options?.materialization ?? true
@@ -10029,6 +10036,64 @@ var ComputeEngineCore = (() => {
10029
10036
  }
10030
10037
 
10031
10038
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
10039
+ var COMPONENT_ACCESS_HEADS = {
10040
+ x: "First",
10041
+ y: "Second",
10042
+ z: "Third",
10043
+ real: "Real",
10044
+ re: "Real",
10045
+ imag: "Imaginary",
10046
+ im: "Imaginary",
10047
+ count: "Length",
10048
+ total: "Sum",
10049
+ max: "Max",
10050
+ min: "Min"
10051
+ };
10052
+ function memberHead(name) {
10053
+ return COMPONENT_ACCESS_HEADS[name] ?? null;
10054
+ }
10055
+ function parseComponentAccess(parser, lhs) {
10056
+ parser.skipVisualSpace();
10057
+ if (parser.match("\\operatorname")) {
10058
+ const name = parser.parseStringGroup();
10059
+ if (name === null) return null;
10060
+ const head = memberHead(name.trim());
10061
+ if (head === null) return null;
10062
+ return [head, lhs];
10063
+ }
10064
+ const tok = parser.peek;
10065
+ if (typeof tok === "string" && tok.startsWith("\\")) {
10066
+ const bare = tok.slice(1);
10067
+ const head = memberHead(bare);
10068
+ if (head !== null) {
10069
+ parser.nextToken();
10070
+ return [head, lhs];
10071
+ }
10072
+ return null;
10073
+ }
10074
+ if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
10075
+ const head = memberHead(tok);
10076
+ if (head === null) return null;
10077
+ parser.nextToken();
10078
+ return [head, lhs];
10079
+ }
10080
+ return null;
10081
+ }
10082
+ function parseWhenRestriction(parser, lhs, close) {
10083
+ parser.addBoundary(close);
10084
+ parser.skipVisualSpace();
10085
+ const cond = parser.parseExpression({ minPrec: 0 });
10086
+ if (cond === null) {
10087
+ parser.removeBoundary();
10088
+ return null;
10089
+ }
10090
+ parser.skipVisualSpace();
10091
+ if (!parser.matchBoundary()) {
10092
+ parser.removeBoundary();
10093
+ return null;
10094
+ }
10095
+ return ["When", lhs, cond];
10096
+ }
10032
10097
  function parseSequence(parser, terminator, lhs, prec, sep) {
10033
10098
  if (terminator && terminator.minPrec >= prec) return null;
10034
10099
  const result = lhs ? [lhs] : ["Nothing"];
@@ -10500,6 +10565,15 @@ var ComputeEngineCore = (() => {
10500
10565
  }
10501
10566
  },
10502
10567
  { name: "LatexTokens", serialize: serializeLatexTokens },
10568
+ // Component-access postfix: expr.member (C3)
10569
+ // The '.' trigger is consumed before the parse function is called.
10570
+ // Precedence 850 > 810 (At/indexing) so .x chains tightly.
10571
+ {
10572
+ kind: "postfix",
10573
+ precedence: 850,
10574
+ latexTrigger: ["."],
10575
+ parse: parseComponentAccess
10576
+ },
10503
10577
  {
10504
10578
  name: "At",
10505
10579
  kind: "postfix",
@@ -10520,6 +10594,29 @@ var ComputeEngineCore = (() => {
10520
10594
  latexTrigger: ["\\left", "\\lbrack"],
10521
10595
  parse: parseAt("\\right", "\\rbrack")
10522
10596
  },
10597
+ // When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
10598
+ {
10599
+ name: "When",
10600
+ kind: "postfix",
10601
+ precedence: 800,
10602
+ latexTrigger: ["\\left", "\\{"],
10603
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
10604
+ serialize: (serializer, expr2) => {
10605
+ const e = operand(expr2, 1);
10606
+ const cond = operand(expr2, 2);
10607
+ if (!e || !cond) return "";
10608
+ const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
10609
+ const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
10610
+ return `${serializer.serialize(e)}${inner}`;
10611
+ }
10612
+ },
10613
+ // When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
10614
+ {
10615
+ kind: "postfix",
10616
+ precedence: 800,
10617
+ latexTrigger: ["\\{"],
10618
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
10619
+ },
10523
10620
  {
10524
10621
  kind: "postfix",
10525
10622
  latexTrigger: ["_"],
@@ -10602,6 +10699,29 @@ var ComputeEngineCore = (() => {
10602
10699
  return "";
10603
10700
  }
10604
10701
  },
10702
+ // Additional triggers for Range: `...`, `\ldots`, and `\dots` are
10703
+ // equivalent to `..` when used as infix operators (e.g. `[1...9]`).
10704
+ // No `name` field here — names must be unique per the dictionary rules;
10705
+ // the first Range entry owns the name. When there is no LHS the symbol
10706
+ // entries near the top of the file still fire (ContinuationPlaceholder).
10707
+ {
10708
+ latexTrigger: [".", ".", "."],
10709
+ kind: "infix",
10710
+ precedence: 800,
10711
+ parse: parseRange
10712
+ },
10713
+ {
10714
+ latexTrigger: ["\\ldots"],
10715
+ kind: "infix",
10716
+ precedence: 800,
10717
+ parse: parseRange
10718
+ },
10719
+ {
10720
+ latexTrigger: ["\\dots"],
10721
+ kind: "infix",
10722
+ precedence: 800,
10723
+ parse: parseRange
10724
+ },
10605
10725
  {
10606
10726
  latexTrigger: [";"],
10607
10727
  kind: "infix",
@@ -10786,13 +10906,24 @@ var ComputeEngineCore = (() => {
10786
10906
  const args = operands(expr2);
10787
10907
  if (!args || args.length < 2) return "";
10788
10908
  const body = args[0];
10789
- const indexing = args[1];
10790
- if (operator(indexing) === "Element") {
10791
- const index = operand(indexing, 1);
10792
- const range2 = operand(indexing, 2);
10793
- if (operator(range2) === "Range") {
10794
- const lo = operand(range2, 1);
10795
- const hi = operand(range2, 2);
10909
+ const elements = args.slice(1);
10910
+ const allElements = elements.every((e) => operator(e) === "Element");
10911
+ if (!allElements) {
10912
+ return joinLatex([
10913
+ "\\operatorname{Loop}(",
10914
+ serializer.serialize(body),
10915
+ ", ",
10916
+ serializer.serialize(elements[0]),
10917
+ ")"
10918
+ ]);
10919
+ }
10920
+ if (elements.length === 1) {
10921
+ const elem = elements[0];
10922
+ const index = operand(elem, 1);
10923
+ const coll = operand(elem, 2);
10924
+ if (operator(coll) === "Range") {
10925
+ const lo = operand(coll, 1);
10926
+ const hi = operand(coll, 2);
10796
10927
  return joinLatex([
10797
10928
  "\\text{for }",
10798
10929
  serializer.serialize(index),
@@ -10804,13 +10935,27 @@ var ComputeEngineCore = (() => {
10804
10935
  serializer.serialize(body)
10805
10936
  ]);
10806
10937
  }
10938
+ return joinLatex([
10939
+ serializer.serialize(body),
10940
+ " \\operatorname{for} ",
10941
+ serializer.serialize(index),
10942
+ " = ",
10943
+ serializer.serialize(coll)
10944
+ ]);
10807
10945
  }
10946
+ const bindings = elements.map((elem) => {
10947
+ const name = operand(elem, 1);
10948
+ const coll = operand(elem, 2);
10949
+ return joinLatex([
10950
+ serializer.serialize(name),
10951
+ " = ",
10952
+ serializer.serialize(coll)
10953
+ ]);
10954
+ }).join(", ");
10808
10955
  return joinLatex([
10809
- "\\operatorname{Loop}(",
10810
10956
  serializer.serialize(body),
10811
- ", ",
10812
- serializer.serialize(indexing),
10813
- ")"
10957
+ " \\operatorname{for} ",
10958
+ bindings
10814
10959
  ]);
10815
10960
  }
10816
10961
  },
@@ -10843,6 +10988,18 @@ var ComputeEngineCore = (() => {
10843
10988
  precedence: 245,
10844
10989
  parse: (parser, until) => parseForExpression(parser, until)
10845
10990
  },
10991
+ // \operatorname{for} as postfix infix (list comprehension):
10992
+ // `body \operatorname{for} x = L_1, y = L_2`
10993
+ // Precedence 19 — just below comma (20) so the body is allowed to use
10994
+ // any operator (including comma sequencing) up to the keyword, and the
10995
+ // bindings can be comma-separated below us.
10996
+ {
10997
+ symbolTrigger: "for",
10998
+ kind: "infix",
10999
+ associativity: "none",
11000
+ precedence: 19,
11001
+ parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
11002
+ },
10846
11003
  // \operatorname{break}
10847
11004
  {
10848
11005
  symbolTrigger: "break",
@@ -11047,7 +11204,10 @@ var ComputeEngineCore = (() => {
11047
11204
  if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
11048
11205
  parser.addBoundary([")"]);
11049
11206
  const expr2 = parser.parseExpression(until);
11050
- if (!parser.matchBoundary()) return null;
11207
+ if (!parser.matchBoundary()) {
11208
+ parser.removeBoundary();
11209
+ return null;
11210
+ }
11051
11211
  if (!parser.match("<}>")) return null;
11052
11212
  return ["Derivative", lhs, expr2];
11053
11213
  }
@@ -11488,7 +11648,12 @@ var ComputeEngineCore = (() => {
11488
11648
  if (isEmptySequence(body)) return ["List"];
11489
11649
  const h = operator(body);
11490
11650
  if (h === "Range" || h === "Linspace") return body;
11491
- if (h === "Sequence") return ["List", ...operands(body)];
11651
+ if (h === "Sequence") {
11652
+ const elems = operands(body);
11653
+ const inferred = tryInferRangeFromElements(elems, parser);
11654
+ if (inferred) return inferred;
11655
+ return ["List", ...elems];
11656
+ }
11492
11657
  if (h === "Delimiter") {
11493
11658
  const delim = stringValue(operand(body, 2)) ?? "...";
11494
11659
  if (delim === ";" || delim === ".;.") {
@@ -11501,12 +11666,37 @@ var ComputeEngineCore = (() => {
11501
11666
  }
11502
11667
  if (delim === "," || delim === ".,.") {
11503
11668
  body = operand(body, 1);
11504
- if (operator(body) === "Sequence") return ["List", ...operands(body)];
11669
+ if (operator(body) === "Sequence") {
11670
+ const elems = operands(body);
11671
+ const inferred = tryInferRangeFromElements(elems, parser);
11672
+ if (inferred) return inferred;
11673
+ return ["List", ...elems];
11674
+ }
11505
11675
  return ["List", body ?? "Nothing"];
11506
11676
  }
11507
11677
  }
11508
11678
  return ["List", body];
11509
11679
  }
11680
+ function tryInferRangeFromElements(elems, parser) {
11681
+ if (elems.length < 4) return null;
11682
+ const penultimate = elems[elems.length - 2];
11683
+ if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
11684
+ const samples = elems.slice(0, -2);
11685
+ const endExpr = elems[elems.length - 1];
11686
+ if (samples.length < 2) return null;
11687
+ const sampleNums = samples.map(machineValue);
11688
+ if (sampleNums.some((n) => n === null)) return null;
11689
+ const nums = sampleNums;
11690
+ const step = nums[nums.length - 1] - nums[nums.length - 2];
11691
+ const tol = parser.options.tolerance;
11692
+ if (Math.abs(step) < tol)
11693
+ return parser.error("degenerate-range-step", parser.index);
11694
+ for (let i = 1; i < nums.length; i++) {
11695
+ if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
11696
+ return parser.error("inconsistent-range-samples", parser.index);
11697
+ }
11698
+ return ["Range", nums[0], endExpr, step];
11699
+ }
11510
11700
  function serializeList(serializer, expr2) {
11511
11701
  if (nops(expr2) > 1 && operands(expr2).every((x) => {
11512
11702
  const op = operator(x);
@@ -11758,6 +11948,35 @@ var ComputeEngineCore = (() => {
11758
11948
  ["Element", index, ["Range", lower, upper]]
11759
11949
  ];
11760
11950
  }
11951
+ function parseForComprehension(parser, lhs, until) {
11952
+ const bindingTerminator = {
11953
+ minPrec: 21,
11954
+ // Above comma (20) and ; (19), so `x = L_1` is captured whole
11955
+ condition: (p) => {
11956
+ if (until?.condition?.(p)) return true;
11957
+ const saved = p.index;
11958
+ p.skipVisualSpace();
11959
+ const isComma = p.peek === ",";
11960
+ p.index = saved;
11961
+ return isComma;
11962
+ }
11963
+ };
11964
+ const elements = [];
11965
+ do {
11966
+ parser.skipVisualSpace();
11967
+ const binding = parser.parseExpression(bindingTerminator);
11968
+ if (binding === null) break;
11969
+ const op = operator(binding);
11970
+ if (op !== "Equal" && op !== "Assign") return null;
11971
+ const name = operand(binding, 1);
11972
+ const list = operand(binding, 2);
11973
+ if (!name || !list) return null;
11974
+ elements.push(["Element", name, list]);
11975
+ parser.skipVisualSpace();
11976
+ } while (parser.match(","));
11977
+ if (elements.length === 0) return null;
11978
+ return ["Loop", lhs, ...elements];
11979
+ }
11761
11980
  function parseWhereExpression(parser, lhs, until) {
11762
11981
  const bindingTerminator = {
11763
11982
  minPrec: 21,
@@ -19529,6 +19748,19 @@ var ComputeEngineCore = (() => {
19529
19748
  } while (postfix !== null);
19530
19749
  }
19531
19750
  if (result !== null) result = this.parseSupsub(result);
19751
+ if (result !== null) {
19752
+ let postfix = null;
19753
+ let index = this.index;
19754
+ do {
19755
+ postfix = this.parsePostfixOperator(result, until);
19756
+ result = postfix ?? result;
19757
+ if (this.index === index && postfix !== null) {
19758
+ console.assert(this.index !== index, "No token consumed");
19759
+ break;
19760
+ }
19761
+ index = this.index;
19762
+ } while (postfix !== null);
19763
+ }
19532
19764
  if (result === null) {
19533
19765
  result = this.options.parseUnexpectedToken?.(null, this) ?? null;
19534
19766
  if (result === null && this.peek.startsWith("\\")) {
@@ -20037,6 +20269,28 @@ var ComputeEngineCore = (() => {
20037
20269
  }
20038
20270
 
20039
20271
  // src/compute-engine/latex-syntax/serializer.ts
20272
+ var DOT_NOTATION_MAP = {
20273
+ First: ".x",
20274
+ Second: ".y",
20275
+ Third: ".z",
20276
+ Real: ".\\operatorname{real}",
20277
+ Imaginary: ".\\operatorname{imag}",
20278
+ Length: ".\\operatorname{count}",
20279
+ Sum: ".\\operatorname{total}",
20280
+ Max: ".\\max",
20281
+ Min: ".\\min"
20282
+ };
20283
+ function trySerializeDotNotation(serializer, expr2) {
20284
+ if (!serializer.options.dotNotation) return null;
20285
+ const ops = operands(expr2);
20286
+ if (!ops || ops.length !== 1) return null;
20287
+ const head = operator(expr2);
20288
+ if (!head) return null;
20289
+ const suffix = DOT_NOTATION_MAP[head];
20290
+ if (suffix === void 0) return null;
20291
+ const lhs = serializer.wrap(ops[0], 810);
20292
+ return `${lhs}${suffix}`;
20293
+ }
20040
20294
  var ACCENT_MODIFIERS = {
20041
20295
  deg: (s) => `${s}\\degree`,
20042
20296
  prime: (s) => `${s}^{\\prime}`,
@@ -20080,6 +20334,7 @@ var ComputeEngineCore = (() => {
20080
20334
  constructor(dictionary, options) {
20081
20335
  this.dictionary = dictionary;
20082
20336
  this.options = {
20337
+ dotNotation: false,
20083
20338
  dmsFormat: false,
20084
20339
  angleNormalization: "none",
20085
20340
  ...options
@@ -20178,6 +20433,8 @@ var ComputeEngineCore = (() => {
20178
20433
  return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
20179
20434
  }
20180
20435
  serializeFunction(expr2, def) {
20436
+ const dotResult = trySerializeDotNotation(this, expr2);
20437
+ if (dotResult !== null) return dotResult;
20181
20438
  if (def?.serialize) return def.serialize(this, expr2);
20182
20439
  const h = operator(expr2);
20183
20440
  return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
@@ -20420,6 +20677,8 @@ var ComputeEngineCore = (() => {
20420
20677
  preserveLatex: opts.preserveLatex ?? false,
20421
20678
  quantifierScope: opts.quantifierScope ?? "tight",
20422
20679
  timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
20680
+ // Standalone mode has no engine; use the same default as ComputeEngine
20681
+ tolerance: 1e-7,
20423
20682
  // Callbacks -- standalone mode has no engine, so these are stubs
20424
20683
  getSymbolType: (_id) => BoxedType.unknown,
20425
20684
  hasSubscriptEvaluate: (_id) => false,
@@ -20452,6 +20711,7 @@ var ComputeEngineCore = (() => {
20452
20711
  invisiblePlus: "",
20453
20712
  multiply: "\\times",
20454
20713
  missingSymbol: "\\blacksquare",
20714
+ dotNotation: false,
20455
20715
  dmsFormat: false,
20456
20716
  angleNormalization: "none",
20457
20717
  // Style callbacks -- use same defaults as the engine
@@ -27422,7 +27682,11 @@ ${lines.join("\n")}`;
27422
27682
  //
27423
27683
  Range: {
27424
27684
  complexity: 8200,
27425
- signature: "(number, number?, step: number?) -> indexed_collection<integer>",
27685
+ signature: "(number, number?, step: number?) -> indexed_collection<number>",
27686
+ type: (ops) => {
27687
+ const allInt = ops.every((op) => op.isInteger);
27688
+ return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
27689
+ },
27426
27690
  canonical: (ops, { engine: ce }) => {
27427
27691
  if (ops.length === 0) return null;
27428
27692
  if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
@@ -27446,19 +27710,26 @@ ${lines.join("\n")}`;
27446
27710
  const [lower, upper, step] = range(expr2);
27447
27711
  if (step === 0) return 0;
27448
27712
  if (!isFinite(lower) || !isFinite(upper)) return Infinity;
27449
- return 1 + Math.max(0, Math.floor((upper - lower) / step));
27713
+ return Math.max(0, Math.floor((upper - lower) / step) + 1);
27450
27714
  },
27451
27715
  contains: (expr2, target) => {
27452
- if (!target.type.matches("integer")) return false;
27453
27716
  const t = target.re;
27717
+ if (!isFinite(t)) return false;
27454
27718
  const [lower, upper, step] = range(expr2);
27455
27719
  if (step === 0) return false;
27456
- if (step > 0) return t >= lower && t <= upper;
27457
- return t <= lower && t >= upper;
27720
+ if (step > 0) {
27721
+ if (t < lower || t > upper) return false;
27722
+ } else {
27723
+ if (t > lower || t < upper) return false;
27724
+ }
27725
+ const k = (t - lower) / step;
27726
+ const tol = expr2.engine.tolerance;
27727
+ const kRounded = Math.round(k);
27728
+ return kRounded >= 0 && Math.abs(k - kRounded) < tol;
27458
27729
  },
27459
27730
  iterator: (expr2) => {
27460
27731
  const [lower, upper, step] = range(expr2);
27461
- const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
27732
+ const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
27462
27733
  let index = 1;
27463
27734
  return {
27464
27735
  next: () => {
@@ -27476,7 +27747,9 @@ ${lines.join("\n")}`;
27476
27747
  at: (expr2, index) => {
27477
27748
  if (typeof index !== "number") return void 0;
27478
27749
  const [lower, upper, step] = range(expr2);
27479
- if (index < 1 || index > 1 + (upper - lower) / step) return void 0;
27750
+ if (step === 0) return void 0;
27751
+ const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
27752
+ if (index < 1 || index > maxCount) return void 0;
27480
27753
  return expr2.engine.number(lower + step * (index - 1));
27481
27754
  },
27482
27755
  indexWhere: void 0,
@@ -27501,7 +27774,13 @@ ${lines.join("\n")}`;
27501
27774
  if (step > 0) return lower <= upper ? "positive" : "negative";
27502
27775
  return lower >= upper ? "positive" : "negative";
27503
27776
  },
27504
- elttype: (_expr) => "finite_integer"
27777
+ elttype: (expr2) => {
27778
+ if (!isFunction2(expr2)) return "finite_integer";
27779
+ for (let i = 1; i <= expr2.nops; i++) {
27780
+ if (!expr2[`op${i}`].isInteger) return "finite_real";
27781
+ }
27782
+ return "finite_integer";
27783
+ }
27505
27784
  }
27506
27785
  },
27507
27786
  Interval: {
@@ -28099,15 +28378,45 @@ ${lines.join("\n")}`;
28099
28378
  },
28100
28379
  First: {
28101
28380
  complexity: 8200,
28102
- signature: "(collection) -> any",
28381
+ signature: "(any) -> any",
28103
28382
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28104
- evaluate: ([xs], { engine: ce }) => xs.at(1) ?? ce.Nothing
28383
+ evaluate: ([xs], { engine: ce }) => {
28384
+ if (!xs.isCollection)
28385
+ return ce.error([
28386
+ "incompatible-type",
28387
+ `'collection'`,
28388
+ xs.type.toString()
28389
+ ]);
28390
+ return xs.at(1) ?? ce.Nothing;
28391
+ }
28105
28392
  },
28106
28393
  Second: {
28107
28394
  complexity: 8200,
28108
- signature: "(collection) -> any",
28395
+ signature: "(any) -> any",
28396
+ type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28397
+ evaluate: ([xs], { engine: ce }) => {
28398
+ if (!xs.isCollection)
28399
+ return ce.error([
28400
+ "incompatible-type",
28401
+ `'collection'`,
28402
+ xs.type.toString()
28403
+ ]);
28404
+ return xs.at(2) ?? ce.Nothing;
28405
+ }
28406
+ },
28407
+ Third: {
28408
+ complexity: 8200,
28409
+ signature: "(any) -> any",
28109
28410
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28110
- evaluate: ([xs], { engine: ce }) => xs.at(2) ?? ce.Nothing
28411
+ evaluate: ([xs], { engine: ce }) => {
28412
+ if (!xs.isCollection)
28413
+ return ce.error([
28414
+ "incompatible-type",
28415
+ `'collection'`,
28416
+ xs.type.toString()
28417
+ ]);
28418
+ return xs.at(3) ?? ce.Nothing;
28419
+ }
28111
28420
  },
28112
28421
  Last: {
28113
28422
  complexity: 8200,
@@ -29086,17 +29395,14 @@ ${lines.join("\n")}`;
29086
29395
  if (!isFunction2(expr2)) return [1, 0, 0];
29087
29396
  if (expr2.nops === 0) return [1, 0, 0];
29088
29397
  let op1 = expr2.op1.re;
29089
- if (!isFinite(op1)) op1 = 1;
29090
- else op1 = Math.round(op1);
29398
+ if (!isFinite(op1) && !op1) op1 = 1;
29091
29399
  if (expr2.nops === 1) return [1, op1, 1];
29092
29400
  let op2 = expr2.op2.re;
29093
29401
  if (!isFinite(op2) && !op2) op2 = 1;
29094
- else if (isFinite(op2)) op2 = Math.round(op2);
29095
- if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
29402
+ if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
29096
29403
  let op3 = expr2.op3.re;
29097
- if (!isFinite(op3)) op3 = 1;
29098
- else op3 = Math.abs(Math.round(op3));
29099
- return [op1, op2, op1 < op2 ? op3 : -op3];
29404
+ if (!isFinite(op3) && !op3) op3 = 1;
29405
+ return [op1, op2, op3];
29100
29406
  }
29101
29407
  function rangeLast(r) {
29102
29408
  const [lower, upper, step] = r;
@@ -42826,12 +43132,42 @@ ${e.message}
42826
43132
  }
42827
43133
  },
42828
43134
  Loop: {
42829
- description: "Evaluate a body expression over elements of a collection.",
43135
+ description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
43136
+ lazy: true,
43137
+ signature: "(body:expression, iterators:expression*) -> any",
43138
+ type: ([body]) => {
43139
+ if (!body) return "nothing";
43140
+ return parseType(`indexed_collection<${String(body.type)}>`);
43141
+ },
43142
+ canonical: canonicalLoop,
43143
+ evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
43144
+ evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
43145
+ },
43146
+ When: {
43147
+ description: "Conditional value: returns expr when cond holds, undefined otherwise.",
42830
43148
  lazy: true,
42831
- signature: "(body:expression, collection:expression) -> any",
42832
- type: ([body]) => body.type,
42833
- evaluate: ([body, collection], { engine: ce }) => run(runLoop(body, collection, ce), ce._timeRemaining),
42834
- evaluateAsync: async ([body, collection], { engine: ce, signal }) => runAsync(runLoop(body, collection, ce), ce._timeRemaining, signal)
43149
+ signature: "(expression, boolean) -> any",
43150
+ type: ([expr2]) => expr2.type,
43151
+ canonical: (args, { engine: ce }) => {
43152
+ if (args.length !== 2) return null;
43153
+ const [expr2, cond] = args;
43154
+ if (isFunction2(expr2, "When")) {
43155
+ const inner = expr2.op1.canonical;
43156
+ const innerCond = expr2.op2.canonical;
43157
+ return ce._fn("When", [
43158
+ inner,
43159
+ ce._fn("And", [innerCond, cond.canonical])
43160
+ ]);
43161
+ }
43162
+ return ce._fn("When", [expr2.canonical, cond.canonical]);
43163
+ },
43164
+ evaluate: ([expr2, cond], { engine: ce }) => {
43165
+ const c = cond.evaluate();
43166
+ const cs = sym(c);
43167
+ if (cs === "True") return expr2.evaluate();
43168
+ if (cs === "False") return ce.symbol("Undefined");
43169
+ return ce._fn("When", [expr2, c]);
43170
+ }
42835
43171
  },
42836
43172
  Which: {
42837
43173
  description: "Return the value for the first condition that is true.",
@@ -42891,9 +43227,141 @@ ${e.message}
42891
43227
  );
42892
43228
  return result;
42893
43229
  }
42894
- function* runLoop(body, collection, ce) {
43230
+ function canonicalLoop(ops, options) {
43231
+ const { engine: ce, scope } = options;
43232
+ if (ops.length === 0) return null;
43233
+ if (ops.length === 1) {
43234
+ return ce._fn("Loop", [ops[0].canonical]);
43235
+ }
43236
+ const body = ops[0];
43237
+ const iterators = ops.slice(1);
43238
+ const allElement = iterators.every((it) => it.operator === "Element");
43239
+ if (!allElement) {
43240
+ return ce._fn(
43241
+ "Loop",
43242
+ ops.map((op) => op.canonical)
43243
+ );
43244
+ }
43245
+ const loopScope = scope ?? {
43246
+ parent: ce.context.lexicalScope,
43247
+ bindings: /* @__PURE__ */ new Map()
43248
+ };
43249
+ loopScope.noAutoDeclare = true;
43250
+ ce.pushScope(loopScope);
43251
+ let canonicalIterators;
43252
+ let canonicalBody;
43253
+ try {
43254
+ canonicalIterators = iterators.map((it) => {
43255
+ if (!isFunction2(it, "Element")) {
43256
+ return ce._fn("Element", [
43257
+ ce.error("missing").canonical,
43258
+ ce.error("missing").canonical
43259
+ ]);
43260
+ }
43261
+ const indexExpr = it.ops[0];
43262
+ const collExpr = it.ops[1];
43263
+ if (!indexExpr || !collExpr) {
43264
+ return ce._fn("Element", [
43265
+ (indexExpr ?? ce.error("missing")).canonical,
43266
+ (collExpr ?? ce.error("missing")).canonical
43267
+ ]);
43268
+ }
43269
+ if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
43270
+ if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
43271
+ ce.declare(indexExpr.symbol, "unknown");
43272
+ }
43273
+ return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
43274
+ });
43275
+ canonicalBody = body.canonical;
43276
+ } finally {
43277
+ ce.popScope();
43278
+ loopScope.noAutoDeclare = false;
43279
+ }
43280
+ return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
43281
+ scope: loopScope
43282
+ });
43283
+ }
43284
+ function* runLoop(body, elements, ce) {
42895
43285
  body ??= ce.Nothing;
42896
43286
  if (sym(body) === "Nothing") return body;
43287
+ if (elements.length === 0) {
43288
+ const result = body.evaluate();
43289
+ yield result;
43290
+ return result;
43291
+ }
43292
+ if (elements.length === 1 && elements[0].operator !== "Element") {
43293
+ return yield* runLoopLegacy(body, elements[0], ce);
43294
+ }
43295
+ const results = [];
43296
+ const state = { stopped: false, broke: false, count: 0 };
43297
+ const freshScope = {
43298
+ parent: ce.context.lexicalScope,
43299
+ bindings: /* @__PURE__ */ new Map()
43300
+ };
43301
+ ce._pushEvalContext(freshScope);
43302
+ try {
43303
+ for (const elem of elements) {
43304
+ if (!isFunction2(elem, "Element")) continue;
43305
+ const idx = elem.ops[0];
43306
+ if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
43307
+ if (!freshScope.bindings.has(idx.symbol))
43308
+ ce.declare(idx.symbol, "unknown");
43309
+ }
43310
+ }
43311
+ yield* runLoopNested(body, elements, 0, ce, results, state);
43312
+ } finally {
43313
+ ce._popEvalContext();
43314
+ }
43315
+ if (state.stopped && state.value !== void 0) {
43316
+ if (!state.broke) return state.value;
43317
+ return state.value;
43318
+ }
43319
+ return ce.function("List", results);
43320
+ }
43321
+ function* runLoopNested(body, elements, index, ce, results, state) {
43322
+ if (state.stopped) return;
43323
+ if (index === elements.length) {
43324
+ const result = body.evaluate();
43325
+ state.count += 1;
43326
+ if (state.count > ce.iterationLimit)
43327
+ throw new CancellationError({ cause: "iteration-limit-exceeded" });
43328
+ if (isFunction2(result, "Break")) {
43329
+ state.stopped = true;
43330
+ state.broke = true;
43331
+ state.value = result.op1;
43332
+ return;
43333
+ }
43334
+ if (result.operator === "Return") {
43335
+ state.stopped = true;
43336
+ state.value = result;
43337
+ return;
43338
+ }
43339
+ results.push(result);
43340
+ yield result;
43341
+ return;
43342
+ }
43343
+ const elem = elements[index];
43344
+ if (!isFunction2(elem, "Element")) {
43345
+ return;
43346
+ }
43347
+ const indexExpr = elem.ops[0];
43348
+ const collExpr = elem.ops[1];
43349
+ if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
43350
+ return;
43351
+ }
43352
+ const name = indexExpr.symbol;
43353
+ const collection = collExpr.evaluate();
43354
+ if (!collection?.isCollection) {
43355
+ return;
43356
+ }
43357
+ const skipAssign = name === "Nothing";
43358
+ for (const value of collection.each()) {
43359
+ if (!skipAssign) ce.assign(name, value);
43360
+ yield* runLoopNested(body, elements, index + 1, ce, results, state);
43361
+ if (state.stopped) return;
43362
+ }
43363
+ }
43364
+ function* runLoopLegacy(body, collection, ce) {
42897
43365
  if (collection?.isCollection) {
42898
43366
  let result = void 0;
42899
43367
  const fn = applicable(body);
@@ -54976,6 +55444,23 @@ Error in definition of "${name}"`,
54976
55444
  };
54977
55445
  return compilePair(0);
54978
55446
  }
55447
+ if (h === "When") {
55448
+ if (args.length !== 2)
55449
+ throw new Error("When: expected exactly 2 arguments (expr, cond)");
55450
+ const fn2 = target.functions?.(h);
55451
+ if (fn2) {
55452
+ if (typeof fn2 === "function") {
55453
+ return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
55454
+ }
55455
+ return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
55456
+ }
55457
+ if (isSymbol2(args[1], "True"))
55458
+ return `(${_BaseCompiler.compile(args[0], target)})`;
55459
+ if (isSymbol2(args[1], "False")) return "NaN";
55460
+ const val = _BaseCompiler.compile(args[0], target);
55461
+ const cond = _BaseCompiler.compile(args[1], target);
55462
+ return `((${cond}) ? (${val}) : NaN)`;
55463
+ }
54979
55464
  if (h === "Block") {
54980
55465
  return _BaseCompiler.compileBlock(args, target);
54981
55466
  }
@@ -55050,17 +55535,91 @@ Error in definition of "${name}"`,
55050
55535
  )}${target.ws("\n")}})()`;
55051
55536
  }
55052
55537
  /**
55053
- * Compile a Loop expression with Element(index, Range(lo, hi)) indexing.
55054
- * Generates: (() => { for (let i = lo; i <= hi; i++) { body } })()
55538
+ * Compile a Loop expression.
55539
+ *
55540
+ * Two forms are supported:
55541
+ *
55542
+ * 1. **Imperative / single-Element form** (existing behaviour):
55543
+ * `Loop(body, Element(i, Range(lo, hi)))`
55544
+ * Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
55545
+ * in an IIFE. The loop counter is always a plain number. For targets
55546
+ * that wrap numeric values (e.g. interval-js uses `_IA.point()`),
55547
+ * references to the loop index inside the body are re-wrapped via
55548
+ * `target.number`. `break` / `continue` / `return` are preserved.
55549
+ *
55550
+ * 2. **Comprehension / variadic-Element form** (new):
55551
+ * `Loop(body, Element(x, coll1), Element(y, coll2), …)`
55552
+ * When two or more `Element` clauses are present — or when the single
55553
+ * Element's collection is not a `Range` — the loop is compiled as a
55554
+ * comprehension that collects results into an array. Each clause
55555
+ * produces a `for (const name of collection)` loop, nested
55556
+ * outermost-to-innermost, and the innermost body pushes into `result`.
55557
+ *
55558
+ * Example output (JS):
55559
+ * ```js
55560
+ * (() => { const result = [];
55561
+ * for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
55562
+ * return result; })()
55563
+ * ```
55055
55564
  *
55056
- * The loop counter is always a raw number. For targets that wrap numeric
55057
- * values (e.g. interval-js wraps with `_IA.point()`), references to the
55058
- * loop index inside the body are wrapped via `target.number`.
55565
+ * GLSL: multi-Element comprehension is not trivially representable in
55566
+ * GLSL (no dynamic arrays, no push). A compile-time error is thrown.
55567
+ * TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
55568
+ * array or by unrolling when bounds are known at compile time.
55059
55569
  */
55060
55570
  static compileForLoop(args, target) {
55061
55571
  if (!args[0]) throw new Error("Loop: no body");
55062
55572
  if (!args[1]) throw new Error("Loop: no indexing set");
55063
- const indexing = args[1];
55573
+ const body = args[0];
55574
+ const elements = args.slice(1);
55575
+ const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
55576
+ if (useComprehension) {
55577
+ const lang = target.language ?? "";
55578
+ if (lang === "glsl" || lang === "wgsl") {
55579
+ throw new Error(
55580
+ `${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
55581
+ );
55582
+ }
55583
+ const narrowedElements = [];
55584
+ for (let i = 0; i < elements.length; i++) {
55585
+ const elem = elements[i];
55586
+ if (!isFunction2(elem, "Element"))
55587
+ throw new Error(
55588
+ `Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
55589
+ );
55590
+ if (!isSymbol2(elem.ops[0]))
55591
+ throw new Error(
55592
+ `Loop: Element index (argument ${i + 1}) must be a symbol`
55593
+ );
55594
+ narrowedElements.push(elem);
55595
+ }
55596
+ const loopVarSet = new Set(
55597
+ narrowedElements.map(
55598
+ (e) => e.ops[0].symbol
55599
+ )
55600
+ );
55601
+ const needsWrap2 = target.number(0) !== "0";
55602
+ const bodyTarget2 = needsWrap2 ? {
55603
+ ...target,
55604
+ var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
55605
+ } : target;
55606
+ const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
55607
+ let inner = `result.push(${bodyCode});`;
55608
+ for (let i = narrowedElements.length - 1; i >= 0; i--) {
55609
+ const elem = narrowedElements[i];
55610
+ const name = elem.ops[0].symbol;
55611
+ const collExpr = elem.ops[1];
55612
+ let collection;
55613
+ if (isFunction2(collExpr, "Range")) {
55614
+ collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
55615
+ } else {
55616
+ collection = _BaseCompiler.compile(collExpr, bodyTarget2);
55617
+ }
55618
+ inner = `for (const ${name} of ${collection}) { ${inner} }`;
55619
+ }
55620
+ return `(() => { const result = []; ${inner} return result; })()`;
55621
+ }
55622
+ const indexing = elements[0];
55064
55623
  if (!isFunction2(indexing, "Element"))
55065
55624
  throw new Error("Loop: expected Element(index, Range(lo, hi))");
55066
55625
  const indexExpr = indexing.ops[0];
@@ -55078,13 +55637,72 @@ Error in definition of "${name}"`,
55078
55637
  ...target,
55079
55638
  var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
55080
55639
  };
55081
- const bodyStmts = _BaseCompiler.compileLoopBody(args[0], bodyTarget);
55640
+ const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
55082
55641
  return `(() => {${target.ws(
55083
55642
  "\n"
55084
55643
  )}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
55085
55644
  "\n"
55086
55645
  )}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
55087
55646
  }
55647
+ /**
55648
+ * Returns `true` when the given collection expression is a `Range` whose
55649
+ * runtime semantics match the legacy imperative for-loop shape
55650
+ * `for (let i = lo; i <= hi; i++)`.
55651
+ *
55652
+ * Concretely: integer-ascending bounds and step omitted-or-1. When bounds
55653
+ * are not statically numeric we accept the Range (the historical
55654
+ * behaviour) — runtime mismatch in the descending-unknown-bounds case is
55655
+ * left as a known limitation; callers can force the iterable path by
55656
+ * supplying an explicit step.
55657
+ */
55658
+ static isLegacyCompatibleRange(coll) {
55659
+ if (!isFunction2(coll, "Range")) return false;
55660
+ if (coll.ops.length >= 3) {
55661
+ const stepExpr = coll.ops[2];
55662
+ if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
55663
+ }
55664
+ const lo = coll.ops[0];
55665
+ const hi = coll.ops[1];
55666
+ if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
55667
+ if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
55668
+ if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
55669
+ return true;
55670
+ }
55671
+ /**
55672
+ * Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
55673
+ * iterable expression. Mirrors the runtime semantics in
55674
+ * `library/collections.ts` Range:
55675
+ * count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
55676
+ * element = lo + step * k (0-indexed)
55677
+ * Default step is 1 when omitted. Bounds and step may be fractional.
55678
+ *
55679
+ * Only used from the comprehension path in `compileForLoop`.
55680
+ * Caller must have already verified `isFunction(rangeExpr, 'Range')`.
55681
+ */
55682
+ static compileRangeIterable(rangeExpr, target) {
55683
+ const loExpr = rangeExpr.ops[0];
55684
+ const hiExpr = rangeExpr.ops[1];
55685
+ const stepExpr = rangeExpr.ops[2];
55686
+ if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
55687
+ const lo2 = loExpr.re;
55688
+ const hi2 = hiExpr.re;
55689
+ const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
55690
+ if (step2 === 0) return "[]";
55691
+ const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
55692
+ if (step2 === 1) {
55693
+ if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
55694
+ return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
55695
+ }
55696
+ return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
55697
+ }
55698
+ const lo = _BaseCompiler.compile(loExpr, target);
55699
+ const hi = _BaseCompiler.compile(hiExpr, target);
55700
+ if (stepExpr === void 0) {
55701
+ return `((_lo,_hi)=>{const _st=_hi>=_lo?1:-1;return Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k);})(${lo},${hi})`;
55702
+ }
55703
+ const step = _BaseCompiler.compile(stepExpr, target);
55704
+ return `((_lo,_hi,_st)=>_st===0?[]:Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k))(${lo},${hi},${step})`;
55705
+ }
55088
55706
  /**
55089
55707
  * Compile a loop body expression as statements (not wrapped in IIFE).
55090
55708
  * Handles Break, Continue, Return as statements, and If as if-else when
@@ -68733,6 +69351,15 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
68733
69351
  lookupDefinition(id) {
68734
69352
  return lookupDefinition(this, id);
68735
69353
  }
69354
+ operatorInfo(head) {
69355
+ const def = this.lookupDefinition(head);
69356
+ if (!def || !isOperatorDef(def)) return void 0;
69357
+ const op = def.operator;
69358
+ return {
69359
+ kind: op.evaluate || op.collection ? "function" : "opaque",
69360
+ signature: op.signature
69361
+ };
69362
+ }
68736
69363
  /**
68737
69364
  * Associate a new definition to a symbol in the current context.
68738
69365
  *
@@ -69020,6 +69647,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69020
69647
  const def = this.lookupDefinition(id);
69021
69648
  return !!(isValueDef(def) && def.value.subscriptEvaluate);
69022
69649
  },
69650
+ tolerance: this.tolerance,
69023
69651
  ...this._latexOptions,
69024
69652
  ...parseOpts
69025
69653
  });
@@ -69184,7 +69812,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
69184
69812
  _setDefaultEngineFactory(() => new ComputeEngine());
69185
69813
 
69186
69814
  // src/core.ts
69187
- var version = "0.56.0";
69815
+ var version = "0.57.0";
69188
69816
  return __toCommonJS(core_exports);
69189
69817
  })();
69190
69818
  /*! Bundled license information: