@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
- /** Compute Engine 0.55.2 */
1
+ /** Compute Engine 0.55.4 */
2
2
 
3
3
  // src/compute-engine/numerics/richardson.ts
4
4
  function extrapolate(f, x0, options = {}) {
@@ -3936,12 +3936,6 @@ function makeLambda(expr) {
3936
3936
  function applicable(fn) {
3937
3937
  return makeLambda(fn) ?? ((xs) => fn.engine.function("Apply", [fn, ...xs]).evaluate());
3938
3938
  }
3939
- function applicableN1(fn) {
3940
- const lambda = makeLambda(fn);
3941
- const ce = fn.engine;
3942
- if (lambda) return (x) => lambda([ce.number(x)])?.re ?? NaN;
3943
- return (x) => ce.function("Apply", [fn, ce.number(x)]).evaluate().re;
3944
- }
3945
3939
 
3946
3940
  // src/compute-engine/collection-utils.ts
3947
3941
  function isFiniteIndexedCollection(col) {
@@ -14666,8 +14660,11 @@ var BaseCompiler = class _BaseCompiler {
14666
14660
  for (const local of locals) {
14667
14661
  for (const arg of args) {
14668
14662
  if (isFunction2(arg, "Assign") && isSymbol2(arg.ops[0], local)) {
14669
- if (_BaseCompiler.isComplexValued(arg.ops[1])) {
14663
+ const rhs = arg.ops[1];
14664
+ if (_BaseCompiler.isComplexValued(rhs)) {
14670
14665
  typeHints[local] = isWGSL ? "vec2f" : "vec2";
14666
+ } else if (_BaseCompiler.isIntegerValued(rhs)) {
14667
+ typeHints[local] = isWGSL ? "i32" : "int";
14671
14668
  }
14672
14669
  break;
14673
14670
  }
@@ -14872,12 +14869,9 @@ var BaseCompiler = class _BaseCompiler {
14872
14869
  /**
14873
14870
  * Determine at compile time whether an expression produces a complex value.
14874
14871
  *
14875
- * Rules:
14876
- * - Numbers: complex if im !== 0
14877
- * - Symbols: ImaginaryUnit is complex; others use expr.isReal
14878
- * (undefined is treated as real -- assume-real policy)
14879
- * - Functions: Abs, Arg, Re, Im always return real.
14880
- * All others: complex if any operand is complex.
14872
+ * Uses the expression's declared type (from operator signatures) when
14873
+ * available. Falls back to operand inspection for functions whose
14874
+ * return type is unknown.
14881
14875
  */
14882
14876
  static isComplexValued(expr) {
14883
14877
  if (isNumber(expr)) return expr.im !== 0;
@@ -14888,13 +14882,24 @@ var BaseCompiler = class _BaseCompiler {
14888
14882
  return t.matches("complex") && !t.matches("real");
14889
14883
  }
14890
14884
  if (isFunction2(expr)) {
14891
- const op = expr.operator;
14892
- if (op === "Abs" || op === "Arg" || op === "Re" || op === "Im")
14893
- return false;
14885
+ const t = expr.type;
14886
+ if (t.matches("complex") && !t.matches("real")) return true;
14887
+ if (t.matches("real")) return false;
14894
14888
  return expr.ops.some((arg) => _BaseCompiler.isComplexValued(arg));
14895
14889
  }
14896
14890
  return false;
14897
14891
  }
14892
+ /** True if the expression is provably integer-typed. */
14893
+ static isIntegerValued(expr) {
14894
+ if (isNumber(expr)) return expr.im === 0 && Number.isInteger(expr.re);
14895
+ const t = expr.type;
14896
+ return t ? t.matches("integer") : false;
14897
+ }
14898
+ /** True if the expression is provably non-negative (sign ≥ 0). */
14899
+ static isNonNegative(expr) {
14900
+ if (isNumber(expr)) return expr.im === 0 && expr.re >= 0;
14901
+ return expr.isNonNegative === true;
14902
+ }
14898
14903
  /**
14899
14904
  * Generate a temporary variable name
14900
14905
  */
@@ -15066,20 +15071,113 @@ function compile(expr, options) {
15066
15071
  } catch (e) {
15067
15072
  if (options?.fallback ?? true) {
15068
15073
  console.warn(
15069
- `Compilation fallback for "${expr.operator}": ${e.message}`
15074
+ `Compilation fallback for "${expr.operator}" (target: ${options?.to ?? "javascript"}): ${e.message}`
15070
15075
  );
15076
+ const ce = expr.engine;
15077
+ const fallbackRun = ((vars) => {
15078
+ ce.pushScope();
15079
+ try {
15080
+ if (vars && typeof vars === "object") {
15081
+ for (const [k, v] of Object.entries(vars))
15082
+ ce.assign(k, v);
15083
+ }
15084
+ return expr.evaluate().re;
15085
+ } finally {
15086
+ ce.popScope();
15087
+ }
15088
+ });
15071
15089
  return {
15072
15090
  target: options?.to ?? "javascript",
15073
15091
  success: false,
15074
15092
  code: "",
15075
15093
  calling: "expression",
15076
- run: applicableN1(expr)
15094
+ run: fallbackRun
15077
15095
  };
15078
15096
  }
15079
15097
  throw e;
15080
15098
  }
15081
15099
  }
15082
15100
 
15101
+ // src/compute-engine/compilation/constant-folding.ts
15102
+ function formatFloat(n) {
15103
+ const str = n.toString();
15104
+ if (!str.includes(".") && !str.includes("e") && !str.includes("E")) {
15105
+ return `${str}.0`;
15106
+ }
15107
+ return str;
15108
+ }
15109
+ function tryGetConstant(expr) {
15110
+ if (!isNumber(expr)) return void 0;
15111
+ if (expr.im !== 0) return void 0;
15112
+ const re = expr.re;
15113
+ if (!isFinite(re)) return void 0;
15114
+ return re;
15115
+ }
15116
+ var NUMERIC_LITERAL_RE = /^-?\d+(\.\d+)?$/;
15117
+ function foldTerms(terms, identity, op) {
15118
+ const identityValue = op === "+" ? 0 : 1;
15119
+ let numericAcc = null;
15120
+ const symbolic = [];
15121
+ for (const term of terms) {
15122
+ if (NUMERIC_LITERAL_RE.test(term)) {
15123
+ const val = parseFloat(term);
15124
+ if (op === "*" && val === 0) return "0.0";
15125
+ if (numericAcc === null) {
15126
+ numericAcc = val;
15127
+ } else {
15128
+ numericAcc = op === "+" ? numericAcc + val : numericAcc * val;
15129
+ }
15130
+ } else {
15131
+ symbolic.push(term);
15132
+ }
15133
+ }
15134
+ if (numericAcc !== null && numericAcc !== identityValue) {
15135
+ symbolic.unshift(formatFloat(numericAcc));
15136
+ }
15137
+ if (symbolic.length === 0) {
15138
+ if (numericAcc !== null) return formatFloat(numericAcc);
15139
+ return identity;
15140
+ }
15141
+ if (symbolic.length === 1) return symbolic[0];
15142
+ return symbolic.join(op === "+" ? " + " : " * ");
15143
+ }
15144
+ function tryGetComplexParts(expr, compile2) {
15145
+ if (isSymbol2(expr, "ImaginaryUnit")) {
15146
+ return { re: null, im: "1.0" };
15147
+ }
15148
+ if (isNumber(expr) && expr.im !== 0) {
15149
+ const re = expr.re;
15150
+ const im = expr.im;
15151
+ return {
15152
+ re: re !== 0 ? formatFloat(re) : null,
15153
+ im: formatFloat(im)
15154
+ };
15155
+ }
15156
+ if (isFunction2(expr, "Multiply")) {
15157
+ const ops = expr.ops;
15158
+ const iIndex = ops.findIndex(
15159
+ (op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
15160
+ );
15161
+ if (iIndex >= 0) {
15162
+ const iFactor = ops[iIndex];
15163
+ const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
15164
+ const remaining = ops.filter((_, idx) => idx !== iIndex);
15165
+ if (remaining.length === 0) {
15166
+ return { re: null, im: formatFloat(iScale) };
15167
+ }
15168
+ const compiledFactors = remaining.map((r) => compile2(r));
15169
+ if (iScale !== 1)
15170
+ compiledFactors.unshift(formatFloat(iScale));
15171
+ const imCode = foldTerms(compiledFactors, "1.0", "*");
15172
+ return { re: null, im: imCode };
15173
+ }
15174
+ }
15175
+ if (BaseCompiler.isComplexValued(expr)) {
15176
+ return null;
15177
+ }
15178
+ return { re: compile2(expr), im: null };
15179
+ }
15180
+
15083
15181
  // node_modules/@arnog/colors/dist/index.mjs
15084
15182
  function gammaCorrect(channel) {
15085
15183
  const abs2 = Math.abs(channel);
@@ -16374,30 +16472,6 @@ var COOLWARM = [
16374
16472
  "#ae2036",
16375
16473
  "#b40426"
16376
16474
  ];
16377
- var OCEAN_BALANCE = [
16378
- "#00441b",
16379
- "#006d5b",
16380
- "#1a8c7d",
16381
- "#2fa394",
16382
- "#4fb3a3",
16383
- "#6fc1b3",
16384
- "#8dcfc3",
16385
- "#a6dbd1",
16386
- "#bfe6de",
16387
- "#d7f0ea",
16388
- "#f7f7f7",
16389
- "#eeeeee",
16390
- "#ddd8e6",
16391
- "#c7bcda",
16392
- "#b3a0d0",
16393
- "#9f86c7",
16394
- "#8d6dbd",
16395
- "#7b56b1",
16396
- "#6a42a3",
16397
- "#5a3093",
16398
- "#4a1f82",
16399
- "#3b0f70"
16400
- ];
16401
16475
  var reversePalette = (palette) => palette.slice().reverse();
16402
16476
  var DIVERGING_PALETTES = {
16403
16477
  roma: ROMA,
@@ -16409,9 +16483,7 @@ var DIVERGING_PALETTES = {
16409
16483
  rdbu: RDBU,
16410
16484
  "rdbu-reversed": reversePalette(RDBU),
16411
16485
  coolwarm: COOLWARM,
16412
- "coolwarm-reversed": reversePalette(COOLWARM),
16413
- "ocean-balance": OCEAN_BALANCE,
16414
- "ocean-balance-reversed": reversePalette(OCEAN_BALANCE)
16486
+ "coolwarm-reversed": reversePalette(COOLWARM)
16415
16487
  };
16416
16488
  var TURBO = [
16417
16489
  "#30123b",
@@ -18495,6 +18567,40 @@ var GREY = [
18495
18567
  "#eeeeee",
18496
18568
  "#ffffff"
18497
18569
  ];
18570
+ var CMOCEAN_PHASE = [
18571
+ "#a8780d",
18572
+ "#b3701b",
18573
+ "#be6828",
18574
+ "#c75f35",
18575
+ "#cf5643",
18576
+ "#d54b53",
18577
+ "#db4066",
18578
+ "#de357b",
18579
+ "#df2a93",
18580
+ "#dc25ad",
18581
+ "#d529c4",
18582
+ "#cc34d7",
18583
+ "#c041e5",
18584
+ "#b24fef",
18585
+ "#a25cf3",
18586
+ "#9168f4",
18587
+ "#7d73f0",
18588
+ "#687ce8",
18589
+ "#5285dc",
18590
+ "#3d8bcd",
18591
+ "#2c90bc",
18592
+ "#2093ac",
18593
+ "#19959c",
18594
+ "#12978c",
18595
+ "#0c987c",
18596
+ "#119a69",
18597
+ "#249a52",
18598
+ "#409839",
18599
+ "#5e9420",
18600
+ "#778d12",
18601
+ "#8b860d",
18602
+ "#9b7f0d"
18603
+ ];
18498
18604
  var reversePalette2 = (palette) => palette.slice().reverse();
18499
18605
  var SEQUENTIAL_PALETTES = {
18500
18606
  turbo: TURBO,
@@ -18518,7 +18624,9 @@ var SEQUENTIAL_PALETTES = {
18518
18624
  "rocket-reversed": reversePalette2(ROCKET),
18519
18625
  mako: MAKO,
18520
18626
  // blue to teal
18521
- "mako-reversed": reversePalette2(MAKO)
18627
+ "mako-reversed": reversePalette2(MAKO),
18628
+ "cmocean-phase": CMOCEAN_PHASE,
18629
+ "cmocean-phase-reversed": reversePalette2(CMOCEAN_PHASE)
18522
18630
  };
18523
18631
 
18524
18632
  // src/compute-engine/numerics/special-functions.ts
@@ -19418,12 +19526,21 @@ var JAVASCRIPT_FUNCTIONS = {
19418
19526
  Abs: (args, compile2) => {
19419
19527
  if (BaseCompiler.isComplexValued(args[0]))
19420
19528
  return `_SYS.cabs(${compile2(args[0])})`;
19529
+ if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
19421
19530
  return `Math.abs(${compile2(args[0])})`;
19422
19531
  },
19423
19532
  Add: (args, compile2) => {
19424
19533
  if (args.length === 1) return compile2(args[0]);
19425
19534
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
19426
- if (!anyComplex) return `(${args.map((x) => compile2(x)).join(" + ")})`;
19535
+ if (!anyComplex) {
19536
+ const constants = args.map(tryGetConstant);
19537
+ if (constants.every((c) => c !== void 0))
19538
+ return String(constants.reduce((a, b) => a + b, 0));
19539
+ const nonZero = args.filter((a) => tryGetConstant(a) !== 0);
19540
+ if (nonZero.length === 0) return "0";
19541
+ if (nonZero.length === 1) return compile2(nonZero[0]);
19542
+ return `(${nonZero.map((x) => compile2(x)).join(" + ")})`;
19543
+ }
19427
19544
  const parts = args.map((a) => {
19428
19545
  const code = compile2(a);
19429
19546
  return { code, isComplex: BaseCompiler.isComplexValued(a) };
@@ -19480,7 +19597,10 @@ var JAVASCRIPT_FUNCTIONS = {
19480
19597
  return `Math.atan(${compile2(args[0])})`;
19481
19598
  },
19482
19599
  Artanh: "Math.atanh",
19483
- Ceil: "Math.ceil",
19600
+ Ceil: (args, compile2) => {
19601
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19602
+ return `Math.ceil(${compile2(args[0])})`;
19603
+ },
19484
19604
  Chop: "_SYS.chop",
19485
19605
  Cos: (args, compile2) => {
19486
19606
  if (BaseCompiler.isComplexValued(args[0]))
@@ -19523,7 +19643,10 @@ var JAVASCRIPT_FUNCTIONS = {
19523
19643
  return `_SYS.cexp(${compile2(args[0])})`;
19524
19644
  return `Math.exp(${compile2(args[0])})`;
19525
19645
  },
19526
- Floor: "Math.floor",
19646
+ Floor: (args, compile2) => {
19647
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19648
+ return `Math.floor(${compile2(args[0])})`;
19649
+ },
19527
19650
  Fract: ([x], compile2) => {
19528
19651
  if (x === null) throw new Error("Fract: no argument");
19529
19652
  return BaseCompiler.inlineExpression("${x} - Math.floor(${x})", compile2(x));
@@ -19619,12 +19742,20 @@ var JAVASCRIPT_FUNCTIONS = {
19619
19742
  if (BaseCompiler.isComplexValued(base) || BaseCompiler.isComplexValued(exp3)) {
19620
19743
  return `_SYS.cpow(${compile2(base)}, ${compile2(exp3)})`;
19621
19744
  }
19622
- const expVal = exp3.re;
19623
- if (expVal === 0.5) return `Math.sqrt(${compile2(base)})`;
19624
- if (expVal === 1 / 3) return `Math.cbrt(${compile2(base)})`;
19625
- if (expVal === 1) return compile2(base);
19626
- if (expVal === -1) return `(1 / (${compile2(base)}))`;
19627
- if (expVal === -0.5) return `(1 / Math.sqrt(${compile2(base)}))`;
19745
+ const bConst = tryGetConstant(base);
19746
+ const eConst = tryGetConstant(exp3);
19747
+ if (bConst !== void 0 && eConst !== void 0)
19748
+ return String(Math.pow(bConst, eConst));
19749
+ if (eConst === 0) return "1";
19750
+ if (eConst === 1) return compile2(base);
19751
+ if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
19752
+ const code = compile2(base);
19753
+ return `(${code} * ${code})`;
19754
+ }
19755
+ if (eConst === -1) return `(1 / (${compile2(base)}))`;
19756
+ if (eConst === 0.5) return `Math.sqrt(${compile2(base)})`;
19757
+ if (eConst === 1 / 3) return `Math.cbrt(${compile2(base)})`;
19758
+ if (eConst === -0.5) return `(1 / Math.sqrt(${compile2(base)}))`;
19628
19759
  return `Math.pow(${compile2(base)}, ${compile2(exp3)})`;
19629
19760
  },
19630
19761
  Range: (args, compile2) => {
@@ -19661,16 +19792,29 @@ var JAVASCRIPT_FUNCTIONS = {
19661
19792
  Root: ([arg, exp3], compile2) => {
19662
19793
  if (arg === null) throw new Error("Root: no argument");
19663
19794
  if (exp3 === null) return `Math.sqrt(${compile2(arg)})`;
19664
- if (exp3?.re === 2) return `Math.sqrt(${compile2(arg)})`;
19665
- if (exp3?.re === 3) return `Math.cbrt(${compile2(arg)})`;
19666
- if (!isNaN(exp3?.re)) return `Math.pow(${compile2(arg)}, ${1 / exp3.re})`;
19795
+ const aConst = tryGetConstant(arg);
19796
+ const nConst = tryGetConstant(exp3);
19797
+ if (aConst !== void 0 && nConst !== void 0 && nConst !== 0)
19798
+ return String(Math.pow(aConst, 1 / nConst));
19799
+ if (nConst === 2) return `Math.sqrt(${compile2(arg)})`;
19800
+ if (nConst === 3) return `Math.cbrt(${compile2(arg)})`;
19801
+ if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
19667
19802
  return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
19668
19803
  },
19669
19804
  Random: "Math.random",
19670
- Round: "Math.round",
19805
+ Round: (args, compile2) => {
19806
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19807
+ return `Math.round(${compile2(args[0])})`;
19808
+ },
19671
19809
  Square: (args, compile2) => {
19672
19810
  const arg = args[0];
19673
19811
  if (arg === null) throw new Error("Square: no argument");
19812
+ const c = tryGetConstant(arg);
19813
+ if (c !== void 0) return String(c * c);
19814
+ if (isSymbol2(arg)) {
19815
+ const code = compile2(arg);
19816
+ return `(${code} * ${code})`;
19817
+ }
19674
19818
  return `Math.pow(${compile2(arg)}, 2)`;
19675
19819
  },
19676
19820
  Sec: (args, compile2) => {
@@ -19703,6 +19847,8 @@ var JAVASCRIPT_FUNCTIONS = {
19703
19847
  Sqrt: (args, compile2) => {
19704
19848
  if (BaseCompiler.isComplexValued(args[0]))
19705
19849
  return `_SYS.csqrt(${compile2(args[0])})`;
19850
+ const c = tryGetConstant(args[0]);
19851
+ if (c !== void 0) return String(Math.sqrt(c));
19706
19852
  return `Math.sqrt(${compile2(args[0])})`;
19707
19853
  },
19708
19854
  Tan: (args, compile2) => {
@@ -19719,9 +19865,14 @@ var JAVASCRIPT_FUNCTIONS = {
19719
19865
  if (a === null || b === null) throw new Error("Mod: missing argument");
19720
19866
  const ca = compile2(a);
19721
19867
  const cb = compile2(b);
19868
+ if (BaseCompiler.isIntegerValued(a) && BaseCompiler.isIntegerValued(b) && BaseCompiler.isNonNegative(a))
19869
+ return `(${ca} % ${cb})`;
19722
19870
  return `((${ca} % ${cb}) + ${cb}) % ${cb}`;
19723
19871
  },
19724
- Truncate: "Math.trunc",
19872
+ Truncate: (args, compile2) => {
19873
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
19874
+ return `Math.trunc(${compile2(args[0])})`;
19875
+ },
19725
19876
  Remainder: ([a, b], compile2) => {
19726
19877
  if (a === null || b === null)
19727
19878
  throw new Error("Remainder: missing argument");
@@ -19729,25 +19880,20 @@ var JAVASCRIPT_FUNCTIONS = {
19729
19880
  a
19730
19881
  )} / ${compile2(b)}))`;
19731
19882
  },
19732
- // Arithmetic operators handled as functions for completeness
19733
- Subtract: ([a, b], compile2) => {
19734
- if (a === null || b === null) throw new Error("Subtract: missing argument");
19735
- const ac = BaseCompiler.isComplexValued(a);
19736
- const bc = BaseCompiler.isComplexValued(b);
19737
- if (!ac && !bc) return `(${compile2(a)} - ${compile2(b)})`;
19738
- const ca = compile2(a);
19739
- const cb = compile2(b);
19740
- const reA = ac ? `(${ca}).re` : ca;
19741
- const imA = ac ? `(${ca}).im` : "0";
19742
- const reB = bc ? `(${cb}).re` : cb;
19743
- const imB = bc ? `(${cb}).im` : "0";
19744
- return `({ re: ${reA} - ${reB}, im: ${imA} - ${imB} })`;
19745
- },
19883
+ // No Subtract function handler Subtract canonicalizes to Add+Negate.
19884
+ // The operator entry in JAVASCRIPT_OPERATORS handles any edge cases.
19746
19885
  Divide: ([a, b], compile2) => {
19747
19886
  if (a === null || b === null) throw new Error("Divide: missing argument");
19748
19887
  const ac = BaseCompiler.isComplexValued(a);
19749
19888
  const bc = BaseCompiler.isComplexValued(b);
19750
- if (!ac && !bc) return `(${compile2(a)} / ${compile2(b)})`;
19889
+ if (!ac && !bc) {
19890
+ const ca = tryGetConstant(a);
19891
+ const cb = tryGetConstant(b);
19892
+ if (ca !== void 0 && cb !== void 0 && cb !== 0)
19893
+ return String(ca / cb);
19894
+ if (cb === 1) return compile2(a);
19895
+ return `(${compile2(a)} / ${compile2(b)})`;
19896
+ }
19751
19897
  if (ac && bc) {
19752
19898
  return `(() => { const _a = ${compile2(a)}, _b = ${compile2(
19753
19899
  b
@@ -19764,13 +19910,26 @@ var JAVASCRIPT_FUNCTIONS = {
19764
19910
  },
19765
19911
  Negate: ([x], compile2) => {
19766
19912
  if (x === null) throw new Error("Negate: no argument");
19767
- if (!BaseCompiler.isComplexValued(x)) return `(-${compile2(x)})`;
19913
+ if (!BaseCompiler.isComplexValued(x)) {
19914
+ const c = tryGetConstant(x);
19915
+ if (c !== void 0) return String(-c);
19916
+ return `(-${compile2(x)})`;
19917
+ }
19768
19918
  return `_SYS.cneg(${compile2(x)})`;
19769
19919
  },
19770
19920
  Multiply: (args, compile2) => {
19771
19921
  if (args.length === 1) return compile2(args[0]);
19772
19922
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
19773
- if (!anyComplex) return `(${args.map((x) => compile2(x)).join(" * ")})`;
19923
+ if (!anyComplex) {
19924
+ if (args.some((a) => tryGetConstant(a) === 0)) return "0";
19925
+ const constants = args.map(tryGetConstant);
19926
+ if (constants.every((c) => c !== void 0))
19927
+ return String(constants.reduce((a, b) => a * b, 1));
19928
+ const nonOne = args.filter((a) => tryGetConstant(a) !== 1);
19929
+ if (nonOne.length === 0) return "1";
19930
+ if (nonOne.length === 1) return compile2(nonOne[0]);
19931
+ return `(${nonOne.map((x) => compile2(x)).join(" * ")})`;
19932
+ }
19774
19933
  if (args.length === 2) {
19775
19934
  const ac = BaseCompiler.isComplexValued(args[0]);
19776
19935
  const bc = BaseCompiler.isComplexValued(args[1]);
@@ -19855,20 +20014,30 @@ var JAVASCRIPT_FUNCTIONS = {
19855
20014
  AiryAi: "_SYS.airyAi",
19856
20015
  AiryBi: "_SYS.airyBi",
19857
20016
  // Combinatorics
20017
+ Mandelbrot: ([c, maxIter], compile2) => {
20018
+ if (c === null || maxIter === null)
20019
+ throw new Error("Mandelbrot: missing arguments");
20020
+ return `_SYS.mandelbrot(${compile2(c)}, ${compile2(maxIter)})`;
20021
+ },
20022
+ Julia: ([z, c, maxIter], compile2) => {
20023
+ if (z === null || c === null || maxIter === null)
20024
+ throw new Error("Julia: missing arguments");
20025
+ return `_SYS.julia(${compile2(z)}, ${compile2(c)}, ${compile2(maxIter)})`;
20026
+ },
19858
20027
  Binomial: (args, compile2) => `_SYS.binomial(${compile2(args[0])}, ${compile2(args[1])})`,
19859
20028
  Fibonacci: "_SYS.fibonacci",
19860
20029
  // Complex-specific functions
19861
- Re: (args, compile2) => {
20030
+ Real: (args, compile2) => {
19862
20031
  if (BaseCompiler.isComplexValued(args[0]))
19863
20032
  return `(${compile2(args[0])}).re`;
19864
20033
  return compile2(args[0]);
19865
20034
  },
19866
- Im: (args, compile2) => {
20035
+ Imaginary: (args, compile2) => {
19867
20036
  if (BaseCompiler.isComplexValued(args[0]))
19868
20037
  return `(${compile2(args[0])}).im`;
19869
20038
  return "0";
19870
20039
  },
19871
- Arg: (args, compile2) => {
20040
+ Argument: (args, compile2) => {
19872
20041
  if (BaseCompiler.isComplexValued(args[0]))
19873
20042
  return `_SYS.carg(${compile2(args[0])})`;
19874
20043
  return `(${compile2(args[0])} >= 0 ? 0 : Math.PI)`;
@@ -20204,6 +20373,41 @@ var SYS_HELPERS = {
20204
20373
  sinc,
20205
20374
  fresnelS,
20206
20375
  fresnelC,
20376
+ mandelbrot: (c, maxIter) => {
20377
+ let zx = 0, zy = 0;
20378
+ const cx = typeof c === "number" ? c : c.re;
20379
+ const cy = typeof c === "number" ? 0 : c.im;
20380
+ const n = Math.round(maxIter);
20381
+ for (let i = 0; i < n; i++) {
20382
+ const newZx = zx * zx - zy * zy + cx;
20383
+ zy = 2 * zx * zy + cy;
20384
+ zx = newZx;
20385
+ const mag2 = zx * zx + zy * zy;
20386
+ if (mag2 > 4) {
20387
+ const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
20388
+ return Math.max(0, Math.min(1, smooth));
20389
+ }
20390
+ }
20391
+ return 1;
20392
+ },
20393
+ julia: (z, c, maxIter) => {
20394
+ let zx = typeof z === "number" ? z : z.re;
20395
+ let zy = typeof z === "number" ? 0 : z.im;
20396
+ const cx = typeof c === "number" ? c : c.re;
20397
+ const cy = typeof c === "number" ? 0 : c.im;
20398
+ const n = Math.round(maxIter);
20399
+ for (let i = 0; i < n; i++) {
20400
+ const newZx = zx * zx - zy * zy + cx;
20401
+ zy = 2 * zx * zy + cy;
20402
+ zx = newZx;
20403
+ const mag2 = zx * zx + zy * zy;
20404
+ if (mag2 > 4) {
20405
+ const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
20406
+ return Math.max(0, Math.min(1, smooth));
20407
+ }
20408
+ }
20409
+ return 1;
20410
+ },
20207
20411
  binomial: choose,
20208
20412
  fibonacci,
20209
20413
  // Complex helpers
@@ -20544,11 +20748,39 @@ function fibonacci(n) {
20544
20748
  return b;
20545
20749
  }
20546
20750
 
20751
+ // src/compute-engine/compilation/fractal-orbit.ts
20752
+ function computeReferenceOrbit(center, maxIter, precision) {
20753
+ const prevPrecision = BigDecimal.precision;
20754
+ BigDecimal.precision = precision;
20755
+ try {
20756
+ const cr = new BigDecimal(center[0]);
20757
+ const ci = new BigDecimal(center[1]);
20758
+ let zr = BigDecimal.ZERO;
20759
+ let zi = BigDecimal.ZERO;
20760
+ const ESCAPE = new BigDecimal(256);
20761
+ const points = [];
20762
+ for (let i = 0; i < maxIter; i++) {
20763
+ points.push(zr.toNumber(), zi.toNumber());
20764
+ const zr2 = zr.mul(zr).toPrecision(precision);
20765
+ const zi2 = zi.mul(zi).toPrecision(precision);
20766
+ const mag2 = zr2.add(zi2);
20767
+ if (mag2.cmp(ESCAPE) > 0) break;
20768
+ const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
20769
+ zr = zr2.sub(zi2).add(cr);
20770
+ zi = new_zi;
20771
+ }
20772
+ return new Float32Array(points);
20773
+ } finally {
20774
+ BigDecimal.precision = prevPrecision;
20775
+ }
20776
+ }
20777
+
20547
20778
  // src/compute-engine/compilation/gpu-target.ts
20548
20779
  var GPU_OPERATORS = {
20549
20780
  Add: ["+", 11],
20550
20781
  Negate: ["-", 14],
20551
20782
  Subtract: ["-", 11],
20783
+ // Subtract canonicalizes to Add+Negate; kept as fallback
20552
20784
  Multiply: ["*", 12],
20553
20785
  Divide: ["/", 13],
20554
20786
  Equal: ["==", 8],
@@ -20564,6 +20796,12 @@ var GPU_OPERATORS = {
20564
20796
  function gpuVec2(target) {
20565
20797
  return target?.language === "wgsl" ? "vec2f" : "vec2";
20566
20798
  }
20799
+ function compileIntArg(expr, compile2, target) {
20800
+ const c = tryGetConstant(expr);
20801
+ if (c !== void 0 && Number.isInteger(c)) return c.toString();
20802
+ const intCast = target?.language === "wgsl" ? "i32" : "int";
20803
+ return `${intCast}(${compile2(expr)})`;
20804
+ }
20567
20805
  var GPU_UNROLL_LIMIT = 100;
20568
20806
  function compileGPUSumProduct(kind, args, _compile, target) {
20569
20807
  if (!args[0]) throw new Error(`${kind}: no body`);
@@ -20620,94 +20858,126 @@ function compileGPUSumProduct(kind, args, _compile, target) {
20620
20858
  ];
20621
20859
  return lines.join("\n");
20622
20860
  }
20861
+ function selectFractalStrategy(target) {
20862
+ const radius = target.hints?.viewport?.radius;
20863
+ if (radius === void 0) return "single";
20864
+ if (radius > 1e-6) return "single";
20865
+ if (radius > 1e-14) return "double";
20866
+ return "perturbation";
20867
+ }
20623
20868
  var GPU_FUNCTIONS = {
20624
20869
  // Variadic arithmetic (for function-call form, e.g., with vectors)
20625
20870
  Add: (args, compile2, target) => {
20626
20871
  if (args.length === 0) return "0.0";
20627
20872
  if (args.length === 1) return compile2(args[0]);
20628
20873
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20629
- if (!anyComplex) return args.map((x) => compile2(x)).join(" + ");
20630
- const v2 = gpuVec2(target);
20631
- return args.map((a) => {
20632
- const code = compile2(a);
20633
- return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20634
- }).join(" + ");
20635
- },
20636
- Multiply: (args, compile2, _target) => {
20637
- if (args.length === 0) return "1.0";
20638
- if (args.length === 1) return compile2(args[0]);
20639
- const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20640
- if (!anyComplex) return args.map((x) => compile2(x)).join(" * ");
20641
- let result = compile2(args[0]);
20642
- let resultIsComplex = BaseCompiler.isComplexValued(args[0]);
20643
- for (let i = 1; i < args.length; i++) {
20644
- const code = compile2(args[i]);
20645
- const argIsComplex = BaseCompiler.isComplexValued(args[i]);
20646
- if (!resultIsComplex && !argIsComplex) {
20647
- result = `(${result} * ${code})`;
20648
- } else if (resultIsComplex && !argIsComplex) {
20649
- result = `(${code} * ${result})`;
20650
- } else if (!resultIsComplex && argIsComplex) {
20651
- result = `(${result} * ${code})`;
20652
- resultIsComplex = true;
20653
- } else {
20654
- result = `_gpu_cmul(${result}, ${code})`;
20655
- }
20874
+ if (!anyComplex) {
20875
+ return foldTerms(
20876
+ args.map((x) => compile2(x)),
20877
+ "0.0",
20878
+ "+"
20879
+ );
20656
20880
  }
20657
- return result;
20658
- },
20659
- Subtract: (args, compile2, target) => {
20660
- if (args.length === 0) return "0.0";
20881
+ const parts = args.map((a) => tryGetComplexParts(a, compile2));
20882
+ if (parts.some((p) => p === null)) {
20883
+ const v2 = gpuVec2(target);
20884
+ return args.map((a) => {
20885
+ const code = compile2(a);
20886
+ return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20887
+ }).join(" + ");
20888
+ }
20889
+ const reParts = [];
20890
+ const imParts = [];
20891
+ for (const p of parts) {
20892
+ if (p.re !== null) reParts.push(p.re);
20893
+ if (p.im !== null) imParts.push(p.im);
20894
+ }
20895
+ const reSum = foldTerms(reParts, "0.0", "+");
20896
+ const imSum = foldTerms(imParts, "0.0", "+");
20897
+ return `${gpuVec2(target)}(${reSum}, ${imSum})`;
20898
+ },
20899
+ Multiply: (args, compile2, target) => {
20900
+ if (args.length === 0) return "1.0";
20661
20901
  if (args.length === 1) return compile2(args[0]);
20662
20902
  const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
20663
20903
  if (!anyComplex) {
20664
- if (args.length === 2) return `${compile2(args[0])} - ${compile2(args[1])}`;
20665
- let result2 = compile2(args[0]);
20666
- for (let i = 1; i < args.length; i++) {
20667
- result2 = `${result2} - ${compile2(args[i])}`;
20668
- }
20669
- return result2;
20670
- }
20671
- const v2 = gpuVec2(target);
20672
- const promote = (a) => {
20673
- const code = compile2(a);
20674
- return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
20675
- };
20676
- if (args.length === 2) return `${promote(args[0])} - ${promote(args[1])}`;
20677
- let result = promote(args[0]);
20678
- for (let i = 1; i < args.length; i++) {
20679
- result = `${result} - ${promote(args[i])}`;
20904
+ return foldTerms(
20905
+ args.map((x) => compile2(x)),
20906
+ "1.0",
20907
+ "*"
20908
+ );
20680
20909
  }
20910
+ const iIndex = args.findIndex(
20911
+ (op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
20912
+ );
20913
+ if (iIndex >= 0) {
20914
+ const iFactor = args[iIndex];
20915
+ const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
20916
+ const realFactors = args.filter((_, i) => i !== iIndex);
20917
+ const v2 = gpuVec2(target);
20918
+ if (realFactors.length === 0)
20919
+ return `${v2}(0.0, ${formatFloat(iScale)})`;
20920
+ const factors = realFactors.map((f) => compile2(f));
20921
+ if (iScale !== 1) factors.unshift(formatFloat(iScale));
20922
+ const imCode = foldTerms(factors, "1.0", "*");
20923
+ return `${v2}(0.0, ${imCode})`;
20924
+ }
20925
+ const realCodes = [];
20926
+ const complexCodes = [];
20927
+ for (const a of args) {
20928
+ if (BaseCompiler.isComplexValued(a)) complexCodes.push(compile2(a));
20929
+ else realCodes.push(compile2(a));
20930
+ }
20931
+ const scalarCode = foldTerms(realCodes, "1.0", "*");
20932
+ let result = complexCodes[0];
20933
+ for (let i = 1; i < complexCodes.length; i++) {
20934
+ result = `_gpu_cmul(${result}, ${complexCodes[i]})`;
20935
+ }
20936
+ if (scalarCode !== "1.0") result = `(${scalarCode} * ${result})`;
20681
20937
  return result;
20682
20938
  },
20939
+ // No Subtract function handler — Subtract canonicalizes to Add+Negate.
20940
+ // The operator entry in GPU_OPERATORS handles any edge cases.
20683
20941
  Divide: (args, compile2, target) => {
20684
20942
  if (args.length === 0) return "1.0";
20685
20943
  if (args.length === 1) return compile2(args[0]);
20686
20944
  const ac = BaseCompiler.isComplexValued(args[0]);
20687
20945
  const bc = args.length >= 2 && BaseCompiler.isComplexValued(args[1]);
20688
20946
  if (!ac && !bc) {
20689
- if (args.length === 2) return `${compile2(args[0])} / ${compile2(args[1])}`;
20947
+ if (args.length === 2) {
20948
+ const a = tryGetConstant(args[0]);
20949
+ const b = tryGetConstant(args[1]);
20950
+ if (a !== void 0 && b !== void 0 && b !== 0)
20951
+ return formatFloat(a / b);
20952
+ if (b === 1) return compile2(args[0]);
20953
+ return `${compile2(args[0])} / ${compile2(args[1])}`;
20954
+ }
20690
20955
  let result = compile2(args[0]);
20691
- for (let i = 1; i < args.length; i++) {
20956
+ for (let i = 1; i < args.length; i++)
20692
20957
  result = `${result} / ${compile2(args[i])}`;
20693
- }
20694
20958
  return result;
20695
20959
  }
20696
20960
  if (ac && bc) return `_gpu_cdiv(${compile2(args[0])}, ${compile2(args[1])})`;
20697
- if (ac && !bc) {
20698
- return `(${compile2(args[0])} / ${compile2(args[1])})`;
20699
- }
20961
+ if (ac && !bc) return `(${compile2(args[0])} / ${compile2(args[1])})`;
20700
20962
  const v2 = gpuVec2(target);
20701
20963
  return `_gpu_cdiv(${v2}(${compile2(args[0])}, 0.0), ${compile2(args[1])})`;
20702
20964
  },
20703
- Negate: ([x], compile2) => {
20965
+ Negate: ([x], compile2, target) => {
20704
20966
  if (x === null) throw new Error("Negate: no argument");
20967
+ const c = tryGetConstant(x);
20968
+ if (c !== void 0) return formatFloat(-c);
20969
+ if (isNumber(x) && x.im !== 0) {
20970
+ return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
20971
+ }
20972
+ if (isSymbol2(x, "ImaginaryUnit"))
20973
+ return `${gpuVec2(target)}(0.0, -1.0)`;
20705
20974
  return `(-${compile2(x)})`;
20706
20975
  },
20707
20976
  // Standard math functions with complex dispatch
20708
20977
  Abs: (args, compile2) => {
20709
20978
  if (BaseCompiler.isComplexValued(args[0]))
20710
20979
  return `length(${compile2(args[0])})`;
20980
+ if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
20711
20981
  return `abs(${compile2(args[0])})`;
20712
20982
  },
20713
20983
  Arccos: (args, compile2) => {
@@ -20725,7 +20995,10 @@ var GPU_FUNCTIONS = {
20725
20995
  return `_gpu_catan(${compile2(args[0])})`;
20726
20996
  return `atan(${compile2(args[0])})`;
20727
20997
  },
20728
- Ceil: "ceil",
20998
+ Ceil: (args, compile2) => {
20999
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21000
+ return `ceil(${compile2(args[0])})`;
21001
+ },
20729
21002
  Clamp: "clamp",
20730
21003
  Cos: (args, compile2) => {
20731
21004
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20739,7 +21012,10 @@ var GPU_FUNCTIONS = {
20739
21012
  return `exp(${compile2(args[0])})`;
20740
21013
  },
20741
21014
  Exp2: "exp2",
20742
- Floor: "floor",
21015
+ Floor: (args, compile2) => {
21016
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21017
+ return `floor(${compile2(args[0])})`;
21018
+ },
20743
21019
  Fract: "fract",
20744
21020
  Ln: (args, compile2) => {
20745
21021
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20761,10 +21037,25 @@ var GPU_FUNCTIONS = {
20761
21037
  const eCode = BaseCompiler.isComplexValued(exp3) ? compile2(exp3) : `${v2}(${compile2(exp3)}, 0.0)`;
20762
21038
  return `_gpu_cpow(${bCode}, ${eCode})`;
20763
21039
  }
21040
+ const bConst = tryGetConstant(base);
21041
+ const eConst = tryGetConstant(exp3);
21042
+ if (bConst !== void 0 && eConst !== void 0)
21043
+ return formatFloat(Math.pow(bConst, eConst));
21044
+ if (eConst === 0) return "1.0";
21045
+ if (eConst === 1) return compile2(base);
21046
+ if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
21047
+ const code = compile2(base);
21048
+ return `(${code} * ${code})`;
21049
+ }
21050
+ if (eConst === -1) return `(1.0 / ${compile2(base)})`;
21051
+ if (eConst === 0.5) return `sqrt(${compile2(base)})`;
20764
21052
  return `pow(${compile2(base)}, ${compile2(exp3)})`;
20765
21053
  },
20766
21054
  Radians: "radians",
20767
- Round: "round",
21055
+ Round: (args, compile2) => {
21056
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21057
+ return `round(${compile2(args[0])})`;
21058
+ },
20768
21059
  Sign: "sign",
20769
21060
  Sin: (args, compile2) => {
20770
21061
  if (BaseCompiler.isComplexValued(args[0]))
@@ -20775,6 +21066,8 @@ var GPU_FUNCTIONS = {
20775
21066
  Sqrt: (args, compile2) => {
20776
21067
  if (BaseCompiler.isComplexValued(args[0]))
20777
21068
  return `_gpu_csqrt(${compile2(args[0])})`;
21069
+ const c = tryGetConstant(args[0]);
21070
+ if (c !== void 0) return formatFloat(Math.sqrt(c));
20778
21071
  return `sqrt(${compile2(args[0])})`;
20779
21072
  },
20780
21073
  Step: "step",
@@ -20783,17 +21076,20 @@ var GPU_FUNCTIONS = {
20783
21076
  return `_gpu_ctan(${compile2(args[0])})`;
20784
21077
  return `tan(${compile2(args[0])})`;
20785
21078
  },
20786
- Truncate: "trunc",
21079
+ Truncate: (args, compile2) => {
21080
+ if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
21081
+ return `trunc(${compile2(args[0])})`;
21082
+ },
20787
21083
  // Complex-specific functions
20788
- Re: (args, compile2) => {
21084
+ Real: (args, compile2) => {
20789
21085
  if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).x`;
20790
21086
  return compile2(args[0]);
20791
21087
  },
20792
- Im: (args, compile2) => {
21088
+ Imaginary: (args, compile2) => {
20793
21089
  if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).y`;
20794
21090
  return "0.0";
20795
21091
  },
20796
- Arg: (args, compile2) => {
21092
+ Argument: (args, compile2) => {
20797
21093
  if (BaseCompiler.isComplexValued(args[0])) {
20798
21094
  const code = compile2(args[0]);
20799
21095
  return `atan(${code}.y, ${code}.x)`;
@@ -21008,13 +21304,20 @@ var GPU_FUNCTIONS = {
21008
21304
  },
21009
21305
  Square: ([x], compile2) => {
21010
21306
  if (x === null) throw new Error("Square: no argument");
21011
- const arg = compile2(x);
21012
- return `(${arg} * ${arg})`;
21307
+ if (isSymbol2(x) || isNumber(x)) {
21308
+ const arg = compile2(x);
21309
+ return `(${arg} * ${arg})`;
21310
+ }
21311
+ return `pow(${compile2(x)}, 2.0)`;
21013
21312
  },
21014
21313
  Root: ([x, n], compile2) => {
21015
21314
  if (x === null) throw new Error("Root: no argument");
21016
21315
  if (n === null || n === void 0) return `sqrt(${compile2(x)})`;
21017
- if (n?.re === 2) return `sqrt(${compile2(x)})`;
21316
+ const nConst = tryGetConstant(n);
21317
+ if (nConst === 2) return `sqrt(${compile2(x)})`;
21318
+ const xConst = tryGetConstant(x);
21319
+ if (xConst !== void 0 && nConst !== void 0)
21320
+ return formatFloat(Math.pow(xConst, 1 / nConst));
21018
21321
  return `pow(${compile2(x)}, 1.0 / ${compile2(n)})`;
21019
21322
  },
21020
21323
  // Color functions (pure-math, GPU-compilable)
@@ -21056,18 +21359,34 @@ var GPU_FUNCTIONS = {
21056
21359
  Mandelbrot: ([c, maxIter], compile2, target) => {
21057
21360
  if (c === null || maxIter === null)
21058
21361
  throw new Error("Mandelbrot: missing arguments");
21059
- const intCast = target?.language === "wgsl" ? "i32" : "int";
21060
- return `_fractal_mandelbrot(${compile2(c)}, ${intCast}(${compile2(
21061
- maxIter
21062
- )}))`;
21362
+ const iterCode = compileIntArg(maxIter, compile2, target);
21363
+ const strategy = selectFractalStrategy(target);
21364
+ if (strategy === "double") {
21365
+ const cCode = compile2(c);
21366
+ return `_fractal_mandelbrot_dp(vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21367
+ }
21368
+ if (strategy === "perturbation") {
21369
+ const cCode = compile2(c);
21370
+ return `_fractal_mandelbrot_pt(${cCode}, ${iterCode})`;
21371
+ }
21372
+ return `_fractal_mandelbrot(${compile2(c)}, ${iterCode})`;
21063
21373
  },
21064
21374
  Julia: ([z, c, maxIter], compile2, target) => {
21065
21375
  if (z === null || c === null || maxIter === null)
21066
21376
  throw new Error("Julia: missing arguments");
21067
- const intCast = target?.language === "wgsl" ? "i32" : "int";
21068
- return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${intCast}(${compile2(
21069
- maxIter
21070
- )}))`;
21377
+ const iterCode = compileIntArg(maxIter, compile2, target);
21378
+ const strategy = selectFractalStrategy(target);
21379
+ if (strategy === "double") {
21380
+ const zCode = compile2(z);
21381
+ const cCode = compile2(c);
21382
+ return `_fractal_julia_dp(vec4(${zCode}, vec2(0.0)), vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21383
+ }
21384
+ if (strategy === "perturbation") {
21385
+ const zCode = compile2(z);
21386
+ const cCode = compile2(c);
21387
+ return `_fractal_julia_pt(${zCode}, ${cCode}, ${iterCode})`;
21388
+ }
21389
+ return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${iterCode})`;
21071
21390
  },
21072
21391
  // Vector/Matrix operations
21073
21392
  Cross: "cross",
@@ -21664,6 +21983,200 @@ fn _gpu_besselJ(n_in: i32, x_in: f32) -> f32 {
21664
21983
  return sgn * vals[n] / norm;
21665
21984
  }
21666
21985
  `;
21986
+ var GPU_DS_ARITHMETIC_PREAMBLE_GLSL = `
21987
+ // Split a float into high and low parts for exact multiplication
21988
+ vec2 ds_split(float a) {
21989
+ const float SPLIT = 4097.0; // 2^12 + 1
21990
+ float t = SPLIT * a;
21991
+ float hi = t - (t - a);
21992
+ float lo = a - hi;
21993
+ return vec2(hi, lo);
21994
+ }
21995
+
21996
+ // Create a double-single from a single float
21997
+ vec2 ds_from(float a) {
21998
+ return vec2(a, 0.0);
21999
+ }
22000
+
22001
+ // Error-free addition (Knuth TwoSum)
22002
+ vec2 ds_add(vec2 a, vec2 b) {
22003
+ float s = a.x + b.x;
22004
+ float v = s - a.x;
22005
+ float e = (a.x - (s - v)) + (b.x - v);
22006
+ float lo = (a.y + b.y) + e;
22007
+ float hi = s + lo;
22008
+ lo = lo - (hi - s);
22009
+ return vec2(hi, lo);
22010
+ }
22011
+
22012
+ // Double-single subtraction
22013
+ vec2 ds_sub(vec2 a, vec2 b) {
22014
+ return ds_add(a, vec2(-b.x, -b.y));
22015
+ }
22016
+
22017
+ // Error-free multiplication (Dekker TwoProduct)
22018
+ vec2 ds_mul(vec2 a, vec2 b) {
22019
+ float p = a.x * b.x;
22020
+ vec2 sa = ds_split(a.x);
22021
+ vec2 sb = ds_split(b.x);
22022
+ float err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22023
+ err += a.x * b.y + a.y * b.x;
22024
+ float hi = p + err;
22025
+ float lo = err - (hi - p);
22026
+ return vec2(hi, lo);
22027
+ }
22028
+
22029
+ // Optimized self-multiply
22030
+ vec2 ds_sqr(vec2 a) {
22031
+ float p = a.x * a.x;
22032
+ vec2 sa = ds_split(a.x);
22033
+ float err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22034
+ err += 2.0 * a.x * a.y;
22035
+ float hi = p + err;
22036
+ float lo = err - (hi - p);
22037
+ return vec2(hi, lo);
22038
+ }
22039
+
22040
+ // Compare magnitude: returns -1, 0, or 1
22041
+ float ds_cmp(vec2 a, vec2 b) {
22042
+ float d = a.x - b.x;
22043
+ if (d != 0.0) return sign(d);
22044
+ return sign(a.y - b.y);
22045
+ }
22046
+ `;
22047
+ var GPU_DS_ARITHMETIC_PREAMBLE_WGSL = `
22048
+ fn ds_split(a: f32) -> vec2f {
22049
+ const SPLIT: f32 = 4097.0;
22050
+ let t = SPLIT * a;
22051
+ let hi = t - (t - a);
22052
+ let lo = a - hi;
22053
+ return vec2f(hi, lo);
22054
+ }
22055
+
22056
+ fn ds_from(a: f32) -> vec2f {
22057
+ return vec2f(a, 0.0);
22058
+ }
22059
+
22060
+ fn ds_add(a: vec2f, b: vec2f) -> vec2f {
22061
+ let s = a.x + b.x;
22062
+ let v = s - a.x;
22063
+ let e = (a.x - (s - v)) + (b.x - v);
22064
+ let lo_t = (a.y + b.y) + e;
22065
+ let hi = s + lo_t;
22066
+ let lo = lo_t - (hi - s);
22067
+ return vec2f(hi, lo);
22068
+ }
22069
+
22070
+ fn ds_sub(a: vec2f, b: vec2f) -> vec2f {
22071
+ return ds_add(a, vec2f(-b.x, -b.y));
22072
+ }
22073
+
22074
+ fn ds_mul(a: vec2f, b: vec2f) -> vec2f {
22075
+ let p = a.x * b.x;
22076
+ let sa = ds_split(a.x);
22077
+ let sb = ds_split(b.x);
22078
+ var err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22079
+ err += a.x * b.y + a.y * b.x;
22080
+ let hi = p + err;
22081
+ let lo = err - (hi - p);
22082
+ return vec2f(hi, lo);
22083
+ }
22084
+
22085
+ fn ds_sqr(a: vec2f) -> vec2f {
22086
+ let p = a.x * a.x;
22087
+ let sa = ds_split(a.x);
22088
+ var err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22089
+ err += 2.0 * a.x * a.y;
22090
+ let hi = p + err;
22091
+ let lo = err - (hi - p);
22092
+ return vec2f(hi, lo);
22093
+ }
22094
+
22095
+ fn ds_cmp(a: vec2f, b: vec2f) -> f32 {
22096
+ let d = a.x - b.x;
22097
+ if (d != 0.0) { return sign(d); }
22098
+ return sign(a.y - b.y);
22099
+ }
22100
+ `;
22101
+ var GPU_FRACTAL_DP_PREAMBLE_GLSL = `
22102
+ float _fractal_mandelbrot_dp(vec4 c, int maxIter) {
22103
+ // c = (re_hi, im_hi, re_lo, im_lo)
22104
+ vec2 cr = vec2(c.x, c.z); // real part as ds
22105
+ vec2 ci = vec2(c.y, c.w); // imag part as ds
22106
+ vec2 zr = vec2(0.0, 0.0);
22107
+ vec2 zi = vec2(0.0, 0.0);
22108
+ for (int i = 0; i < maxIter; i++) {
22109
+ vec2 zr2 = ds_sqr(zr);
22110
+ vec2 zi2 = ds_sqr(zi);
22111
+ // |z|^2 > 4.0 ?
22112
+ vec2 mag2 = ds_add(zr2, zi2);
22113
+ if (mag2.x > 4.0)
22114
+ return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22115
+ // z = z^2 + c
22116
+ vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci); // 2*zr*zi + ci
22117
+ zr = ds_add(ds_sub(zr2, zi2), cr); // zr^2 - zi^2 + cr
22118
+ zi = new_zi;
22119
+ }
22120
+ return 1.0;
22121
+ }
22122
+
22123
+ float _fractal_julia_dp(vec4 z_in, vec4 c, int maxIter) {
22124
+ vec2 zr = vec2(z_in.x, z_in.z);
22125
+ vec2 zi = vec2(z_in.y, z_in.w);
22126
+ vec2 cr = vec2(c.x, c.z);
22127
+ vec2 ci = vec2(c.y, c.w);
22128
+ for (int i = 0; i < maxIter; i++) {
22129
+ vec2 zr2 = ds_sqr(zr);
22130
+ vec2 zi2 = ds_sqr(zi);
22131
+ vec2 mag2 = ds_add(zr2, zi2);
22132
+ if (mag2.x > 4.0)
22133
+ return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22134
+ vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22135
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22136
+ zi = new_zi;
22137
+ }
22138
+ return 1.0;
22139
+ }
22140
+ `;
22141
+ var GPU_FRACTAL_DP_PREAMBLE_WGSL = `
22142
+ fn _fractal_mandelbrot_dp(c: vec4f, maxIter: i32) -> f32 {
22143
+ let cr = vec2f(c.x, c.z);
22144
+ let ci = vec2f(c.y, c.w);
22145
+ var zr = vec2f(0.0, 0.0);
22146
+ var zi = vec2f(0.0, 0.0);
22147
+ for (var i: i32 = 0; i < maxIter; i++) {
22148
+ let zr2 = ds_sqr(zr);
22149
+ let zi2 = ds_sqr(zi);
22150
+ let mag2 = ds_add(zr2, zi2);
22151
+ if (mag2.x > 4.0) {
22152
+ return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22153
+ }
22154
+ let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22155
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22156
+ zi = new_zi;
22157
+ }
22158
+ return 1.0;
22159
+ }
22160
+
22161
+ fn _fractal_julia_dp(z_in: vec4f, c: vec4f, maxIter: i32) -> f32 {
22162
+ var zr = vec2f(z_in.x, z_in.z);
22163
+ var zi = vec2f(z_in.y, z_in.w);
22164
+ let cr = vec2f(c.x, c.z);
22165
+ let ci = vec2f(c.y, c.w);
22166
+ for (var i: i32 = 0; i < maxIter; i++) {
22167
+ let zr2 = ds_sqr(zr);
22168
+ let zi2 = ds_sqr(zi);
22169
+ let mag2 = ds_add(zr2, zi2);
22170
+ if (mag2.x > 4.0) {
22171
+ return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22172
+ }
22173
+ let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22174
+ zr = ds_add(ds_sub(zr2, zi2), cr);
22175
+ zi = new_zi;
22176
+ }
22177
+ return 1.0;
22178
+ }
22179
+ `;
21667
22180
  var GPU_FRACTAL_PREAMBLE_GLSL = `
21668
22181
  float _fractal_mandelbrot(vec2 c, int maxIter) {
21669
22182
  vec2 z = vec2(0.0, 0.0);
@@ -21707,6 +22220,188 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
21707
22220
  return 1.0;
21708
22221
  }
21709
22222
  `;
22223
+ var GPU_FRACTAL_PT_PREAMBLE_GLSL = `
22224
+ uniform sampler2D _refOrbit;
22225
+ uniform int _refOrbitLen;
22226
+ uniform int _refOrbitTexWidth;
22227
+
22228
+ vec2 _pt_fetch_orbit(int i) {
22229
+ int y = i / _refOrbitTexWidth;
22230
+ int x = i - y * _refOrbitTexWidth;
22231
+ return texelFetch(_refOrbit, ivec2(x, y), 0).rg;
22232
+ }
22233
+
22234
+ float _fractal_mandelbrot_pt(vec2 delta_c, int maxIter) {
22235
+ float dr = 0.0;
22236
+ float di = 0.0;
22237
+ int orbitLen = min(maxIter, _refOrbitLen);
22238
+ for (int i = 0; i < orbitLen; i++) {
22239
+ vec2 Zn = _pt_fetch_orbit(i);
22240
+ // delta_{n+1} = 2*Z_n*delta_n + delta_n^2 + delta_c
22241
+ float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22242
+ float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22243
+ dr = new_dr;
22244
+ di = new_di;
22245
+ // Full z = Z_{n+1} + delta for escape check
22246
+ vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22247
+ float zr = Zn1.x + dr;
22248
+ float zi = Zn1.y + di;
22249
+ float mag2 = zr * zr + zi * zi;
22250
+ if (mag2 > 4.0)
22251
+ return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22252
+ // Glitch detection: |delta|^2 > |Z|^2
22253
+ float dmag2 = dr * dr + di * di;
22254
+ float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22255
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22256
+ // Rebase to absolute coordinates and continue with single-float
22257
+ float abs_zr = Zn1.x + dr;
22258
+ float abs_zi = Zn1.y + di;
22259
+ // Reconstruct absolute c from reference + delta
22260
+ // (Use ds_from for the concept, but single-float suffices for fallback)
22261
+ float cx = abs_zr - dr + delta_c.x;
22262
+ float cy = abs_zi - di + delta_c.y;
22263
+ for (int j = i + 1; j < maxIter; j++) {
22264
+ float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22265
+ abs_zi = 2.0 * abs_zr * abs_zi + cy;
22266
+ abs_zr = new_zr;
22267
+ mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22268
+ if (mag2 > 4.0)
22269
+ return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22270
+ }
22271
+ return 1.0;
22272
+ }
22273
+ }
22274
+ return 1.0;
22275
+ }
22276
+
22277
+ float _fractal_julia_pt(vec2 z_delta, vec2 delta_c, int maxIter) {
22278
+ float dr = z_delta.x;
22279
+ float di = z_delta.y;
22280
+ int orbitLen = min(maxIter, _refOrbitLen);
22281
+ for (int i = 0; i < orbitLen; i++) {
22282
+ vec2 Zn = _pt_fetch_orbit(i);
22283
+ float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22284
+ float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22285
+ dr = new_dr;
22286
+ di = new_di;
22287
+ vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22288
+ float zr = Zn1.x + dr;
22289
+ float zi = Zn1.y + di;
22290
+ float mag2 = zr * zr + zi * zi;
22291
+ if (mag2 > 4.0)
22292
+ return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22293
+ float dmag2 = dr * dr + di * di;
22294
+ float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22295
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22296
+ float abs_zr = Zn1.x + dr;
22297
+ float abs_zi = Zn1.y + di;
22298
+ float cx = delta_c.x;
22299
+ float cy = delta_c.y;
22300
+ for (int j = i + 1; j < maxIter; j++) {
22301
+ float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22302
+ abs_zi = 2.0 * abs_zr * abs_zi + cy;
22303
+ abs_zr = new_zr;
22304
+ mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22305
+ if (mag2 > 4.0)
22306
+ return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22307
+ }
22308
+ return 1.0;
22309
+ }
22310
+ }
22311
+ return 1.0;
22312
+ }
22313
+ `;
22314
+ var GPU_FRACTAL_PT_PREAMBLE_WGSL = `
22315
+ @group(0) @binding(1) var _refOrbit: texture_2d<f32>;
22316
+ var<uniform> _refOrbitLen: i32;
22317
+ var<uniform> _refOrbitTexWidth: i32;
22318
+
22319
+ fn _pt_fetch_orbit(i: i32) -> vec2f {
22320
+ let y = i / _refOrbitTexWidth;
22321
+ let x = i - y * _refOrbitTexWidth;
22322
+ return textureLoad(_refOrbit, vec2i(x, y), 0).rg;
22323
+ }
22324
+
22325
+ fn _fractal_mandelbrot_pt(delta_c: vec2f, maxIter: i32) -> f32 {
22326
+ var dr: f32 = 0.0;
22327
+ var di: f32 = 0.0;
22328
+ let orbitLen = min(maxIter, _refOrbitLen);
22329
+ for (var i: i32 = 0; i < orbitLen; i++) {
22330
+ let Zn = _pt_fetch_orbit(i);
22331
+ let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22332
+ let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22333
+ dr = new_dr;
22334
+ di = new_di;
22335
+ var Zn1 = vec2f(0.0);
22336
+ if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22337
+ let zr = Zn1.x + dr;
22338
+ let zi = Zn1.y + di;
22339
+ var mag2 = zr * zr + zi * zi;
22340
+ if (mag2 > 4.0) {
22341
+ return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22342
+ }
22343
+ let dmag2 = dr * dr + di * di;
22344
+ let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22345
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22346
+ var f_zr = Zn1.x + dr;
22347
+ var f_zi = Zn1.y + di;
22348
+ let cx = delta_c.x;
22349
+ let cy = delta_c.y;
22350
+ for (var j: i32 = i + 1; j < maxIter; j++) {
22351
+ let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22352
+ f_zi = 2.0 * f_zr * f_zi + cy;
22353
+ f_zr = t_zr;
22354
+ mag2 = f_zr * f_zr + f_zi * f_zi;
22355
+ if (mag2 > 4.0) {
22356
+ return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22357
+ }
22358
+ }
22359
+ return 1.0;
22360
+ }
22361
+ }
22362
+ return 1.0;
22363
+ }
22364
+
22365
+ fn _fractal_julia_pt(z_delta: vec2f, delta_c: vec2f, maxIter: i32) -> f32 {
22366
+ var dr = z_delta.x;
22367
+ var di = z_delta.y;
22368
+ let orbitLen = min(maxIter, _refOrbitLen);
22369
+ for (var i: i32 = 0; i < orbitLen; i++) {
22370
+ let Zn = _pt_fetch_orbit(i);
22371
+ let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22372
+ let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22373
+ dr = new_dr;
22374
+ di = new_di;
22375
+ var Zn1 = vec2f(0.0);
22376
+ if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22377
+ let zr = Zn1.x + dr;
22378
+ let zi = Zn1.y + di;
22379
+ var mag2 = zr * zr + zi * zi;
22380
+ if (mag2 > 4.0) {
22381
+ return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22382
+ }
22383
+ let dmag2 = dr * dr + di * di;
22384
+ let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22385
+ if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22386
+ var f_zr = Zn1.x + dr;
22387
+ var f_zi = Zn1.y + di;
22388
+ let cx = delta_c.x;
22389
+ let cy = delta_c.y;
22390
+ for (var j: i32 = i + 1; j < maxIter; j++) {
22391
+ let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22392
+ f_zi = 2.0 * f_zr * f_zi + cy;
22393
+ f_zr = t_zr;
22394
+ mag2 = f_zr * f_zr + f_zi * f_zi;
22395
+ if (mag2 > 4.0) {
22396
+ return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22397
+ }
22398
+ }
22399
+ return 1.0;
22400
+ }
22401
+ }
22402
+ return 1.0;
22403
+ }
22404
+ `;
21710
22405
  var GPU_COLOR_PREAMBLE_GLSL = `
21711
22406
  float _gpu_srgb_to_linear(float c) {
21712
22407
  if (c <= 0.04045) return c / 12.92;
@@ -22145,6 +22840,7 @@ var GPUShaderTarget = class {
22145
22840
  const constants = this.getConstants();
22146
22841
  const v2 = this.languageId === "wgsl" ? "vec2f" : "vec2";
22147
22842
  const target = this.createTarget({
22843
+ hints: options.hints,
22148
22844
  functions: (id) => {
22149
22845
  if (userFunctions && id in userFunctions) {
22150
22846
  const fn = userFunctions[id];
@@ -22183,12 +22879,65 @@ var GPUShaderTarget = class {
22183
22879
  if (code.includes("_gpu_besselJ"))
22184
22880
  preamble += this.languageId === "wgsl" ? GPU_BESSELJ_PREAMBLE_WGSL : GPU_BESSELJ_PREAMBLE_GLSL;
22185
22881
  if (code.includes("_fractal_")) {
22186
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22882
+ if (code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) {
22883
+ preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22884
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PT_PREAMBLE_WGSL : GPU_FRACTAL_PT_PREAMBLE_GLSL;
22885
+ } else if (code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) {
22886
+ preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22887
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_DP_PREAMBLE_WGSL : GPU_FRACTAL_DP_PREAMBLE_GLSL;
22888
+ } else {
22889
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22890
+ }
22187
22891
  }
22188
22892
  if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
22189
22893
  preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
22190
22894
  }
22191
22895
  if (preamble) result.preamble = preamble;
22896
+ if (code.includes("_fractal_") && options.hints?.viewport) {
22897
+ const strategy = selectFractalStrategy(target);
22898
+ const radius = options.hints.viewport.radius;
22899
+ switch (strategy) {
22900
+ case "single":
22901
+ result.staleWhen = { radiusBelow: 1e-6 };
22902
+ break;
22903
+ case "double":
22904
+ result.staleWhen = { radiusBelow: 1e-14, radiusAbove: 1e-5 };
22905
+ break;
22906
+ case "perturbation":
22907
+ result.staleWhen = {
22908
+ radiusAbove: 1e-5,
22909
+ radiusBelow: radius * 0.01,
22910
+ centerDistance: radius * 2
22911
+ };
22912
+ break;
22913
+ }
22914
+ }
22915
+ if ((code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) && options.hints?.viewport) {
22916
+ const viewport = options.hints.viewport;
22917
+ const digits = Math.max(50, Math.ceil(-Math.log10(viewport.radius)) + 10);
22918
+ const maxIter = 1e3;
22919
+ const orbit = computeReferenceOrbit(
22920
+ viewport.center,
22921
+ maxIter,
22922
+ digits
22923
+ );
22924
+ const orbitLen = orbit.length / 2;
22925
+ const texWidth = Math.min(orbitLen, 4096);
22926
+ const texHeight = Math.ceil(orbitLen / texWidth);
22927
+ result.textures = {
22928
+ _refOrbit: {
22929
+ data: orbit,
22930
+ width: texWidth,
22931
+ height: texHeight,
22932
+ format: "rg32f"
22933
+ }
22934
+ };
22935
+ result.uniforms = {
22936
+ ...result.uniforms,
22937
+ _refOrbitLen: orbitLen,
22938
+ _refOrbitTexWidth: texWidth
22939
+ };
22940
+ }
22192
22941
  return result;
22193
22942
  }
22194
22943
  compileToSource(expr, _options = {}) {
@@ -22422,6 +23171,7 @@ var PYTHON_OPERATORS = {
22422
23171
  Negate: ["-", 14],
22423
23172
  // Unary operator
22424
23173
  Subtract: ["-", 11],
23174
+ // Subtract canonicalizes to Add+Negate; kept as fallback
22425
23175
  Multiply: ["*", 12],
22426
23176
  Divide: ["/", 13],
22427
23177
  Power: ["**", 15],
@@ -22449,16 +23199,7 @@ var PYTHON_FUNCTIONS = {
22449
23199
  if (args.length === 1) return compile2(args[0]);
22450
23200
  return args.map((x) => compile2(x)).join(" * ");
22451
23201
  },
22452
- Subtract: (args, compile2) => {
22453
- if (args.length === 0) return "0";
22454
- if (args.length === 1) return compile2(args[0]);
22455
- if (args.length === 2) return `${compile2(args[0])} - ${compile2(args[1])}`;
22456
- let result = compile2(args[0]);
22457
- for (let i = 1; i < args.length; i++) {
22458
- result = `${result} - ${compile2(args[i])}`;
22459
- }
22460
- return result;
22461
- },
23202
+ // No Subtract handler canonicalizes to Add+Negate before compilation.
22462
23203
  Divide: (args, compile2) => {
22463
23204
  if (args.length === 0) return "1";
22464
23205
  if (args.length === 1) return compile2(args[0]);
@@ -24123,6 +24864,7 @@ var INTERVAL_JAVASCRIPT_OPERATORS = {
24123
24864
  Add: ["_IA.add", 20],
24124
24865
  Negate: ["_IA.negate", 20],
24125
24866
  Subtract: ["_IA.sub", 20],
24867
+ // Subtract canonicalizes to Add+Negate; kept as fallback
24126
24868
  Multiply: ["_IA.mul", 20],
24127
24869
  Divide: ["_IA.div", 20],
24128
24870
  // Comparisons return BoolInterval
@@ -24147,17 +24889,7 @@ var INTERVAL_JAVASCRIPT_FUNCTIONS = {
24147
24889
  }
24148
24890
  return result;
24149
24891
  },
24150
- Subtract: (args, compile2) => {
24151
- if (args.length === 0) return "_IA.point(0)";
24152
- if (args.length === 1) return `_IA.negate(${compile2(args[0])})`;
24153
- if (args.length === 2)
24154
- return `_IA.sub(${compile2(args[0])}, ${compile2(args[1])})`;
24155
- let result = compile2(args[0]);
24156
- for (let i = 1; i < args.length; i++) {
24157
- result = `_IA.sub(${result}, ${compile2(args[i])})`;
24158
- }
24159
- return result;
24160
- },
24892
+ // No Subtract handler canonicalizes to Add+Negate before compilation.
24161
24893
  Multiply: (args, compile2) => {
24162
24894
  if (args.length === 0) return "_IA.point(1)";
24163
24895
  if (args.length === 1) return compile2(args[0]);
@@ -24540,7 +25272,7 @@ function compileToIntervalTarget(expr, target) {
24540
25272
  }
24541
25273
 
24542
25274
  // src/compile.ts
24543
- var version = "0.55.2";
25275
+ var version = "0.55.4";
24544
25276
  export {
24545
25277
  BaseCompiler,
24546
25278
  GLSLTarget,