@cortex-js/compute-engine 0.55.2 → 0.55.4

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 +908 -176
  2. package/dist/compile.min.esm.js +441 -71
  3. package/dist/compile.min.umd.cjs +442 -72
  4. package/dist/compile.umd.cjs +908 -176
  5. package/dist/compute-engine.esm.js +954 -185
  6. package/dist/compute-engine.min.esm.js +444 -74
  7. package/dist/compute-engine.min.umd.cjs +444 -74
  8. package/dist/compute-engine.umd.cjs +954 -185
  9. package/dist/core.esm.js +951 -174
  10. package/dist/core.min.esm.js +442 -72
  11. package/dist/core.min.umd.cjs +442 -72
  12. package/dist/core.umd.cjs +951 -174
  13. package/dist/interval.esm.js +2 -2
  14. package/dist/interval.min.esm.js +2 -2
  15. package/dist/interval.min.umd.cjs +2 -2
  16. package/dist/interval.umd.cjs +2 -2
  17. package/dist/latex-syntax.esm.js +43 -13
  18. package/dist/latex-syntax.min.esm.js +5 -5
  19. package/dist/latex-syntax.min.umd.cjs +5 -5
  20. package/dist/latex-syntax.umd.cjs +43 -13
  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 +1 -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 +8 -7
  105. package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
  106. package/dist/types/compute-engine/compilation/constant-folding.d.ts +50 -0
  107. package/dist/types/compute-engine/compilation/fractal-orbit.d.ts +13 -0
  108. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  109. package/dist/types/compute-engine/compilation/gpu-target.d.ts +47 -1
  110. package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
  111. package/dist/types/compute-engine/compilation/javascript-target.d.ts +23 -1
  112. package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
  113. package/dist/types/compute-engine/compilation/types.d.ts +48 -1
  114. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  115. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  126. package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  131. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  132. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  133. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  134. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  135. package/dist/types/compute-engine/global-types.d.ts +1 -1
  136. package/dist/types/compute-engine/index.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  142. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  143. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  144. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +1 -1
  145. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  146. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  147. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  148. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  149. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
  150. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
  151. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  152. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  153. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
  154. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  155. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  156. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  157. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  158. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
  159. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
  160. package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +1 -1
  161. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
  162. package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
  163. package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
  164. package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
  165. package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
  166. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  167. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  168. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
  169. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  170. package/dist/types/compute-engine/latex-syntax/types.d.ts +1 -1
  171. package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
  172. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  173. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  174. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  175. package/dist/types/compute-engine/library/colors.d.ts +1 -1
  176. package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
  177. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  178. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  179. package/dist/types/compute-engine/library/core.d.ts +1 -1
  180. package/dist/types/compute-engine/library/fractals.d.ts +1 -1
  181. package/dist/types/compute-engine/library/library.d.ts +1 -1
  182. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  183. package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
  184. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  185. package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
  186. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  187. package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
  188. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  189. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  190. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  191. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  192. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  193. package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
  194. package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
  195. package/dist/types/compute-engine/library/units.d.ts +1 -1
  196. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  197. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
  198. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
  199. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
  200. package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
  201. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  202. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  203. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  204. package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
  205. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  206. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  207. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  208. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  209. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  210. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  211. package/dist/types/compute-engine/numerics/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 +1 -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 +3 -3
@@ -1,4 +1,4 @@
1
- /** Compile 0.55.2 */
1
+ /** Compile 0.55.4 */
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.Compile = {}));})(this, (function (exports) { 'use strict';
3
3
  var Compile = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -3969,12 +3969,6 @@ var Compile = (() => {
3969
3969
  function applicable(fn) {
3970
3970
  return makeLambda(fn) ?? ((xs) => fn.engine.function("Apply", [fn, ...xs]).evaluate());
3971
3971
  }
3972
- function applicableN1(fn) {
3973
- const lambda = makeLambda(fn);
3974
- const ce = fn.engine;
3975
- if (lambda) return (x) => lambda([ce.number(x)])?.re ?? NaN;
3976
- return (x) => ce.function("Apply", [fn, ce.number(x)]).evaluate().re;
3977
- }
3978
3972
 
3979
3973
  // src/compute-engine/collection-utils.ts
3980
3974
  function isFiniteIndexedCollection(col) {
@@ -14699,8 +14693,11 @@ ${lines.join("\n")}`;
14699
14693
  for (const local of locals) {
14700
14694
  for (const arg of args) {
14701
14695
  if (isFunction2(arg, "Assign") && isSymbol2(arg.ops[0], local)) {
14702
- if (_BaseCompiler.isComplexValued(arg.ops[1])) {
14696
+ const rhs = arg.ops[1];
14697
+ if (_BaseCompiler.isComplexValued(rhs)) {
14703
14698
  typeHints[local] = isWGSL ? "vec2f" : "vec2";
14699
+ } else if (_BaseCompiler.isIntegerValued(rhs)) {
14700
+ typeHints[local] = isWGSL ? "i32" : "int";
14704
14701
  }
14705
14702
  break;
14706
14703
  }
@@ -14905,12 +14902,9 @@ ${lines.join("\n")}`;
14905
14902
  /**
14906
14903
  * Determine at compile time whether an expression produces a complex value.
14907
14904
  *
14908
- * Rules:
14909
- * - Numbers: complex if im !== 0
14910
- * - Symbols: ImaginaryUnit is complex; others use expr.isReal
14911
- * (undefined is treated as real -- assume-real policy)
14912
- * - Functions: Abs, Arg, Re, Im always return real.
14913
- * All others: complex if any operand is complex.
14905
+ * Uses the expression's declared type (from operator signatures) when
14906
+ * available. Falls back to operand inspection for functions whose
14907
+ * return type is unknown.
14914
14908
  */
14915
14909
  static isComplexValued(expr) {
14916
14910
  if (isNumber(expr)) return expr.im !== 0;
@@ -14921,13 +14915,24 @@ ${lines.join("\n")}`;
14921
14915
  return t.matches("complex") && !t.matches("real");
14922
14916
  }
14923
14917
  if (isFunction2(expr)) {
14924
- const op = expr.operator;
14925
- if (op === "Abs" || op === "Arg" || op === "Re" || op === "Im")
14926
- return false;
14918
+ const t = expr.type;
14919
+ if (t.matches("complex") && !t.matches("real")) return true;
14920
+ if (t.matches("real")) return false;
14927
14921
  return expr.ops.some((arg) => _BaseCompiler.isComplexValued(arg));
14928
14922
  }
14929
14923
  return false;
14930
14924
  }
14925
+ /** True if the expression is provably integer-typed. */
14926
+ static isIntegerValued(expr) {
14927
+ if (isNumber(expr)) return expr.im === 0 && Number.isInteger(expr.re);
14928
+ const t = expr.type;
14929
+ return t ? t.matches("integer") : false;
14930
+ }
14931
+ /** True if the expression is provably non-negative (sign ≥ 0). */
14932
+ static isNonNegative(expr) {
14933
+ if (isNumber(expr)) return expr.im === 0 && expr.re >= 0;
14934
+ return expr.isNonNegative === true;
14935
+ }
14931
14936
  /**
14932
14937
  * Generate a temporary variable name
14933
14938
  */
@@ -15099,20 +15104,113 @@ ${lines.join("\n")}`;
15099
15104
  } catch (e) {
15100
15105
  if (options?.fallback ?? true) {
15101
15106
  console.warn(
15102
- `Compilation fallback for "${expr.operator}": ${e.message}`
15107
+ `Compilation fallback for "${expr.operator}" (target: ${options?.to ?? "javascript"}): ${e.message}`
15103
15108
  );
15109
+ const ce = expr.engine;
15110
+ const fallbackRun = ((vars) => {
15111
+ ce.pushScope();
15112
+ try {
15113
+ if (vars && typeof vars === "object") {
15114
+ for (const [k, v] of Object.entries(vars))
15115
+ ce.assign(k, v);
15116
+ }
15117
+ return expr.evaluate().re;
15118
+ } finally {
15119
+ ce.popScope();
15120
+ }
15121
+ });
15104
15122
  return {
15105
15123
  target: options?.to ?? "javascript",
15106
15124
  success: false,
15107
15125
  code: "",
15108
15126
  calling: "expression",
15109
- run: applicableN1(expr)
15127
+ run: fallbackRun
15110
15128
  };
15111
15129
  }
15112
15130
  throw e;
15113
15131
  }
15114
15132
  }
15115
15133
 
15134
+ // src/compute-engine/compilation/constant-folding.ts
15135
+ function formatFloat(n) {
15136
+ const str = n.toString();
15137
+ if (!str.includes(".") && !str.includes("e") && !str.includes("E")) {
15138
+ return `${str}.0`;
15139
+ }
15140
+ return str;
15141
+ }
15142
+ function tryGetConstant(expr) {
15143
+ if (!isNumber(expr)) return void 0;
15144
+ if (expr.im !== 0) return void 0;
15145
+ const re = expr.re;
15146
+ if (!isFinite(re)) return void 0;
15147
+ return re;
15148
+ }
15149
+ var NUMERIC_LITERAL_RE = /^-?\d+(\.\d+)?$/;
15150
+ function foldTerms(terms, identity, op) {
15151
+ const identityValue = op === "+" ? 0 : 1;
15152
+ let numericAcc = null;
15153
+ const symbolic = [];
15154
+ for (const term of terms) {
15155
+ if (NUMERIC_LITERAL_RE.test(term)) {
15156
+ const val = parseFloat(term);
15157
+ if (op === "*" && val === 0) return "0.0";
15158
+ if (numericAcc === null) {
15159
+ numericAcc = val;
15160
+ } else {
15161
+ numericAcc = op === "+" ? numericAcc + val : numericAcc * val;
15162
+ }
15163
+ } else {
15164
+ symbolic.push(term);
15165
+ }
15166
+ }
15167
+ if (numericAcc !== null && numericAcc !== identityValue) {
15168
+ symbolic.unshift(formatFloat(numericAcc));
15169
+ }
15170
+ if (symbolic.length === 0) {
15171
+ if (numericAcc !== null) return formatFloat(numericAcc);
15172
+ return identity;
15173
+ }
15174
+ if (symbolic.length === 1) return symbolic[0];
15175
+ return symbolic.join(op === "+" ? " + " : " * ");
15176
+ }
15177
+ function tryGetComplexParts(expr, compile2) {
15178
+ if (isSymbol2(expr, "ImaginaryUnit")) {
15179
+ return { re: null, im: "1.0" };
15180
+ }
15181
+ if (isNumber(expr) && expr.im !== 0) {
15182
+ const re = expr.re;
15183
+ const im = expr.im;
15184
+ return {
15185
+ re: re !== 0 ? formatFloat(re) : null,
15186
+ im: formatFloat(im)
15187
+ };
15188
+ }
15189
+ if (isFunction2(expr, "Multiply")) {
15190
+ const ops = expr.ops;
15191
+ const iIndex = ops.findIndex(
15192
+ (op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
15193
+ );
15194
+ if (iIndex >= 0) {
15195
+ const iFactor = ops[iIndex];
15196
+ const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
15197
+ const remaining = ops.filter((_, idx) => idx !== iIndex);
15198
+ if (remaining.length === 0) {
15199
+ return { re: null, im: formatFloat(iScale) };
15200
+ }
15201
+ const compiledFactors = remaining.map((r) => compile2(r));
15202
+ if (iScale !== 1)
15203
+ compiledFactors.unshift(formatFloat(iScale));
15204
+ const imCode = foldTerms(compiledFactors, "1.0", "*");
15205
+ return { re: null, im: imCode };
15206
+ }
15207
+ }
15208
+ if (BaseCompiler.isComplexValued(expr)) {
15209
+ return null;
15210
+ }
15211
+ return { re: compile2(expr), im: null };
15212
+ }
15213
+
15116
15214
  // node_modules/@arnog/colors/dist/index.mjs
15117
15215
  function gammaCorrect(channel) {
15118
15216
  const abs2 = Math.abs(channel);
@@ -16407,30 +16505,6 @@ ${lines.join("\n")}`;
16407
16505
  "#ae2036",
16408
16506
  "#b40426"
16409
16507
  ];
16410
- var OCEAN_BALANCE = [
16411
- "#00441b",
16412
- "#006d5b",
16413
- "#1a8c7d",
16414
- "#2fa394",
16415
- "#4fb3a3",
16416
- "#6fc1b3",
16417
- "#8dcfc3",
16418
- "#a6dbd1",
16419
- "#bfe6de",
16420
- "#d7f0ea",
16421
- "#f7f7f7",
16422
- "#eeeeee",
16423
- "#ddd8e6",
16424
- "#c7bcda",
16425
- "#b3a0d0",
16426
- "#9f86c7",
16427
- "#8d6dbd",
16428
- "#7b56b1",
16429
- "#6a42a3",
16430
- "#5a3093",
16431
- "#4a1f82",
16432
- "#3b0f70"
16433
- ];
16434
16508
  var reversePalette = (palette) => palette.slice().reverse();
16435
16509
  var DIVERGING_PALETTES = {
16436
16510
  roma: ROMA,
@@ -16442,9 +16516,7 @@ ${lines.join("\n")}`;
16442
16516
  rdbu: RDBU,
16443
16517
  "rdbu-reversed": reversePalette(RDBU),
16444
16518
  coolwarm: COOLWARM,
16445
- "coolwarm-reversed": reversePalette(COOLWARM),
16446
- "ocean-balance": OCEAN_BALANCE,
16447
- "ocean-balance-reversed": reversePalette(OCEAN_BALANCE)
16519
+ "coolwarm-reversed": reversePalette(COOLWARM)
16448
16520
  };
16449
16521
  var TURBO = [
16450
16522
  "#30123b",
@@ -18528,6 +18600,40 @@ ${lines.join("\n")}`;
18528
18600
  "#eeeeee",
18529
18601
  "#ffffff"
18530
18602
  ];
18603
+ var CMOCEAN_PHASE = [
18604
+ "#a8780d",
18605
+ "#b3701b",
18606
+ "#be6828",
18607
+ "#c75f35",
18608
+ "#cf5643",
18609
+ "#d54b53",
18610
+ "#db4066",
18611
+ "#de357b",
18612
+ "#df2a93",
18613
+ "#dc25ad",
18614
+ "#d529c4",
18615
+ "#cc34d7",
18616
+ "#c041e5",
18617
+ "#b24fef",
18618
+ "#a25cf3",
18619
+ "#9168f4",
18620
+ "#7d73f0",
18621
+ "#687ce8",
18622
+ "#5285dc",
18623
+ "#3d8bcd",
18624
+ "#2c90bc",
18625
+ "#2093ac",
18626
+ "#19959c",
18627
+ "#12978c",
18628
+ "#0c987c",
18629
+ "#119a69",
18630
+ "#249a52",
18631
+ "#409839",
18632
+ "#5e9420",
18633
+ "#778d12",
18634
+ "#8b860d",
18635
+ "#9b7f0d"
18636
+ ];
18531
18637
  var reversePalette2 = (palette) => palette.slice().reverse();
18532
18638
  var SEQUENTIAL_PALETTES = {
18533
18639
  turbo: TURBO,
@@ -18551,7 +18657,9 @@ ${lines.join("\n")}`;
18551
18657
  "rocket-reversed": reversePalette2(ROCKET),
18552
18658
  mako: MAKO,
18553
18659
  // blue to teal
18554
- "mako-reversed": reversePalette2(MAKO)
18660
+ "mako-reversed": reversePalette2(MAKO),
18661
+ "cmocean-phase": CMOCEAN_PHASE,
18662
+ "cmocean-phase-reversed": reversePalette2(CMOCEAN_PHASE)
18555
18663
  };
18556
18664
 
18557
18665
  // src/compute-engine/numerics/special-functions.ts
@@ -19451,12 +19559,21 @@ ${lines.join("\n")}`;
19451
19559
  Abs: (args, compile2) => {
19452
19560
  if (BaseCompiler.isComplexValued(args[0]))
19453
19561
  return `_SYS.cabs(${compile2(args[0])})`;
19562
+ if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
19454
19563
  return `Math.abs(${compile2(args[0])})`;
19455
19564
  },
19456
19565
  Add: (args, compile2) => {
19457
19566
  if (args.length === 1) return compile2(args[0]);
19458
19567
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
19459
- if (!anyComplex) return `(${args.map((x) => compile2(x)).join(" + ")})`;
19568
+ if (!anyComplex) {
19569
+ const constants = args.map(tryGetConstant);
19570
+ if (constants.every((c) => c !== void 0))
19571
+ return String(constants.reduce((a, b) => a + b, 0));
19572
+ const nonZero = args.filter((a) => tryGetConstant(a) !== 0);
19573
+ if (nonZero.length === 0) return "0";
19574
+ if (nonZero.length === 1) return compile2(nonZero[0]);
19575
+ return `(${nonZero.map((x) => compile2(x)).join(" + ")})`;
19576
+ }
19460
19577
  const parts = args.map((a) => {
19461
19578
  const code = compile2(a);
19462
19579
  return { code, isComplex: BaseCompiler.isComplexValued(a) };
@@ -19513,7 +19630,10 @@ ${lines.join("\n")}`;
19513
19630
  return `Math.atan(${compile2(args[0])})`;
19514
19631
  },
19515
19632
  Artanh: "Math.atanh",
19516
- Ceil: "Math.ceil",
19633
+ Ceil: (args, compile2) => {
19634
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19635
+ return `Math.ceil(${compile2(args[0])})`;
19636
+ },
19517
19637
  Chop: "_SYS.chop",
19518
19638
  Cos: (args, compile2) => {
19519
19639
  if (BaseCompiler.isComplexValued(args[0]))
@@ -19556,7 +19676,10 @@ ${lines.join("\n")}`;
19556
19676
  return `_SYS.cexp(${compile2(args[0])})`;
19557
19677
  return `Math.exp(${compile2(args[0])})`;
19558
19678
  },
19559
- Floor: "Math.floor",
19679
+ Floor: (args, compile2) => {
19680
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19681
+ return `Math.floor(${compile2(args[0])})`;
19682
+ },
19560
19683
  Fract: ([x], compile2) => {
19561
19684
  if (x === null) throw new Error("Fract: no argument");
19562
19685
  return BaseCompiler.inlineExpression("${x} - Math.floor(${x})", compile2(x));
@@ -19652,12 +19775,20 @@ ${lines.join("\n")}`;
19652
19775
  if (BaseCompiler.isComplexValued(base) || BaseCompiler.isComplexValued(exp3)) {
19653
19776
  return `_SYS.cpow(${compile2(base)}, ${compile2(exp3)})`;
19654
19777
  }
19655
- const expVal = exp3.re;
19656
- if (expVal === 0.5) return `Math.sqrt(${compile2(base)})`;
19657
- if (expVal === 1 / 3) return `Math.cbrt(${compile2(base)})`;
19658
- if (expVal === 1) return compile2(base);
19659
- if (expVal === -1) return `(1 / (${compile2(base)}))`;
19660
- if (expVal === -0.5) return `(1 / Math.sqrt(${compile2(base)}))`;
19778
+ const bConst = tryGetConstant(base);
19779
+ const eConst = tryGetConstant(exp3);
19780
+ if (bConst !== void 0 && eConst !== void 0)
19781
+ return String(Math.pow(bConst, eConst));
19782
+ if (eConst === 0) return "1";
19783
+ if (eConst === 1) return compile2(base);
19784
+ if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
19785
+ const code = compile2(base);
19786
+ return `(${code} * ${code})`;
19787
+ }
19788
+ if (eConst === -1) return `(1 / (${compile2(base)}))`;
19789
+ if (eConst === 0.5) return `Math.sqrt(${compile2(base)})`;
19790
+ if (eConst === 1 / 3) return `Math.cbrt(${compile2(base)})`;
19791
+ if (eConst === -0.5) return `(1 / Math.sqrt(${compile2(base)}))`;
19661
19792
  return `Math.pow(${compile2(base)}, ${compile2(exp3)})`;
19662
19793
  },
19663
19794
  Range: (args, compile2) => {
@@ -19694,16 +19825,29 @@ ${lines.join("\n")}`;
19694
19825
  Root: ([arg, exp3], compile2) => {
19695
19826
  if (arg === null) throw new Error("Root: no argument");
19696
19827
  if (exp3 === null) return `Math.sqrt(${compile2(arg)})`;
19697
- if (exp3?.re === 2) return `Math.sqrt(${compile2(arg)})`;
19698
- if (exp3?.re === 3) return `Math.cbrt(${compile2(arg)})`;
19699
- if (!isNaN(exp3?.re)) return `Math.pow(${compile2(arg)}, ${1 / exp3.re})`;
19828
+ const aConst = tryGetConstant(arg);
19829
+ const nConst = tryGetConstant(exp3);
19830
+ if (aConst !== void 0 && nConst !== void 0 && nConst !== 0)
19831
+ return String(Math.pow(aConst, 1 / nConst));
19832
+ if (nConst === 2) return `Math.sqrt(${compile2(arg)})`;
19833
+ if (nConst === 3) return `Math.cbrt(${compile2(arg)})`;
19834
+ if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
19700
19835
  return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
19701
19836
  },
19702
19837
  Random: "Math.random",
19703
- Round: "Math.round",
19838
+ Round: (args, compile2) => {
19839
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19840
+ return `Math.round(${compile2(args[0])})`;
19841
+ },
19704
19842
  Square: (args, compile2) => {
19705
19843
  const arg = args[0];
19706
19844
  if (arg === null) throw new Error("Square: no argument");
19845
+ const c = tryGetConstant(arg);
19846
+ if (c !== void 0) return String(c * c);
19847
+ if (isSymbol2(arg)) {
19848
+ const code = compile2(arg);
19849
+ return `(${code} * ${code})`;
19850
+ }
19707
19851
  return `Math.pow(${compile2(arg)}, 2)`;
19708
19852
  },
19709
19853
  Sec: (args, compile2) => {
@@ -19736,6 +19880,8 @@ ${lines.join("\n")}`;
19736
19880
  Sqrt: (args, compile2) => {
19737
19881
  if (BaseCompiler.isComplexValued(args[0]))
19738
19882
  return `_SYS.csqrt(${compile2(args[0])})`;
19883
+ const c = tryGetConstant(args[0]);
19884
+ if (c !== void 0) return String(Math.sqrt(c));
19739
19885
  return `Math.sqrt(${compile2(args[0])})`;
19740
19886
  },
19741
19887
  Tan: (args, compile2) => {
@@ -19752,9 +19898,14 @@ ${lines.join("\n")}`;
19752
19898
  if (a === null || b === null) throw new Error("Mod: missing argument");
19753
19899
  const ca = compile2(a);
19754
19900
  const cb = compile2(b);
19901
+ if (BaseCompiler.isIntegerValued(a) && BaseCompiler.isIntegerValued(b) && BaseCompiler.isNonNegative(a))
19902
+ return `(${ca} % ${cb})`;
19755
19903
  return `((${ca} % ${cb}) + ${cb}) % ${cb}`;
19756
19904
  },
19757
- Truncate: "Math.trunc",
19905
+ Truncate: (args, compile2) => {
19906
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19907
+ return `Math.trunc(${compile2(args[0])})`;
19908
+ },
19758
19909
  Remainder: ([a, b], compile2) => {
19759
19910
  if (a === null || b === null)
19760
19911
  throw new Error("Remainder: missing argument");
@@ -19762,25 +19913,20 @@ ${lines.join("\n")}`;
19762
19913
  a
19763
19914
  )} / ${compile2(b)}))`;
19764
19915
  },
19765
- // Arithmetic operators handled as functions for completeness
19766
- Subtract: ([a, b], compile2) => {
19767
- if (a === null || b === null) throw new Error("Subtract: missing argument");
19768
- const ac = BaseCompiler.isComplexValued(a);
19769
- const bc = BaseCompiler.isComplexValued(b);
19770
- if (!ac && !bc) return `(${compile2(a)} - ${compile2(b)})`;
19771
- const ca = compile2(a);
19772
- const cb = compile2(b);
19773
- const reA = ac ? `(${ca}).re` : ca;
19774
- const imA = ac ? `(${ca}).im` : "0";
19775
- const reB = bc ? `(${cb}).re` : cb;
19776
- const imB = bc ? `(${cb}).im` : "0";
19777
- return `({ re: ${reA} - ${reB}, im: ${imA} - ${imB} })`;
19778
- },
19916
+ // No Subtract function handler Subtract canonicalizes to Add+Negate.
19917
+ // The operator entry in JAVASCRIPT_OPERATORS handles any edge cases.
19779
19918
  Divide: ([a, b], compile2) => {
19780
19919
  if (a === null || b === null) throw new Error("Divide: missing argument");
19781
19920
  const ac = BaseCompiler.isComplexValued(a);
19782
19921
  const bc = BaseCompiler.isComplexValued(b);
19783
- if (!ac && !bc) return `(${compile2(a)} / ${compile2(b)})`;
19922
+ if (!ac && !bc) {
19923
+ const ca = tryGetConstant(a);
19924
+ const cb = tryGetConstant(b);
19925
+ if (ca !== void 0 && cb !== void 0 && cb !== 0)
19926
+ return String(ca / cb);
19927
+ if (cb === 1) return compile2(a);
19928
+ return `(${compile2(a)} / ${compile2(b)})`;
19929
+ }
19784
19930
  if (ac && bc) {
19785
19931
  return `(() => { const _a = ${compile2(a)}, _b = ${compile2(
19786
19932
  b
@@ -19797,13 +19943,26 @@ ${lines.join("\n")}`;
19797
19943
  },
19798
19944
  Negate: ([x], compile2) => {
19799
19945
  if (x === null) throw new Error("Negate: no argument");
19800
- if (!BaseCompiler.isComplexValued(x)) return `(-${compile2(x)})`;
19946
+ if (!BaseCompiler.isComplexValued(x)) {
19947
+ const c = tryGetConstant(x);
19948
+ if (c !== void 0) return String(-c);
19949
+ return `(-${compile2(x)})`;
19950
+ }
19801
19951
  return `_SYS.cneg(${compile2(x)})`;
19802
19952
  },
19803
19953
  Multiply: (args, compile2) => {
19804
19954
  if (args.length === 1) return compile2(args[0]);
19805
19955
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
19806
- if (!anyComplex) return `(${args.map((x) => compile2(x)).join(" * ")})`;
19956
+ if (!anyComplex) {
19957
+ if (args.some((a) => tryGetConstant(a) === 0)) return "0";
19958
+ const constants = args.map(tryGetConstant);
19959
+ if (constants.every((c) => c !== void 0))
19960
+ return String(constants.reduce((a, b) => a * b, 1));
19961
+ const nonOne = args.filter((a) => tryGetConstant(a) !== 1);
19962
+ if (nonOne.length === 0) return "1";
19963
+ if (nonOne.length === 1) return compile2(nonOne[0]);
19964
+ return `(${nonOne.map((x) => compile2(x)).join(" * ")})`;
19965
+ }
19807
19966
  if (args.length === 2) {
19808
19967
  const ac = BaseCompiler.isComplexValued(args[0]);
19809
19968
  const bc = BaseCompiler.isComplexValued(args[1]);
@@ -19888,20 +20047,30 @@ ${lines.join("\n")}`;
19888
20047
  AiryAi: "_SYS.airyAi",
19889
20048
  AiryBi: "_SYS.airyBi",
19890
20049
  // Combinatorics
20050
+ Mandelbrot: ([c, maxIter], compile2) => {
20051
+ if (c === null || maxIter === null)
20052
+ throw new Error("Mandelbrot: missing arguments");
20053
+ return `_SYS.mandelbrot(${compile2(c)}, ${compile2(maxIter)})`;
20054
+ },
20055
+ Julia: ([z, c, maxIter], compile2) => {
20056
+ if (z === null || c === null || maxIter === null)
20057
+ throw new Error("Julia: missing arguments");
20058
+ return `_SYS.julia(${compile2(z)}, ${compile2(c)}, ${compile2(maxIter)})`;
20059
+ },
19891
20060
  Binomial: (args, compile2) => `_SYS.binomial(${compile2(args[0])}, ${compile2(args[1])})`,
19892
20061
  Fibonacci: "_SYS.fibonacci",
19893
20062
  // Complex-specific functions
19894
- Re: (args, compile2) => {
20063
+ Real: (args, compile2) => {
19895
20064
  if (BaseCompiler.isComplexValued(args[0]))
19896
20065
  return `(${compile2(args[0])}).re`;
19897
20066
  return compile2(args[0]);
19898
20067
  },
19899
- Im: (args, compile2) => {
20068
+ Imaginary: (args, compile2) => {
19900
20069
  if (BaseCompiler.isComplexValued(args[0]))
19901
20070
  return `(${compile2(args[0])}).im`;
19902
20071
  return "0";
19903
20072
  },
19904
- Arg: (args, compile2) => {
20073
+ Argument: (args, compile2) => {
19905
20074
  if (BaseCompiler.isComplexValued(args[0]))
19906
20075
  return `_SYS.carg(${compile2(args[0])})`;
19907
20076
  return `(${compile2(args[0])} >= 0 ? 0 : Math.PI)`;
@@ -20237,6 +20406,41 @@ ${lines.join("\n")}`;
20237
20406
  sinc,
20238
20407
  fresnelS,
20239
20408
  fresnelC,
20409
+ mandelbrot: (c, maxIter) => {
20410
+ let zx = 0, zy = 0;
20411
+ const cx = typeof c === "number" ? c : c.re;
20412
+ const cy = typeof c === "number" ? 0 : c.im;
20413
+ const n = Math.round(maxIter);
20414
+ for (let i = 0; i < n; i++) {
20415
+ const newZx = zx * zx - zy * zy + cx;
20416
+ zy = 2 * zx * zy + cy;
20417
+ zx = newZx;
20418
+ const mag2 = zx * zx + zy * zy;
20419
+ if (mag2 > 4) {
20420
+ const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
20421
+ return Math.max(0, Math.min(1, smooth));
20422
+ }
20423
+ }
20424
+ return 1;
20425
+ },
20426
+ julia: (z, c, maxIter) => {
20427
+ let zx = typeof z === "number" ? z : z.re;
20428
+ let zy = typeof z === "number" ? 0 : z.im;
20429
+ const cx = typeof c === "number" ? c : c.re;
20430
+ const cy = typeof c === "number" ? 0 : c.im;
20431
+ const n = Math.round(maxIter);
20432
+ for (let i = 0; i < n; i++) {
20433
+ const newZx = zx * zx - zy * zy + cx;
20434
+ zy = 2 * zx * zy + cy;
20435
+ zx = newZx;
20436
+ const mag2 = zx * zx + zy * zy;
20437
+ if (mag2 > 4) {
20438
+ const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
20439
+ return Math.max(0, Math.min(1, smooth));
20440
+ }
20441
+ }
20442
+ return 1;
20443
+ },
20240
20444
  binomial: choose,
20241
20445
  fibonacci,
20242
20446
  // Complex helpers
@@ -20577,11 +20781,39 @@ ${lines.join("\n")}`;
20577
20781
  return b;
20578
20782
  }
20579
20783
 
20784
+ // src/compute-engine/compilation/fractal-orbit.ts
20785
+ function computeReferenceOrbit(center, maxIter, precision) {
20786
+ const prevPrecision = BigDecimal.precision;
20787
+ BigDecimal.precision = precision;
20788
+ try {
20789
+ const cr = new BigDecimal(center[0]);
20790
+ const ci = new BigDecimal(center[1]);
20791
+ let zr = BigDecimal.ZERO;
20792
+ let zi = BigDecimal.ZERO;
20793
+ const ESCAPE = new BigDecimal(256);
20794
+ const points = [];
20795
+ for (let i = 0; i < maxIter; i++) {
20796
+ points.push(zr.toNumber(), zi.toNumber());
20797
+ const zr2 = zr.mul(zr).toPrecision(precision);
20798
+ const zi2 = zi.mul(zi).toPrecision(precision);
20799
+ const mag2 = zr2.add(zi2);
20800
+ if (mag2.cmp(ESCAPE) > 0) break;
20801
+ const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
20802
+ zr = zr2.sub(zi2).add(cr);
20803
+ zi = new_zi;
20804
+ }
20805
+ return new Float32Array(points);
20806
+ } finally {
20807
+ BigDecimal.precision = prevPrecision;
20808
+ }
20809
+ }
20810
+
20580
20811
  // src/compute-engine/compilation/gpu-target.ts
20581
20812
  var GPU_OPERATORS = {
20582
20813
  Add: ["+", 11],
20583
20814
  Negate: ["-", 14],
20584
20815
  Subtract: ["-", 11],
20816
+ // Subtract canonicalizes to Add+Negate; kept as fallback
20585
20817
  Multiply: ["*", 12],
20586
20818
  Divide: ["/", 13],
20587
20819
  Equal: ["==", 8],
@@ -20597,6 +20829,12 @@ ${lines.join("\n")}`;
20597
20829
  function gpuVec2(target) {
20598
20830
  return target?.language === "wgsl" ? "vec2f" : "vec2";
20599
20831
  }
20832
+ function compileIntArg(expr, compile2, target) {
20833
+ const c = tryGetConstant(expr);
20834
+ if (c !== void 0 && Number.isInteger(c)) return c.toString();
20835
+ const intCast = target?.language === "wgsl" ? "i32" : "int";
20836
+ return `${intCast}(${compile2(expr)})`;
20837
+ }
20600
20838
  var GPU_UNROLL_LIMIT = 100;
20601
20839
  function compileGPUSumProduct(kind, args, _compile, target) {
20602
20840
  if (!args[0]) throw new Error(`${kind}: no body`);
@@ -20653,94 +20891,126 @@ ${lines.join("\n")}`;
20653
20891
  ];
20654
20892
  return lines.join("\n");
20655
20893
  }
20894
+ function selectFractalStrategy(target) {
20895
+ const radius = target.hints?.viewport?.radius;
20896
+ if (radius === void 0) return "single";
20897
+ if (radius > 1e-6) return "single";
20898
+ if (radius > 1e-14) return "double";
20899
+ return "perturbation";
20900
+ }
20656
20901
  var GPU_FUNCTIONS = {
20657
20902
  // Variadic arithmetic (for function-call form, e.g., with vectors)
20658
20903
  Add: (args, compile2, target) => {
20659
20904
  if (args.length === 0) return "0.0";
20660
20905
  if (args.length === 1) return compile2(args[0]);
20661
20906
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20662
- if (!anyComplex) return args.map((x) => compile2(x)).join(" + ");
20663
- const v2 = gpuVec2(target);
20664
- return args.map((a) => {
20665
- const code = compile2(a);
20666
- return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20667
- }).join(" + ");
20668
- },
20669
- Multiply: (args, compile2, _target) => {
20670
- if (args.length === 0) return "1.0";
20671
- if (args.length === 1) return compile2(args[0]);
20672
- const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20673
- if (!anyComplex) return args.map((x) => compile2(x)).join(" * ");
20674
- let result = compile2(args[0]);
20675
- let resultIsComplex = BaseCompiler.isComplexValued(args[0]);
20676
- for (let i = 1; i < args.length; i++) {
20677
- const code = compile2(args[i]);
20678
- const argIsComplex = BaseCompiler.isComplexValued(args[i]);
20679
- if (!resultIsComplex && !argIsComplex) {
20680
- result = `(${result} * ${code})`;
20681
- } else if (resultIsComplex && !argIsComplex) {
20682
- result = `(${code} * ${result})`;
20683
- } else if (!resultIsComplex && argIsComplex) {
20684
- result = `(${result} * ${code})`;
20685
- resultIsComplex = true;
20686
- } else {
20687
- result = `_gpu_cmul(${result}, ${code})`;
20688
- }
20907
+ if (!anyComplex) {
20908
+ return foldTerms(
20909
+ args.map((x) => compile2(x)),
20910
+ "0.0",
20911
+ "+"
20912
+ );
20689
20913
  }
20690
- return result;
20691
- },
20692
- Subtract: (args, compile2, target) => {
20693
- if (args.length === 0) return "0.0";
20914
+ const parts = args.map((a) => tryGetComplexParts(a, compile2));
20915
+ if (parts.some((p) => p === null)) {
20916
+ const v2 = gpuVec2(target);
20917
+ return args.map((a) => {
20918
+ const code = compile2(a);
20919
+ return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20920
+ }).join(" + ");
20921
+ }
20922
+ const reParts = [];
20923
+ const imParts = [];
20924
+ for (const p of parts) {
20925
+ if (p.re !== null) reParts.push(p.re);
20926
+ if (p.im !== null) imParts.push(p.im);
20927
+ }
20928
+ const reSum = foldTerms(reParts, "0.0", "+");
20929
+ const imSum = foldTerms(imParts, "0.0", "+");
20930
+ return `${gpuVec2(target)}(${reSum}, ${imSum})`;
20931
+ },
20932
+ Multiply: (args, compile2, target) => {
20933
+ if (args.length === 0) return "1.0";
20694
20934
  if (args.length === 1) return compile2(args[0]);
20695
20935
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20696
20936
  if (!anyComplex) {
20697
- if (args.length === 2) return `${compile2(args[0])} - ${compile2(args[1])}`;
20698
- let result2 = compile2(args[0]);
20699
- for (let i = 1; i < args.length; i++) {
20700
- result2 = `${result2} - ${compile2(args[i])}`;
20701
- }
20702
- return result2;
20703
- }
20704
- const v2 = gpuVec2(target);
20705
- const promote = (a) => {
20706
- const code = compile2(a);
20707
- return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20708
- };
20709
- if (args.length === 2) return `${promote(args[0])} - ${promote(args[1])}`;
20710
- let result = promote(args[0]);
20711
- for (let i = 1; i < args.length; i++) {
20712
- result = `${result} - ${promote(args[i])}`;
20937
+ return foldTerms(
20938
+ args.map((x) => compile2(x)),
20939
+ "1.0",
20940
+ "*"
20941
+ );
20713
20942
  }
20943
+ const iIndex = args.findIndex(
20944
+ (op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
20945
+ );
20946
+ if (iIndex >= 0) {
20947
+ const iFactor = args[iIndex];
20948
+ const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
20949
+ const realFactors = args.filter((_, i) => i !== iIndex);
20950
+ const v2 = gpuVec2(target);
20951
+ if (realFactors.length === 0)
20952
+ return `${v2}(0.0, ${formatFloat(iScale)})`;
20953
+ const factors = realFactors.map((f) => compile2(f));
20954
+ if (iScale !== 1) factors.unshift(formatFloat(iScale));
20955
+ const imCode = foldTerms(factors, "1.0", "*");
20956
+ return `${v2}(0.0, ${imCode})`;
20957
+ }
20958
+ const realCodes = [];
20959
+ const complexCodes = [];
20960
+ for (const a of args) {
20961
+ if (BaseCompiler.isComplexValued(a)) complexCodes.push(compile2(a));
20962
+ else realCodes.push(compile2(a));
20963
+ }
20964
+ const scalarCode = foldTerms(realCodes, "1.0", "*");
20965
+ let result = complexCodes[0];
20966
+ for (let i = 1; i < complexCodes.length; i++) {
20967
+ result = `_gpu_cmul(${result}, ${complexCodes[i]})`;
20968
+ }
20969
+ if (scalarCode !== "1.0") result = `(${scalarCode} * ${result})`;
20714
20970
  return result;
20715
20971
  },
20972
+ // No Subtract function handler — Subtract canonicalizes to Add+Negate.
20973
+ // The operator entry in GPU_OPERATORS handles any edge cases.
20716
20974
  Divide: (args, compile2, target) => {
20717
20975
  if (args.length === 0) return "1.0";
20718
20976
  if (args.length === 1) return compile2(args[0]);
20719
20977
  const ac = BaseCompiler.isComplexValued(args[0]);
20720
20978
  const bc = args.length >= 2 && BaseCompiler.isComplexValued(args[1]);
20721
20979
  if (!ac && !bc) {
20722
- if (args.length === 2) return `${compile2(args[0])} / ${compile2(args[1])}`;
20980
+ if (args.length === 2) {
20981
+ const a = tryGetConstant(args[0]);
20982
+ const b = tryGetConstant(args[1]);
20983
+ if (a !== void 0 && b !== void 0 && b !== 0)
20984
+ return formatFloat(a / b);
20985
+ if (b === 1) return compile2(args[0]);
20986
+ return `${compile2(args[0])} / ${compile2(args[1])}`;
20987
+ }
20723
20988
  let result = compile2(args[0]);
20724
- for (let i = 1; i < args.length; i++) {
20989
+ for (let i = 1; i < args.length; i++)
20725
20990
  result = `${result} / ${compile2(args[i])}`;
20726
- }
20727
20991
  return result;
20728
20992
  }
20729
20993
  if (ac && bc) return `_gpu_cdiv(${compile2(args[0])}, ${compile2(args[1])})`;
20730
- if (ac && !bc) {
20731
- return `(${compile2(args[0])} / ${compile2(args[1])})`;
20732
- }
20994
+ if (ac && !bc) return `(${compile2(args[0])} / ${compile2(args[1])})`;
20733
20995
  const v2 = gpuVec2(target);
20734
20996
  return `_gpu_cdiv(${v2}(${compile2(args[0])}, 0.0), ${compile2(args[1])})`;
20735
20997
  },
20736
- Negate: ([x], compile2) => {
20998
+ Negate: ([x], compile2, target) => {
20737
20999
  if (x === null) throw new Error("Negate: no argument");
21000
+ const c = tryGetConstant(x);
21001
+ if (c !== void 0) return formatFloat(-c);
21002
+ if (isNumber(x) && x.im !== 0) {
21003
+ return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
21004
+ }
21005
+ if (isSymbol2(x, "ImaginaryUnit"))
21006
+ return `${gpuVec2(target)}(0.0, -1.0)`;
20738
21007
  return `(-${compile2(x)})`;
20739
21008
  },
20740
21009
  // Standard math functions with complex dispatch
20741
21010
  Abs: (args, compile2) => {
20742
21011
  if (BaseCompiler.isComplexValued(args[0]))
20743
21012
  return `length(${compile2(args[0])})`;
21013
+ if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
20744
21014
  return `abs(${compile2(args[0])})`;
20745
21015
  },
20746
21016
  Arccos: (args, compile2) => {
@@ -20758,7 +21028,10 @@ ${lines.join("\n")}`;
20758
21028
  return `_gpu_catan(${compile2(args[0])})`;
20759
21029
  return `atan(${compile2(args[0])})`;
20760
21030
  },
20761
- Ceil: "ceil",
21031
+ Ceil: (args, compile2) => {
21032
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21033
+ return `ceil(${compile2(args[0])})`;
21034
+ },
20762
21035
  Clamp: "clamp",
20763
21036
  Cos: (args, compile2) => {
20764
21037
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20772,7 +21045,10 @@ ${lines.join("\n")}`;
20772
21045
  return `exp(${compile2(args[0])})`;
20773
21046
  },
20774
21047
  Exp2: "exp2",
20775
- Floor: "floor",
21048
+ Floor: (args, compile2) => {
21049
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21050
+ return `floor(${compile2(args[0])})`;
21051
+ },
20776
21052
  Fract: "fract",
20777
21053
  Ln: (args, compile2) => {
20778
21054
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20794,10 +21070,25 @@ ${lines.join("\n")}`;
20794
21070
  const eCode = BaseCompiler.isComplexValued(exp3) ? compile2(exp3) : `${v2}(${compile2(exp3)}, 0.0)`;
20795
21071
  return `_gpu_cpow(${bCode}, ${eCode})`;
20796
21072
  }
21073
+ const bConst = tryGetConstant(base);
21074
+ const eConst = tryGetConstant(exp3);
21075
+ if (bConst !== void 0 && eConst !== void 0)
21076
+ return formatFloat(Math.pow(bConst, eConst));
21077
+ if (eConst === 0) return "1.0";
21078
+ if (eConst === 1) return compile2(base);
21079
+ if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
21080
+ const code = compile2(base);
21081
+ return `(${code} * ${code})`;
21082
+ }
21083
+ if (eConst === -1) return `(1.0 / ${compile2(base)})`;
21084
+ if (eConst === 0.5) return `sqrt(${compile2(base)})`;
20797
21085
  return `pow(${compile2(base)}, ${compile2(exp3)})`;
20798
21086
  },
20799
21087
  Radians: "radians",
20800
- Round: "round",
21088
+ Round: (args, compile2) => {
21089
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21090
+ return `round(${compile2(args[0])})`;
21091
+ },
20801
21092
  Sign: "sign",
20802
21093
  Sin: (args, compile2) => {
20803
21094
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20808,6 +21099,8 @@ ${lines.join("\n")}`;
20808
21099
  Sqrt: (args, compile2) => {
20809
21100
  if (BaseCompiler.isComplexValued(args[0]))
20810
21101
  return `_gpu_csqrt(${compile2(args[0])})`;
21102
+ const c = tryGetConstant(args[0]);
21103
+ if (c !== void 0) return formatFloat(Math.sqrt(c));
20811
21104
  return `sqrt(${compile2(args[0])})`;
20812
21105
  },
20813
21106
  Step: "step",
@@ -20816,17 +21109,20 @@ ${lines.join("\n")}`;
20816
21109
  return `_gpu_ctan(${compile2(args[0])})`;
20817
21110
  return `tan(${compile2(args[0])})`;
20818
21111
  },
20819
- Truncate: "trunc",
21112
+ Truncate: (args, compile2) => {
21113
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21114
+ return `trunc(${compile2(args[0])})`;
21115
+ },
20820
21116
  // Complex-specific functions
20821
- Re: (args, compile2) => {
21117
+ Real: (args, compile2) => {
20822
21118
  if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).x`;
20823
21119
  return compile2(args[0]);
20824
21120
  },
20825
- Im: (args, compile2) => {
21121
+ Imaginary: (args, compile2) => {
20826
21122
  if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).y`;
20827
21123
  return "0.0";
20828
21124
  },
20829
- Arg: (args, compile2) => {
21125
+ Argument: (args, compile2) => {
20830
21126
  if (BaseCompiler.isComplexValued(args[0])) {
20831
21127
  const code = compile2(args[0]);
20832
21128
  return `atan(${code}.y, ${code}.x)`;
@@ -21041,13 +21337,20 @@ ${lines.join("\n")}`;
21041
21337
  },
21042
21338
  Square: ([x], compile2) => {
21043
21339
  if (x === null) throw new Error("Square: no argument");
21044
- const arg = compile2(x);
21045
- return `(${arg} * ${arg})`;
21340
+ if (isSymbol2(x) || isNumber(x)) {
21341
+ const arg = compile2(x);
21342
+ return `(${arg} * ${arg})`;
21343
+ }
21344
+ return `pow(${compile2(x)}, 2.0)`;
21046
21345
  },
21047
21346
  Root: ([x, n], compile2) => {
21048
21347
  if (x === null) throw new Error("Root: no argument");
21049
21348
  if (n === null || n === void 0) return `sqrt(${compile2(x)})`;
21050
- if (n?.re === 2) return `sqrt(${compile2(x)})`;
21349
+ const nConst = tryGetConstant(n);
21350
+ if (nConst === 2) return `sqrt(${compile2(x)})`;
21351
+ const xConst = tryGetConstant(x);
21352
+ if (xConst !== void 0 && nConst !== void 0)
21353
+ return formatFloat(Math.pow(xConst, 1 / nConst));
21051
21354
  return `pow(${compile2(x)}, 1.0 / ${compile2(n)})`;
21052
21355
  },
21053
21356
  // Color functions (pure-math, GPU-compilable)
@@ -21089,18 +21392,34 @@ ${lines.join("\n")}`;
21089
21392
  Mandelbrot: ([c, maxIter], compile2, target) => {
21090
21393
  if (c === null || maxIter === null)
21091
21394
  throw new Error("Mandelbrot: missing arguments");
21092
- const intCast = target?.language === "wgsl" ? "i32" : "int";
21093
- return `_fractal_mandelbrot(${compile2(c)}, ${intCast}(${compile2(
21094
- maxIter
21095
- )}))`;
21395
+ const iterCode = compileIntArg(maxIter, compile2, target);
21396
+ const strategy = selectFractalStrategy(target);
21397
+ if (strategy === "double") {
21398
+ const cCode = compile2(c);
21399
+ return `_fractal_mandelbrot_dp(vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21400
+ }
21401
+ if (strategy === "perturbation") {
21402
+ const cCode = compile2(c);
21403
+ return `_fractal_mandelbrot_pt(${cCode}, ${iterCode})`;
21404
+ }
21405
+ return `_fractal_mandelbrot(${compile2(c)}, ${iterCode})`;
21096
21406
  },
21097
21407
  Julia: ([z, c, maxIter], compile2, target) => {
21098
21408
  if (z === null || c === null || maxIter === null)
21099
21409
  throw new Error("Julia: missing arguments");
21100
- const intCast = target?.language === "wgsl" ? "i32" : "int";
21101
- return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${intCast}(${compile2(
21102
- maxIter
21103
- )}))`;
21410
+ const iterCode = compileIntArg(maxIter, compile2, target);
21411
+ const strategy = selectFractalStrategy(target);
21412
+ if (strategy === "double") {
21413
+ const zCode = compile2(z);
21414
+ const cCode = compile2(c);
21415
+ return `_fractal_julia_dp(vec4(${zCode}, vec2(0.0)), vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21416
+ }
21417
+ if (strategy === "perturbation") {
21418
+ const zCode = compile2(z);
21419
+ const cCode = compile2(c);
21420
+ return `_fractal_julia_pt(${zCode}, ${cCode}, ${iterCode})`;
21421
+ }
21422
+ return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${iterCode})`;
21104
21423
  },
21105
21424
  // Vector/Matrix operations
21106
21425
  Cross: "cross",
@@ -21696,6 +22015,200 @@ fn _gpu_besselJ(n_in: i32, x_in: f32) -> f32 {
21696
22015
  for (var k2: i32 = 2; k2 <= M; k2 += 2) { norm += 2.0 * vals[k2]; }
21697
22016
  return sgn * vals[n] / norm;
21698
22017
  }
22018
+ `;
22019
+ var GPU_DS_ARITHMETIC_PREAMBLE_GLSL = `
22020
+ // Split a float into high and low parts for exact multiplication
22021
+ vec2 ds_split(float a) {
22022
+ const float SPLIT = 4097.0; // 2^12 + 1
22023
+ float t = SPLIT * a;
22024
+ float hi = t - (t - a);
22025
+ float lo = a - hi;
22026
+ return vec2(hi, lo);
22027
+ }
22028
+
22029
+ // Create a double-single from a single float
22030
+ vec2 ds_from(float a) {
22031
+ return vec2(a, 0.0);
22032
+ }
22033
+
22034
+ // Error-free addition (Knuth TwoSum)
22035
+ vec2 ds_add(vec2 a, vec2 b) {
22036
+ float s = a.x + b.x;
22037
+ float v = s - a.x;
22038
+ float e = (a.x - (s - v)) + (b.x - v);
22039
+ float lo = (a.y + b.y) + e;
22040
+ float hi = s + lo;
22041
+ lo = lo - (hi - s);
22042
+ return vec2(hi, lo);
22043
+ }
22044
+
22045
+ // Double-single subtraction
22046
+ vec2 ds_sub(vec2 a, vec2 b) {
22047
+ return ds_add(a, vec2(-b.x, -b.y));
22048
+ }
22049
+
22050
+ // Error-free multiplication (Dekker TwoProduct)
22051
+ vec2 ds_mul(vec2 a, vec2 b) {
22052
+ float p = a.x * b.x;
22053
+ vec2 sa = ds_split(a.x);
22054
+ vec2 sb = ds_split(b.x);
22055
+ float err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22056
+ err += a.x * b.y + a.y * b.x;
22057
+ float hi = p + err;
22058
+ float lo = err - (hi - p);
22059
+ return vec2(hi, lo);
22060
+ }
22061
+
22062
+ // Optimized self-multiply
22063
+ vec2 ds_sqr(vec2 a) {
22064
+ float p = a.x * a.x;
22065
+ vec2 sa = ds_split(a.x);
22066
+ float err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22067
+ err += 2.0 * a.x * a.y;
22068
+ float hi = p + err;
22069
+ float lo = err - (hi - p);
22070
+ return vec2(hi, lo);
22071
+ }
22072
+
22073
+ // Compare magnitude: returns -1, 0, or 1
22074
+ float ds_cmp(vec2 a, vec2 b) {
22075
+ float d = a.x - b.x;
22076
+ if (d != 0.0) return sign(d);
22077
+ return sign(a.y - b.y);
22078
+ }
22079
+ `;
22080
+ var GPU_DS_ARITHMETIC_PREAMBLE_WGSL = `
22081
+ fn ds_split(a: f32) -> vec2f {
22082
+ const SPLIT: f32 = 4097.0;
22083
+ let t = SPLIT * a;
22084
+ let hi = t - (t - a);
22085
+ let lo = a - hi;
22086
+ return vec2f(hi, lo);
22087
+ }
22088
+
22089
+ fn ds_from(a: f32) -> vec2f {
22090
+ return vec2f(a, 0.0);
22091
+ }
22092
+
22093
+ fn ds_add(a: vec2f, b: vec2f) -> vec2f {
22094
+ let s = a.x + b.x;
22095
+ let v = s - a.x;
22096
+ let e = (a.x - (s - v)) + (b.x - v);
22097
+ let lo_t = (a.y + b.y) + e;
22098
+ let hi = s + lo_t;
22099
+ let lo = lo_t - (hi - s);
22100
+ return vec2f(hi, lo);
22101
+ }
22102
+
22103
+ fn ds_sub(a: vec2f, b: vec2f) -> vec2f {
22104
+ return ds_add(a, vec2f(-b.x, -b.y));
22105
+ }
22106
+
22107
+ fn ds_mul(a: vec2f, b: vec2f) -> vec2f {
22108
+ let p = a.x * b.x;
22109
+ let sa = ds_split(a.x);
22110
+ let sb = ds_split(b.x);
22111
+ var err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22112
+ err += a.x * b.y + a.y * b.x;
22113
+ let hi = p + err;
22114
+ let lo = err - (hi - p);
22115
+ return vec2f(hi, lo);
22116
+ }
22117
+
22118
+ fn ds_sqr(a: vec2f) -> vec2f {
22119
+ let p = a.x * a.x;
22120
+ let sa = ds_split(a.x);
22121
+ var err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22122
+ err += 2.0 * a.x * a.y;
22123
+ let hi = p + err;
22124
+ let lo = err - (hi - p);
22125
+ return vec2f(hi, lo);
22126
+ }
22127
+
22128
+ fn ds_cmp(a: vec2f, b: vec2f) -> f32 {
22129
+ let d = a.x - b.x;
22130
+ if (d != 0.0) { return sign(d); }
22131
+ return sign(a.y - b.y);
22132
+ }
22133
+ `;
22134
+ var GPU_FRACTAL_DP_PREAMBLE_GLSL = `
22135
+ float _fractal_mandelbrot_dp(vec4 c, int maxIter) {
22136
+ // c = (re_hi, im_hi, re_lo, im_lo)
22137
+ vec2 cr = vec2(c.x, c.z); // real part as ds
22138
+ vec2 ci = vec2(c.y, c.w); // imag part as ds
22139
+ vec2 zr = vec2(0.0, 0.0);
22140
+ vec2 zi = vec2(0.0, 0.0);
22141
+ for (int i = 0; i < maxIter; i++) {
22142
+ vec2 zr2 = ds_sqr(zr);
22143
+ vec2 zi2 = ds_sqr(zi);
22144
+ // |z|^2 > 4.0 ?
22145
+ vec2 mag2 = ds_add(zr2, zi2);
22146
+ if (mag2.x > 4.0)
22147
+ return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22148
+ // z = z^2 + c
22149
+ vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci); // 2*zr*zi + ci
22150
+ zr = ds_add(ds_sub(zr2, zi2), cr); // zr^2 - zi^2 + cr
22151
+ zi = new_zi;
22152
+ }
22153
+ return 1.0;
22154
+ }
22155
+
22156
+ float _fractal_julia_dp(vec4 z_in, vec4 c, int maxIter) {
22157
+ vec2 zr = vec2(z_in.x, z_in.z);
22158
+ vec2 zi = vec2(z_in.y, z_in.w);
22159
+ vec2 cr = vec2(c.x, c.z);
22160
+ vec2 ci = vec2(c.y, c.w);
22161
+ for (int i = 0; i < maxIter; i++) {
22162
+ vec2 zr2 = ds_sqr(zr);
22163
+ vec2 zi2 = ds_sqr(zi);
22164
+ vec2 mag2 = ds_add(zr2, zi2);
22165
+ if (mag2.x > 4.0)
22166
+ return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22167
+ vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22168
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22169
+ zi = new_zi;
22170
+ }
22171
+ return 1.0;
22172
+ }
22173
+ `;
22174
+ var GPU_FRACTAL_DP_PREAMBLE_WGSL = `
22175
+ fn _fractal_mandelbrot_dp(c: vec4f, maxIter: i32) -> f32 {
22176
+ let cr = vec2f(c.x, c.z);
22177
+ let ci = vec2f(c.y, c.w);
22178
+ var zr = vec2f(0.0, 0.0);
22179
+ var zi = vec2f(0.0, 0.0);
22180
+ for (var i: i32 = 0; i < maxIter; i++) {
22181
+ let zr2 = ds_sqr(zr);
22182
+ let zi2 = ds_sqr(zi);
22183
+ let mag2 = ds_add(zr2, zi2);
22184
+ if (mag2.x > 4.0) {
22185
+ return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22186
+ }
22187
+ let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22188
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22189
+ zi = new_zi;
22190
+ }
22191
+ return 1.0;
22192
+ }
22193
+
22194
+ fn _fractal_julia_dp(z_in: vec4f, c: vec4f, maxIter: i32) -> f32 {
22195
+ var zr = vec2f(z_in.x, z_in.z);
22196
+ var zi = vec2f(z_in.y, z_in.w);
22197
+ let cr = vec2f(c.x, c.z);
22198
+ let ci = vec2f(c.y, c.w);
22199
+ for (var i: i32 = 0; i < maxIter; i++) {
22200
+ let zr2 = ds_sqr(zr);
22201
+ let zi2 = ds_sqr(zi);
22202
+ let mag2 = ds_add(zr2, zi2);
22203
+ if (mag2.x > 4.0) {
22204
+ return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22205
+ }
22206
+ let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22207
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22208
+ zi = new_zi;
22209
+ }
22210
+ return 1.0;
22211
+ }
21699
22212
  `;
21700
22213
  var GPU_FRACTAL_PREAMBLE_GLSL = `
21701
22214
  float _fractal_mandelbrot(vec2 c, int maxIter) {
@@ -21739,6 +22252,188 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
21739
22252
  }
21740
22253
  return 1.0;
21741
22254
  }
22255
+ `;
22256
+ var GPU_FRACTAL_PT_PREAMBLE_GLSL = `
22257
+ uniform sampler2D _refOrbit;
22258
+ uniform int _refOrbitLen;
22259
+ uniform int _refOrbitTexWidth;
22260
+
22261
+ vec2 _pt_fetch_orbit(int i) {
22262
+ int y = i / _refOrbitTexWidth;
22263
+ int x = i - y * _refOrbitTexWidth;
22264
+ return texelFetch(_refOrbit, ivec2(x, y), 0).rg;
22265
+ }
22266
+
22267
+ float _fractal_mandelbrot_pt(vec2 delta_c, int maxIter) {
22268
+ float dr = 0.0;
22269
+ float di = 0.0;
22270
+ int orbitLen = min(maxIter, _refOrbitLen);
22271
+ for (int i = 0; i < orbitLen; i++) {
22272
+ vec2 Zn = _pt_fetch_orbit(i);
22273
+ // delta_{n+1} = 2*Z_n*delta_n + delta_n^2 + delta_c
22274
+ float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22275
+ float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22276
+ dr = new_dr;
22277
+ di = new_di;
22278
+ // Full z = Z_{n+1} + delta for escape check
22279
+ vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22280
+ float zr = Zn1.x + dr;
22281
+ float zi = Zn1.y + di;
22282
+ float mag2 = zr * zr + zi * zi;
22283
+ if (mag2 > 4.0)
22284
+ return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22285
+ // Glitch detection: |delta|^2 > |Z|^2
22286
+ float dmag2 = dr * dr + di * di;
22287
+ float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22288
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22289
+ // Rebase to absolute coordinates and continue with single-float
22290
+ float abs_zr = Zn1.x + dr;
22291
+ float abs_zi = Zn1.y + di;
22292
+ // Reconstruct absolute c from reference + delta
22293
+ // (Use ds_from for the concept, but single-float suffices for fallback)
22294
+ float cx = abs_zr - dr + delta_c.x;
22295
+ float cy = abs_zi - di + delta_c.y;
22296
+ for (int j = i + 1; j < maxIter; j++) {
22297
+ float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22298
+ abs_zi = 2.0 * abs_zr * abs_zi + cy;
22299
+ abs_zr = new_zr;
22300
+ mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22301
+ if (mag2 > 4.0)
22302
+ return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22303
+ }
22304
+ return 1.0;
22305
+ }
22306
+ }
22307
+ return 1.0;
22308
+ }
22309
+
22310
+ float _fractal_julia_pt(vec2 z_delta, vec2 delta_c, int maxIter) {
22311
+ float dr = z_delta.x;
22312
+ float di = z_delta.y;
22313
+ int orbitLen = min(maxIter, _refOrbitLen);
22314
+ for (int i = 0; i < orbitLen; i++) {
22315
+ vec2 Zn = _pt_fetch_orbit(i);
22316
+ float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22317
+ float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22318
+ dr = new_dr;
22319
+ di = new_di;
22320
+ vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22321
+ float zr = Zn1.x + dr;
22322
+ float zi = Zn1.y + di;
22323
+ float mag2 = zr * zr + zi * zi;
22324
+ if (mag2 > 4.0)
22325
+ return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22326
+ float dmag2 = dr * dr + di * di;
22327
+ float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22328
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22329
+ float abs_zr = Zn1.x + dr;
22330
+ float abs_zi = Zn1.y + di;
22331
+ float cx = delta_c.x;
22332
+ float cy = delta_c.y;
22333
+ for (int j = i + 1; j < maxIter; j++) {
22334
+ float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22335
+ abs_zi = 2.0 * abs_zr * abs_zi + cy;
22336
+ abs_zr = new_zr;
22337
+ mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22338
+ if (mag2 > 4.0)
22339
+ return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22340
+ }
22341
+ return 1.0;
22342
+ }
22343
+ }
22344
+ return 1.0;
22345
+ }
22346
+ `;
22347
+ var GPU_FRACTAL_PT_PREAMBLE_WGSL = `
22348
+ @group(0) @binding(1) var _refOrbit: texture_2d<f32>;
22349
+ var<uniform> _refOrbitLen: i32;
22350
+ var<uniform> _refOrbitTexWidth: i32;
22351
+
22352
+ fn _pt_fetch_orbit(i: i32) -> vec2f {
22353
+ let y = i / _refOrbitTexWidth;
22354
+ let x = i - y * _refOrbitTexWidth;
22355
+ return textureLoad(_refOrbit, vec2i(x, y), 0).rg;
22356
+ }
22357
+
22358
+ fn _fractal_mandelbrot_pt(delta_c: vec2f, maxIter: i32) -> f32 {
22359
+ var dr: f32 = 0.0;
22360
+ var di: f32 = 0.0;
22361
+ let orbitLen = min(maxIter, _refOrbitLen);
22362
+ for (var i: i32 = 0; i < orbitLen; i++) {
22363
+ let Zn = _pt_fetch_orbit(i);
22364
+ let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22365
+ let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22366
+ dr = new_dr;
22367
+ di = new_di;
22368
+ var Zn1 = vec2f(0.0);
22369
+ if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22370
+ let zr = Zn1.x + dr;
22371
+ let zi = Zn1.y + di;
22372
+ var mag2 = zr * zr + zi * zi;
22373
+ if (mag2 > 4.0) {
22374
+ return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22375
+ }
22376
+ let dmag2 = dr * dr + di * di;
22377
+ let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22378
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22379
+ var f_zr = Zn1.x + dr;
22380
+ var f_zi = Zn1.y + di;
22381
+ let cx = delta_c.x;
22382
+ let cy = delta_c.y;
22383
+ for (var j: i32 = i + 1; j < maxIter; j++) {
22384
+ let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22385
+ f_zi = 2.0 * f_zr * f_zi + cy;
22386
+ f_zr = t_zr;
22387
+ mag2 = f_zr * f_zr + f_zi * f_zi;
22388
+ if (mag2 > 4.0) {
22389
+ return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22390
+ }
22391
+ }
22392
+ return 1.0;
22393
+ }
22394
+ }
22395
+ return 1.0;
22396
+ }
22397
+
22398
+ fn _fractal_julia_pt(z_delta: vec2f, delta_c: vec2f, maxIter: i32) -> f32 {
22399
+ var dr = z_delta.x;
22400
+ var di = z_delta.y;
22401
+ let orbitLen = min(maxIter, _refOrbitLen);
22402
+ for (var i: i32 = 0; i < orbitLen; i++) {
22403
+ let Zn = _pt_fetch_orbit(i);
22404
+ let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22405
+ let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22406
+ dr = new_dr;
22407
+ di = new_di;
22408
+ var Zn1 = vec2f(0.0);
22409
+ if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22410
+ let zr = Zn1.x + dr;
22411
+ let zi = Zn1.y + di;
22412
+ var mag2 = zr * zr + zi * zi;
22413
+ if (mag2 > 4.0) {
22414
+ return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22415
+ }
22416
+ let dmag2 = dr * dr + di * di;
22417
+ let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22418
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22419
+ var f_zr = Zn1.x + dr;
22420
+ var f_zi = Zn1.y + di;
22421
+ let cx = delta_c.x;
22422
+ let cy = delta_c.y;
22423
+ for (var j: i32 = i + 1; j < maxIter; j++) {
22424
+ let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22425
+ f_zi = 2.0 * f_zr * f_zi + cy;
22426
+ f_zr = t_zr;
22427
+ mag2 = f_zr * f_zr + f_zi * f_zi;
22428
+ if (mag2 > 4.0) {
22429
+ return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22430
+ }
22431
+ }
22432
+ return 1.0;
22433
+ }
22434
+ }
22435
+ return 1.0;
22436
+ }
21742
22437
  `;
21743
22438
  var GPU_COLOR_PREAMBLE_GLSL = `
21744
22439
  float _gpu_srgb_to_linear(float c) {
@@ -22178,6 +22873,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22178
22873
  const constants = this.getConstants();
22179
22874
  const v2 = this.languageId === "wgsl" ? "vec2f" : "vec2";
22180
22875
  const target = this.createTarget({
22876
+ hints: options.hints,
22181
22877
  functions: (id) => {
22182
22878
  if (userFunctions && id in userFunctions) {
22183
22879
  const fn = userFunctions[id];
@@ -22216,12 +22912,65 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22216
22912
  if (code.includes("_gpu_besselJ"))
22217
22913
  preamble += this.languageId === "wgsl" ? GPU_BESSELJ_PREAMBLE_WGSL : GPU_BESSELJ_PREAMBLE_GLSL;
22218
22914
  if (code.includes("_fractal_")) {
22219
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22915
+ if (code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) {
22916
+ preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22917
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PT_PREAMBLE_WGSL : GPU_FRACTAL_PT_PREAMBLE_GLSL;
22918
+ } else if (code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) {
22919
+ preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22920
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_DP_PREAMBLE_WGSL : GPU_FRACTAL_DP_PREAMBLE_GLSL;
22921
+ } else {
22922
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22923
+ }
22220
22924
  }
22221
22925
  if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
22222
22926
  preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
22223
22927
  }
22224
22928
  if (preamble) result.preamble = preamble;
22929
+ if (code.includes("_fractal_") && options.hints?.viewport) {
22930
+ const strategy = selectFractalStrategy(target);
22931
+ const radius = options.hints.viewport.radius;
22932
+ switch (strategy) {
22933
+ case "single":
22934
+ result.staleWhen = { radiusBelow: 1e-6 };
22935
+ break;
22936
+ case "double":
22937
+ result.staleWhen = { radiusBelow: 1e-14, radiusAbove: 1e-5 };
22938
+ break;
22939
+ case "perturbation":
22940
+ result.staleWhen = {
22941
+ radiusAbove: 1e-5,
22942
+ radiusBelow: radius * 0.01,
22943
+ centerDistance: radius * 2
22944
+ };
22945
+ break;
22946
+ }
22947
+ }
22948
+ if ((code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) && options.hints?.viewport) {
22949
+ const viewport = options.hints.viewport;
22950
+ const digits = Math.max(50, Math.ceil(-Math.log10(viewport.radius)) + 10);
22951
+ const maxIter = 1e3;
22952
+ const orbit = computeReferenceOrbit(
22953
+ viewport.center,
22954
+ maxIter,
22955
+ digits
22956
+ );
22957
+ const orbitLen = orbit.length / 2;
22958
+ const texWidth = Math.min(orbitLen, 4096);
22959
+ const texHeight = Math.ceil(orbitLen / texWidth);
22960
+ result.textures = {
22961
+ _refOrbit: {
22962
+ data: orbit,
22963
+ width: texWidth,
22964
+ height: texHeight,
22965
+ format: "rg32f"
22966
+ }
22967
+ };
22968
+ result.uniforms = {
22969
+ ...result.uniforms,
22970
+ _refOrbitLen: orbitLen,
22971
+ _refOrbitTexWidth: texWidth
22972
+ };
22973
+ }
22225
22974
  return result;
22226
22975
  }
22227
22976
  compileToSource(expr, _options = {}) {
@@ -22455,6 +23204,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
22455
23204
  Negate: ["-", 14],
22456
23205
  // Unary operator
22457
23206
  Subtract: ["-", 11],
23207
+ // Subtract canonicalizes to Add+Negate; kept as fallback
22458
23208
  Multiply: ["*", 12],
22459
23209
  Divide: ["/", 13],
22460
23210
  Power: ["**", 15],
@@ -22482,16 +23232,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
22482
23232
  if (args.length === 1) return compile2(args[0]);
22483
23233
  return args.map((x) => compile2(x)).join(" * ");
22484
23234
  },
22485
- Subtract: (args, compile2) => {
22486
- if (args.length === 0) return "0";
22487
- if (args.length === 1) return compile2(args[0]);
22488
- if (args.length === 2) return `${compile2(args[0])} - ${compile2(args[1])}`;
22489
- let result = compile2(args[0]);
22490
- for (let i = 1; i < args.length; i++) {
22491
- result = `${result} - ${compile2(args[i])}`;
22492
- }
22493
- return result;
22494
- },
23235
+ // No Subtract handler canonicalizes to Add+Negate before compilation.
22495
23236
  Divide: (args, compile2) => {
22496
23237
  if (args.length === 0) return "1";
22497
23238
  if (args.length === 1) return compile2(args[0]);
@@ -24156,6 +24897,7 @@ ${code}`;
24156
24897
  Add: ["_IA.add", 20],
24157
24898
  Negate: ["_IA.negate", 20],
24158
24899
  Subtract: ["_IA.sub", 20],
24900
+ // Subtract canonicalizes to Add+Negate; kept as fallback
24159
24901
  Multiply: ["_IA.mul", 20],
24160
24902
  Divide: ["_IA.div", 20],
24161
24903
  // Comparisons return BoolInterval
@@ -24180,17 +24922,7 @@ ${code}`;
24180
24922
  }
24181
24923
  return result;
24182
24924
  },
24183
- Subtract: (args, compile2) => {
24184
- if (args.length === 0) return "_IA.point(0)";
24185
- if (args.length === 1) return `_IA.negate(${compile2(args[0])})`;
24186
- if (args.length === 2)
24187
- return `_IA.sub(${compile2(args[0])}, ${compile2(args[1])})`;
24188
- let result = compile2(args[0]);
24189
- for (let i = 1; i < args.length; i++) {
24190
- result = `_IA.sub(${result}, ${compile2(args[i])})`;
24191
- }
24192
- return result;
24193
- },
24925
+ // No Subtract handler canonicalizes to Add+Negate before compilation.
24194
24926
  Multiply: (args, compile2) => {
24195
24927
  if (args.length === 0) return "_IA.point(1)";
24196
24928
  if (args.length === 1) return compile2(args[0]);
@@ -24573,7 +25305,7 @@ ${code}`;
24573
25305
  }
24574
25306
 
24575
25307
  // src/compile.ts
24576
- var version = "0.55.2";
25308
+ var version = "0.55.4";
24577
25309
  return __toCommonJS(compile_exports);
24578
25310
  })();
24579
25311
  /*! Bundled license information: