@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
@@ -1,4 +1,4 @@
1
- /** Compute Engine 0.56.0 */
1
+ /** Compute Engine 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.ComputeEngine = {}));})(this, (function (exports) { 'use strict';
3
3
  var ComputeEngine = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -7914,8 +7914,15 @@ var ComputeEngine = (() => {
7914
7914
  *
7915
7915
  * Numeric values are rounded to `ce.precision` significant digits
7916
7916
  * (via `fractionalDigits: 'auto'`).
7917
+ *
7918
+ * If `options.verbatim` is `true` and `verbatimLatex` is set on this
7919
+ * expression (i.e. it was parsed with `preserveLatex: true`), return
7920
+ * the verbatim source instead of re-serializing. Falls through to
7921
+ * re-serialization if no verbatim is available.
7917
7922
  */
7918
7923
  toLatex(options) {
7924
+ if (options?.verbatim === true && this.verbatimLatex !== void 0)
7925
+ return this.verbatimLatex;
7919
7926
  if (this.isLazyCollection) {
7920
7927
  const materialized = this.evaluate({
7921
7928
  materialization: options?.materialization ?? true
@@ -10058,6 +10065,64 @@ var ComputeEngine = (() => {
10058
10065
  }
10059
10066
 
10060
10067
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
10068
+ var COMPONENT_ACCESS_HEADS = {
10069
+ x: "First",
10070
+ y: "Second",
10071
+ z: "Third",
10072
+ real: "Real",
10073
+ re: "Real",
10074
+ imag: "Imaginary",
10075
+ im: "Imaginary",
10076
+ count: "Length",
10077
+ total: "Sum",
10078
+ max: "Max",
10079
+ min: "Min"
10080
+ };
10081
+ function memberHead(name) {
10082
+ return COMPONENT_ACCESS_HEADS[name] ?? null;
10083
+ }
10084
+ function parseComponentAccess(parser, lhs) {
10085
+ parser.skipVisualSpace();
10086
+ if (parser.match("\\operatorname")) {
10087
+ const name = parser.parseStringGroup();
10088
+ if (name === null) return null;
10089
+ const head = memberHead(name.trim());
10090
+ if (head === null) return null;
10091
+ return [head, lhs];
10092
+ }
10093
+ const tok = parser.peek;
10094
+ if (typeof tok === "string" && tok.startsWith("\\")) {
10095
+ const bare = tok.slice(1);
10096
+ const head = memberHead(bare);
10097
+ if (head !== null) {
10098
+ parser.nextToken();
10099
+ return [head, lhs];
10100
+ }
10101
+ return null;
10102
+ }
10103
+ if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
10104
+ const head = memberHead(tok);
10105
+ if (head === null) return null;
10106
+ parser.nextToken();
10107
+ return [head, lhs];
10108
+ }
10109
+ return null;
10110
+ }
10111
+ function parseWhenRestriction(parser, lhs, close) {
10112
+ parser.addBoundary(close);
10113
+ parser.skipVisualSpace();
10114
+ const cond = parser.parseExpression({ minPrec: 0 });
10115
+ if (cond === null) {
10116
+ parser.removeBoundary();
10117
+ return null;
10118
+ }
10119
+ parser.skipVisualSpace();
10120
+ if (!parser.matchBoundary()) {
10121
+ parser.removeBoundary();
10122
+ return null;
10123
+ }
10124
+ return ["When", lhs, cond];
10125
+ }
10061
10126
  function parseSequence(parser, terminator, lhs, prec, sep) {
10062
10127
  if (terminator && terminator.minPrec >= prec) return null;
10063
10128
  const result = lhs ? [lhs] : ["Nothing"];
@@ -10529,6 +10594,15 @@ var ComputeEngine = (() => {
10529
10594
  }
10530
10595
  },
10531
10596
  { name: "LatexTokens", serialize: serializeLatexTokens },
10597
+ // Component-access postfix: expr.member (C3)
10598
+ // The '.' trigger is consumed before the parse function is called.
10599
+ // Precedence 850 > 810 (At/indexing) so .x chains tightly.
10600
+ {
10601
+ kind: "postfix",
10602
+ precedence: 850,
10603
+ latexTrigger: ["."],
10604
+ parse: parseComponentAccess
10605
+ },
10532
10606
  {
10533
10607
  name: "At",
10534
10608
  kind: "postfix",
@@ -10549,6 +10623,29 @@ var ComputeEngine = (() => {
10549
10623
  latexTrigger: ["\\left", "\\lbrack"],
10550
10624
  parse: parseAt("\\right", "\\rbrack")
10551
10625
  },
10626
+ // When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
10627
+ {
10628
+ name: "When",
10629
+ kind: "postfix",
10630
+ precedence: 800,
10631
+ latexTrigger: ["\\left", "\\{"],
10632
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
10633
+ serialize: (serializer, expr2) => {
10634
+ const e = operand(expr2, 1);
10635
+ const cond = operand(expr2, 2);
10636
+ if (!e || !cond) return "";
10637
+ const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
10638
+ const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
10639
+ return `${serializer.serialize(e)}${inner}`;
10640
+ }
10641
+ },
10642
+ // When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
10643
+ {
10644
+ kind: "postfix",
10645
+ precedence: 800,
10646
+ latexTrigger: ["\\{"],
10647
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
10648
+ },
10552
10649
  {
10553
10650
  kind: "postfix",
10554
10651
  latexTrigger: ["_"],
@@ -10631,6 +10728,29 @@ var ComputeEngine = (() => {
10631
10728
  return "";
10632
10729
  }
10633
10730
  },
10731
+ // Additional triggers for Range: `...`, `\ldots`, and `\dots` are
10732
+ // equivalent to `..` when used as infix operators (e.g. `[1...9]`).
10733
+ // No `name` field here — names must be unique per the dictionary rules;
10734
+ // the first Range entry owns the name. When there is no LHS the symbol
10735
+ // entries near the top of the file still fire (ContinuationPlaceholder).
10736
+ {
10737
+ latexTrigger: [".", ".", "."],
10738
+ kind: "infix",
10739
+ precedence: 800,
10740
+ parse: parseRange
10741
+ },
10742
+ {
10743
+ latexTrigger: ["\\ldots"],
10744
+ kind: "infix",
10745
+ precedence: 800,
10746
+ parse: parseRange
10747
+ },
10748
+ {
10749
+ latexTrigger: ["\\dots"],
10750
+ kind: "infix",
10751
+ precedence: 800,
10752
+ parse: parseRange
10753
+ },
10634
10754
  {
10635
10755
  latexTrigger: [";"],
10636
10756
  kind: "infix",
@@ -10815,13 +10935,24 @@ var ComputeEngine = (() => {
10815
10935
  const args = operands(expr2);
10816
10936
  if (!args || args.length < 2) return "";
10817
10937
  const body = args[0];
10818
- const indexing = args[1];
10819
- if (operator(indexing) === "Element") {
10820
- const index = operand(indexing, 1);
10821
- const range2 = operand(indexing, 2);
10822
- if (operator(range2) === "Range") {
10823
- const lo = operand(range2, 1);
10824
- const hi = operand(range2, 2);
10938
+ const elements = args.slice(1);
10939
+ const allElements = elements.every((e) => operator(e) === "Element");
10940
+ if (!allElements) {
10941
+ return joinLatex([
10942
+ "\\operatorname{Loop}(",
10943
+ serializer.serialize(body),
10944
+ ", ",
10945
+ serializer.serialize(elements[0]),
10946
+ ")"
10947
+ ]);
10948
+ }
10949
+ if (elements.length === 1) {
10950
+ const elem = elements[0];
10951
+ const index = operand(elem, 1);
10952
+ const coll = operand(elem, 2);
10953
+ if (operator(coll) === "Range") {
10954
+ const lo = operand(coll, 1);
10955
+ const hi = operand(coll, 2);
10825
10956
  return joinLatex([
10826
10957
  "\\text{for }",
10827
10958
  serializer.serialize(index),
@@ -10833,13 +10964,27 @@ var ComputeEngine = (() => {
10833
10964
  serializer.serialize(body)
10834
10965
  ]);
10835
10966
  }
10967
+ return joinLatex([
10968
+ serializer.serialize(body),
10969
+ " \\operatorname{for} ",
10970
+ serializer.serialize(index),
10971
+ " = ",
10972
+ serializer.serialize(coll)
10973
+ ]);
10836
10974
  }
10975
+ const bindings = elements.map((elem) => {
10976
+ const name = operand(elem, 1);
10977
+ const coll = operand(elem, 2);
10978
+ return joinLatex([
10979
+ serializer.serialize(name),
10980
+ " = ",
10981
+ serializer.serialize(coll)
10982
+ ]);
10983
+ }).join(", ");
10837
10984
  return joinLatex([
10838
- "\\operatorname{Loop}(",
10839
10985
  serializer.serialize(body),
10840
- ", ",
10841
- serializer.serialize(indexing),
10842
- ")"
10986
+ " \\operatorname{for} ",
10987
+ bindings
10843
10988
  ]);
10844
10989
  }
10845
10990
  },
@@ -10872,6 +11017,18 @@ var ComputeEngine = (() => {
10872
11017
  precedence: 245,
10873
11018
  parse: (parser, until) => parseForExpression(parser, until)
10874
11019
  },
11020
+ // \operatorname{for} as postfix infix (list comprehension):
11021
+ // `body \operatorname{for} x = L_1, y = L_2`
11022
+ // Precedence 19 — just below comma (20) so the body is allowed to use
11023
+ // any operator (including comma sequencing) up to the keyword, and the
11024
+ // bindings can be comma-separated below us.
11025
+ {
11026
+ symbolTrigger: "for",
11027
+ kind: "infix",
11028
+ associativity: "none",
11029
+ precedence: 19,
11030
+ parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
11031
+ },
10875
11032
  // \operatorname{break}
10876
11033
  {
10877
11034
  symbolTrigger: "break",
@@ -11076,7 +11233,10 @@ var ComputeEngine = (() => {
11076
11233
  if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
11077
11234
  parser.addBoundary([")"]);
11078
11235
  const expr2 = parser.parseExpression(until);
11079
- if (!parser.matchBoundary()) return null;
11236
+ if (!parser.matchBoundary()) {
11237
+ parser.removeBoundary();
11238
+ return null;
11239
+ }
11080
11240
  if (!parser.match("<}>")) return null;
11081
11241
  return ["Derivative", lhs, expr2];
11082
11242
  }
@@ -11517,7 +11677,12 @@ var ComputeEngine = (() => {
11517
11677
  if (isEmptySequence(body)) return ["List"];
11518
11678
  const h = operator(body);
11519
11679
  if (h === "Range" || h === "Linspace") return body;
11520
- if (h === "Sequence") return ["List", ...operands(body)];
11680
+ if (h === "Sequence") {
11681
+ const elems = operands(body);
11682
+ const inferred = tryInferRangeFromElements(elems, parser);
11683
+ if (inferred) return inferred;
11684
+ return ["List", ...elems];
11685
+ }
11521
11686
  if (h === "Delimiter") {
11522
11687
  const delim = stringValue(operand(body, 2)) ?? "...";
11523
11688
  if (delim === ";" || delim === ".;.") {
@@ -11530,12 +11695,37 @@ var ComputeEngine = (() => {
11530
11695
  }
11531
11696
  if (delim === "," || delim === ".,.") {
11532
11697
  body = operand(body, 1);
11533
- if (operator(body) === "Sequence") return ["List", ...operands(body)];
11698
+ if (operator(body) === "Sequence") {
11699
+ const elems = operands(body);
11700
+ const inferred = tryInferRangeFromElements(elems, parser);
11701
+ if (inferred) return inferred;
11702
+ return ["List", ...elems];
11703
+ }
11534
11704
  return ["List", body ?? "Nothing"];
11535
11705
  }
11536
11706
  }
11537
11707
  return ["List", body];
11538
11708
  }
11709
+ function tryInferRangeFromElements(elems, parser) {
11710
+ if (elems.length < 4) return null;
11711
+ const penultimate = elems[elems.length - 2];
11712
+ if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
11713
+ const samples = elems.slice(0, -2);
11714
+ const endExpr = elems[elems.length - 1];
11715
+ if (samples.length < 2) return null;
11716
+ const sampleNums = samples.map(machineValue);
11717
+ if (sampleNums.some((n) => n === null)) return null;
11718
+ const nums = sampleNums;
11719
+ const step = nums[nums.length - 1] - nums[nums.length - 2];
11720
+ const tol = parser.options.tolerance;
11721
+ if (Math.abs(step) < tol)
11722
+ return parser.error("degenerate-range-step", parser.index);
11723
+ for (let i = 1; i < nums.length; i++) {
11724
+ if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
11725
+ return parser.error("inconsistent-range-samples", parser.index);
11726
+ }
11727
+ return ["Range", nums[0], endExpr, step];
11728
+ }
11539
11729
  function serializeList(serializer, expr2) {
11540
11730
  if (nops(expr2) > 1 && operands(expr2).every((x) => {
11541
11731
  const op = operator(x);
@@ -11787,6 +11977,35 @@ var ComputeEngine = (() => {
11787
11977
  ["Element", index, ["Range", lower, upper]]
11788
11978
  ];
11789
11979
  }
11980
+ function parseForComprehension(parser, lhs, until) {
11981
+ const bindingTerminator = {
11982
+ minPrec: 21,
11983
+ // Above comma (20) and ; (19), so `x = L_1` is captured whole
11984
+ condition: (p) => {
11985
+ if (until?.condition?.(p)) return true;
11986
+ const saved = p.index;
11987
+ p.skipVisualSpace();
11988
+ const isComma = p.peek === ",";
11989
+ p.index = saved;
11990
+ return isComma;
11991
+ }
11992
+ };
11993
+ const elements = [];
11994
+ do {
11995
+ parser.skipVisualSpace();
11996
+ const binding = parser.parseExpression(bindingTerminator);
11997
+ if (binding === null) break;
11998
+ const op = operator(binding);
11999
+ if (op !== "Equal" && op !== "Assign") return null;
12000
+ const name = operand(binding, 1);
12001
+ const list = operand(binding, 2);
12002
+ if (!name || !list) return null;
12003
+ elements.push(["Element", name, list]);
12004
+ parser.skipVisualSpace();
12005
+ } while (parser.match(","));
12006
+ if (elements.length === 0) return null;
12007
+ return ["Loop", lhs, ...elements];
12008
+ }
11790
12009
  function parseWhereExpression(parser, lhs, until) {
11791
12010
  const bindingTerminator = {
11792
12011
  minPrec: 21,
@@ -19558,6 +19777,19 @@ var ComputeEngine = (() => {
19558
19777
  } while (postfix !== null);
19559
19778
  }
19560
19779
  if (result !== null) result = this.parseSupsub(result);
19780
+ if (result !== null) {
19781
+ let postfix = null;
19782
+ let index = this.index;
19783
+ do {
19784
+ postfix = this.parsePostfixOperator(result, until);
19785
+ result = postfix ?? result;
19786
+ if (this.index === index && postfix !== null) {
19787
+ console.assert(this.index !== index, "No token consumed");
19788
+ break;
19789
+ }
19790
+ index = this.index;
19791
+ } while (postfix !== null);
19792
+ }
19561
19793
  if (result === null) {
19562
19794
  result = this.options.parseUnexpectedToken?.(null, this) ?? null;
19563
19795
  if (result === null && this.peek.startsWith("\\")) {
@@ -20066,6 +20298,28 @@ var ComputeEngine = (() => {
20066
20298
  }
20067
20299
 
20068
20300
  // src/compute-engine/latex-syntax/serializer.ts
20301
+ var DOT_NOTATION_MAP = {
20302
+ First: ".x",
20303
+ Second: ".y",
20304
+ Third: ".z",
20305
+ Real: ".\\operatorname{real}",
20306
+ Imaginary: ".\\operatorname{imag}",
20307
+ Length: ".\\operatorname{count}",
20308
+ Sum: ".\\operatorname{total}",
20309
+ Max: ".\\max",
20310
+ Min: ".\\min"
20311
+ };
20312
+ function trySerializeDotNotation(serializer, expr2) {
20313
+ if (!serializer.options.dotNotation) return null;
20314
+ const ops = operands(expr2);
20315
+ if (!ops || ops.length !== 1) return null;
20316
+ const head = operator(expr2);
20317
+ if (!head) return null;
20318
+ const suffix = DOT_NOTATION_MAP[head];
20319
+ if (suffix === void 0) return null;
20320
+ const lhs = serializer.wrap(ops[0], 810);
20321
+ return `${lhs}${suffix}`;
20322
+ }
20069
20323
  var ACCENT_MODIFIERS = {
20070
20324
  deg: (s) => `${s}\\degree`,
20071
20325
  prime: (s) => `${s}^{\\prime}`,
@@ -20109,6 +20363,7 @@ var ComputeEngine = (() => {
20109
20363
  constructor(dictionary, options) {
20110
20364
  this.dictionary = dictionary;
20111
20365
  this.options = {
20366
+ dotNotation: false,
20112
20367
  dmsFormat: false,
20113
20368
  angleNormalization: "none",
20114
20369
  ...options
@@ -20207,6 +20462,8 @@ var ComputeEngine = (() => {
20207
20462
  return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
20208
20463
  }
20209
20464
  serializeFunction(expr2, def) {
20465
+ const dotResult = trySerializeDotNotation(this, expr2);
20466
+ if (dotResult !== null) return dotResult;
20210
20467
  if (def?.serialize) return def.serialize(this, expr2);
20211
20468
  const h = operator(expr2);
20212
20469
  return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
@@ -20449,6 +20706,8 @@ var ComputeEngine = (() => {
20449
20706
  preserveLatex: opts.preserveLatex ?? false,
20450
20707
  quantifierScope: opts.quantifierScope ?? "tight",
20451
20708
  timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
20709
+ // Standalone mode has no engine; use the same default as ComputeEngine
20710
+ tolerance: 1e-7,
20452
20711
  // Callbacks -- standalone mode has no engine, so these are stubs
20453
20712
  getSymbolType: (_id) => BoxedType.unknown,
20454
20713
  hasSubscriptEvaluate: (_id) => false,
@@ -20481,6 +20740,7 @@ var ComputeEngine = (() => {
20481
20740
  invisiblePlus: "",
20482
20741
  multiply: "\\times",
20483
20742
  missingSymbol: "\\blacksquare",
20743
+ dotNotation: false,
20484
20744
  dmsFormat: false,
20485
20745
  angleNormalization: "none",
20486
20746
  // Style callbacks -- use same defaults as the engine
@@ -27451,7 +27711,11 @@ ${lines.join("\n")}`;
27451
27711
  //
27452
27712
  Range: {
27453
27713
  complexity: 8200,
27454
- signature: "(number, number?, step: number?) -> indexed_collection<integer>",
27714
+ signature: "(number, number?, step: number?) -> indexed_collection<number>",
27715
+ type: (ops) => {
27716
+ const allInt = ops.every((op) => op.isInteger);
27717
+ return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
27718
+ },
27455
27719
  canonical: (ops, { engine: ce }) => {
27456
27720
  if (ops.length === 0) return null;
27457
27721
  if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
@@ -27475,19 +27739,26 @@ ${lines.join("\n")}`;
27475
27739
  const [lower, upper, step] = range(expr2);
27476
27740
  if (step === 0) return 0;
27477
27741
  if (!isFinite(lower) || !isFinite(upper)) return Infinity;
27478
- return 1 + Math.max(0, Math.floor((upper - lower) / step));
27742
+ return Math.max(0, Math.floor((upper - lower) / step) + 1);
27479
27743
  },
27480
27744
  contains: (expr2, target) => {
27481
- if (!target.type.matches("integer")) return false;
27482
27745
  const t = target.re;
27746
+ if (!isFinite(t)) return false;
27483
27747
  const [lower, upper, step] = range(expr2);
27484
27748
  if (step === 0) return false;
27485
- if (step > 0) return t >= lower && t <= upper;
27486
- return t <= lower && t >= upper;
27749
+ if (step > 0) {
27750
+ if (t < lower || t > upper) return false;
27751
+ } else {
27752
+ if (t > lower || t < upper) return false;
27753
+ }
27754
+ const k = (t - lower) / step;
27755
+ const tol = expr2.engine.tolerance;
27756
+ const kRounded = Math.round(k);
27757
+ return kRounded >= 0 && Math.abs(k - kRounded) < tol;
27487
27758
  },
27488
27759
  iterator: (expr2) => {
27489
27760
  const [lower, upper, step] = range(expr2);
27490
- const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
27761
+ const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
27491
27762
  let index = 1;
27492
27763
  return {
27493
27764
  next: () => {
@@ -27505,7 +27776,9 @@ ${lines.join("\n")}`;
27505
27776
  at: (expr2, index) => {
27506
27777
  if (typeof index !== "number") return void 0;
27507
27778
  const [lower, upper, step] = range(expr2);
27508
- if (index < 1 || index > 1 + (upper - lower) / step) return void 0;
27779
+ if (step === 0) return void 0;
27780
+ const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
27781
+ if (index < 1 || index > maxCount) return void 0;
27509
27782
  return expr2.engine.number(lower + step * (index - 1));
27510
27783
  },
27511
27784
  indexWhere: void 0,
@@ -27530,7 +27803,13 @@ ${lines.join("\n")}`;
27530
27803
  if (step > 0) return lower <= upper ? "positive" : "negative";
27531
27804
  return lower >= upper ? "positive" : "negative";
27532
27805
  },
27533
- elttype: (_expr) => "finite_integer"
27806
+ elttype: (expr2) => {
27807
+ if (!isFunction2(expr2)) return "finite_integer";
27808
+ for (let i = 1; i <= expr2.nops; i++) {
27809
+ if (!expr2[`op${i}`].isInteger) return "finite_real";
27810
+ }
27811
+ return "finite_integer";
27812
+ }
27534
27813
  }
27535
27814
  },
27536
27815
  Interval: {
@@ -28128,15 +28407,45 @@ ${lines.join("\n")}`;
28128
28407
  },
28129
28408
  First: {
28130
28409
  complexity: 8200,
28131
- signature: "(collection) -> any",
28410
+ signature: "(any) -> any",
28132
28411
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28133
- evaluate: ([xs], { engine: ce }) => xs.at(1) ?? ce.Nothing
28412
+ evaluate: ([xs], { engine: ce }) => {
28413
+ if (!xs.isCollection)
28414
+ return ce.error([
28415
+ "incompatible-type",
28416
+ `'collection'`,
28417
+ xs.type.toString()
28418
+ ]);
28419
+ return xs.at(1) ?? ce.Nothing;
28420
+ }
28134
28421
  },
28135
28422
  Second: {
28136
28423
  complexity: 8200,
28137
- signature: "(collection) -> any",
28424
+ signature: "(any) -> any",
28425
+ type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28426
+ evaluate: ([xs], { engine: ce }) => {
28427
+ if (!xs.isCollection)
28428
+ return ce.error([
28429
+ "incompatible-type",
28430
+ `'collection'`,
28431
+ xs.type.toString()
28432
+ ]);
28433
+ return xs.at(2) ?? ce.Nothing;
28434
+ }
28435
+ },
28436
+ Third: {
28437
+ complexity: 8200,
28438
+ signature: "(any) -> any",
28138
28439
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28139
- evaluate: ([xs], { engine: ce }) => xs.at(2) ?? ce.Nothing
28440
+ evaluate: ([xs], { engine: ce }) => {
28441
+ if (!xs.isCollection)
28442
+ return ce.error([
28443
+ "incompatible-type",
28444
+ `'collection'`,
28445
+ xs.type.toString()
28446
+ ]);
28447
+ return xs.at(3) ?? ce.Nothing;
28448
+ }
28140
28449
  },
28141
28450
  Last: {
28142
28451
  complexity: 8200,
@@ -29115,17 +29424,14 @@ ${lines.join("\n")}`;
29115
29424
  if (!isFunction2(expr2)) return [1, 0, 0];
29116
29425
  if (expr2.nops === 0) return [1, 0, 0];
29117
29426
  let op1 = expr2.op1.re;
29118
- if (!isFinite(op1)) op1 = 1;
29119
- else op1 = Math.round(op1);
29427
+ if (!isFinite(op1) && !op1) op1 = 1;
29120
29428
  if (expr2.nops === 1) return [1, op1, 1];
29121
29429
  let op2 = expr2.op2.re;
29122
29430
  if (!isFinite(op2) && !op2) op2 = 1;
29123
- else if (isFinite(op2)) op2 = Math.round(op2);
29124
- if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
29431
+ if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
29125
29432
  let op3 = expr2.op3.re;
29126
- if (!isFinite(op3)) op3 = 1;
29127
- else op3 = Math.abs(Math.round(op3));
29128
- return [op1, op2, op1 < op2 ? op3 : -op3];
29433
+ if (!isFinite(op3) && !op3) op3 = 1;
29434
+ return [op1, op2, op3];
29129
29435
  }
29130
29436
  function rangeLast(r) {
29131
29437
  const [lower, upper, step] = r;
@@ -42855,12 +43161,42 @@ ${e.message}
42855
43161
  }
42856
43162
  },
42857
43163
  Loop: {
42858
- description: "Evaluate a body expression over elements of a collection.",
43164
+ description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
43165
+ lazy: true,
43166
+ signature: "(body:expression, iterators:expression*) -> any",
43167
+ type: ([body]) => {
43168
+ if (!body) return "nothing";
43169
+ return parseType(`indexed_collection<${String(body.type)}>`);
43170
+ },
43171
+ canonical: canonicalLoop,
43172
+ evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
43173
+ evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
43174
+ },
43175
+ When: {
43176
+ description: "Conditional value: returns expr when cond holds, undefined otherwise.",
42859
43177
  lazy: true,
42860
- signature: "(body:expression, collection:expression) -> any",
42861
- type: ([body]) => body.type,
42862
- evaluate: ([body, collection], { engine: ce }) => run(runLoop(body, collection, ce), ce._timeRemaining),
42863
- evaluateAsync: async ([body, collection], { engine: ce, signal }) => runAsync(runLoop(body, collection, ce), ce._timeRemaining, signal)
43178
+ signature: "(expression, boolean) -> any",
43179
+ type: ([expr2]) => expr2.type,
43180
+ canonical: (args, { engine: ce }) => {
43181
+ if (args.length !== 2) return null;
43182
+ const [expr2, cond] = args;
43183
+ if (isFunction2(expr2, "When")) {
43184
+ const inner = expr2.op1.canonical;
43185
+ const innerCond = expr2.op2.canonical;
43186
+ return ce._fn("When", [
43187
+ inner,
43188
+ ce._fn("And", [innerCond, cond.canonical])
43189
+ ]);
43190
+ }
43191
+ return ce._fn("When", [expr2.canonical, cond.canonical]);
43192
+ },
43193
+ evaluate: ([expr2, cond], { engine: ce }) => {
43194
+ const c = cond.evaluate();
43195
+ const cs = sym(c);
43196
+ if (cs === "True") return expr2.evaluate();
43197
+ if (cs === "False") return ce.symbol("Undefined");
43198
+ return ce._fn("When", [expr2, c]);
43199
+ }
42864
43200
  },
42865
43201
  Which: {
42866
43202
  description: "Return the value for the first condition that is true.",
@@ -42920,9 +43256,141 @@ ${e.message}
42920
43256
  );
42921
43257
  return result;
42922
43258
  }
42923
- function* runLoop(body, collection, ce) {
43259
+ function canonicalLoop(ops, options) {
43260
+ const { engine: ce, scope } = options;
43261
+ if (ops.length === 0) return null;
43262
+ if (ops.length === 1) {
43263
+ return ce._fn("Loop", [ops[0].canonical]);
43264
+ }
43265
+ const body = ops[0];
43266
+ const iterators = ops.slice(1);
43267
+ const allElement = iterators.every((it) => it.operator === "Element");
43268
+ if (!allElement) {
43269
+ return ce._fn(
43270
+ "Loop",
43271
+ ops.map((op) => op.canonical)
43272
+ );
43273
+ }
43274
+ const loopScope = scope ?? {
43275
+ parent: ce.context.lexicalScope,
43276
+ bindings: /* @__PURE__ */ new Map()
43277
+ };
43278
+ loopScope.noAutoDeclare = true;
43279
+ ce.pushScope(loopScope);
43280
+ let canonicalIterators;
43281
+ let canonicalBody;
43282
+ try {
43283
+ canonicalIterators = iterators.map((it) => {
43284
+ if (!isFunction2(it, "Element")) {
43285
+ return ce._fn("Element", [
43286
+ ce.error("missing").canonical,
43287
+ ce.error("missing").canonical
43288
+ ]);
43289
+ }
43290
+ const indexExpr = it.ops[0];
43291
+ const collExpr = it.ops[1];
43292
+ if (!indexExpr || !collExpr) {
43293
+ return ce._fn("Element", [
43294
+ (indexExpr ?? ce.error("missing")).canonical,
43295
+ (collExpr ?? ce.error("missing")).canonical
43296
+ ]);
43297
+ }
43298
+ if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
43299
+ if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
43300
+ ce.declare(indexExpr.symbol, "unknown");
43301
+ }
43302
+ return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
43303
+ });
43304
+ canonicalBody = body.canonical;
43305
+ } finally {
43306
+ ce.popScope();
43307
+ loopScope.noAutoDeclare = false;
43308
+ }
43309
+ return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
43310
+ scope: loopScope
43311
+ });
43312
+ }
43313
+ function* runLoop(body, elements, ce) {
42924
43314
  body ??= ce.Nothing;
42925
43315
  if (sym(body) === "Nothing") return body;
43316
+ if (elements.length === 0) {
43317
+ const result = body.evaluate();
43318
+ yield result;
43319
+ return result;
43320
+ }
43321
+ if (elements.length === 1 && elements[0].operator !== "Element") {
43322
+ return yield* runLoopLegacy(body, elements[0], ce);
43323
+ }
43324
+ const results = [];
43325
+ const state = { stopped: false, broke: false, count: 0 };
43326
+ const freshScope = {
43327
+ parent: ce.context.lexicalScope,
43328
+ bindings: /* @__PURE__ */ new Map()
43329
+ };
43330
+ ce._pushEvalContext(freshScope);
43331
+ try {
43332
+ for (const elem of elements) {
43333
+ if (!isFunction2(elem, "Element")) continue;
43334
+ const idx = elem.ops[0];
43335
+ if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
43336
+ if (!freshScope.bindings.has(idx.symbol))
43337
+ ce.declare(idx.symbol, "unknown");
43338
+ }
43339
+ }
43340
+ yield* runLoopNested(body, elements, 0, ce, results, state);
43341
+ } finally {
43342
+ ce._popEvalContext();
43343
+ }
43344
+ if (state.stopped && state.value !== void 0) {
43345
+ if (!state.broke) return state.value;
43346
+ return state.value;
43347
+ }
43348
+ return ce.function("List", results);
43349
+ }
43350
+ function* runLoopNested(body, elements, index, ce, results, state) {
43351
+ if (state.stopped) return;
43352
+ if (index === elements.length) {
43353
+ const result = body.evaluate();
43354
+ state.count += 1;
43355
+ if (state.count > ce.iterationLimit)
43356
+ throw new CancellationError({ cause: "iteration-limit-exceeded" });
43357
+ if (isFunction2(result, "Break")) {
43358
+ state.stopped = true;
43359
+ state.broke = true;
43360
+ state.value = result.op1;
43361
+ return;
43362
+ }
43363
+ if (result.operator === "Return") {
43364
+ state.stopped = true;
43365
+ state.value = result;
43366
+ return;
43367
+ }
43368
+ results.push(result);
43369
+ yield result;
43370
+ return;
43371
+ }
43372
+ const elem = elements[index];
43373
+ if (!isFunction2(elem, "Element")) {
43374
+ return;
43375
+ }
43376
+ const indexExpr = elem.ops[0];
43377
+ const collExpr = elem.ops[1];
43378
+ if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
43379
+ return;
43380
+ }
43381
+ const name = indexExpr.symbol;
43382
+ const collection = collExpr.evaluate();
43383
+ if (!collection?.isCollection) {
43384
+ return;
43385
+ }
43386
+ const skipAssign = name === "Nothing";
43387
+ for (const value of collection.each()) {
43388
+ if (!skipAssign) ce.assign(name, value);
43389
+ yield* runLoopNested(body, elements, index + 1, ce, results, state);
43390
+ if (state.stopped) return;
43391
+ }
43392
+ }
43393
+ function* runLoopLegacy(body, collection, ce) {
42926
43394
  if (collection?.isCollection) {
42927
43395
  let result = void 0;
42928
43396
  const fn = applicable(body);
@@ -55005,6 +55473,23 @@ Error in definition of "${name}"`,
55005
55473
  };
55006
55474
  return compilePair(0);
55007
55475
  }
55476
+ if (h === "When") {
55477
+ if (args.length !== 2)
55478
+ throw new Error("When: expected exactly 2 arguments (expr, cond)");
55479
+ const fn2 = target.functions?.(h);
55480
+ if (fn2) {
55481
+ if (typeof fn2 === "function") {
55482
+ return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
55483
+ }
55484
+ return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
55485
+ }
55486
+ if (isSymbol2(args[1], "True"))
55487
+ return `(${_BaseCompiler.compile(args[0], target)})`;
55488
+ if (isSymbol2(args[1], "False")) return "NaN";
55489
+ const val = _BaseCompiler.compile(args[0], target);
55490
+ const cond = _BaseCompiler.compile(args[1], target);
55491
+ return `((${cond}) ? (${val}) : NaN)`;
55492
+ }
55008
55493
  if (h === "Block") {
55009
55494
  return _BaseCompiler.compileBlock(args, target);
55010
55495
  }
@@ -55079,17 +55564,91 @@ Error in definition of "${name}"`,
55079
55564
  )}${target.ws("\n")}})()`;
55080
55565
  }
55081
55566
  /**
55082
- * Compile a Loop expression with Element(index, Range(lo, hi)) indexing.
55083
- * Generates: (() => { for (let i = lo; i <= hi; i++) { body } })()
55567
+ * Compile a Loop expression.
55568
+ *
55569
+ * Two forms are supported:
55570
+ *
55571
+ * 1. **Imperative / single-Element form** (existing behaviour):
55572
+ * `Loop(body, Element(i, Range(lo, hi)))`
55573
+ * Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
55574
+ * in an IIFE. The loop counter is always a plain number. For targets
55575
+ * that wrap numeric values (e.g. interval-js uses `_IA.point()`),
55576
+ * references to the loop index inside the body are re-wrapped via
55577
+ * `target.number`. `break` / `continue` / `return` are preserved.
55578
+ *
55579
+ * 2. **Comprehension / variadic-Element form** (new):
55580
+ * `Loop(body, Element(x, coll1), Element(y, coll2), …)`
55581
+ * When two or more `Element` clauses are present — or when the single
55582
+ * Element's collection is not a `Range` — the loop is compiled as a
55583
+ * comprehension that collects results into an array. Each clause
55584
+ * produces a `for (const name of collection)` loop, nested
55585
+ * outermost-to-innermost, and the innermost body pushes into `result`.
55586
+ *
55587
+ * Example output (JS):
55588
+ * ```js
55589
+ * (() => { const result = [];
55590
+ * for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
55591
+ * return result; })()
55592
+ * ```
55084
55593
  *
55085
- * The loop counter is always a raw number. For targets that wrap numeric
55086
- * values (e.g. interval-js wraps with `_IA.point()`), references to the
55087
- * loop index inside the body are wrapped via `target.number`.
55594
+ * GLSL: multi-Element comprehension is not trivially representable in
55595
+ * GLSL (no dynamic arrays, no push). A compile-time error is thrown.
55596
+ * TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
55597
+ * array or by unrolling when bounds are known at compile time.
55088
55598
  */
55089
55599
  static compileForLoop(args, target) {
55090
55600
  if (!args[0]) throw new Error("Loop: no body");
55091
55601
  if (!args[1]) throw new Error("Loop: no indexing set");
55092
- const indexing = args[1];
55602
+ const body = args[0];
55603
+ const elements = args.slice(1);
55604
+ const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
55605
+ if (useComprehension) {
55606
+ const lang = target.language ?? "";
55607
+ if (lang === "glsl" || lang === "wgsl") {
55608
+ throw new Error(
55609
+ `${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
55610
+ );
55611
+ }
55612
+ const narrowedElements = [];
55613
+ for (let i = 0; i < elements.length; i++) {
55614
+ const elem = elements[i];
55615
+ if (!isFunction2(elem, "Element"))
55616
+ throw new Error(
55617
+ `Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
55618
+ );
55619
+ if (!isSymbol2(elem.ops[0]))
55620
+ throw new Error(
55621
+ `Loop: Element index (argument ${i + 1}) must be a symbol`
55622
+ );
55623
+ narrowedElements.push(elem);
55624
+ }
55625
+ const loopVarSet = new Set(
55626
+ narrowedElements.map(
55627
+ (e) => e.ops[0].symbol
55628
+ )
55629
+ );
55630
+ const needsWrap2 = target.number(0) !== "0";
55631
+ const bodyTarget2 = needsWrap2 ? {
55632
+ ...target,
55633
+ var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
55634
+ } : target;
55635
+ const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
55636
+ let inner = `result.push(${bodyCode});`;
55637
+ for (let i = narrowedElements.length - 1; i >= 0; i--) {
55638
+ const elem = narrowedElements[i];
55639
+ const name = elem.ops[0].symbol;
55640
+ const collExpr = elem.ops[1];
55641
+ let collection;
55642
+ if (isFunction2(collExpr, "Range")) {
55643
+ collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
55644
+ } else {
55645
+ collection = _BaseCompiler.compile(collExpr, bodyTarget2);
55646
+ }
55647
+ inner = `for (const ${name} of ${collection}) { ${inner} }`;
55648
+ }
55649
+ return `(() => { const result = []; ${inner} return result; })()`;
55650
+ }
55651
+ const indexing = elements[0];
55093
55652
  if (!isFunction2(indexing, "Element"))
55094
55653
  throw new Error("Loop: expected Element(index, Range(lo, hi))");
55095
55654
  const indexExpr = indexing.ops[0];
@@ -55107,13 +55666,72 @@ Error in definition of "${name}"`,
55107
55666
  ...target,
55108
55667
  var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
55109
55668
  };
55110
- const bodyStmts = _BaseCompiler.compileLoopBody(args[0], bodyTarget);
55669
+ const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
55111
55670
  return `(() => {${target.ws(
55112
55671
  "\n"
55113
55672
  )}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
55114
55673
  "\n"
55115
55674
  )}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
55116
55675
  }
55676
+ /**
55677
+ * Returns `true` when the given collection expression is a `Range` whose
55678
+ * runtime semantics match the legacy imperative for-loop shape
55679
+ * `for (let i = lo; i <= hi; i++)`.
55680
+ *
55681
+ * Concretely: integer-ascending bounds and step omitted-or-1. When bounds
55682
+ * are not statically numeric we accept the Range (the historical
55683
+ * behaviour) — runtime mismatch in the descending-unknown-bounds case is
55684
+ * left as a known limitation; callers can force the iterable path by
55685
+ * supplying an explicit step.
55686
+ */
55687
+ static isLegacyCompatibleRange(coll) {
55688
+ if (!isFunction2(coll, "Range")) return false;
55689
+ if (coll.ops.length >= 3) {
55690
+ const stepExpr = coll.ops[2];
55691
+ if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
55692
+ }
55693
+ const lo = coll.ops[0];
55694
+ const hi = coll.ops[1];
55695
+ if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
55696
+ if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
55697
+ if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
55698
+ return true;
55699
+ }
55700
+ /**
55701
+ * Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
55702
+ * iterable expression. Mirrors the runtime semantics in
55703
+ * `library/collections.ts` Range:
55704
+ * count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
55705
+ * element = lo + step * k (0-indexed)
55706
+ * Default step is 1 when omitted. Bounds and step may be fractional.
55707
+ *
55708
+ * Only used from the comprehension path in `compileForLoop`.
55709
+ * Caller must have already verified `isFunction(rangeExpr, 'Range')`.
55710
+ */
55711
+ static compileRangeIterable(rangeExpr, target) {
55712
+ const loExpr = rangeExpr.ops[0];
55713
+ const hiExpr = rangeExpr.ops[1];
55714
+ const stepExpr = rangeExpr.ops[2];
55715
+ if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
55716
+ const lo2 = loExpr.re;
55717
+ const hi2 = hiExpr.re;
55718
+ const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
55719
+ if (step2 === 0) return "[]";
55720
+ const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
55721
+ if (step2 === 1) {
55722
+ if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
55723
+ return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
55724
+ }
55725
+ return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
55726
+ }
55727
+ const lo = _BaseCompiler.compile(loExpr, target);
55728
+ const hi = _BaseCompiler.compile(hiExpr, target);
55729
+ if (stepExpr === void 0) {
55730
+ 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})`;
55731
+ }
55732
+ const step = _BaseCompiler.compile(stepExpr, target);
55733
+ 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})`;
55734
+ }
55117
55735
  /**
55118
55736
  * Compile a loop body expression as statements (not wrapped in IIFE).
55119
55737
  * Handles Break, Continue, Return as statements, and If as if-else when
@@ -69184,6 +69802,15 @@ ${code}`;
69184
69802
  lookupDefinition(id) {
69185
69803
  return lookupDefinition(this, id);
69186
69804
  }
69805
+ operatorInfo(head) {
69806
+ const def = this.lookupDefinition(head);
69807
+ if (!def || !isOperatorDef(def)) return void 0;
69808
+ const op = def.operator;
69809
+ return {
69810
+ kind: op.evaluate || op.collection ? "function" : "opaque",
69811
+ signature: op.signature
69812
+ };
69813
+ }
69187
69814
  /**
69188
69815
  * Associate a new definition to a symbol in the current context.
69189
69816
  *
@@ -69471,6 +70098,7 @@ ${code}`;
69471
70098
  const def = this.lookupDefinition(id);
69472
70099
  return !!(isValueDef(def) && def.value.subscriptEvaluate);
69473
70100
  },
70101
+ tolerance: this.tolerance,
69474
70102
  ...this._latexOptions,
69475
70103
  ...parseOpts
69476
70104
  });
@@ -69635,14 +70263,14 @@ ${code}`;
69635
70263
  _setDefaultEngineFactory(() => new ComputeEngine());
69636
70264
 
69637
70265
  // src/compute-engine.ts
69638
- var version = "0.56.0";
70266
+ var version = "0.57.0";
69639
70267
  ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
69640
70268
  _setDefaultEngineFactory(
69641
70269
  () => new ComputeEngine({ latexSyntax: new LatexSyntax() })
69642
70270
  );
69643
70271
  globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
69644
70272
  ComputeEngine: ComputeEngine.prototype.constructor,
69645
- version: "0.56.0"
70273
+ version: "0.57.0"
69646
70274
  };
69647
70275
  return __toCommonJS(compute_engine_exports);
69648
70276
  })();