@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
 
3
3
  // node_modules/complex-esm/dist/src/complex.js
4
4
  var cosh = Math.cosh || function(x) {
@@ -7838,8 +7838,15 @@ var _BoxedExpression = class __BoxedExpression {
7838
7838
  *
7839
7839
  * Numeric values are rounded to `ce.precision` significant digits
7840
7840
  * (via `fractionalDigits: 'auto'`).
7841
+ *
7842
+ * If `options.verbatim` is `true` and `verbatimLatex` is set on this
7843
+ * expression (i.e. it was parsed with `preserveLatex: true`), return
7844
+ * the verbatim source instead of re-serializing. Falls through to
7845
+ * re-serialization if no verbatim is available.
7841
7846
  */
7842
7847
  toLatex(options) {
7848
+ if (options?.verbatim === true && this.verbatimLatex !== void 0)
7849
+ return this.verbatimLatex;
7843
7850
  if (this.isLazyCollection) {
7844
7851
  const materialized = this.evaluate({
7845
7852
  materialization: options?.materialization ?? true
@@ -9982,6 +9989,64 @@ function parseQuantifier(kind) {
9982
9989
  }
9983
9990
 
9984
9991
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
9992
+ var COMPONENT_ACCESS_HEADS = {
9993
+ x: "First",
9994
+ y: "Second",
9995
+ z: "Third",
9996
+ real: "Real",
9997
+ re: "Real",
9998
+ imag: "Imaginary",
9999
+ im: "Imaginary",
10000
+ count: "Length",
10001
+ total: "Sum",
10002
+ max: "Max",
10003
+ min: "Min"
10004
+ };
10005
+ function memberHead(name) {
10006
+ return COMPONENT_ACCESS_HEADS[name] ?? null;
10007
+ }
10008
+ function parseComponentAccess(parser, lhs) {
10009
+ parser.skipVisualSpace();
10010
+ if (parser.match("\\operatorname")) {
10011
+ const name = parser.parseStringGroup();
10012
+ if (name === null) return null;
10013
+ const head = memberHead(name.trim());
10014
+ if (head === null) return null;
10015
+ return [head, lhs];
10016
+ }
10017
+ const tok = parser.peek;
10018
+ if (typeof tok === "string" && tok.startsWith("\\")) {
10019
+ const bare = tok.slice(1);
10020
+ const head = memberHead(bare);
10021
+ if (head !== null) {
10022
+ parser.nextToken();
10023
+ return [head, lhs];
10024
+ }
10025
+ return null;
10026
+ }
10027
+ if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
10028
+ const head = memberHead(tok);
10029
+ if (head === null) return null;
10030
+ parser.nextToken();
10031
+ return [head, lhs];
10032
+ }
10033
+ return null;
10034
+ }
10035
+ function parseWhenRestriction(parser, lhs, close) {
10036
+ parser.addBoundary(close);
10037
+ parser.skipVisualSpace();
10038
+ const cond = parser.parseExpression({ minPrec: 0 });
10039
+ if (cond === null) {
10040
+ parser.removeBoundary();
10041
+ return null;
10042
+ }
10043
+ parser.skipVisualSpace();
10044
+ if (!parser.matchBoundary()) {
10045
+ parser.removeBoundary();
10046
+ return null;
10047
+ }
10048
+ return ["When", lhs, cond];
10049
+ }
9985
10050
  function parseSequence(parser, terminator, lhs, prec, sep) {
9986
10051
  if (terminator && terminator.minPrec >= prec) return null;
9987
10052
  const result = lhs ? [lhs] : ["Nothing"];
@@ -10453,6 +10518,15 @@ var DEFINITIONS_CORE = [
10453
10518
  }
10454
10519
  },
10455
10520
  { name: "LatexTokens", serialize: serializeLatexTokens },
10521
+ // Component-access postfix: expr.member (C3)
10522
+ // The '.' trigger is consumed before the parse function is called.
10523
+ // Precedence 850 > 810 (At/indexing) so .x chains tightly.
10524
+ {
10525
+ kind: "postfix",
10526
+ precedence: 850,
10527
+ latexTrigger: ["."],
10528
+ parse: parseComponentAccess
10529
+ },
10456
10530
  {
10457
10531
  name: "At",
10458
10532
  kind: "postfix",
@@ -10473,6 +10547,29 @@ var DEFINITIONS_CORE = [
10473
10547
  latexTrigger: ["\\left", "\\lbrack"],
10474
10548
  parse: parseAt("\\right", "\\rbrack")
10475
10549
  },
10550
+ // When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
10551
+ {
10552
+ name: "When",
10553
+ kind: "postfix",
10554
+ precedence: 800,
10555
+ latexTrigger: ["\\left", "\\{"],
10556
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
10557
+ serialize: (serializer, expr2) => {
10558
+ const e = operand(expr2, 1);
10559
+ const cond = operand(expr2, 2);
10560
+ if (!e || !cond) return "";
10561
+ const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
10562
+ const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
10563
+ return `${serializer.serialize(e)}${inner}`;
10564
+ }
10565
+ },
10566
+ // When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
10567
+ {
10568
+ kind: "postfix",
10569
+ precedence: 800,
10570
+ latexTrigger: ["\\{"],
10571
+ parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
10572
+ },
10476
10573
  {
10477
10574
  kind: "postfix",
10478
10575
  latexTrigger: ["_"],
@@ -10555,6 +10652,29 @@ var DEFINITIONS_CORE = [
10555
10652
  return "";
10556
10653
  }
10557
10654
  },
10655
+ // Additional triggers for Range: `...`, `\ldots`, and `\dots` are
10656
+ // equivalent to `..` when used as infix operators (e.g. `[1...9]`).
10657
+ // No `name` field here — names must be unique per the dictionary rules;
10658
+ // the first Range entry owns the name. When there is no LHS the symbol
10659
+ // entries near the top of the file still fire (ContinuationPlaceholder).
10660
+ {
10661
+ latexTrigger: [".", ".", "."],
10662
+ kind: "infix",
10663
+ precedence: 800,
10664
+ parse: parseRange
10665
+ },
10666
+ {
10667
+ latexTrigger: ["\\ldots"],
10668
+ kind: "infix",
10669
+ precedence: 800,
10670
+ parse: parseRange
10671
+ },
10672
+ {
10673
+ latexTrigger: ["\\dots"],
10674
+ kind: "infix",
10675
+ precedence: 800,
10676
+ parse: parseRange
10677
+ },
10558
10678
  {
10559
10679
  latexTrigger: [";"],
10560
10680
  kind: "infix",
@@ -10739,13 +10859,24 @@ var DEFINITIONS_CORE = [
10739
10859
  const args = operands(expr2);
10740
10860
  if (!args || args.length < 2) return "";
10741
10861
  const body = args[0];
10742
- const indexing = args[1];
10743
- if (operator(indexing) === "Element") {
10744
- const index = operand(indexing, 1);
10745
- const range2 = operand(indexing, 2);
10746
- if (operator(range2) === "Range") {
10747
- const lo = operand(range2, 1);
10748
- const hi = operand(range2, 2);
10862
+ const elements = args.slice(1);
10863
+ const allElements = elements.every((e) => operator(e) === "Element");
10864
+ if (!allElements) {
10865
+ return joinLatex([
10866
+ "\\operatorname{Loop}(",
10867
+ serializer.serialize(body),
10868
+ ", ",
10869
+ serializer.serialize(elements[0]),
10870
+ ")"
10871
+ ]);
10872
+ }
10873
+ if (elements.length === 1) {
10874
+ const elem = elements[0];
10875
+ const index = operand(elem, 1);
10876
+ const coll = operand(elem, 2);
10877
+ if (operator(coll) === "Range") {
10878
+ const lo = operand(coll, 1);
10879
+ const hi = operand(coll, 2);
10749
10880
  return joinLatex([
10750
10881
  "\\text{for }",
10751
10882
  serializer.serialize(index),
@@ -10757,13 +10888,27 @@ var DEFINITIONS_CORE = [
10757
10888
  serializer.serialize(body)
10758
10889
  ]);
10759
10890
  }
10891
+ return joinLatex([
10892
+ serializer.serialize(body),
10893
+ " \\operatorname{for} ",
10894
+ serializer.serialize(index),
10895
+ " = ",
10896
+ serializer.serialize(coll)
10897
+ ]);
10760
10898
  }
10899
+ const bindings = elements.map((elem) => {
10900
+ const name = operand(elem, 1);
10901
+ const coll = operand(elem, 2);
10902
+ return joinLatex([
10903
+ serializer.serialize(name),
10904
+ " = ",
10905
+ serializer.serialize(coll)
10906
+ ]);
10907
+ }).join(", ");
10761
10908
  return joinLatex([
10762
- "\\operatorname{Loop}(",
10763
10909
  serializer.serialize(body),
10764
- ", ",
10765
- serializer.serialize(indexing),
10766
- ")"
10910
+ " \\operatorname{for} ",
10911
+ bindings
10767
10912
  ]);
10768
10913
  }
10769
10914
  },
@@ -10796,6 +10941,18 @@ var DEFINITIONS_CORE = [
10796
10941
  precedence: 245,
10797
10942
  parse: (parser, until) => parseForExpression(parser, until)
10798
10943
  },
10944
+ // \operatorname{for} as postfix infix (list comprehension):
10945
+ // `body \operatorname{for} x = L_1, y = L_2`
10946
+ // Precedence 19 — just below comma (20) so the body is allowed to use
10947
+ // any operator (including comma sequencing) up to the keyword, and the
10948
+ // bindings can be comma-separated below us.
10949
+ {
10950
+ symbolTrigger: "for",
10951
+ kind: "infix",
10952
+ associativity: "none",
10953
+ precedence: 19,
10954
+ parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
10955
+ },
10799
10956
  // \operatorname{break}
10800
10957
  {
10801
10958
  symbolTrigger: "break",
@@ -11000,7 +11157,10 @@ var DEFINITIONS_CORE = [
11000
11157
  if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
11001
11158
  parser.addBoundary([")"]);
11002
11159
  const expr2 = parser.parseExpression(until);
11003
- if (!parser.matchBoundary()) return null;
11160
+ if (!parser.matchBoundary()) {
11161
+ parser.removeBoundary();
11162
+ return null;
11163
+ }
11004
11164
  if (!parser.match("<}>")) return null;
11005
11165
  return ["Derivative", lhs, expr2];
11006
11166
  }
@@ -11441,7 +11601,12 @@ function parseBrackets(parser, body) {
11441
11601
  if (isEmptySequence(body)) return ["List"];
11442
11602
  const h = operator(body);
11443
11603
  if (h === "Range" || h === "Linspace") return body;
11444
- if (h === "Sequence") return ["List", ...operands(body)];
11604
+ if (h === "Sequence") {
11605
+ const elems = operands(body);
11606
+ const inferred = tryInferRangeFromElements(elems, parser);
11607
+ if (inferred) return inferred;
11608
+ return ["List", ...elems];
11609
+ }
11445
11610
  if (h === "Delimiter") {
11446
11611
  const delim = stringValue(operand(body, 2)) ?? "...";
11447
11612
  if (delim === ";" || delim === ".;.") {
@@ -11454,12 +11619,37 @@ function parseBrackets(parser, body) {
11454
11619
  }
11455
11620
  if (delim === "," || delim === ".,.") {
11456
11621
  body = operand(body, 1);
11457
- if (operator(body) === "Sequence") return ["List", ...operands(body)];
11622
+ if (operator(body) === "Sequence") {
11623
+ const elems = operands(body);
11624
+ const inferred = tryInferRangeFromElements(elems, parser);
11625
+ if (inferred) return inferred;
11626
+ return ["List", ...elems];
11627
+ }
11458
11628
  return ["List", body ?? "Nothing"];
11459
11629
  }
11460
11630
  }
11461
11631
  return ["List", body];
11462
11632
  }
11633
+ function tryInferRangeFromElements(elems, parser) {
11634
+ if (elems.length < 4) return null;
11635
+ const penultimate = elems[elems.length - 2];
11636
+ if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
11637
+ const samples = elems.slice(0, -2);
11638
+ const endExpr = elems[elems.length - 1];
11639
+ if (samples.length < 2) return null;
11640
+ const sampleNums = samples.map(machineValue);
11641
+ if (sampleNums.some((n) => n === null)) return null;
11642
+ const nums = sampleNums;
11643
+ const step = nums[nums.length - 1] - nums[nums.length - 2];
11644
+ const tol = parser.options.tolerance;
11645
+ if (Math.abs(step) < tol)
11646
+ return parser.error("degenerate-range-step", parser.index);
11647
+ for (let i = 1; i < nums.length; i++) {
11648
+ if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
11649
+ return parser.error("inconsistent-range-samples", parser.index);
11650
+ }
11651
+ return ["Range", nums[0], endExpr, step];
11652
+ }
11463
11653
  function serializeList(serializer, expr2) {
11464
11654
  if (nops(expr2) > 1 && operands(expr2).every((x) => {
11465
11655
  const op = operator(x);
@@ -11711,6 +11901,35 @@ function parseForExpression(parser, until) {
11711
11901
  ["Element", index, ["Range", lower, upper]]
11712
11902
  ];
11713
11903
  }
11904
+ function parseForComprehension(parser, lhs, until) {
11905
+ const bindingTerminator = {
11906
+ minPrec: 21,
11907
+ // Above comma (20) and ; (19), so `x = L_1` is captured whole
11908
+ condition: (p) => {
11909
+ if (until?.condition?.(p)) return true;
11910
+ const saved = p.index;
11911
+ p.skipVisualSpace();
11912
+ const isComma = p.peek === ",";
11913
+ p.index = saved;
11914
+ return isComma;
11915
+ }
11916
+ };
11917
+ const elements = [];
11918
+ do {
11919
+ parser.skipVisualSpace();
11920
+ const binding = parser.parseExpression(bindingTerminator);
11921
+ if (binding === null) break;
11922
+ const op = operator(binding);
11923
+ if (op !== "Equal" && op !== "Assign") return null;
11924
+ const name = operand(binding, 1);
11925
+ const list = operand(binding, 2);
11926
+ if (!name || !list) return null;
11927
+ elements.push(["Element", name, list]);
11928
+ parser.skipVisualSpace();
11929
+ } while (parser.match(","));
11930
+ if (elements.length === 0) return null;
11931
+ return ["Loop", lhs, ...elements];
11932
+ }
11714
11933
  function parseWhereExpression(parser, lhs, until) {
11715
11934
  const bindingTerminator = {
11716
11935
  minPrec: 21,
@@ -19482,6 +19701,19 @@ var _Parser = class __Parser {
19482
19701
  } while (postfix !== null);
19483
19702
  }
19484
19703
  if (result !== null) result = this.parseSupsub(result);
19704
+ if (result !== null) {
19705
+ let postfix = null;
19706
+ let index = this.index;
19707
+ do {
19708
+ postfix = this.parsePostfixOperator(result, until);
19709
+ result = postfix ?? result;
19710
+ if (this.index === index && postfix !== null) {
19711
+ console.assert(this.index !== index, "No token consumed");
19712
+ break;
19713
+ }
19714
+ index = this.index;
19715
+ } while (postfix !== null);
19716
+ }
19485
19717
  if (result === null) {
19486
19718
  result = this.options.parseUnexpectedToken?.(null, this) ?? null;
19487
19719
  if (result === null && this.peek.startsWith("\\")) {
@@ -19990,6 +20222,28 @@ function toDecimalNumber(wholePart, fractionalPart, exp3) {
19990
20222
  }
19991
20223
 
19992
20224
  // src/compute-engine/latex-syntax/serializer.ts
20225
+ var DOT_NOTATION_MAP = {
20226
+ First: ".x",
20227
+ Second: ".y",
20228
+ Third: ".z",
20229
+ Real: ".\\operatorname{real}",
20230
+ Imaginary: ".\\operatorname{imag}",
20231
+ Length: ".\\operatorname{count}",
20232
+ Sum: ".\\operatorname{total}",
20233
+ Max: ".\\max",
20234
+ Min: ".\\min"
20235
+ };
20236
+ function trySerializeDotNotation(serializer, expr2) {
20237
+ if (!serializer.options.dotNotation) return null;
20238
+ const ops = operands(expr2);
20239
+ if (!ops || ops.length !== 1) return null;
20240
+ const head = operator(expr2);
20241
+ if (!head) return null;
20242
+ const suffix = DOT_NOTATION_MAP[head];
20243
+ if (suffix === void 0) return null;
20244
+ const lhs = serializer.wrap(ops[0], 810);
20245
+ return `${lhs}${suffix}`;
20246
+ }
19993
20247
  var ACCENT_MODIFIERS = {
19994
20248
  deg: (s) => `${s}\\degree`,
19995
20249
  prime: (s) => `${s}^{\\prime}`,
@@ -20033,6 +20287,7 @@ var Serializer5 = class {
20033
20287
  constructor(dictionary, options) {
20034
20288
  this.dictionary = dictionary;
20035
20289
  this.options = {
20290
+ dotNotation: false,
20036
20291
  dmsFormat: false,
20037
20292
  angleNormalization: "none",
20038
20293
  ...options
@@ -20131,6 +20386,8 @@ var Serializer5 = class {
20131
20386
  return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
20132
20387
  }
20133
20388
  serializeFunction(expr2, def) {
20389
+ const dotResult = trySerializeDotNotation(this, expr2);
20390
+ if (dotResult !== null) return dotResult;
20134
20391
  if (def?.serialize) return def.serialize(this, expr2);
20135
20392
  const h = operator(expr2);
20136
20393
  return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
@@ -20373,6 +20630,8 @@ function defaultParseOptions(opts) {
20373
20630
  preserveLatex: opts.preserveLatex ?? false,
20374
20631
  quantifierScope: opts.quantifierScope ?? "tight",
20375
20632
  timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
20633
+ // Standalone mode has no engine; use the same default as ComputeEngine
20634
+ tolerance: 1e-7,
20376
20635
  // Callbacks -- standalone mode has no engine, so these are stubs
20377
20636
  getSymbolType: (_id) => BoxedType.unknown,
20378
20637
  hasSubscriptEvaluate: (_id) => false,
@@ -20405,6 +20664,7 @@ function defaultSerializeOptions(opts) {
20405
20664
  invisiblePlus: "",
20406
20665
  multiply: "\\times",
20407
20666
  missingSymbol: "\\blacksquare",
20667
+ dotNotation: false,
20408
20668
  dmsFormat: false,
20409
20669
  angleNormalization: "none",
20410
20670
  // Style callbacks -- use same defaults as the engine
@@ -27375,7 +27635,11 @@ var COLLECTIONS_LIBRARY = {
27375
27635
  //
27376
27636
  Range: {
27377
27637
  complexity: 8200,
27378
- signature: "(number, number?, step: number?) -> indexed_collection<integer>",
27638
+ signature: "(number, number?, step: number?) -> indexed_collection<number>",
27639
+ type: (ops) => {
27640
+ const allInt = ops.every((op) => op.isInteger);
27641
+ return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
27642
+ },
27379
27643
  canonical: (ops, { engine: ce }) => {
27380
27644
  if (ops.length === 0) return null;
27381
27645
  if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
@@ -27399,19 +27663,26 @@ var COLLECTIONS_LIBRARY = {
27399
27663
  const [lower, upper, step] = range(expr2);
27400
27664
  if (step === 0) return 0;
27401
27665
  if (!isFinite(lower) || !isFinite(upper)) return Infinity;
27402
- return 1 + Math.max(0, Math.floor((upper - lower) / step));
27666
+ return Math.max(0, Math.floor((upper - lower) / step) + 1);
27403
27667
  },
27404
27668
  contains: (expr2, target) => {
27405
- if (!target.type.matches("integer")) return false;
27406
27669
  const t = target.re;
27670
+ if (!isFinite(t)) return false;
27407
27671
  const [lower, upper, step] = range(expr2);
27408
27672
  if (step === 0) return false;
27409
- if (step > 0) return t >= lower && t <= upper;
27410
- return t <= lower && t >= upper;
27673
+ if (step > 0) {
27674
+ if (t < lower || t > upper) return false;
27675
+ } else {
27676
+ if (t > lower || t < upper) return false;
27677
+ }
27678
+ const k = (t - lower) / step;
27679
+ const tol = expr2.engine.tolerance;
27680
+ const kRounded = Math.round(k);
27681
+ return kRounded >= 0 && Math.abs(k - kRounded) < tol;
27411
27682
  },
27412
27683
  iterator: (expr2) => {
27413
27684
  const [lower, upper, step] = range(expr2);
27414
- const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
27685
+ const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
27415
27686
  let index = 1;
27416
27687
  return {
27417
27688
  next: () => {
@@ -27429,7 +27700,9 @@ var COLLECTIONS_LIBRARY = {
27429
27700
  at: (expr2, index) => {
27430
27701
  if (typeof index !== "number") return void 0;
27431
27702
  const [lower, upper, step] = range(expr2);
27432
- if (index < 1 || index > 1 + (upper - lower) / step) return void 0;
27703
+ if (step === 0) return void 0;
27704
+ const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
27705
+ if (index < 1 || index > maxCount) return void 0;
27433
27706
  return expr2.engine.number(lower + step * (index - 1));
27434
27707
  },
27435
27708
  indexWhere: void 0,
@@ -27454,7 +27727,13 @@ var COLLECTIONS_LIBRARY = {
27454
27727
  if (step > 0) return lower <= upper ? "positive" : "negative";
27455
27728
  return lower >= upper ? "positive" : "negative";
27456
27729
  },
27457
- elttype: (_expr) => "finite_integer"
27730
+ elttype: (expr2) => {
27731
+ if (!isFunction2(expr2)) return "finite_integer";
27732
+ for (let i = 1; i <= expr2.nops; i++) {
27733
+ if (!expr2[`op${i}`].isInteger) return "finite_real";
27734
+ }
27735
+ return "finite_integer";
27736
+ }
27458
27737
  }
27459
27738
  },
27460
27739
  Interval: {
@@ -28052,15 +28331,45 @@ var COLLECTIONS_LIBRARY = {
28052
28331
  },
28053
28332
  First: {
28054
28333
  complexity: 8200,
28055
- signature: "(collection) -> any",
28334
+ signature: "(any) -> any",
28056
28335
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28057
- evaluate: ([xs], { engine: ce }) => xs.at(1) ?? ce.Nothing
28336
+ evaluate: ([xs], { engine: ce }) => {
28337
+ if (!xs.isCollection)
28338
+ return ce.error([
28339
+ "incompatible-type",
28340
+ `'collection'`,
28341
+ xs.type.toString()
28342
+ ]);
28343
+ return xs.at(1) ?? ce.Nothing;
28344
+ }
28058
28345
  },
28059
28346
  Second: {
28060
28347
  complexity: 8200,
28061
- signature: "(collection) -> any",
28348
+ signature: "(any) -> any",
28349
+ type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28350
+ evaluate: ([xs], { engine: ce }) => {
28351
+ if (!xs.isCollection)
28352
+ return ce.error([
28353
+ "incompatible-type",
28354
+ `'collection'`,
28355
+ xs.type.toString()
28356
+ ]);
28357
+ return xs.at(2) ?? ce.Nothing;
28358
+ }
28359
+ },
28360
+ Third: {
28361
+ complexity: 8200,
28362
+ signature: "(any) -> any",
28062
28363
  type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
28063
- evaluate: ([xs], { engine: ce }) => xs.at(2) ?? ce.Nothing
28364
+ evaluate: ([xs], { engine: ce }) => {
28365
+ if (!xs.isCollection)
28366
+ return ce.error([
28367
+ "incompatible-type",
28368
+ `'collection'`,
28369
+ xs.type.toString()
28370
+ ]);
28371
+ return xs.at(3) ?? ce.Nothing;
28372
+ }
28064
28373
  },
28065
28374
  Last: {
28066
28375
  complexity: 8200,
@@ -29039,17 +29348,14 @@ function range(expr2) {
29039
29348
  if (!isFunction2(expr2)) return [1, 0, 0];
29040
29349
  if (expr2.nops === 0) return [1, 0, 0];
29041
29350
  let op1 = expr2.op1.re;
29042
- if (!isFinite(op1)) op1 = 1;
29043
- else op1 = Math.round(op1);
29351
+ if (!isFinite(op1) && !op1) op1 = 1;
29044
29352
  if (expr2.nops === 1) return [1, op1, 1];
29045
29353
  let op2 = expr2.op2.re;
29046
29354
  if (!isFinite(op2) && !op2) op2 = 1;
29047
- else if (isFinite(op2)) op2 = Math.round(op2);
29048
- if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
29355
+ if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
29049
29356
  let op3 = expr2.op3.re;
29050
- if (!isFinite(op3)) op3 = 1;
29051
- else op3 = Math.abs(Math.round(op3));
29052
- return [op1, op2, op1 < op2 ? op3 : -op3];
29357
+ if (!isFinite(op3) && !op3) op3 = 1;
29358
+ return [op1, op2, op3];
29053
29359
  }
29054
29360
  function rangeLast(r) {
29055
29361
  const [lower, upper, step] = r;
@@ -42779,12 +43085,42 @@ var CONTROL_STRUCTURES_LIBRARY = [
42779
43085
  }
42780
43086
  },
42781
43087
  Loop: {
42782
- description: "Evaluate a body expression over elements of a collection.",
43088
+ description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
43089
+ lazy: true,
43090
+ signature: "(body:expression, iterators:expression*) -> any",
43091
+ type: ([body]) => {
43092
+ if (!body) return "nothing";
43093
+ return parseType(`indexed_collection<${String(body.type)}>`);
43094
+ },
43095
+ canonical: canonicalLoop,
43096
+ evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
43097
+ evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
43098
+ },
43099
+ When: {
43100
+ description: "Conditional value: returns expr when cond holds, undefined otherwise.",
42783
43101
  lazy: true,
42784
- signature: "(body:expression, collection:expression) -> any",
42785
- type: ([body]) => body.type,
42786
- evaluate: ([body, collection], { engine: ce }) => run(runLoop(body, collection, ce), ce._timeRemaining),
42787
- evaluateAsync: async ([body, collection], { engine: ce, signal }) => runAsync(runLoop(body, collection, ce), ce._timeRemaining, signal)
43102
+ signature: "(expression, boolean) -> any",
43103
+ type: ([expr2]) => expr2.type,
43104
+ canonical: (args, { engine: ce }) => {
43105
+ if (args.length !== 2) return null;
43106
+ const [expr2, cond] = args;
43107
+ if (isFunction2(expr2, "When")) {
43108
+ const inner = expr2.op1.canonical;
43109
+ const innerCond = expr2.op2.canonical;
43110
+ return ce._fn("When", [
43111
+ inner,
43112
+ ce._fn("And", [innerCond, cond.canonical])
43113
+ ]);
43114
+ }
43115
+ return ce._fn("When", [expr2.canonical, cond.canonical]);
43116
+ },
43117
+ evaluate: ([expr2, cond], { engine: ce }) => {
43118
+ const c = cond.evaluate();
43119
+ const cs = sym(c);
43120
+ if (cs === "True") return expr2.evaluate();
43121
+ if (cs === "False") return ce.symbol("Undefined");
43122
+ return ce._fn("When", [expr2, c]);
43123
+ }
42788
43124
  },
42789
43125
  Which: {
42790
43126
  description: "Return the value for the first condition that is true.",
@@ -42844,9 +43180,141 @@ function canonicalBlock(ops, options) {
42844
43180
  );
42845
43181
  return result;
42846
43182
  }
42847
- function* runLoop(body, collection, ce) {
43183
+ function canonicalLoop(ops, options) {
43184
+ const { engine: ce, scope } = options;
43185
+ if (ops.length === 0) return null;
43186
+ if (ops.length === 1) {
43187
+ return ce._fn("Loop", [ops[0].canonical]);
43188
+ }
43189
+ const body = ops[0];
43190
+ const iterators = ops.slice(1);
43191
+ const allElement = iterators.every((it) => it.operator === "Element");
43192
+ if (!allElement) {
43193
+ return ce._fn(
43194
+ "Loop",
43195
+ ops.map((op) => op.canonical)
43196
+ );
43197
+ }
43198
+ const loopScope = scope ?? {
43199
+ parent: ce.context.lexicalScope,
43200
+ bindings: /* @__PURE__ */ new Map()
43201
+ };
43202
+ loopScope.noAutoDeclare = true;
43203
+ ce.pushScope(loopScope);
43204
+ let canonicalIterators;
43205
+ let canonicalBody;
43206
+ try {
43207
+ canonicalIterators = iterators.map((it) => {
43208
+ if (!isFunction2(it, "Element")) {
43209
+ return ce._fn("Element", [
43210
+ ce.error("missing").canonical,
43211
+ ce.error("missing").canonical
43212
+ ]);
43213
+ }
43214
+ const indexExpr = it.ops[0];
43215
+ const collExpr = it.ops[1];
43216
+ if (!indexExpr || !collExpr) {
43217
+ return ce._fn("Element", [
43218
+ (indexExpr ?? ce.error("missing")).canonical,
43219
+ (collExpr ?? ce.error("missing")).canonical
43220
+ ]);
43221
+ }
43222
+ if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
43223
+ if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
43224
+ ce.declare(indexExpr.symbol, "unknown");
43225
+ }
43226
+ return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
43227
+ });
43228
+ canonicalBody = body.canonical;
43229
+ } finally {
43230
+ ce.popScope();
43231
+ loopScope.noAutoDeclare = false;
43232
+ }
43233
+ return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
43234
+ scope: loopScope
43235
+ });
43236
+ }
43237
+ function* runLoop(body, elements, ce) {
42848
43238
  body ??= ce.Nothing;
42849
43239
  if (sym(body) === "Nothing") return body;
43240
+ if (elements.length === 0) {
43241
+ const result = body.evaluate();
43242
+ yield result;
43243
+ return result;
43244
+ }
43245
+ if (elements.length === 1 && elements[0].operator !== "Element") {
43246
+ return yield* runLoopLegacy(body, elements[0], ce);
43247
+ }
43248
+ const results = [];
43249
+ const state = { stopped: false, broke: false, count: 0 };
43250
+ const freshScope = {
43251
+ parent: ce.context.lexicalScope,
43252
+ bindings: /* @__PURE__ */ new Map()
43253
+ };
43254
+ ce._pushEvalContext(freshScope);
43255
+ try {
43256
+ for (const elem of elements) {
43257
+ if (!isFunction2(elem, "Element")) continue;
43258
+ const idx = elem.ops[0];
43259
+ if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
43260
+ if (!freshScope.bindings.has(idx.symbol))
43261
+ ce.declare(idx.symbol, "unknown");
43262
+ }
43263
+ }
43264
+ yield* runLoopNested(body, elements, 0, ce, results, state);
43265
+ } finally {
43266
+ ce._popEvalContext();
43267
+ }
43268
+ if (state.stopped && state.value !== void 0) {
43269
+ if (!state.broke) return state.value;
43270
+ return state.value;
43271
+ }
43272
+ return ce.function("List", results);
43273
+ }
43274
+ function* runLoopNested(body, elements, index, ce, results, state) {
43275
+ if (state.stopped) return;
43276
+ if (index === elements.length) {
43277
+ const result = body.evaluate();
43278
+ state.count += 1;
43279
+ if (state.count > ce.iterationLimit)
43280
+ throw new CancellationError({ cause: "iteration-limit-exceeded" });
43281
+ if (isFunction2(result, "Break")) {
43282
+ state.stopped = true;
43283
+ state.broke = true;
43284
+ state.value = result.op1;
43285
+ return;
43286
+ }
43287
+ if (result.operator === "Return") {
43288
+ state.stopped = true;
43289
+ state.value = result;
43290
+ return;
43291
+ }
43292
+ results.push(result);
43293
+ yield result;
43294
+ return;
43295
+ }
43296
+ const elem = elements[index];
43297
+ if (!isFunction2(elem, "Element")) {
43298
+ return;
43299
+ }
43300
+ const indexExpr = elem.ops[0];
43301
+ const collExpr = elem.ops[1];
43302
+ if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
43303
+ return;
43304
+ }
43305
+ const name = indexExpr.symbol;
43306
+ const collection = collExpr.evaluate();
43307
+ if (!collection?.isCollection) {
43308
+ return;
43309
+ }
43310
+ const skipAssign = name === "Nothing";
43311
+ for (const value of collection.each()) {
43312
+ if (!skipAssign) ce.assign(name, value);
43313
+ yield* runLoopNested(body, elements, index + 1, ce, results, state);
43314
+ if (state.stopped) return;
43315
+ }
43316
+ }
43317
+ function* runLoopLegacy(body, collection, ce) {
42850
43318
  if (collection?.isCollection) {
42851
43319
  let result = void 0;
42852
43320
  const fn = applicable(body);
@@ -54929,6 +55397,23 @@ var BaseCompiler = class _BaseCompiler {
54929
55397
  };
54930
55398
  return compilePair(0);
54931
55399
  }
55400
+ if (h === "When") {
55401
+ if (args.length !== 2)
55402
+ throw new Error("When: expected exactly 2 arguments (expr, cond)");
55403
+ const fn2 = target.functions?.(h);
55404
+ if (fn2) {
55405
+ if (typeof fn2 === "function") {
55406
+ return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
55407
+ }
55408
+ return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
55409
+ }
55410
+ if (isSymbol2(args[1], "True"))
55411
+ return `(${_BaseCompiler.compile(args[0], target)})`;
55412
+ if (isSymbol2(args[1], "False")) return "NaN";
55413
+ const val = _BaseCompiler.compile(args[0], target);
55414
+ const cond = _BaseCompiler.compile(args[1], target);
55415
+ return `((${cond}) ? (${val}) : NaN)`;
55416
+ }
54932
55417
  if (h === "Block") {
54933
55418
  return _BaseCompiler.compileBlock(args, target);
54934
55419
  }
@@ -55003,17 +55488,91 @@ var BaseCompiler = class _BaseCompiler {
55003
55488
  )}${target.ws("\n")}})()`;
55004
55489
  }
55005
55490
  /**
55006
- * Compile a Loop expression with Element(index, Range(lo, hi)) indexing.
55007
- * Generates: (() => { for (let i = lo; i <= hi; i++) { body } })()
55491
+ * Compile a Loop expression.
55492
+ *
55493
+ * Two forms are supported:
55494
+ *
55495
+ * 1. **Imperative / single-Element form** (existing behaviour):
55496
+ * `Loop(body, Element(i, Range(lo, hi)))`
55497
+ * Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
55498
+ * in an IIFE. The loop counter is always a plain number. For targets
55499
+ * that wrap numeric values (e.g. interval-js uses `_IA.point()`),
55500
+ * references to the loop index inside the body are re-wrapped via
55501
+ * `target.number`. `break` / `continue` / `return` are preserved.
55502
+ *
55503
+ * 2. **Comprehension / variadic-Element form** (new):
55504
+ * `Loop(body, Element(x, coll1), Element(y, coll2), …)`
55505
+ * When two or more `Element` clauses are present — or when the single
55506
+ * Element's collection is not a `Range` — the loop is compiled as a
55507
+ * comprehension that collects results into an array. Each clause
55508
+ * produces a `for (const name of collection)` loop, nested
55509
+ * outermost-to-innermost, and the innermost body pushes into `result`.
55510
+ *
55511
+ * Example output (JS):
55512
+ * ```js
55513
+ * (() => { const result = [];
55514
+ * for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
55515
+ * return result; })()
55516
+ * ```
55008
55517
  *
55009
- * The loop counter is always a raw number. For targets that wrap numeric
55010
- * values (e.g. interval-js wraps with `_IA.point()`), references to the
55011
- * loop index inside the body are wrapped via `target.number`.
55518
+ * GLSL: multi-Element comprehension is not trivially representable in
55519
+ * GLSL (no dynamic arrays, no push). A compile-time error is thrown.
55520
+ * TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
55521
+ * array or by unrolling when bounds are known at compile time.
55012
55522
  */
55013
55523
  static compileForLoop(args, target) {
55014
55524
  if (!args[0]) throw new Error("Loop: no body");
55015
55525
  if (!args[1]) throw new Error("Loop: no indexing set");
55016
- const indexing = args[1];
55526
+ const body = args[0];
55527
+ const elements = args.slice(1);
55528
+ const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
55529
+ if (useComprehension) {
55530
+ const lang = target.language ?? "";
55531
+ if (lang === "glsl" || lang === "wgsl") {
55532
+ throw new Error(
55533
+ `${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
55534
+ );
55535
+ }
55536
+ const narrowedElements = [];
55537
+ for (let i = 0; i < elements.length; i++) {
55538
+ const elem = elements[i];
55539
+ if (!isFunction2(elem, "Element"))
55540
+ throw new Error(
55541
+ `Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
55542
+ );
55543
+ if (!isSymbol2(elem.ops[0]))
55544
+ throw new Error(
55545
+ `Loop: Element index (argument ${i + 1}) must be a symbol`
55546
+ );
55547
+ narrowedElements.push(elem);
55548
+ }
55549
+ const loopVarSet = new Set(
55550
+ narrowedElements.map(
55551
+ (e) => e.ops[0].symbol
55552
+ )
55553
+ );
55554
+ const needsWrap2 = target.number(0) !== "0";
55555
+ const bodyTarget2 = needsWrap2 ? {
55556
+ ...target,
55557
+ var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
55558
+ } : target;
55559
+ const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
55560
+ let inner = `result.push(${bodyCode});`;
55561
+ for (let i = narrowedElements.length - 1; i >= 0; i--) {
55562
+ const elem = narrowedElements[i];
55563
+ const name = elem.ops[0].symbol;
55564
+ const collExpr = elem.ops[1];
55565
+ let collection;
55566
+ if (isFunction2(collExpr, "Range")) {
55567
+ collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
55568
+ } else {
55569
+ collection = _BaseCompiler.compile(collExpr, bodyTarget2);
55570
+ }
55571
+ inner = `for (const ${name} of ${collection}) { ${inner} }`;
55572
+ }
55573
+ return `(() => { const result = []; ${inner} return result; })()`;
55574
+ }
55575
+ const indexing = elements[0];
55017
55576
  if (!isFunction2(indexing, "Element"))
55018
55577
  throw new Error("Loop: expected Element(index, Range(lo, hi))");
55019
55578
  const indexExpr = indexing.ops[0];
@@ -55031,13 +55590,72 @@ var BaseCompiler = class _BaseCompiler {
55031
55590
  ...target,
55032
55591
  var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
55033
55592
  };
55034
- const bodyStmts = _BaseCompiler.compileLoopBody(args[0], bodyTarget);
55593
+ const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
55035
55594
  return `(() => {${target.ws(
55036
55595
  "\n"
55037
55596
  )}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
55038
55597
  "\n"
55039
55598
  )}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
55040
55599
  }
55600
+ /**
55601
+ * Returns `true` when the given collection expression is a `Range` whose
55602
+ * runtime semantics match the legacy imperative for-loop shape
55603
+ * `for (let i = lo; i <= hi; i++)`.
55604
+ *
55605
+ * Concretely: integer-ascending bounds and step omitted-or-1. When bounds
55606
+ * are not statically numeric we accept the Range (the historical
55607
+ * behaviour) — runtime mismatch in the descending-unknown-bounds case is
55608
+ * left as a known limitation; callers can force the iterable path by
55609
+ * supplying an explicit step.
55610
+ */
55611
+ static isLegacyCompatibleRange(coll) {
55612
+ if (!isFunction2(coll, "Range")) return false;
55613
+ if (coll.ops.length >= 3) {
55614
+ const stepExpr = coll.ops[2];
55615
+ if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
55616
+ }
55617
+ const lo = coll.ops[0];
55618
+ const hi = coll.ops[1];
55619
+ if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
55620
+ if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
55621
+ if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
55622
+ return true;
55623
+ }
55624
+ /**
55625
+ * Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
55626
+ * iterable expression. Mirrors the runtime semantics in
55627
+ * `library/collections.ts` Range:
55628
+ * count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
55629
+ * element = lo + step * k (0-indexed)
55630
+ * Default step is 1 when omitted. Bounds and step may be fractional.
55631
+ *
55632
+ * Only used from the comprehension path in `compileForLoop`.
55633
+ * Caller must have already verified `isFunction(rangeExpr, 'Range')`.
55634
+ */
55635
+ static compileRangeIterable(rangeExpr, target) {
55636
+ const loExpr = rangeExpr.ops[0];
55637
+ const hiExpr = rangeExpr.ops[1];
55638
+ const stepExpr = rangeExpr.ops[2];
55639
+ if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
55640
+ const lo2 = loExpr.re;
55641
+ const hi2 = hiExpr.re;
55642
+ const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
55643
+ if (step2 === 0) return "[]";
55644
+ const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
55645
+ if (step2 === 1) {
55646
+ if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
55647
+ return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
55648
+ }
55649
+ return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
55650
+ }
55651
+ const lo = _BaseCompiler.compile(loExpr, target);
55652
+ const hi = _BaseCompiler.compile(hiExpr, target);
55653
+ if (stepExpr === void 0) {
55654
+ 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})`;
55655
+ }
55656
+ const step = _BaseCompiler.compile(stepExpr, target);
55657
+ 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})`;
55658
+ }
55041
55659
  /**
55042
55660
  * Compile a loop body expression as statements (not wrapped in IIFE).
55043
55661
  * Handles Break, Continue, Return as statements, and If as if-else when
@@ -69108,6 +69726,15 @@ var ComputeEngine = class _ComputeEngine {
69108
69726
  lookupDefinition(id) {
69109
69727
  return lookupDefinition(this, id);
69110
69728
  }
69729
+ operatorInfo(head) {
69730
+ const def = this.lookupDefinition(head);
69731
+ if (!def || !isOperatorDef(def)) return void 0;
69732
+ const op = def.operator;
69733
+ return {
69734
+ kind: op.evaluate || op.collection ? "function" : "opaque",
69735
+ signature: op.signature
69736
+ };
69737
+ }
69111
69738
  /**
69112
69739
  * Associate a new definition to a symbol in the current context.
69113
69740
  *
@@ -69395,6 +70022,7 @@ var ComputeEngine = class _ComputeEngine {
69395
70022
  const def = this.lookupDefinition(id);
69396
70023
  return !!(isValueDef(def) && def.value.subscriptEvaluate);
69397
70024
  },
70025
+ tolerance: this.tolerance,
69398
70026
  ...this._latexOptions,
69399
70027
  ...parseOpts
69400
70028
  });
@@ -69559,14 +70187,14 @@ var ComputeEngine = class _ComputeEngine {
69559
70187
  _setDefaultEngineFactory(() => new ComputeEngine());
69560
70188
 
69561
70189
  // src/compute-engine.ts
69562
- var version = "0.56.0";
70190
+ var version = "0.57.0";
69563
70191
  ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
69564
70192
  _setDefaultEngineFactory(
69565
70193
  () => new ComputeEngine({ latexSyntax: new LatexSyntax() })
69566
70194
  );
69567
70195
  globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
69568
70196
  ComputeEngine: ComputeEngine.prototype.constructor,
69569
- version: "0.56.0"
70197
+ version: "0.57.0"
69570
70198
  };
69571
70199
  export {
69572
70200
  DEFINITIONS_ALGEBRA as ALGEBRA_DICTIONARY,