@cortex-js/compute-engine 0.55.5 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/dist/compile.esm.js +912 -770
  2. package/dist/compile.min.esm.js +300 -523
  3. package/dist/compile.min.umd.cjs +301 -524
  4. package/dist/compile.umd.cjs +912 -770
  5. package/dist/compute-engine.esm.js +1517 -902
  6. package/dist/compute-engine.min.esm.js +300 -522
  7. package/dist/compute-engine.min.umd.cjs +300 -522
  8. package/dist/compute-engine.umd.cjs +1517 -902
  9. package/dist/core.esm.js +1516 -901
  10. package/dist/core.min.esm.js +299 -521
  11. package/dist/core.min.umd.cjs +299 -521
  12. package/dist/core.umd.cjs +1516 -901
  13. package/dist/interval.esm.js +268 -63
  14. package/dist/interval.min.esm.js +7 -7
  15. package/dist/interval.min.umd.cjs +7 -7
  16. package/dist/interval.umd.cjs +268 -63
  17. package/dist/latex-syntax.esm.js +371 -77
  18. package/dist/latex-syntax.min.esm.js +7 -6
  19. package/dist/latex-syntax.min.umd.cjs +7 -6
  20. package/dist/latex-syntax.umd.cjs +371 -77
  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 +4 -2
  26. package/dist/numerics.min.esm.js +3 -3
  27. package/dist/numerics.min.umd.cjs +3 -3
  28. package/dist/numerics.umd.cjs +4 -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 +2 -2
  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 +1 -1
  105. package/dist/types/compute-engine/compilation/compile-expression.d.ts +2 -3
  106. package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
  107. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  108. package/dist/types/compute-engine/compilation/gpu-target.d.ts +15 -58
  109. package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
  110. package/dist/types/compute-engine/compilation/javascript-target.d.ts +25 -3
  111. package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
  112. package/dist/types/compute-engine/compilation/types.d.ts +1 -67
  113. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  114. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  115. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
  126. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  131. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  132. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  133. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  134. package/dist/types/compute-engine/global-types.d.ts +1 -1
  135. package/dist/types/compute-engine/index.d.ts +23 -3
  136. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  142. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  143. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +4 -3
  144. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  145. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  146. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  147. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +10 -0
  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 +9 -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 +4 -2
  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 +6 -2
  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 +2 -3
  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 +2 -2
  259. package/dist/types/compute-engine/compilation/fractal-orbit.d.ts +0 -19
@@ -1,4 +1,4 @@
1
- /** Compute Engine 0.55.5 */
1
+ /** Compute Engine 0.56.0 */
2
2
 
3
3
  // src/compute-engine/numerics/richardson.ts
4
4
  function extrapolate(f, x0, options = {}) {
@@ -1511,6 +1511,7 @@ var SCALAR_TYPES = [
1511
1511
  ];
1512
1512
  var VALUE_TYPES = [
1513
1513
  "value",
1514
+ "color",
1514
1515
  ...COLLECTION_TYPES,
1515
1516
  ...SCALAR_TYPES
1516
1517
  ];
@@ -3206,6 +3207,7 @@ var PRIMITIVE_SUBTYPES = {
3206
3207
  symbol: [],
3207
3208
  boolean: [],
3208
3209
  string: [],
3210
+ color: [],
3209
3211
  expression: EXPRESSION_TYPES
3210
3212
  };
3211
3213
  function isPrimitiveSubtype(lhs, rhs) {
@@ -6240,10 +6242,6 @@ var DEFINITIONS_CORE = [
6240
6242
  // Lagrange notation
6241
6243
  {
6242
6244
  name: "Derivative",
6243
- // @todo: Leibniz notation: {% latex " \\frac{d^n}{dx^n} f(x)" %}
6244
- // @todo: Euler modified notation: This notation is used by Mathematica. The Euler notation uses `D` instead of
6245
- // `\partial`: `\partial_{x} f`, `\partial_{x,y} f`
6246
- // Newton notation (\dot{v}, \ddot{v}) is implemented below
6247
6245
  serialize: (serializer, expr) => {
6248
6246
  const degree = machineValue(operand(expr, 2)) ?? 1;
6249
6247
  const base = serializer.serialize(operand(expr, 1));
@@ -7281,14 +7279,18 @@ var DEFINITIONS_SETS = [
7281
7279
  return ["Complement", lhs];
7282
7280
  }
7283
7281
  // precedence: 240,
7284
- // @todo: serialize for the multiple argument case
7285
7282
  },
7286
7283
  {
7287
7284
  name: "Complement",
7288
7285
  latexTrigger: ["^", "<{>", "\\complement", "<}>"],
7289
- kind: "postfix"
7286
+ kind: "postfix",
7290
7287
  // precedence: 240,
7291
- // @todo: serialize for the multiple argument case
7288
+ serialize: (serializer, expr) => {
7289
+ return joinLatex([
7290
+ serializer.serialize(operand(expr, 1)),
7291
+ "^\\complement"
7292
+ ]);
7293
+ }
7292
7294
  },
7293
7295
  {
7294
7296
  name: "Intersection",
@@ -7375,7 +7377,6 @@ var DEFINITIONS_SETS = [
7375
7377
  // commands like \rbrack a, b \rbrack which are unambiguous.
7376
7378
  {
7377
7379
  name: "Multiple",
7378
- // @todo: parse
7379
7380
  serialize: serializeSet
7380
7381
  },
7381
7382
  {
@@ -7384,14 +7385,28 @@ var DEFINITIONS_SETS = [
7384
7385
  kind: "infix",
7385
7386
  precedence: 350
7386
7387
  },
7388
+ // \mid as a separator/operator (used in set-builder notation: {x \mid x > 0})
7389
+ // Low precedence so it binds loosely — everything on each side is parsed first
7390
+ {
7391
+ name: "Divides",
7392
+ latexTrigger: ["\\mid"],
7393
+ kind: "infix",
7394
+ precedence: 160
7395
+ },
7387
7396
  {
7388
7397
  name: "Set",
7389
7398
  kind: "matchfix",
7390
7399
  openTrigger: "{",
7391
7400
  closeTrigger: "}",
7392
- // @todo: the set syntax can also include conditions...
7393
7401
  parse: (_parser, body) => {
7394
7402
  if (isEmptySequence(body)) return "EmptySet";
7403
+ const h = operator(body);
7404
+ if (h === "Divides" || h === "Colon") {
7405
+ const expr = operand(body, 1);
7406
+ const condition = operand(body, 2);
7407
+ if (expr !== null && condition !== null)
7408
+ return ["Set", expr, ["Condition", condition]];
7409
+ }
7395
7410
  if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
7396
7411
  body = operand(body, 1);
7397
7412
  }
@@ -7399,6 +7414,17 @@ var DEFINITIONS_SETS = [
7399
7414
  return ["Set", ...operands(body)];
7400
7415
  },
7401
7416
  serialize: (serializer, expr) => {
7417
+ if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
7418
+ const condition = operand(expr, 2);
7419
+ return joinLatex([
7420
+ "\\lbrace",
7421
+ serializer.serialize(operand(expr, 1)),
7422
+ "\\mid",
7423
+ // Serialize the inner expression of the Condition wrapper
7424
+ serializer.serialize(operand(condition, 1)),
7425
+ "\\rbrace"
7426
+ ]);
7427
+ }
7402
7428
  return joinLatex([
7403
7429
  "\\lbrace",
7404
7430
  operands(expr).map((x) => serializer.serialize(x)).join(", "),
@@ -7565,23 +7591,6 @@ function serializeSet(serializer, expr) {
7565
7591
  if (expr === null) return "";
7566
7592
  const h = operator(expr);
7567
7593
  if (!h) return "";
7568
- if (h === "Set") {
7569
- if (nops(expr) === 0) return "\\emptyset";
7570
- if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
7571
- return joinLatex([
7572
- "\\left\\lbrace",
7573
- serializer.serialize(operand(expr, 1)),
7574
- "\\middle\\mid",
7575
- serializer.serialize(operand(expr, 2)),
7576
- "\\right\\rbrace"
7577
- ]);
7578
- }
7579
- return joinLatex([
7580
- "\\left\\lbrace",
7581
- ...operands(expr).map((x) => serializer.serialize(x) + " ,"),
7582
- "\\right\\rbrace"
7583
- ]);
7584
- }
7585
7594
  if (h === "Multiple") {
7586
7595
  }
7587
7596
  if (h === "Range") {
@@ -8699,11 +8708,13 @@ var DEFINITIONS_ARITHMETIC = [
8699
8708
  if (!parser.match("_")) return null;
8700
8709
  const base = parser.parseGroup();
8701
8710
  if (operator(base) !== "To") return null;
8702
- const expr = parser.parseArguments("implicit");
8711
+ const expr = parser.parseExpression({
8712
+ minPrec: MULTIPLICATION_PRECEDENCE
8713
+ });
8703
8714
  if (!expr) return null;
8704
8715
  return [
8705
8716
  "Limit",
8706
- ["Function", expr[0], operand(base, 1)],
8717
+ ["Function", expr, operand(base, 1)],
8707
8718
  operand(base, 2)
8708
8719
  ];
8709
8720
  },
@@ -8784,6 +8795,8 @@ var DEFINITIONS_ARITHMETIC = [
8784
8795
  precedence: DIVISION_PRECEDENCE,
8785
8796
  parse: "Mod"
8786
8797
  },
8798
+ // Function-style alias: `\operatorname{mod}(a, b)`
8799
+ { latexTrigger: "\\operatorname{mod}", parse: "Mod" },
8787
8800
  {
8788
8801
  latexTrigger: "\\pmod",
8789
8802
  kind: "prefix",
@@ -9024,6 +9037,13 @@ var DEFINITIONS_ARITHMETIC = [
9024
9037
  const rhs = serializer.wrap(operand(expr, 2), ADDITION_PRECEDENCE + 3);
9025
9038
  return joinLatex([lhs, "-", rhs]);
9026
9039
  }
9040
+ },
9041
+ // Euclidean distance between two points (tuples of numbers).
9042
+ {
9043
+ name: "Distance",
9044
+ latexTrigger: ["\\operatorname{distance}"],
9045
+ kind: "function",
9046
+ serialize: (serializer, expr) => "\\operatorname{distance}" + serializer.wrapArguments(expr)
9027
9047
  }
9028
9048
  ];
9029
9049
  function getIndexAssignment(expr, upper) {
@@ -10448,7 +10468,9 @@ var DEFINITIONS_STATISTICS = [
10448
10468
  if (!expr || !symbol(expr)) return null;
10449
10469
  return ["Mean", expr];
10450
10470
  }
10451
- }
10471
+ },
10472
+ // Function-style alias: `\operatorname{var}(...)`
10473
+ { latexTrigger: "\\operatorname{var}", parse: "Variance" }
10452
10474
  ];
10453
10475
 
10454
10476
  // src/compute-engine/numerics/unit-data.ts
@@ -10907,12 +10929,52 @@ var DEFINITIONS_UNITS = [
10907
10929
  ];
10908
10930
 
10909
10931
  // src/compute-engine/latex-syntax/dictionary/definitions-other.ts
10932
+ var TEX_UNITS = [
10933
+ "pt",
10934
+ "em",
10935
+ "mu",
10936
+ "ex",
10937
+ "mm",
10938
+ "cm",
10939
+ "in",
10940
+ "bp",
10941
+ "sp",
10942
+ "dd",
10943
+ "cc",
10944
+ "pc",
10945
+ "nc",
10946
+ "nd"
10947
+ ];
10948
+ function skipTexDimension(parser) {
10949
+ parser.skipSpace();
10950
+ if (parser.peek === "-" || parser.peek === "+") parser.nextToken();
10951
+ while (/^[\d.]$/.test(parser.peek)) parser.nextToken();
10952
+ for (const unit of TEX_UNITS) {
10953
+ if (parser.matchAll([...unit])) return;
10954
+ }
10955
+ }
10910
10956
  function parseSingleArg(cmd) {
10911
10957
  return (parser) => {
10912
10958
  const arg = parser.parseGroup();
10913
10959
  return arg === null ? [cmd] : [cmd, arg];
10914
10960
  };
10915
10961
  }
10962
+ function parseMathStyleSwitch(mathStyle) {
10963
+ return (parser) => {
10964
+ const body = parser.parseExpression();
10965
+ if (body !== null && !isEmptySequence(body))
10966
+ return ["Annotated", body, { dict: { mathStyle } }];
10967
+ return "Nothing";
10968
+ };
10969
+ }
10970
+ function parseSizeSwitch(size) {
10971
+ return (parser) => {
10972
+ const body = parser.parseExpression();
10973
+ if (body !== null && !isEmptySequence(body))
10974
+ return ["Annotated", body, { dict: { size } }];
10975
+ return "Nothing";
10976
+ };
10977
+ }
10916
10978
  var DEFINITIONS_OTHERS = [
10917
10979
  {
10918
10980
  name: "Overscript",
@@ -11152,80 +11214,71 @@ var DEFINITIONS_OTHERS = [
11152
11214
  },
11153
11215
  {
11154
11216
  latexTrigger: ["\\displaystyle"],
11155
- parse: () => "Nothing"
11156
- // @todo: parse as ['Annotated'...]
11217
+ parse: parseMathStyleSwitch("normal")
11157
11218
  },
11158
11219
  {
11159
11220
  latexTrigger: ["\\textstyle"],
11160
- parse: () => "Nothing"
11161
- // @todo: parse as ['Annotated'...]
11221
+ parse: parseMathStyleSwitch("compact")
11162
11222
  },
11163
11223
  {
11164
11224
  latexTrigger: ["\\scriptstyle"],
11165
- parse: () => "Nothing"
11166
- // @todo: parse as ['Annotated'...]
11225
+ parse: parseMathStyleSwitch("script")
11167
11226
  },
11168
11227
  {
11169
11228
  latexTrigger: ["\\scriptscriptstyle"],
11170
- parse: () => "Nothing"
11171
- // @todo: parse as ['Annotated'...]
11229
+ parse: parseMathStyleSwitch("scriptscript")
11172
11230
  },
11173
11231
  {
11174
11232
  latexTrigger: ["\\color"],
11175
11233
  parse: (parser) => {
11176
- parser.parseGroup();
11234
+ const color = parser.parseStringGroup();
11235
+ if (color !== null) {
11236
+ const body = parser.parseExpression();
11237
+ if (body !== null && !isEmptySequence(body))
11238
+ return ["Annotated", body, { dict: { color } }];
11239
+ }
11177
11240
  return "Nothing";
11178
11241
  }
11179
11242
  },
11180
11243
  {
11181
11244
  latexTrigger: ["\\tiny"],
11182
- parse: () => "Nothing"
11183
- // @todo: parse as ['Annotated'...]
11245
+ parse: parseSizeSwitch(1)
11184
11246
  },
11185
11247
  {
11186
11248
  latexTrigger: ["\\scriptsize"],
11187
- parse: () => "Nothing"
11188
- // @todo: parse as ['Annotated'...]
11249
+ parse: parseSizeSwitch(2)
11189
11250
  },
11190
11251
  {
11191
11252
  latexTrigger: ["\\footnotesize"],
11192
- parse: () => "Nothing"
11193
- // @todo: parse as ['Annotated'...]
11253
+ parse: parseSizeSwitch(3)
11194
11254
  },
11195
11255
  {
11196
11256
  latexTrigger: ["\\small"],
11197
- parse: () => "Nothing"
11198
- // @todo: parse as ['Annotated'...]
11257
+ parse: parseSizeSwitch(4)
11199
11258
  },
11200
11259
  {
11201
11260
  latexTrigger: ["\\normalsize"],
11202
- parse: () => "Nothing"
11203
- // @todo: parse as ['Annotated'...]
11261
+ parse: parseSizeSwitch(5)
11204
11262
  },
11205
11263
  {
11206
11264
  latexTrigger: ["\\large"],
11207
- parse: () => "Nothing"
11208
- // @todo: parse as ['Annotated'...]
11265
+ parse: parseSizeSwitch(6)
11209
11266
  },
11210
11267
  {
11211
11268
  latexTrigger: ["\\Large"],
11212
- parse: () => "Nothing"
11213
- // @todo: parse as ['Annotated'...]
11269
+ parse: parseSizeSwitch(7)
11214
11270
  },
11215
11271
  {
11216
11272
  latexTrigger: ["\\LARGE"],
11217
- parse: () => "Nothing"
11218
- // @todo: parse as ['Annotated'...]
11273
+ parse: parseSizeSwitch(8)
11219
11274
  },
11220
11275
  {
11221
11276
  latexTrigger: ["\\huge"],
11222
- parse: () => "Nothing"
11223
- // @todo: parse as ['Annotated'...]
11277
+ parse: parseSizeSwitch(9)
11224
11278
  },
11225
11279
  {
11226
11280
  latexTrigger: ["\\Huge"],
11227
- parse: () => "Nothing"
11228
- // @todo: parse as ['Annotated'...]
11281
+ parse: parseSizeSwitch(10)
11229
11282
  },
11230
11283
  {
11231
11284
  name: "Annotated",
@@ -11237,6 +11290,10 @@ var DEFINITIONS_OTHERS = [
11237
11290
  result = joinLatex(["{\\displaystyle", result, "}"]);
11238
11291
  else if (dict.dict.mathStyle === "compact")
11239
11292
  result = joinLatex(["{\\textstyle", result, "}"]);
11293
+ else if (dict.dict.mathStyle === "script")
11294
+ result = joinLatex(["{\\scriptstyle", result, "}"]);
11295
+ else if (dict.dict.mathStyle === "scriptscript")
11296
+ result = joinLatex(["{\\scriptscriptstyle", result, "}"]);
11240
11297
  const v = dict.dict.size;
11241
11298
  if (v !== null && v >= 1 && v <= 10) {
11242
11299
  result = joinLatex([
@@ -11324,6 +11381,28 @@ var DEFINITIONS_OTHERS = [
11324
11381
  latexTrigger: ["\\enspace"],
11325
11382
  parse: () => ["HorizontalSpacing", 9]
11326
11383
  },
11384
+ {
11385
+ latexTrigger: ["\\hspace"],
11386
+ parse: (parser) => {
11387
+ if (parser.peek === "*") parser.nextToken();
11388
+ parser.parseStringGroup();
11389
+ return ["HorizontalSpacing", 0];
11390
+ }
11391
+ },
11392
+ {
11393
+ latexTrigger: ["\\hskip"],
11394
+ parse: (parser) => {
11395
+ skipTexDimension(parser);
11396
+ return ["HorizontalSpacing", 0];
11397
+ }
11398
+ },
11399
+ {
11400
+ latexTrigger: ["\\kern"],
11401
+ parse: (parser) => {
11402
+ skipTexDimension(parser);
11403
+ return ["HorizontalSpacing", 0];
11404
+ }
11405
+ },
11327
11406
  {
11328
11407
  latexTrigger: ["\\phantom"],
11329
11408
  parse: (parser) => {
@@ -11374,7 +11453,17 @@ var DEFINITIONS_OTHERS = [
11374
11453
  // `["HorizontalSpacing", expr, 'op'|'bin'|rel]` -> indicate a spacing around and expression, i.e. `\mathbin{x}`, etc...
11375
11454
  serialize: (serializer, expr) => {
11376
11455
  if (operand(expr, 2) !== null) {
11377
- return serializer.serialize(operand(expr, 1));
11456
+ const cls = stringValue(operand(expr, 2));
11457
+ const inner = serializer.serialize(operand(expr, 1));
11458
+ if (cls === "bin") return `\\mathbin{${inner}}`;
11459
+ if (cls === "op") return `\\mathop{${inner}}`;
11460
+ if (cls === "rel") return `\\mathrel{${inner}}`;
11461
+ if (cls === "ord") return `\\mathord{${inner}}`;
11462
+ if (cls === "open") return `\\mathopen{${inner}}`;
11463
+ if (cls === "close") return `\\mathclose{${inner}}`;
11464
+ if (cls === "punct") return `\\mathpunct{${inner}}`;
11465
+ if (cls === "inner") return `\\mathinner{${inner}}`;
11466
+ return inner;
11378
11467
  }
11379
11468
  const v = machineValue(operand(expr, 1));
11380
11469
  if (v === null) return "";
@@ -11389,7 +11478,7 @@ var DEFINITIONS_OTHERS = [
11389
11478
  36: "\\qquad"
11390
11479
  }[v] ?? "";
11391
11480
  }
11392
- }
11481
+ },
11393
11482
  // if (
11394
11483
  // [
11395
11484
  // '\\!',
@@ -11413,6 +11502,121 @@ var DEFINITIONS_OTHERS = [
11413
11502
  // name: '',
11414
11503
  // trigger: '\\check',
11415
11504
  // },
11505
+ // ---------------------------------------------------------------------------
11506
+ // Function-style aliases for collection / random operators that some
11507
+ // notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
11508
+ // The capitalized library entries already exist; these are pure parse
11509
+ // aliases so the lowercase names don't land in `unsupported-operator`.
11510
+ // ---------------------------------------------------------------------------
11511
+ { latexTrigger: "\\operatorname{random}", parse: "Random" },
11512
+ { latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
11513
+ { latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
11514
+ { latexTrigger: "\\operatorname{join}", parse: "Join" },
11515
+ // ---------------------------------------------------------------------------
11516
+ // Geometric primitive heads. Registered as known typed heads so consumers
11517
+ // can branch on the operator name; CE itself doesn't render them. The
11518
+ // library entries (with no evaluator) live in `library/core.ts`.
11519
+ // ---------------------------------------------------------------------------
11520
+ {
11521
+ name: "Triangle",
11522
+ latexTrigger: ["\\operatorname{triangle}"],
11523
+ kind: "function",
11524
+ serialize: (serializer, expr) => "\\operatorname{triangle}" + serializer.wrapArguments(expr)
11525
+ },
11526
+ // Desmos's geometric `vector(p1, p2)` — a directed segment between two
11527
+ // points. Routed to a dedicated head (not the existing column-vector
11528
+ // `Vector`, which has a narrower `(number+) -> vector` signature).
11529
+ {
11530
+ name: "GeometricVector",
11531
+ latexTrigger: ["\\operatorname{vector}"],
11532
+ kind: "function",
11533
+ serialize: (serializer, expr) => "\\operatorname{vector}" + serializer.wrapArguments(expr)
11534
+ },
11535
+ {
11536
+ name: "Sphere",
11537
+ latexTrigger: ["\\operatorname{sphere}"],
11538
+ kind: "function",
11539
+ serialize: (serializer, expr) => "\\operatorname{sphere}" + serializer.wrapArguments(expr)
11540
+ },
11541
+ {
11542
+ name: "Segment",
11543
+ latexTrigger: ["\\operatorname{segment}"],
11544
+ kind: "function",
11545
+ serialize: (serializer, expr) => "\\operatorname{segment}" + serializer.wrapArguments(expr)
11546
+ }
11547
+ ];
11548
+
11549
+ // src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
11550
+ var DEFINITIONS_COLORS = [
11551
+ // Color constructors (one per colorspace, preserves space on evaluation)
11552
+ {
11553
+ name: "Rgb",
11554
+ latexTrigger: ["\\operatorname{rgb}"],
11555
+ kind: "function",
11556
+ serialize: (serializer, expr) => "\\operatorname{rgb}" + serializer.wrapArguments(expr)
11557
+ },
11558
+ {
11559
+ name: "Hsv",
11560
+ latexTrigger: ["\\operatorname{hsv}"],
11561
+ kind: "function",
11562
+ serialize: (serializer, expr) => "\\operatorname{hsv}" + serializer.wrapArguments(expr)
11563
+ },
11564
+ {
11565
+ name: "Hsl",
11566
+ latexTrigger: ["\\operatorname{hsl}"],
11567
+ kind: "function",
11568
+ serialize: (serializer, expr) => "\\operatorname{hsl}" + serializer.wrapArguments(expr)
11569
+ },
11570
+ {
11571
+ name: "Oklab",
11572
+ latexTrigger: ["\\operatorname{oklab}"],
11573
+ kind: "function",
11574
+ serialize: (serializer, expr) => "\\operatorname{oklab}" + serializer.wrapArguments(expr)
11575
+ },
11576
+ {
11577
+ name: "Oklch",
11578
+ latexTrigger: ["\\operatorname{oklch}"],
11579
+ kind: "function",
11580
+ serialize: (serializer, expr) => "\\operatorname{oklch}" + serializer.wrapArguments(expr)
11581
+ },
11582
+ // Conversion functions (color → color in the named space)
11583
+ {
11584
+ name: "AsRgb",
11585
+ latexTrigger: ["\\operatorname{asRgb}"],
11586
+ kind: "function",
11587
+ serialize: (serializer, expr) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr)
11588
+ },
11589
+ {
11590
+ name: "AsHsv",
11591
+ latexTrigger: ["\\operatorname{asHsv}"],
11592
+ kind: "function",
11593
+ serialize: (serializer, expr) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr)
11594
+ },
11595
+ {
11596
+ name: "AsHsl",
11597
+ latexTrigger: ["\\operatorname{asHsl}"],
11598
+ kind: "function",
11599
+ serialize: (serializer, expr) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr)
11600
+ },
11601
+ {
11602
+ name: "AsOklab",
11603
+ latexTrigger: ["\\operatorname{asOklab}"],
11604
+ kind: "function",
11605
+ serialize: (serializer, expr) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr)
11606
+ },
11607
+ {
11608
+ name: "AsOklch",
11609
+ latexTrigger: ["\\operatorname{asOklch}"],
11610
+ kind: "function",
11611
+ serialize: (serializer, expr) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr)
11612
+ },
11613
+ // Perceptual difference (returns a scalar in [0, ~1])
11614
+ {
11615
+ name: "ColorDelta",
11616
+ latexTrigger: ["\\operatorname{colorDelta}"],
11617
+ kind: "function",
11618
+ serialize: (serializer, expr) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr)
11619
+ }
11416
11620
  ];
11417
11621
 
11418
11622
  // src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
@@ -11443,7 +11647,8 @@ var LATEX_DICTIONARY = [
11443
11647
  ...DEFINITIONS_STATISTICS,
11444
11648
  ...DEFINITIONS_UNITS,
11445
11649
  ...DEFINITIONS_OTHERS,
11446
- ...DEFINITIONS_PHYSICS
11650
+ ...DEFINITIONS_PHYSICS,
11651
+ ...DEFINITIONS_COLORS
11447
11652
  ];
11448
11653
 
11449
11654
  // src/math-json/symbols.ts
@@ -15066,8 +15271,7 @@ function compile(expr, options) {
15066
15271
  vars: options?.vars,
15067
15272
  imports: options?.imports,
15068
15273
  preamble: options?.preamble,
15069
- realOnly: options?.realOnly,
15070
- hints: options?.hints
15274
+ realOnly: options?.realOnly
15071
15275
  });
15072
15276
  } catch (e) {
15073
15277
  if (options?.fallback ?? true) {
@@ -15079,8 +15283,7 @@ function compile(expr, options) {
15079
15283
  ce.pushScope();
15080
15284
  try {
15081
15285
  if (vars && typeof vars === "object") {
15082
- for (const [k, v] of Object.entries(vars))
15083
- ce.assign(k, v);
15286
+ for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
15084
15287
  }
15085
15288
  return expr.evaluate().re;
15086
15289
  } finally {
@@ -15167,8 +15370,7 @@ function tryGetComplexParts(expr, compile2) {
15167
15370
  return { re: null, im: formatFloat(iScale) };
15168
15371
  }
15169
15372
  const compiledFactors = remaining.map((r) => compile2(r));
15170
- if (iScale !== 1)
15171
- compiledFactors.unshift(formatFloat(iScale));
15373
+ if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
15172
15374
  const imCode = foldTerms(compiledFactors, "1.0", "*");
15173
15375
  return { re: null, im: imCode };
15174
15376
  }
@@ -15233,6 +15435,40 @@ function rgbToHsl(r, g, b) {
15233
15435
  else h = ((r - g) / d + 4) / 6;
15234
15436
  return { h: h * 360, s, l };
15235
15437
  }
15438
+ function hsvToRgb(h, s, v) {
15439
+ h = (h % 360 + 360) % 360;
15440
+ s = Math.max(0, Math.min(1, s));
15441
+ v = Math.max(0, Math.min(1, v));
15442
+ const c = v * s;
15443
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
15444
+ const m = v - c;
15445
+ let r = 0, g = 0, b = 0;
15446
+ if (h < 60) [r, g, b] = [c, x, 0];
15447
+ else if (h < 120) [r, g, b] = [x, c, 0];
15448
+ else if (h < 180) [r, g, b] = [0, c, x];
15449
+ else if (h < 240) [r, g, b] = [0, x, c];
15450
+ else if (h < 300) [r, g, b] = [x, 0, c];
15451
+ else [r, g, b] = [c, 0, x];
15452
+ return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
15453
+ }
15454
+ function rgbToHsv(r, g, b) {
15455
+ r /= 255;
15456
+ g /= 255;
15457
+ b /= 255;
15458
+ const max2 = Math.max(r, g, b);
15459
+ const min2 = Math.min(r, g, b);
15460
+ const d = max2 - min2;
15461
+ let h = 0;
15462
+ if (d > 0) {
15463
+ if (max2 === r) h = (g - b) / d % 6;
15464
+ else if (max2 === g) h = (b - r) / d + 2;
15465
+ else h = (r - g) / d + 4;
15466
+ h *= 60;
15467
+ if (h < 0) h += 360;
15468
+ }
15469
+ const s = max2 === 0 ? 0 : d / max2;
15470
+ return { h, s, v: max2 };
15471
+ }
15236
15472
  function parseHexColor(s) {
15237
15473
  const hex = s.startsWith("#") ? s.substring(1) : s;
15238
15474
  let r, g, b;
@@ -15688,6 +15924,13 @@ var NAMED_COLORS = {
15688
15924
  };
15689
15925
  function parseColor(s, darkMode) {
15690
15926
  const str = s.trim().toLowerCase();
15927
+ const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
15928
+ if (opacityMatch) {
15929
+ const base = parseColor(opacityMatch[1].trim(), darkMode);
15930
+ const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
15931
+ const alpha = Math.round(opacity / 100 * 255);
15932
+ return base & 4294967040 | alpha;
15933
+ }
15691
15934
  if (str.startsWith("#")) {
15692
15935
  const hex = str.substring(1);
15693
15936
  let r, g, b, a = 255;
@@ -15820,14 +16063,6 @@ function parseColor(s, darkMode) {
15820
16063
  console.warn(`parseColor: unrecognized color "${s}"`);
15821
16064
  return 0;
15822
16065
  }
15823
- function parseColorToRgb01(s, darkMode) {
15824
- const color = parseColor(s, darkMode);
15825
- return [
15826
- (color >>> 24 & 255) / 255,
15827
- (color >>> 16 & 255) / 255,
15828
- (color >>> 8 & 255) / 255
15829
- ];
15830
- }
15831
16066
  function apca(bgColor, fgColor) {
15832
16067
  const bgRgb = asRgb(bgColor);
15833
16068
  const fgRgb = asRgb(fgColor);
@@ -15886,6 +16121,12 @@ function contrastingColor(arg) {
15886
16121
  const contrast2 = Math.abs(apca(fg2, bg));
15887
16122
  return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
15888
16123
  }
16124
+ function oklabDeltaE(a, b) {
16125
+ const dL = a.L - b.L;
16126
+ const da = a.a - b.a;
16127
+ const db = a.b - b.b;
16128
+ return Math.sqrt(dL * dL + da * da + db * db);
16129
+ }
15889
16130
  var TYCHO_11 = [
15890
16131
  "#4e79a7",
15891
16132
  // Blue
@@ -20097,39 +20338,130 @@ var JAVASCRIPT_FUNCTIONS = {
20097
20338
  if (args.length >= 2)
20098
20339
  return `_SYS.colormap(${compile2(args[0])}, ${compile2(args[1])})`;
20099
20340
  return `_SYS.colormap(${compile2(args[0])})`;
20341
+ },
20342
+ // -----------------------------------------------------------------------
20343
+ // Color constructor heads. All compile to OKLCh arrays at runtime — the
20344
+ // canonical color representation in this target. The constructors take
20345
+ // their own colorspace's components and convert internally.
20346
+ // (Mirrors the GPU target's design: color values are vec3 OKLCh.)
20347
+ // -----------------------------------------------------------------------
20348
+ Rgb: (args, compile2) => {
20349
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
20350
+ return `_SYS.rgb(${args.map(compile2).join(", ")})`;
20351
+ },
20352
+ Hsv: (args, compile2) => {
20353
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
20354
+ return `_SYS.hsv(${args.map(compile2).join(", ")})`;
20355
+ },
20356
+ Hsl: (args, compile2) => {
20357
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
20358
+ return `_SYS.hsl(${args.map(compile2).join(", ")})`;
20359
+ },
20360
+ Oklab: (args, compile2) => {
20361
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
20362
+ return `_SYS.oklab(${args.map(compile2).join(", ")})`;
20363
+ },
20364
+ Oklch: (args, compile2) => {
20365
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
20366
+ return `_SYS.oklch(${args.map(compile2).join(", ")})`;
20367
+ },
20368
+ // -----------------------------------------------------------------------
20369
+ // As* converters. Compile-time output convention matches the engine and
20370
+ // the GPU target: each returns components in the named space as a 3- or
20371
+ // 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
20372
+ // layers). `AsOklch` is the identity (canonical form).
20373
+ // -----------------------------------------------------------------------
20374
+ AsRgb: ([c], compile2) => {
20375
+ if (c === null) throw new Error("AsRgb: no argument");
20376
+ return `_SYS.asRgb(${compile2(c)})`;
20377
+ },
20378
+ AsHsv: ([c], compile2) => {
20379
+ if (c === null) throw new Error("AsHsv: no argument");
20380
+ return `_SYS.asHsv(${compile2(c)})`;
20381
+ },
20382
+ AsHsl: ([c], compile2) => {
20383
+ if (c === null) throw new Error("AsHsl: no argument");
20384
+ return `_SYS.asHsl(${compile2(c)})`;
20385
+ },
20386
+ AsOklab: ([c], compile2) => {
20387
+ if (c === null) throw new Error("AsOklab: no argument");
20388
+ return `_SYS.asOklab(${compile2(c)})`;
20389
+ },
20390
+ AsOklch: ([c], compile2) => {
20391
+ if (c === null) throw new Error("AsOklch: no argument");
20392
+ return compile2(c);
20393
+ },
20394
+ // Perceptual color difference (ΔE_OK).
20395
+ ColorDelta: ([a, b], compile2) => {
20396
+ if (a === null || b === null)
20397
+ throw new Error("ColorDelta: need two colors");
20398
+ return `_SYS.colorDelta(${compile2(a)}, ${compile2(b)})`;
20399
+ },
20400
+ // Euclidean distance between two tuples (any positive dimension).
20401
+ // The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
20402
+ // (vec-only); this JS handler works on plain arrays of any length.
20403
+ Distance: ([a, b], compile2) => {
20404
+ if (a === null || b === null) throw new Error("Distance: need two points");
20405
+ return `_SYS.distance(${compile2(a)}, ${compile2(b)})`;
20100
20406
  }
20101
20407
  };
20102
20408
  function toRI(c) {
20103
20409
  return { re: c.re, im: c.im };
20104
20410
  }
20411
+ function normalizeAlpha(a) {
20412
+ if (a === void 0) return void 0;
20413
+ if (!Number.isFinite(a)) return void 0;
20414
+ if (Math.abs(a - 1) < 1e-9) return void 0;
20415
+ return a;
20416
+ }
20105
20417
  function toRgb255(input) {
20106
20418
  if (typeof input === "string") {
20107
20419
  const c = parseColor(input);
20108
- return {
20420
+ const rgb2 = {
20109
20421
  r: c >>> 24 & 255,
20110
20422
  g: c >>> 16 & 255,
20111
- b: c >>> 8 & 255,
20112
- alpha: (c & 255) / 255
20423
+ b: c >>> 8 & 255
20113
20424
  };
20425
+ const alpha = normalizeAlpha((c & 255) / 255);
20426
+ if (alpha !== void 0) rgb2.alpha = alpha;
20427
+ return rgb2;
20428
+ }
20429
+ const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
20430
+ if (input.length >= 4) {
20431
+ const alpha = normalizeAlpha(input[3]);
20432
+ if (alpha !== void 0) rgb.alpha = alpha;
20114
20433
  }
20115
- const rgb = {
20116
- r: input[0] * 255,
20117
- g: input[1] * 255,
20118
- b: input[2] * 255
20119
- };
20120
- if (input.length >= 4) rgb.alpha = input[3];
20121
20434
  return rgb;
20122
20435
  }
20123
- function packedToArray(c) {
20124
- const r = (c >>> 24 & 255) / 255;
20125
- const g = (c >>> 16 & 255) / 255;
20126
- const b = (c >>> 8 & 255) / 255;
20127
- const a = (c & 255) / 255;
20128
- return Math.abs(a - 1) < 1e-4 ? [r, g, b] : [r, g, b, a];
20436
+ function toOklch(input) {
20437
+ if (typeof input === "string") {
20438
+ const c = parseColor(input);
20439
+ const r = c >>> 24 & 255;
20440
+ const g = c >>> 16 & 255;
20441
+ const b = c >>> 8 & 255;
20442
+ const oklch2 = rgbToOklch({ r, g, b });
20443
+ const alpha = normalizeAlpha((c & 255) / 255);
20444
+ if (alpha !== void 0) oklch2.alpha = alpha;
20445
+ return oklch2;
20446
+ }
20447
+ return {
20448
+ L: input[0],
20449
+ C: input[1],
20450
+ H: input[2],
20451
+ alpha: input.length >= 4 ? normalizeAlpha(input[3]) : void 0
20452
+ };
20453
+ }
20454
+ function packedToOklch(c) {
20455
+ const r = c >>> 24 & 255;
20456
+ const g = c >>> 16 & 255;
20457
+ const b = c >>> 8 & 255;
20458
+ const oklch2 = rgbToOklch({ r, g, b });
20459
+ const alpha = normalizeAlpha((c & 255) / 255);
20460
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
20129
20461
  }
20130
20462
  var colorHelpers = {
20131
20463
  color(input) {
20132
- return packedToArray(parseColor(input));
20464
+ return packedToOklch(parseColor(input));
20133
20465
  },
20134
20466
  colorToString(input, format) {
20135
20467
  const rgb = toRgb255(input);
@@ -20140,7 +20472,7 @@ var colorHelpers = {
20140
20472
  const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
20141
20473
  const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
20142
20474
  let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
20143
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4) {
20475
+ if (rgb.alpha !== void 0) {
20144
20476
  const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
20145
20477
  hex += a.toString(16).padStart(2, "0");
20146
20478
  }
@@ -20150,7 +20482,7 @@ var colorHelpers = {
20150
20482
  const r = Math.round(rgb.r);
20151
20483
  const g = Math.round(rgb.g);
20152
20484
  const b = Math.round(rgb.b);
20153
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20485
+ if (rgb.alpha !== void 0)
20154
20486
  return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
20155
20487
  return `rgb(${r} ${g} ${b})`;
20156
20488
  }
@@ -20159,7 +20491,7 @@ var colorHelpers = {
20159
20491
  const h = Math.round(hsl.h * 10) / 10;
20160
20492
  const s = Math.round(hsl.s * 1e3) / 10;
20161
20493
  const l = Math.round(hsl.l * 1e3) / 10;
20162
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20494
+ if (rgb.alpha !== void 0)
20163
20495
  return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
20164
20496
  return `hsl(${h} ${s}% ${l}%)`;
20165
20497
  }
@@ -20168,7 +20500,7 @@ var colorHelpers = {
20168
20500
  const L = Math.round(c.L * 1e3) / 1e3;
20169
20501
  const C = Math.round(c.C * 1e3) / 1e3;
20170
20502
  const H = Math.round(c.H * 10) / 10;
20171
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20503
+ if (rgb.alpha !== void 0)
20172
20504
  return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
20173
20505
  return `oklch(${L} ${C} ${H})`;
20174
20506
  }
@@ -20177,29 +20509,29 @@ var colorHelpers = {
20177
20509
  }
20178
20510
  },
20179
20511
  colorMix(input1, input2, ratio = 0.5) {
20180
- const rgb1 = toRgb255(input1);
20181
- const rgb2 = toRgb255(input2);
20512
+ const c1 = toOklch(input1);
20513
+ const c2 = toOklch(input2);
20182
20514
  ratio = Math.max(0, Math.min(1, ratio));
20183
- const c1 = rgbToOklch(rgb1);
20184
- const c2 = rgbToOklch(rgb2);
20185
- let dh = c2.H - c1.H;
20186
- if (dh > 180) dh -= 360;
20187
- if (dh < -180) dh += 360;
20188
- let H = c1.H + dh * ratio;
20189
- if (H < 0) H += 360;
20190
- if (H >= 360) H -= 360;
20191
- const mixed = oklchToRgb({
20192
- L: c1.L + (c2.L - c1.L) * ratio,
20193
- C: c1.C + (c2.C - c1.C) * ratio,
20194
- H
20195
- });
20196
- const r = mixed.r / 255;
20197
- const g = mixed.g / 255;
20198
- const b = mixed.b / 255;
20199
- const a1 = rgb1.alpha ?? 1;
20200
- const a2 = rgb2.alpha ?? 1;
20201
- const alpha = a1 + (a2 - a1) * ratio;
20202
- return Math.abs(alpha - 1) > 1e-4 ? [r, g, b, alpha] : [r, g, b];
20515
+ const c1Achromatic = c1.C < 1e-6;
20516
+ const c2Achromatic = c2.C < 1e-6;
20517
+ let H;
20518
+ if (c1Achromatic && c2Achromatic) H = c1.H;
20519
+ else if (c1Achromatic) H = c2.H;
20520
+ else if (c2Achromatic) H = c1.H;
20521
+ else {
20522
+ let dh = c2.H - c1.H;
20523
+ if (dh > 180) dh -= 360;
20524
+ if (dh < -180) dh += 360;
20525
+ H = c1.H + dh * ratio;
20526
+ if (H < 0) H += 360;
20527
+ if (H >= 360) H -= 360;
20528
+ }
20529
+ const L = c1.L + (c2.L - c1.L) * ratio;
20530
+ const C = c1.C + (c2.C - c1.C) * ratio;
20531
+ const a1 = c1.alpha ?? 1;
20532
+ const a2 = c2.alpha ?? 1;
20533
+ const alpha = normalizeAlpha(a1 + (a2 - a1) * ratio);
20534
+ return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
20203
20535
  },
20204
20536
  colorContrast(bg, fg) {
20205
20537
  return apca(toRgb255(bg), toRgb255(fg));
@@ -20207,11 +20539,11 @@ var colorHelpers = {
20207
20539
  contrastingColor(bg, fg1, fg2) {
20208
20540
  const bgRgb = toRgb255(bg);
20209
20541
  if (fg1 !== void 0 && fg2 !== void 0) {
20210
- return packedToArray(
20542
+ return packedToOklch(
20211
20543
  contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
20212
20544
  );
20213
20545
  }
20214
- return packedToArray(contrastingColor(bgRgb));
20546
+ return packedToOklch(contrastingColor(bgRgb));
20215
20547
  },
20216
20548
  colorToColorspace(input, space) {
20217
20549
  const rgb = toRgb255(input);
@@ -20240,7 +20572,7 @@ var colorHelpers = {
20240
20572
  default:
20241
20573
  throw new Error(`Unknown color space: ${space}`);
20242
20574
  }
20243
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
20575
+ if (alpha !== void 0) result.push(alpha);
20244
20576
  return result;
20245
20577
  },
20246
20578
  colormap(name, arg) {
@@ -20252,7 +20584,7 @@ var colorHelpers = {
20252
20584
  const palette = allPalettes[name];
20253
20585
  if (!palette) throw new Error(`Unknown palette: ${name}`);
20254
20586
  const colors = palette.map(
20255
- (hex) => parseColorToRgb01(hex)
20587
+ (hex) => packedToOklch(parseColor(hex))
20256
20588
  );
20257
20589
  if (arg === void 0) return colors;
20258
20590
  if (Number.isInteger(arg) && arg >= 2) {
@@ -20276,62 +20608,128 @@ var colorHelpers = {
20276
20608
  const frac = pos - i;
20277
20609
  if (frac === 0 || i >= colors.length - 1)
20278
20610
  return [...colors[Math.min(i, colors.length - 1)]];
20279
- const rgb1 = {
20280
- r: colors[i][0] * 255,
20281
- g: colors[i][1] * 255,
20282
- b: colors[i][2] * 255
20283
- };
20284
- const rgb2 = {
20285
- r: colors[i + 1][0] * 255,
20286
- g: colors[i + 1][1] * 255,
20287
- b: colors[i + 1][2] * 255
20288
- };
20289
- const c1 = rgbToOklch(rgb1);
20290
- const c2 = rgbToOklch(rgb2);
20291
- let dh = c2.H - c1.H;
20292
- if (dh > 180) dh -= 360;
20293
- if (dh < -180) dh += 360;
20294
- let H = c1.H + dh * frac;
20295
- if (H < 0) H += 360;
20296
- if (H >= 360) H -= 360;
20297
- const mixed = oklchToRgb({
20298
- L: c1.L + (c2.L - c1.L) * frac,
20299
- C: c1.C + (c2.C - c1.C) * frac,
20300
- H
20301
- });
20302
- return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
20611
+ const [L1, C1, H1] = colors[i];
20612
+ const [L2, C2, H2] = colors[i + 1];
20613
+ const c1Achromatic = C1 < 1e-6;
20614
+ const c2Achromatic = C2 < 1e-6;
20615
+ let H;
20616
+ if (c1Achromatic && c2Achromatic) H = H1;
20617
+ else if (c1Achromatic) H = H2;
20618
+ else if (c2Achromatic) H = H1;
20619
+ else {
20620
+ let dh = H2 - H1;
20621
+ if (dh > 180) dh -= 360;
20622
+ if (dh < -180) dh += 360;
20623
+ H = H1 + dh * frac;
20624
+ if (H < 0) H += 360;
20625
+ if (H >= 360) H -= 360;
20626
+ }
20627
+ return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
20303
20628
  },
20304
20629
  colorFromColorspace(components, space) {
20305
20630
  const c0 = components[0];
20306
20631
  const c1 = components[1];
20307
20632
  const c2 = components[2];
20308
20633
  const alpha = components.length >= 4 ? components[3] : void 0;
20309
- let result;
20634
+ let oklch2;
20310
20635
  switch (space.toLowerCase()) {
20311
20636
  case "rgb":
20312
- result = [c0, c1, c2];
20637
+ oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
20313
20638
  break;
20314
20639
  case "hsl": {
20315
- const r = hslToRgb(c0, c1, c2);
20316
- result = [r.r / 255, r.g / 255, r.b / 255];
20640
+ const rgb = hslToRgb(c0, c1, c2);
20641
+ oklch2 = rgbToOklch(rgb);
20317
20642
  break;
20318
20643
  }
20319
- case "oklch": {
20320
- const r = oklchToRgb({ L: c0, C: c1, H: c2 });
20321
- result = [r.r / 255, r.g / 255, r.b / 255];
20644
+ case "oklch":
20645
+ oklch2 = { L: c0, C: c1, H: c2 };
20322
20646
  break;
20323
- }
20324
20647
  case "oklab":
20325
- case "lab": {
20326
- const r = oklabToRgb({ L: c0, a: c1, b: c2 });
20327
- result = [r.r / 255, r.g / 255, r.b / 255];
20648
+ case "lab":
20649
+ oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
20328
20650
  break;
20329
- }
20330
20651
  default:
20331
20652
  throw new Error(`Unknown color space: ${space}`);
20332
20653
  }
20333
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
20334
- return result;
20654
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
20655
+ },
20656
+ // -----------------------------------------------------------------------
20657
+ // Color constructors. Each accepts components in its colorspace's natural
20658
+ // units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
20659
+ // -----------------------------------------------------------------------
20660
+ rgb(r, g, b, alpha) {
20661
+ const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
20662
+ const a = normalizeAlpha(alpha);
20663
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20664
+ },
20665
+ hsv(h, s, v, alpha) {
20666
+ const rgb = hsvToRgb(h, s, v);
20667
+ const c = rgbToOklch(rgb);
20668
+ const a = normalizeAlpha(alpha);
20669
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20670
+ },
20671
+ hsl(h, s, l, alpha) {
20672
+ const rgb = hslToRgb(h, s, l);
20673
+ const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
20674
+ const a = normalizeAlpha(alpha);
20675
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20676
+ },
20677
+ oklab(L, a, b, alpha) {
20678
+ const c = oklabToOklch({ L, a, b });
20679
+ const al = normalizeAlpha(alpha);
20680
+ return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
20681
+ },
20682
+ oklch(L, C, H, alpha) {
20683
+ const a = normalizeAlpha(alpha);
20684
+ return a !== void 0 ? [L, C, H, a] : [L, C, H];
20685
+ },
20686
+ // -----------------------------------------------------------------------
20687
+ // As* converters. Inputs are anything `toOklch` accepts (string, packed
20688
+ // int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
20689
+ // space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
20690
+ // consistency with the GPU target's shader convention.
20691
+ // -----------------------------------------------------------------------
20692
+ asRgb(input) {
20693
+ const rgb = toRgb255(input);
20694
+ const r = rgb.r / 255;
20695
+ const g = rgb.g / 255;
20696
+ const b = rgb.b / 255;
20697
+ return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
20698
+ },
20699
+ asHsv(input) {
20700
+ const rgb = toRgb255(input);
20701
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
20702
+ return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
20703
+ },
20704
+ asHsl(input) {
20705
+ const rgb = toRgb255(input);
20706
+ const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
20707
+ return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
20708
+ },
20709
+ asOklab(input) {
20710
+ const c = toOklch(input);
20711
+ const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
20712
+ return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
20713
+ },
20714
+ // asOklch is identity — handled at compile time as a pass-through
20715
+ // Perceptual color difference (ΔE_OK).
20716
+ colorDelta(a, b) {
20717
+ const labA = oklchToOklab(toOklch(a));
20718
+ const labB = oklchToOklab(toOklch(b));
20719
+ return oklabDeltaE(labA, labB);
20720
+ },
20721
+ // Euclidean distance between two tuples. Plain numeric — not a color
20722
+ // operation despite living in the same helpers block.
20723
+ distance(a, b) {
20724
+ if (!Array.isArray(a) || !Array.isArray(b))
20725
+ throw new Error("Distance: expected two arrays");
20726
+ if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
20727
+ let sumSq = 0;
20728
+ for (let i = 0; i < a.length; i++) {
20729
+ const d = a[i] - b[i];
20730
+ sumSq += d * d;
20731
+ }
20732
+ return Math.sqrt(sumSq);
20335
20733
  }
20336
20734
  };
20337
20735
  var SYS_HELPERS = {
@@ -20749,43 +21147,6 @@ function fibonacci(n) {
20749
21147
  return b;
20750
21148
  }
20751
21149
 
20752
- // src/compute-engine/compilation/fractal-orbit.ts
20753
- function toBigDecimal(v) {
20754
- if (typeof v === "object" && "hi" in v)
20755
- return new BigDecimal(v.hi).add(new BigDecimal(v.lo));
20756
- return new BigDecimal(v);
20757
- }
20758
- function hpToNumber(v) {
20759
- if (typeof v === "number") return v;
20760
- if (typeof v === "string") return Number(v);
20761
- return v.hi + v.lo;
20762
- }
20763
- function computeReferenceOrbit(center, maxIter, precision) {
20764
- const prevPrecision = BigDecimal.precision;
20765
- BigDecimal.precision = precision;
20766
- try {
20767
- const cr = toBigDecimal(center[0]);
20768
- const ci = toBigDecimal(center[1]);
20769
- let zr = BigDecimal.ZERO;
20770
- let zi = BigDecimal.ZERO;
20771
- const ESCAPE = new BigDecimal(256);
20772
- const points = [];
20773
- for (let i = 0; i < maxIter; i++) {
20774
- points.push(zr.toNumber(), zi.toNumber());
20775
- const zr2 = zr.mul(zr).toPrecision(precision);
20776
- const zi2 = zi.mul(zi).toPrecision(precision);
20777
- const mag2 = zr2.add(zi2);
20778
- if (mag2.cmp(ESCAPE) > 0) break;
20779
- const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
20780
- zr = zr2.sub(zi2).add(cr);
20781
- zi = new_zi;
20782
- }
20783
- return new Float32Array(points);
20784
- } finally {
20785
- BigDecimal.precision = prevPrecision;
20786
- }
20787
- }
20788
-
20789
21150
  // src/compute-engine/compilation/gpu-target.ts
20790
21151
  var GPU_OPERATORS = {
20791
21152
  Add: ["+", 11],
@@ -20807,6 +21168,13 @@ var GPU_OPERATORS = {
20807
21168
  function gpuVec2(target) {
20808
21169
  return target?.language === "wgsl" ? "vec2f" : "vec2";
20809
21170
  }
21171
+ function gpuVec3(target) {
21172
+ return target?.language === "wgsl" ? "vec3f" : "vec3";
21173
+ }
21174
+ function readStringLiteral(expr) {
21175
+ if (!isString(expr)) return null;
21176
+ return expr.string?.toLowerCase() ?? null;
21177
+ }
20810
21178
  function compileIntArg(expr, compile2, target) {
20811
21179
  const c = tryGetConstant(expr);
20812
21180
  if (c !== void 0 && Number.isInteger(c)) return c.toString();
@@ -20865,17 +21233,10 @@ function compileGPUSumProduct(kind, args, _compile, target) {
20865
21233
  `for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
20866
21234
  ` ${acc} ${op}= ${body};`,
20867
21235
  `}`,
20868
- `return ${acc}`
21236
+ `return ${acc};`
20869
21237
  ];
20870
21238
  return lines.join("\n");
20871
21239
  }
20872
- function selectFractalStrategy(target) {
20873
- const radius = target.hints?.viewport?.radius;
20874
- if (radius === void 0) return "single";
20875
- if (radius > 1e-6) return "single";
20876
- if (radius > 1e-14) return "double";
20877
- return "perturbation";
20878
- }
20879
21240
  var GPU_FUNCTIONS = {
20880
21241
  // Variadic arithmetic (for function-call form, e.g., with vectors)
20881
21242
  Add: (args, compile2, target) => {
@@ -20926,8 +21287,7 @@ var GPU_FUNCTIONS = {
20926
21287
  const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
20927
21288
  const realFactors = args.filter((_, i) => i !== iIndex);
20928
21289
  const v2 = gpuVec2(target);
20929
- if (realFactors.length === 0)
20930
- return `${v2}(0.0, ${formatFloat(iScale)})`;
21290
+ if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
20931
21291
  const factors = realFactors.map((f) => compile2(f));
20932
21292
  if (iScale !== 1) factors.unshift(formatFloat(iScale));
20933
21293
  const imCode = foldTerms(factors, "1.0", "*");
@@ -20980,8 +21340,7 @@ var GPU_FUNCTIONS = {
20980
21340
  if (isNumber(x) && x.im !== 0) {
20981
21341
  return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
20982
21342
  }
20983
- if (isSymbol2(x, "ImaginaryUnit"))
20984
- return `${gpuVec2(target)}(0.0, -1.0)`;
21343
+ if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
20985
21344
  return `(-${compile2(x)})`;
20986
21345
  },
20987
21346
  // Standard math functions with complex dispatch
@@ -21354,49 +21713,139 @@ var GPU_FUNCTIONS = {
21354
21713
  }
21355
21714
  const isWGSL = target?.language === "wgsl";
21356
21715
  const v3 = isWGSL ? "vec3f" : "vec3";
21357
- return `((_gpu_apca(${bg}, ${v3}(0.0)) > 50.0) ? ${v3}(0.0) : ${v3}(1.0))`;
21716
+ const black = `${v3}(0.0)`;
21717
+ const white = `${v3}(1.0, 0.0, 0.0)`;
21718
+ return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
21358
21719
  },
21359
21720
  ColorToColorspace: ([color, space], compile2) => {
21360
21721
  if (color === null || space === null)
21361
21722
  throw new Error("ColorToColorspace: need color and space");
21362
- return `_gpu_srgb_to_oklab(${compile2(color)})`;
21723
+ const spaceName = readStringLiteral(space);
21724
+ if (spaceName === null)
21725
+ throw new Error("ColorToColorspace: space must be a string literal");
21726
+ const c = compile2(color);
21727
+ switch (spaceName) {
21728
+ case "oklch":
21729
+ return c;
21730
+ case "oklab":
21731
+ case "lab":
21732
+ return `_gpu_oklch_to_oklab(${c})`;
21733
+ case "rgb":
21734
+ return `_gpu_oklch_to_srgb(${c})`;
21735
+ case "hsl":
21736
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
21737
+ case "hsv":
21738
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
21739
+ default:
21740
+ throw new Error(
21741
+ `ColorToColorspace: unsupported space "${spaceName}" on GPU target`
21742
+ );
21743
+ }
21363
21744
  },
21364
21745
  ColorFromColorspace: ([components, space], compile2) => {
21365
21746
  if (components === null || space === null)
21366
21747
  throw new Error("ColorFromColorspace: need components and space");
21367
- return `_gpu_oklab_to_srgb(${compile2(components)})`;
21748
+ const spaceName = readStringLiteral(space);
21749
+ if (spaceName === null)
21750
+ throw new Error("ColorFromColorspace: space must be a string literal");
21751
+ const c = compile2(components);
21752
+ switch (spaceName) {
21753
+ case "oklch":
21754
+ return c;
21755
+ case "oklab":
21756
+ case "lab":
21757
+ return `_gpu_oklab_to_oklch(${c})`;
21758
+ case "rgb":
21759
+ return `_gpu_srgb_to_oklch(${c})`;
21760
+ case "hsl":
21761
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
21762
+ case "hsv":
21763
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
21764
+ default:
21765
+ throw new Error(
21766
+ `ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
21767
+ );
21768
+ }
21769
+ },
21770
+ // ---------------------------------------------------------------------------
21771
+ // Color literals. Each typed head compiles to a canonical OKLCh vec3.
21772
+ // Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
21773
+ // alpha as a separate uniform if it's needed at the framebuffer boundary.
21774
+ // ---------------------------------------------------------------------------
21775
+ Color: ([s], _compile, target) => {
21776
+ if (s === null) throw new Error("Color: no argument");
21777
+ const str = readStringLiteral(s);
21778
+ if (str === null)
21779
+ throw new Error("Color: argument must be a string literal on GPU target");
21780
+ const packed = parseColor(str);
21781
+ if (packed === 0 && str.trim().toLowerCase() !== "transparent")
21782
+ throw new Error(`Color: invalid color string "${str}"`);
21783
+ const r = packed >>> 24 & 255;
21784
+ const g = packed >>> 16 & 255;
21785
+ const b = packed >>> 8 & 255;
21786
+ const oklch2 = rgbToOklch({ r, g, b });
21787
+ return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
21788
+ },
21789
+ Rgb: (args, compile2, target) => {
21790
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
21791
+ const v3 = gpuVec3(target);
21792
+ return `_gpu_srgb_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
21793
+ },
21794
+ Hsv: (args, compile2, target) => {
21795
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
21796
+ const v3 = gpuVec3(target);
21797
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
21798
+ },
21799
+ Hsl: (args, compile2, target) => {
21800
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
21801
+ const v3 = gpuVec3(target);
21802
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
21803
+ },
21804
+ Oklab: (args, compile2, target) => {
21805
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
21806
+ const v3 = gpuVec3(target);
21807
+ return `_gpu_oklab_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
21808
+ },
21809
+ Oklch: (args, compile2, target) => {
21810
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
21811
+ const v3 = gpuVec3(target);
21812
+ return `${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})`;
21813
+ },
21814
+ // ---------------------------------------------------------------------------
21815
+ // As* operators. AsOklch is identity (canonical). The other As* return
21816
+ // components in the named space, equivalent to ColorToColorspace(c, 'x').
21817
+ // ---------------------------------------------------------------------------
21818
+ AsOklch: ([c], compile2) => {
21819
+ if (c === null) throw new Error("AsOklch: no argument");
21820
+ return compile2(c);
21821
+ },
21822
+ AsOklab: ([c], compile2) => {
21823
+ if (c === null) throw new Error("AsOklab: no argument");
21824
+ return `_gpu_oklch_to_oklab(${compile2(c)})`;
21825
+ },
21826
+ AsRgb: ([c], compile2) => {
21827
+ if (c === null) throw new Error("AsRgb: no argument");
21828
+ return `_gpu_oklch_to_srgb(${compile2(c)})`;
21829
+ },
21830
+ AsHsv: ([c], compile2) => {
21831
+ if (c === null) throw new Error("AsHsv: no argument");
21832
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile2(c)}))`;
21833
+ },
21834
+ AsHsl: ([c], compile2) => {
21835
+ if (c === null) throw new Error("AsHsl: no argument");
21836
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile2(c)}))`;
21368
21837
  },
21369
21838
  // Fractal functions
21370
21839
  Mandelbrot: ([c, maxIter], compile2, target) => {
21371
21840
  if (c === null || maxIter === null)
21372
21841
  throw new Error("Mandelbrot: missing arguments");
21373
21842
  const iterCode = compileIntArg(maxIter, compile2, target);
21374
- const strategy = selectFractalStrategy(target);
21375
- if (strategy === "double") {
21376
- const dpCoord = target?.language === "wgsl" ? "_dp_coord(v_uv)" : "_dp_coord()";
21377
- return `_fractal_mandelbrot_dp(${dpCoord}, ${iterCode})`;
21378
- }
21379
- if (strategy === "perturbation") {
21380
- const ptDelta = target?.language === "wgsl" ? "_pt_delta(v_uv)" : "_pt_delta()";
21381
- return `_fractal_mandelbrot_pt(${ptDelta}, ${iterCode})`;
21382
- }
21383
21843
  return `_fractal_mandelbrot(${compile2(c)}, ${iterCode})`;
21384
21844
  },
21385
21845
  Julia: ([z, c, maxIter], compile2, target) => {
21386
21846
  if (z === null || c === null || maxIter === null)
21387
21847
  throw new Error("Julia: missing arguments");
21388
21848
  const iterCode = compileIntArg(maxIter, compile2, target);
21389
- const strategy = selectFractalStrategy(target);
21390
- if (strategy === "double") {
21391
- const dpCoord = target?.language === "wgsl" ? "_dp_coord(v_uv)" : "_dp_coord()";
21392
- const cCode = compile2(c);
21393
- return `_fractal_julia_dp(${dpCoord}, vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21394
- }
21395
- if (strategy === "perturbation") {
21396
- const ptDelta = target?.language === "wgsl" ? "_pt_delta(v_uv)" : "_pt_delta()";
21397
- const cCode = compile2(c);
21398
- return `_fractal_julia_pt(${ptDelta}, ${cCode}, ${iterCode})`;
21399
- }
21400
21849
  return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${iterCode})`;
21401
21850
  },
21402
21851
  // Vector/Matrix operations
@@ -21994,232 +22443,6 @@ fn _gpu_besselJ(n_in: i32, x_in: f32) -> f32 {
21994
22443
  return sgn * vals[n] / norm;
21995
22444
  }
21996
22445
  `;
21997
- var GPU_DS_ARITHMETIC_PREAMBLE_GLSL = `
21998
- // Split a float into high and low parts for exact multiplication
21999
- vec2 ds_split(float a) {
22000
- const float SPLIT = 4097.0; // 2^12 + 1
22001
- float t = SPLIT * a;
22002
- float hi = t - (t - a);
22003
- float lo = a - hi;
22004
- return vec2(hi, lo);
22005
- }
22006
-
22007
- // Create a double-single from a single float
22008
- vec2 ds_from(float a) {
22009
- return vec2(a, 0.0);
22010
- }
22011
-
22012
- // Error-free addition (Knuth TwoSum)
22013
- vec2 ds_add(vec2 a, vec2 b) {
22014
- float s = a.x + b.x;
22015
- float v = s - a.x;
22016
- float e = (a.x - (s - v)) + (b.x - v);
22017
- float lo = (a.y + b.y) + e;
22018
- float hi = s + lo;
22019
- lo = lo - (hi - s);
22020
- return vec2(hi, lo);
22021
- }
22022
-
22023
- // Double-single subtraction
22024
- vec2 ds_sub(vec2 a, vec2 b) {
22025
- return ds_add(a, vec2(-b.x, -b.y));
22026
- }
22027
-
22028
- // Error-free multiplication (Dekker TwoProduct)
22029
- vec2 ds_mul(vec2 a, vec2 b) {
22030
- float p = a.x * b.x;
22031
- vec2 sa = ds_split(a.x);
22032
- vec2 sb = ds_split(b.x);
22033
- float err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22034
- err += a.x * b.y + a.y * b.x;
22035
- float hi = p + err;
22036
- float lo = err - (hi - p);
22037
- return vec2(hi, lo);
22038
- }
22039
-
22040
- // Optimized self-multiply
22041
- vec2 ds_sqr(vec2 a) {
22042
- float p = a.x * a.x;
22043
- vec2 sa = ds_split(a.x);
22044
- float err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22045
- err += 2.0 * a.x * a.y;
22046
- float hi = p + err;
22047
- float lo = err - (hi - p);
22048
- return vec2(hi, lo);
22049
- }
22050
-
22051
- // Compare magnitude: returns -1, 0, or 1
22052
- float ds_cmp(vec2 a, vec2 b) {
22053
- float d = a.x - b.x;
22054
- if (d != 0.0) return sign(d);
22055
- return sign(a.y - b.y);
22056
- }
22057
- `;
22058
- var GPU_DS_ARITHMETIC_PREAMBLE_WGSL = `
22059
- fn ds_split(a: f32) -> vec2f {
22060
- const SPLIT: f32 = 4097.0;
22061
- let t = SPLIT * a;
22062
- let hi = t - (t - a);
22063
- let lo = a - hi;
22064
- return vec2f(hi, lo);
22065
- }
22066
-
22067
- fn ds_from(a: f32) -> vec2f {
22068
- return vec2f(a, 0.0);
22069
- }
22070
-
22071
- fn ds_add(a: vec2f, b: vec2f) -> vec2f {
22072
- let s = a.x + b.x;
22073
- let v = s - a.x;
22074
- let e = (a.x - (s - v)) + (b.x - v);
22075
- let lo_t = (a.y + b.y) + e;
22076
- let hi = s + lo_t;
22077
- let lo = lo_t - (hi - s);
22078
- return vec2f(hi, lo);
22079
- }
22080
-
22081
- fn ds_sub(a: vec2f, b: vec2f) -> vec2f {
22082
- return ds_add(a, vec2f(-b.x, -b.y));
22083
- }
22084
-
22085
- fn ds_mul(a: vec2f, b: vec2f) -> vec2f {
22086
- let p = a.x * b.x;
22087
- let sa = ds_split(a.x);
22088
- let sb = ds_split(b.x);
22089
- var err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22090
- err += a.x * b.y + a.y * b.x;
22091
- let hi = p + err;
22092
- let lo = err - (hi - p);
22093
- return vec2f(hi, lo);
22094
- }
22095
-
22096
- fn ds_sqr(a: vec2f) -> vec2f {
22097
- let p = a.x * a.x;
22098
- let sa = ds_split(a.x);
22099
- var err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22100
- err += 2.0 * a.x * a.y;
22101
- let hi = p + err;
22102
- let lo = err - (hi - p);
22103
- return vec2f(hi, lo);
22104
- }
22105
-
22106
- fn ds_cmp(a: vec2f, b: vec2f) -> f32 {
22107
- let d = a.x - b.x;
22108
- if (d != 0.0) { return sign(d); }
22109
- return sign(a.y - b.y);
22110
- }
22111
- `;
22112
- var GPU_FRACTAL_DP_PREAMBLE_GLSL = `
22113
- uniform float _dp_cx_hi;
22114
- uniform float _dp_cx_lo;
22115
- uniform float _dp_cy_hi;
22116
- uniform float _dp_cy_lo;
22117
- uniform float _dp_w;
22118
- uniform float _dp_h;
22119
-
22120
- vec4 _dp_coord() {
22121
- // Per-pixel offset from center \u2014 small, so float-precise
22122
- float dx = (v_uv.x - 0.5) * _dp_w;
22123
- float dy = (v_uv.y - 0.5) * _dp_h;
22124
- // Combine center (hi+lo) + delta with emulated double precision
22125
- vec2 cre = ds_add(vec2(_dp_cx_hi, _dp_cx_lo), ds_from(dx));
22126
- vec2 cim = ds_add(vec2(_dp_cy_hi, _dp_cy_lo), ds_from(dy));
22127
- return vec4(cre.x, cim.x, cre.y, cim.y);
22128
- }
22129
-
22130
- float _fractal_mandelbrot_dp(vec4 c, int maxIter) {
22131
- // c = (re_hi, im_hi, re_lo, im_lo)
22132
- vec2 cr = vec2(c.x, c.z); // real part as ds
22133
- vec2 ci = vec2(c.y, c.w); // imag part as ds
22134
- vec2 zr = vec2(0.0, 0.0);
22135
- vec2 zi = vec2(0.0, 0.0);
22136
- for (int i = 0; i < maxIter; i++) {
22137
- vec2 zr2 = ds_sqr(zr);
22138
- vec2 zi2 = ds_sqr(zi);
22139
- // |z|^2 > 4.0 ?
22140
- vec2 mag2 = ds_add(zr2, zi2);
22141
- if (mag2.x > 4.0)
22142
- return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22143
- // z = z^2 + c
22144
- vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci); // 2*zr*zi + ci
22145
- zr = ds_add(ds_sub(zr2, zi2), cr); // zr^2 - zi^2 + cr
22146
- zi = new_zi;
22147
- }
22148
- return 1.0;
22149
- }
22150
-
22151
- float _fractal_julia_dp(vec4 z_in, vec4 c, int maxIter) {
22152
- vec2 zr = vec2(z_in.x, z_in.z);
22153
- vec2 zi = vec2(z_in.y, z_in.w);
22154
- vec2 cr = vec2(c.x, c.z);
22155
- vec2 ci = vec2(c.y, c.w);
22156
- for (int i = 0; i < maxIter; i++) {
22157
- vec2 zr2 = ds_sqr(zr);
22158
- vec2 zi2 = ds_sqr(zi);
22159
- vec2 mag2 = ds_add(zr2, zi2);
22160
- if (mag2.x > 4.0)
22161
- return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22162
- vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22163
- zr = ds_add(ds_sub(zr2, zi2), cr);
22164
- zi = new_zi;
22165
- }
22166
- return 1.0;
22167
- }
22168
- `;
22169
- var GPU_FRACTAL_DP_PREAMBLE_WGSL = `
22170
- @group(0) @binding(10) var<uniform> _dp_cx_hi: f32;
22171
- @group(0) @binding(11) var<uniform> _dp_cx_lo: f32;
22172
- @group(0) @binding(12) var<uniform> _dp_cy_hi: f32;
22173
- @group(0) @binding(13) var<uniform> _dp_cy_lo: f32;
22174
- @group(0) @binding(14) var<uniform> _dp_w: f32;
22175
- @group(0) @binding(15) var<uniform> _dp_h: f32;
22176
-
22177
- fn _dp_coord(uv: vec2f) -> vec4f {
22178
- let dx = (uv.x - 0.5) * _dp_w;
22179
- let dy = (uv.y - 0.5) * _dp_h;
22180
- let cre = ds_add(vec2f(_dp_cx_hi, _dp_cx_lo), ds_from(dx));
22181
- let cim = ds_add(vec2f(_dp_cy_hi, _dp_cy_lo), ds_from(dy));
22182
- return vec4f(cre.x, cim.x, cre.y, cim.y);
22183
- }
22184
-
22185
- fn _fractal_mandelbrot_dp(c: vec4f, maxIter: i32) -> f32 {
22186
- let cr = vec2f(c.x, c.z);
22187
- let ci = vec2f(c.y, c.w);
22188
- var zr = vec2f(0.0, 0.0);
22189
- var zi = vec2f(0.0, 0.0);
22190
- for (var i: i32 = 0; i < maxIter; i++) {
22191
- let zr2 = ds_sqr(zr);
22192
- let zi2 = ds_sqr(zi);
22193
- let mag2 = ds_add(zr2, zi2);
22194
- if (mag2.x > 4.0) {
22195
- return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22196
- }
22197
- let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22198
- zr = ds_add(ds_sub(zr2, zi2), cr);
22199
- zi = new_zi;
22200
- }
22201
- return 1.0;
22202
- }
22203
-
22204
- fn _fractal_julia_dp(z_in: vec4f, c: vec4f, maxIter: i32) -> f32 {
22205
- var zr = vec2f(z_in.x, z_in.z);
22206
- var zi = vec2f(z_in.y, z_in.w);
22207
- let cr = vec2f(c.x, c.z);
22208
- let ci = vec2f(c.y, c.w);
22209
- for (var i: i32 = 0; i < maxIter; i++) {
22210
- let zr2 = ds_sqr(zr);
22211
- let zi2 = ds_sqr(zi);
22212
- let mag2 = ds_add(zr2, zi2);
22213
- if (mag2.x > 4.0) {
22214
- return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22215
- }
22216
- let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22217
- zr = ds_add(ds_sub(zr2, zi2), cr);
22218
- zi = new_zi;
22219
- }
22220
- return 1.0;
22221
- }
22222
- `;
22223
22446
  var GPU_FRACTAL_PREAMBLE_GLSL = `
22224
22447
  float _fractal_mandelbrot(vec2 c, int maxIter) {
22225
22448
  vec2 z = vec2(0.0, 0.0);
@@ -22263,208 +22486,6 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
22263
22486
  return 1.0;
22264
22487
  }
22265
22488
  `;
22266
- var GPU_FRACTAL_PT_PREAMBLE_GLSL = `
22267
- uniform sampler2D _refOrbit;
22268
- uniform int _refOrbitLen;
22269
- uniform int _refOrbitTexWidth;
22270
- uniform float _pt_offset_x;
22271
- uniform float _pt_offset_y;
22272
- uniform float _pt_w;
22273
- uniform float _pt_h;
22274
-
22275
- vec2 _pt_delta() {
22276
- float dx = _pt_offset_x + (v_uv.x - 0.5) * _pt_w;
22277
- float dy = _pt_offset_y + (v_uv.y - 0.5) * _pt_h;
22278
- return vec2(dx, dy);
22279
- }
22280
-
22281
- vec2 _pt_fetch_orbit(int i) {
22282
- int y = i / _refOrbitTexWidth;
22283
- int x = i - y * _refOrbitTexWidth;
22284
- return texelFetch(_refOrbit, ivec2(x, y), 0).rg;
22285
- }
22286
-
22287
- float _fractal_mandelbrot_pt(vec2 delta_c, int maxIter) {
22288
- float dr = 0.0;
22289
- float di = 0.0;
22290
- int orbitLen = min(maxIter, _refOrbitLen);
22291
- for (int i = 0; i < orbitLen; i++) {
22292
- vec2 Zn = _pt_fetch_orbit(i);
22293
- // delta_{n+1} = 2*Z_n*delta_n + delta_n^2 + delta_c
22294
- float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22295
- float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22296
- dr = new_dr;
22297
- di = new_di;
22298
- // Full z = Z_{n+1} + delta for escape check
22299
- vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22300
- float zr = Zn1.x + dr;
22301
- float zi = Zn1.y + di;
22302
- float mag2 = zr * zr + zi * zi;
22303
- if (mag2 > 4.0)
22304
- return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22305
- // Glitch detection: |delta|^2 > |Z|^2
22306
- float dmag2 = dr * dr + di * di;
22307
- float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22308
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22309
- // Rebase to absolute coordinates and continue with single-float
22310
- float abs_zr = Zn1.x + dr;
22311
- float abs_zi = Zn1.y + di;
22312
- // Reconstruct absolute c from reference + delta
22313
- // (Use ds_from for the concept, but single-float suffices for fallback)
22314
- float cx = abs_zr - dr + delta_c.x;
22315
- float cy = abs_zi - di + delta_c.y;
22316
- for (int j = i + 1; j < maxIter; j++) {
22317
- float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22318
- abs_zi = 2.0 * abs_zr * abs_zi + cy;
22319
- abs_zr = new_zr;
22320
- mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22321
- if (mag2 > 4.0)
22322
- return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22323
- }
22324
- return 1.0;
22325
- }
22326
- }
22327
- return 1.0;
22328
- }
22329
-
22330
- float _fractal_julia_pt(vec2 z_delta, vec2 delta_c, int maxIter) {
22331
- float dr = z_delta.x;
22332
- float di = z_delta.y;
22333
- int orbitLen = min(maxIter, _refOrbitLen);
22334
- for (int i = 0; i < orbitLen; i++) {
22335
- vec2 Zn = _pt_fetch_orbit(i);
22336
- float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22337
- float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22338
- dr = new_dr;
22339
- di = new_di;
22340
- vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22341
- float zr = Zn1.x + dr;
22342
- float zi = Zn1.y + di;
22343
- float mag2 = zr * zr + zi * zi;
22344
- if (mag2 > 4.0)
22345
- return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22346
- float dmag2 = dr * dr + di * di;
22347
- float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22348
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22349
- float abs_zr = Zn1.x + dr;
22350
- float abs_zi = Zn1.y + di;
22351
- float cx = delta_c.x;
22352
- float cy = delta_c.y;
22353
- for (int j = i + 1; j < maxIter; j++) {
22354
- float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22355
- abs_zi = 2.0 * abs_zr * abs_zi + cy;
22356
- abs_zr = new_zr;
22357
- mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22358
- if (mag2 > 4.0)
22359
- return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22360
- }
22361
- return 1.0;
22362
- }
22363
- }
22364
- return 1.0;
22365
- }
22366
- `;
22367
- var GPU_FRACTAL_PT_PREAMBLE_WGSL = `
22368
- @group(0) @binding(1) var _refOrbit: texture_2d<f32>;
22369
- var<uniform> _refOrbitLen: i32;
22370
- var<uniform> _refOrbitTexWidth: i32;
22371
- var<uniform> _pt_offset_x: f32;
22372
- var<uniform> _pt_offset_y: f32;
22373
- var<uniform> _pt_w: f32;
22374
- var<uniform> _pt_h: f32;
22375
-
22376
- fn _pt_delta(uv: vec2f) -> vec2f {
22377
- let dx = _pt_offset_x + (uv.x - 0.5) * _pt_w;
22378
- let dy = _pt_offset_y + (uv.y - 0.5) * _pt_h;
22379
- return vec2f(dx, dy);
22380
- }
22381
-
22382
- fn _pt_fetch_orbit(i: i32) -> vec2f {
22383
- let y = i / _refOrbitTexWidth;
22384
- let x = i - y * _refOrbitTexWidth;
22385
- return textureLoad(_refOrbit, vec2i(x, y), 0).rg;
22386
- }
22387
-
22388
- fn _fractal_mandelbrot_pt(delta_c: vec2f, maxIter: i32) -> f32 {
22389
- var dr: f32 = 0.0;
22390
- var di: f32 = 0.0;
22391
- let orbitLen = min(maxIter, _refOrbitLen);
22392
- for (var i: i32 = 0; i < orbitLen; i++) {
22393
- let Zn = _pt_fetch_orbit(i);
22394
- let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22395
- let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22396
- dr = new_dr;
22397
- di = new_di;
22398
- var Zn1 = vec2f(0.0);
22399
- if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22400
- let zr = Zn1.x + dr;
22401
- let zi = Zn1.y + di;
22402
- var mag2 = zr * zr + zi * zi;
22403
- if (mag2 > 4.0) {
22404
- return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22405
- }
22406
- let dmag2 = dr * dr + di * di;
22407
- let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22408
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22409
- var f_zr = Zn1.x + dr;
22410
- var f_zi = Zn1.y + di;
22411
- let cx = delta_c.x;
22412
- let cy = delta_c.y;
22413
- for (var j: i32 = i + 1; j < maxIter; j++) {
22414
- let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22415
- f_zi = 2.0 * f_zr * f_zi + cy;
22416
- f_zr = t_zr;
22417
- mag2 = f_zr * f_zr + f_zi * f_zi;
22418
- if (mag2 > 4.0) {
22419
- return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22420
- }
22421
- }
22422
- return 1.0;
22423
- }
22424
- }
22425
- return 1.0;
22426
- }
22427
-
22428
- fn _fractal_julia_pt(z_delta: vec2f, delta_c: vec2f, maxIter: i32) -> f32 {
22429
- var dr = z_delta.x;
22430
- var di = z_delta.y;
22431
- let orbitLen = min(maxIter, _refOrbitLen);
22432
- for (var i: i32 = 0; i < orbitLen; i++) {
22433
- let Zn = _pt_fetch_orbit(i);
22434
- let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22435
- let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22436
- dr = new_dr;
22437
- di = new_di;
22438
- var Zn1 = vec2f(0.0);
22439
- if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22440
- let zr = Zn1.x + dr;
22441
- let zi = Zn1.y + di;
22442
- var mag2 = zr * zr + zi * zi;
22443
- if (mag2 > 4.0) {
22444
- return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22445
- }
22446
- let dmag2 = dr * dr + di * di;
22447
- let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22448
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22449
- var f_zr = Zn1.x + dr;
22450
- var f_zi = Zn1.y + di;
22451
- let cx = delta_c.x;
22452
- let cy = delta_c.y;
22453
- for (var j: i32 = i + 1; j < maxIter; j++) {
22454
- let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22455
- f_zi = 2.0 * f_zr * f_zi + cy;
22456
- f_zr = t_zr;
22457
- mag2 = f_zr * f_zr + f_zi * f_zi;
22458
- if (mag2 > 4.0) {
22459
- return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22460
- }
22461
- }
22462
- return 1.0;
22463
- }
22464
- }
22465
- return 1.0;
22466
- }
22467
- `;
22468
22489
  var GPU_COLOR_PREAMBLE_GLSL = `
22469
22490
  float _gpu_srgb_to_linear(float c) {
22470
22491
  if (c <= 0.04045) return c / 12.92;
@@ -22505,28 +22526,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
22505
22526
 
22506
22527
  vec3 _gpu_oklab_to_oklch(vec3 lab) {
22507
22528
  float C = length(lab.yz);
22508
- float H = atan(lab.z, lab.y);
22529
+ float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
22530
+ if (H < 0.0) H += 360.0;
22509
22531
  return vec3(lab.x, C, H);
22510
22532
  }
22511
22533
 
22512
22534
  vec3 _gpu_oklch_to_oklab(vec3 lch) {
22513
- return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
22535
+ float h_rad = lch.z * (3.14159265359 / 180.0);
22536
+ return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
22514
22537
  }
22515
22538
 
22516
- vec3 _gpu_color_mix(vec3 rgb1, vec3 rgb2, float t) {
22517
- vec3 lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
22518
- vec3 lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
22539
+ vec3 _gpu_srgb_to_oklch(vec3 rgb) {
22540
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
22541
+ }
22542
+
22543
+ vec3 _gpu_oklch_to_srgb(vec3 lch) {
22544
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
22545
+ }
22546
+
22547
+ // HSL conversion. Hue in degrees, saturation/lightness in 0-1.
22548
+ vec3 _gpu_hsl_to_rgb(vec3 hsl) {
22549
+ float h = hsl.x;
22550
+ float s = hsl.y;
22551
+ float l = hsl.z;
22552
+ float c = (1.0 - abs(2.0 * l - 1.0)) * s;
22553
+ float h6 = h / 60.0;
22554
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
22555
+ float r = 0.0;
22556
+ float g = 0.0;
22557
+ float b = 0.0;
22558
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22559
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22560
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22561
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22562
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22563
+ else { r = c; g = 0.0; b = x; }
22564
+ float m = l - c / 2.0;
22565
+ return vec3(r + m, g + m, b + m);
22566
+ }
22567
+
22568
+ vec3 _gpu_rgb_to_hsl(vec3 rgb) {
22569
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
22570
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
22571
+ float l = (maxc + minc) / 2.0;
22572
+ float d = maxc - minc;
22573
+ if (d < 1e-6) return vec3(0.0, 0.0, l);
22574
+ float s = d / (1.0 - abs(2.0 * l - 1.0));
22575
+ float h;
22576
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
22577
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
22578
+ else h = (rgb.x - rgb.y) / d + 4.0;
22579
+ h *= 60.0;
22580
+ if (h < 0.0) h += 360.0;
22581
+ return vec3(h, s, l);
22582
+ }
22583
+
22584
+ // HSV conversion. Hue in degrees, saturation/value in 0-1.
22585
+ vec3 _gpu_hsv_to_rgb(vec3 hsv) {
22586
+ float h = hsv.x;
22587
+ float s = hsv.y;
22588
+ float v = hsv.z;
22589
+ float c = v * s;
22590
+ float h6 = h / 60.0;
22591
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
22592
+ float r = 0.0;
22593
+ float g = 0.0;
22594
+ float b = 0.0;
22595
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22596
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22597
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22598
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22599
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22600
+ else { r = c; g = 0.0; b = x; }
22601
+ float m = v - c;
22602
+ return vec3(r + m, g + m, b + m);
22603
+ }
22604
+
22605
+ vec3 _gpu_rgb_to_hsv(vec3 rgb) {
22606
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
22607
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
22608
+ float v = maxc;
22609
+ float d = maxc - minc;
22610
+ if (d < 1e-6) return vec3(0.0, 0.0, v);
22611
+ float s = (maxc < 1e-6) ? 0.0 : d / maxc;
22612
+ float h;
22613
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
22614
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
22615
+ else h = (rgb.x - rgb.y) / d + 4.0;
22616
+ h *= 60.0;
22617
+ if (h < 0.0) h += 360.0;
22618
+ return vec3(h, s, v);
22619
+ }
22620
+
22621
+ vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
22519
22622
  float L = mix(lch1.x, lch2.x, t);
22520
22623
  float C = mix(lch1.y, lch2.y, t);
22521
- float dh = lch2.z - lch1.z;
22522
- const float PI = 3.14159265359;
22523
- if (dh > PI) dh -= 2.0 * PI;
22524
- if (dh < -PI) dh += 2.0 * PI;
22525
- float H = lch1.z + dh * t;
22526
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3(L, C, H)));
22624
+ bool a1 = lch1.y < 1e-6;
22625
+ bool a2 = lch2.y < 1e-6;
22626
+ float H;
22627
+ if (a1 && a2) {
22628
+ H = lch1.z;
22629
+ } else if (a1) {
22630
+ H = lch2.z;
22631
+ } else if (a2) {
22632
+ H = lch1.z;
22633
+ } else {
22634
+ float dh = lch2.z - lch1.z;
22635
+ if (dh > 180.0) dh -= 360.0;
22636
+ if (dh < -180.0) dh += 360.0;
22637
+ H = lch1.z + dh * t;
22638
+ if (H < 0.0) H += 360.0;
22639
+ if (H >= 360.0) H -= 360.0;
22640
+ }
22641
+ return vec3(L, C, H);
22527
22642
  }
22528
22643
 
22529
- float _gpu_apca(vec3 bg, vec3 fg) {
22644
+ float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
22645
+ vec3 bg = _gpu_oklch_to_srgb(lch_bg);
22646
+ vec3 fg = _gpu_oklch_to_srgb(lch_fg);
22530
22647
  float bgR = _gpu_srgb_to_linear(bg.x);
22531
22648
  float bgG = _gpu_srgb_to_linear(bg.y);
22532
22649
  float bgB = _gpu_srgb_to_linear(bg.z);
@@ -22537,9 +22654,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
22537
22654
  float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
22538
22655
  float bgC = pow(bgY, 0.56);
22539
22656
  float fgC = pow(fgY, 0.57);
22540
- float contrast = (bgC > fgC)
22541
- ? (bgC - fgC) * 1.14
22542
- : (bgC - fgC) * 1.14;
22657
+ float contrast = (bgC - fgC) * 1.14;
22543
22658
  return contrast * 100.0;
22544
22659
  }
22545
22660
  `;
@@ -22583,28 +22698,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
22583
22698
 
22584
22699
  fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
22585
22700
  let C = length(lab.yz);
22586
- let H = atan2(lab.z, lab.y);
22701
+ var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
22702
+ if (H < 0.0) { H = H + 360.0; }
22587
22703
  return vec3f(lab.x, C, H);
22588
22704
  }
22589
22705
 
22590
22706
  fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
22591
- return vec3f(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
22707
+ let h_rad = lch.z * (3.14159265359 / 180.0);
22708
+ return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
22709
+ }
22710
+
22711
+ fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
22712
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
22713
+ }
22714
+
22715
+ fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
22716
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
22717
+ }
22718
+
22719
+ fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
22720
+ let h = hsl.x;
22721
+ let s = hsl.y;
22722
+ let l = hsl.z;
22723
+ let c = (1.0 - abs(2.0 * l - 1.0)) * s;
22724
+ let h6 = h / 60.0;
22725
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
22726
+ var r: f32 = 0.0;
22727
+ var g: f32 = 0.0;
22728
+ var b: f32 = 0.0;
22729
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22730
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22731
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22732
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22733
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22734
+ else { r = c; g = 0.0; b = x; }
22735
+ let m = l - c / 2.0;
22736
+ return vec3f(r + m, g + m, b + m);
22737
+ }
22738
+
22739
+ fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
22740
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
22741
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
22742
+ let l = (maxc + minc) / 2.0;
22743
+ let d = maxc - minc;
22744
+ if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
22745
+ let s = d / (1.0 - abs(2.0 * l - 1.0));
22746
+ var h: f32;
22747
+ if (maxc == rgb.x) {
22748
+ let v = (rgb.y - rgb.z) / d;
22749
+ h = v - 6.0 * floor(v / 6.0);
22750
+ } else if (maxc == rgb.y) {
22751
+ h = (rgb.z - rgb.x) / d + 2.0;
22752
+ } else {
22753
+ h = (rgb.x - rgb.y) / d + 4.0;
22754
+ }
22755
+ h = h * 60.0;
22756
+ if (h < 0.0) { h = h + 360.0; }
22757
+ return vec3f(h, s, l);
22758
+ }
22759
+
22760
+ fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
22761
+ let h = hsv.x;
22762
+ let s = hsv.y;
22763
+ let v = hsv.z;
22764
+ let c = v * s;
22765
+ let h6 = h / 60.0;
22766
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
22767
+ var r: f32 = 0.0;
22768
+ var g: f32 = 0.0;
22769
+ var b: f32 = 0.0;
22770
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22771
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22772
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22773
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22774
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22775
+ else { r = c; g = 0.0; b = x; }
22776
+ let m = v - c;
22777
+ return vec3f(r + m, g + m, b + m);
22778
+ }
22779
+
22780
+ fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
22781
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
22782
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
22783
+ let v = maxc;
22784
+ let d = maxc - minc;
22785
+ if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
22786
+ var s: f32 = 0.0;
22787
+ if (maxc >= 1e-6) { s = d / maxc; }
22788
+ var h: f32;
22789
+ if (maxc == rgb.x) {
22790
+ let q = (rgb.y - rgb.z) / d;
22791
+ h = q - 6.0 * floor(q / 6.0);
22792
+ } else if (maxc == rgb.y) {
22793
+ h = (rgb.z - rgb.x) / d + 2.0;
22794
+ } else {
22795
+ h = (rgb.x - rgb.y) / d + 4.0;
22796
+ }
22797
+ h = h * 60.0;
22798
+ if (h < 0.0) { h = h + 360.0; }
22799
+ return vec3f(h, s, v);
22592
22800
  }
22593
22801
 
22594
- fn _gpu_color_mix(rgb1: vec3f, rgb2: vec3f, t: f32) -> vec3f {
22595
- let lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
22596
- let lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
22802
+ fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
22597
22803
  let L = mix(lch1.x, lch2.x, t);
22598
22804
  let C = mix(lch1.y, lch2.y, t);
22599
- let PI = 3.14159265359;
22600
- var dh = lch2.z - lch1.z;
22601
- if (dh > PI) { dh -= 2.0 * PI; }
22602
- if (dh < -PI) { dh += 2.0 * PI; }
22603
- let H = lch1.z + dh * t;
22604
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3f(L, C, H)));
22805
+ let a1 = lch1.y < 1e-6;
22806
+ let a2 = lch2.y < 1e-6;
22807
+ var H: f32;
22808
+ if (a1 && a2) {
22809
+ H = lch1.z;
22810
+ } else if (a1) {
22811
+ H = lch2.z;
22812
+ } else if (a2) {
22813
+ H = lch1.z;
22814
+ } else {
22815
+ var dh = lch2.z - lch1.z;
22816
+ if (dh > 180.0) { dh = dh - 360.0; }
22817
+ if (dh < -180.0) { dh = dh + 360.0; }
22818
+ H = lch1.z + dh * t;
22819
+ if (H < 0.0) { H = H + 360.0; }
22820
+ if (H >= 360.0) { H = H - 360.0; }
22821
+ }
22822
+ return vec3f(L, C, H);
22605
22823
  }
22606
22824
 
22607
- fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22825
+ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
22826
+ let bg = _gpu_oklch_to_srgb(lch_bg);
22827
+ let fg = _gpu_oklch_to_srgb(lch_fg);
22608
22828
  let bgR = _gpu_srgb_to_linear(bg.x);
22609
22829
  let bgG = _gpu_srgb_to_linear(bg.y);
22610
22830
  let bgB = _gpu_srgb_to_linear(bg.z);
@@ -22892,7 +23112,7 @@ var GPUShaderTarget = class {
22892
23112
  if (stmts.length === 0) return "";
22893
23113
  const last = stmts.length - 1;
22894
23114
  stmts[last] = `return ${stmts[last]}`;
22895
- return stmts.join(";\n");
23115
+ return stmts.join(";\n") + ";";
22896
23116
  },
22897
23117
  ...options
22898
23118
  };
@@ -22903,7 +23123,6 @@ var GPUShaderTarget = class {
22903
23123
  const constants = this.getConstants();
22904
23124
  const v2 = this.languageId === "wgsl" ? "vec2f" : "vec2";
22905
23125
  const target = this.createTarget({
22906
- hints: options.hints,
22907
23126
  functions: (id) => {
22908
23127
  if (userFunctions && id in userFunctions) {
22909
23128
  const fn = userFunctions[id];
@@ -22942,89 +23161,12 @@ var GPUShaderTarget = class {
22942
23161
  if (code.includes("_gpu_besselJ"))
22943
23162
  preamble += this.languageId === "wgsl" ? GPU_BESSELJ_PREAMBLE_WGSL : GPU_BESSELJ_PREAMBLE_GLSL;
22944
23163
  if (code.includes("_fractal_")) {
22945
- if (code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) {
22946
- preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22947
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PT_PREAMBLE_WGSL : GPU_FRACTAL_PT_PREAMBLE_GLSL;
22948
- } else if (code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) {
22949
- preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22950
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_DP_PREAMBLE_WGSL : GPU_FRACTAL_DP_PREAMBLE_GLSL;
22951
- } else {
22952
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22953
- }
23164
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22954
23165
  }
22955
23166
  if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
22956
23167
  preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
22957
23168
  }
22958
23169
  if (preamble) result.preamble = preamble;
22959
- if (code.includes("_fractal_") && options.hints?.viewport) {
22960
- const strategy = selectFractalStrategy(target);
22961
- const radius = options.hints.viewport.radius;
22962
- switch (strategy) {
22963
- case "single":
22964
- result.staleWhen = { radiusBelow: 1e-6 };
22965
- break;
22966
- case "double":
22967
- result.staleWhen = { radiusBelow: 1e-14, radiusAbove: 1e-5 };
22968
- break;
22969
- case "perturbation":
22970
- result.staleWhen = {
22971
- radiusAbove: 1e-5,
22972
- radiusBelow: radius * 0.01,
22973
- centerDistance: radius * 2
22974
- };
22975
- break;
22976
- }
22977
- }
22978
- if ((code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) && options.hints?.viewport) {
22979
- const cx = hpToNumber(options.hints.viewport.center[0]);
22980
- const cy = hpToNumber(options.hints.viewport.center[1]);
22981
- const size = options.hints.viewport.radius * 2;
22982
- const cx_hi = Math.fround(cx);
22983
- const cy_hi = Math.fround(cy);
22984
- result.uniforms = {
22985
- ...result.uniforms,
22986
- _dp_cx_hi: cx_hi,
22987
- _dp_cx_lo: cx - cx_hi,
22988
- _dp_cy_hi: cy_hi,
22989
- _dp_cy_lo: cy - cy_hi,
22990
- _dp_w: size,
22991
- _dp_h: size
22992
- };
22993
- }
22994
- if ((code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) && options.hints?.viewport) {
22995
- const viewport = options.hints.viewport;
22996
- const size = viewport.radius * 2;
22997
- result.uniforms = {
22998
- ...result.uniforms,
22999
- _pt_offset_x: 0,
23000
- _pt_offset_y: 0,
23001
- _pt_w: size,
23002
- _pt_h: size
23003
- };
23004
- const digits = Math.max(50, Math.ceil(-Math.log10(viewport.radius)) + 10);
23005
- const maxIter = 1e3;
23006
- const orbit = computeReferenceOrbit(
23007
- viewport.center,
23008
- maxIter,
23009
- digits
23010
- );
23011
- const orbitLen = orbit.length / 2;
23012
- const texWidth = Math.min(orbitLen, 4096);
23013
- const texHeight = Math.ceil(orbitLen / texWidth);
23014
- result.textures = {
23015
- _refOrbit: {
23016
- data: orbit,
23017
- width: texWidth,
23018
- height: texHeight,
23019
- format: "rg32f"
23020
- }
23021
- };
23022
- result.uniforms = {
23023
- ...result.uniforms,
23024
- _refOrbitLen: orbitLen,
23025
- _refOrbitTexWidth: texWidth
23026
- };
23027
- }
23028
23170
  return result;
23029
23171
  }
23030
23172
  compileToSource(expr, _options = {}) {
@@ -23069,7 +23211,7 @@ var GLSLTarget = class extends GPUShaderTarget {
23069
23211
  if (body.includes("\n")) {
23070
23212
  const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
23071
23213
  return `${returnType} ${functionName}(${params}) {
23072
- ${indented};
23214
+ ${indented}
23073
23215
  }`;
23074
23216
  }
23075
23217
  return `${returnType} ${functionName}(${params}) {
@@ -23180,7 +23322,7 @@ var WGSLTarget = class extends GPUShaderTarget {
23180
23322
  return `fn ${functionName}(${params}) -> ${toWGSLType(
23181
23323
  returnType
23182
23324
  )} {
23183
- ${indented};
23325
+ ${indented}
23184
23326
  }`;
23185
23327
  }
23186
23328
  return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
@@ -25359,7 +25501,7 @@ function compileToIntervalTarget(expr, target) {
25359
25501
  }
25360
25502
 
25361
25503
  // src/compile.ts
25362
- var version = "0.55.5";
25504
+ var version = "0.56.0";
25363
25505
  export {
25364
25506
  BaseCompiler,
25365
25507
  GLSLTarget,