@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
- /** Compile 0.55.5 */
1
+ /** Compile 0.56.0 */
2
2
  (function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Compile = {}));})(this, (function (exports) { 'use strict';
3
3
  var Compile = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -1544,6 +1544,7 @@ var Compile = (() => {
1544
1544
  ];
1545
1545
  var VALUE_TYPES = [
1546
1546
  "value",
1547
+ "color",
1547
1548
  ...COLLECTION_TYPES,
1548
1549
  ...SCALAR_TYPES
1549
1550
  ];
@@ -3239,6 +3240,7 @@ var Compile = (() => {
3239
3240
  symbol: [],
3240
3241
  boolean: [],
3241
3242
  string: [],
3243
+ color: [],
3242
3244
  expression: EXPRESSION_TYPES
3243
3245
  };
3244
3246
  function isPrimitiveSubtype(lhs, rhs) {
@@ -6273,10 +6275,6 @@ var Compile = (() => {
6273
6275
  // Lagrange notation
6274
6276
  {
6275
6277
  name: "Derivative",
6276
- // @todo: Leibniz notation: {% latex " \\frac{d^n}{dx^n} f(x)" %}
6277
- // @todo: Euler modified notation: This notation is used by Mathematica. The Euler notation uses `D` instead of
6278
- // `\partial`: `\partial_{x} f`, `\partial_{x,y} f`
6279
- // Newton notation (\dot{v}, \ddot{v}) is implemented below
6280
6278
  serialize: (serializer, expr) => {
6281
6279
  const degree = machineValue(operand(expr, 2)) ?? 1;
6282
6280
  const base = serializer.serialize(operand(expr, 1));
@@ -7314,14 +7312,18 @@ var Compile = (() => {
7314
7312
  return ["Complement", lhs];
7315
7313
  }
7316
7314
  // precedence: 240,
7317
- // @todo: serialize for the multiple argument case
7318
7315
  },
7319
7316
  {
7320
7317
  name: "Complement",
7321
7318
  latexTrigger: ["^", "<{>", "\\complement", "<}>"],
7322
- kind: "postfix"
7319
+ kind: "postfix",
7323
7320
  // precedence: 240,
7324
- // @todo: serialize for the multiple argument case
7321
+ serialize: (serializer, expr) => {
7322
+ return joinLatex([
7323
+ serializer.serialize(operand(expr, 1)),
7324
+ "^\\complement"
7325
+ ]);
7326
+ }
7325
7327
  },
7326
7328
  {
7327
7329
  name: "Intersection",
@@ -7408,7 +7410,6 @@ var Compile = (() => {
7408
7410
  // commands like \rbrack a, b \rbrack which are unambiguous.
7409
7411
  {
7410
7412
  name: "Multiple",
7411
- // @todo: parse
7412
7413
  serialize: serializeSet
7413
7414
  },
7414
7415
  {
@@ -7417,14 +7418,28 @@ var Compile = (() => {
7417
7418
  kind: "infix",
7418
7419
  precedence: 350
7419
7420
  },
7421
+ // \mid as a separator/operator (used in set-builder notation: {x \mid x > 0})
7422
+ // Low precedence so it binds loosely — everything on each side is parsed first
7423
+ {
7424
+ name: "Divides",
7425
+ latexTrigger: ["\\mid"],
7426
+ kind: "infix",
7427
+ precedence: 160
7428
+ },
7420
7429
  {
7421
7430
  name: "Set",
7422
7431
  kind: "matchfix",
7423
7432
  openTrigger: "{",
7424
7433
  closeTrigger: "}",
7425
- // @todo: the set syntax can also include conditions...
7426
7434
  parse: (_parser, body) => {
7427
7435
  if (isEmptySequence(body)) return "EmptySet";
7436
+ const h = operator(body);
7437
+ if (h === "Divides" || h === "Colon") {
7438
+ const expr = operand(body, 1);
7439
+ const condition = operand(body, 2);
7440
+ if (expr !== null && condition !== null)
7441
+ return ["Set", expr, ["Condition", condition]];
7442
+ }
7428
7443
  if (operator(body) == "Delimiter" && stringValue(operand(body, 2)) === ",") {
7429
7444
  body = operand(body, 1);
7430
7445
  }
@@ -7432,6 +7447,17 @@ var Compile = (() => {
7432
7447
  return ["Set", ...operands(body)];
7433
7448
  },
7434
7449
  serialize: (serializer, expr) => {
7450
+ if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
7451
+ const condition = operand(expr, 2);
7452
+ return joinLatex([
7453
+ "\\lbrace",
7454
+ serializer.serialize(operand(expr, 1)),
7455
+ "\\mid",
7456
+ // Serialize the inner expression of the Condition wrapper
7457
+ serializer.serialize(operand(condition, 1)),
7458
+ "\\rbrace"
7459
+ ]);
7460
+ }
7435
7461
  return joinLatex([
7436
7462
  "\\lbrace",
7437
7463
  operands(expr).map((x) => serializer.serialize(x)).join(", "),
@@ -7598,23 +7624,6 @@ var Compile = (() => {
7598
7624
  if (expr === null) return "";
7599
7625
  const h = operator(expr);
7600
7626
  if (!h) return "";
7601
- if (h === "Set") {
7602
- if (nops(expr) === 0) return "\\emptyset";
7603
- if (nops(expr) === 2 && operator(operand(expr, 2)) === "Condition") {
7604
- return joinLatex([
7605
- "\\left\\lbrace",
7606
- serializer.serialize(operand(expr, 1)),
7607
- "\\middle\\mid",
7608
- serializer.serialize(operand(expr, 2)),
7609
- "\\right\\rbrace"
7610
- ]);
7611
- }
7612
- return joinLatex([
7613
- "\\left\\lbrace",
7614
- ...operands(expr).map((x) => serializer.serialize(x) + " ,"),
7615
- "\\right\\rbrace"
7616
- ]);
7617
- }
7618
7627
  if (h === "Multiple") {
7619
7628
  }
7620
7629
  if (h === "Range") {
@@ -8732,11 +8741,13 @@ var Compile = (() => {
8732
8741
  if (!parser.match("_")) return null;
8733
8742
  const base = parser.parseGroup();
8734
8743
  if (operator(base) !== "To") return null;
8735
- const expr = parser.parseArguments("implicit");
8744
+ const expr = parser.parseExpression({
8745
+ minPrec: MULTIPLICATION_PRECEDENCE
8746
+ });
8736
8747
  if (!expr) return null;
8737
8748
  return [
8738
8749
  "Limit",
8739
- ["Function", expr[0], operand(base, 1)],
8750
+ ["Function", expr, operand(base, 1)],
8740
8751
  operand(base, 2)
8741
8752
  ];
8742
8753
  },
@@ -8817,6 +8828,8 @@ var Compile = (() => {
8817
8828
  precedence: DIVISION_PRECEDENCE,
8818
8829
  parse: "Mod"
8819
8830
  },
8831
+ // Function-style alias: `\operatorname{mod}(a, b)`
8832
+ { latexTrigger: "\\operatorname{mod}", parse: "Mod" },
8820
8833
  {
8821
8834
  latexTrigger: "\\pmod",
8822
8835
  kind: "prefix",
@@ -9057,6 +9070,13 @@ var Compile = (() => {
9057
9070
  const rhs = serializer.wrap(operand(expr, 2), ADDITION_PRECEDENCE + 3);
9058
9071
  return joinLatex([lhs, "-", rhs]);
9059
9072
  }
9073
+ },
9074
+ // Euclidean distance between two points (tuples of numbers).
9075
+ {
9076
+ name: "Distance",
9077
+ latexTrigger: ["\\operatorname{distance}"],
9078
+ kind: "function",
9079
+ serialize: (serializer, expr) => "\\operatorname{distance}" + serializer.wrapArguments(expr)
9060
9080
  }
9061
9081
  ];
9062
9082
  function getIndexAssignment(expr, upper) {
@@ -10481,7 +10501,9 @@ var Compile = (() => {
10481
10501
  if (!expr || !symbol(expr)) return null;
10482
10502
  return ["Mean", expr];
10483
10503
  }
10484
- }
10504
+ },
10505
+ // Function-style alias: `\operatorname{var}(...)`
10506
+ { latexTrigger: "\\operatorname{var}", parse: "Variance" }
10485
10507
  ];
10486
10508
 
10487
10509
  // src/compute-engine/numerics/unit-data.ts
@@ -10940,12 +10962,52 @@ var Compile = (() => {
10940
10962
  ];
10941
10963
 
10942
10964
  // src/compute-engine/latex-syntax/dictionary/definitions-other.ts
10965
+ var TEX_UNITS = [
10966
+ "pt",
10967
+ "em",
10968
+ "mu",
10969
+ "ex",
10970
+ "mm",
10971
+ "cm",
10972
+ "in",
10973
+ "bp",
10974
+ "sp",
10975
+ "dd",
10976
+ "cc",
10977
+ "pc",
10978
+ "nc",
10979
+ "nd"
10980
+ ];
10981
+ function skipTexDimension(parser) {
10982
+ parser.skipSpace();
10983
+ if (parser.peek === "-" || parser.peek === "+") parser.nextToken();
10984
+ while (/^[\d.]$/.test(parser.peek)) parser.nextToken();
10985
+ for (const unit of TEX_UNITS) {
10986
+ if (parser.matchAll([...unit])) return;
10987
+ }
10988
+ }
10943
10989
  function parseSingleArg(cmd) {
10944
10990
  return (parser) => {
10945
10991
  const arg = parser.parseGroup();
10946
10992
  return arg === null ? [cmd] : [cmd, arg];
10947
10993
  };
10948
10994
  }
10995
+ function parseMathStyleSwitch(mathStyle) {
10996
+ return (parser) => {
10997
+ const body = parser.parseExpression();
10998
+ if (body !== null && !isEmptySequence(body))
10999
+ return ["Annotated", body, { dict: { mathStyle } }];
11000
+ return "Nothing";
11001
+ };
11002
+ }
11003
+ function parseSizeSwitch(size) {
11004
+ return (parser) => {
11005
+ const body = parser.parseExpression();
11006
+ if (body !== null && !isEmptySequence(body))
11007
+ return ["Annotated", body, { dict: { size } }];
11008
+ return "Nothing";
11009
+ };
11010
+ }
10949
11011
  var DEFINITIONS_OTHERS = [
10950
11012
  {
10951
11013
  name: "Overscript",
@@ -11185,80 +11247,71 @@ var Compile = (() => {
11185
11247
  },
11186
11248
  {
11187
11249
  latexTrigger: ["\\displaystyle"],
11188
- parse: () => "Nothing"
11189
- // @todo: parse as ['Annotated'...]
11250
+ parse: parseMathStyleSwitch("normal")
11190
11251
  },
11191
11252
  {
11192
11253
  latexTrigger: ["\\textstyle"],
11193
- parse: () => "Nothing"
11194
- // @todo: parse as ['Annotated'...]
11254
+ parse: parseMathStyleSwitch("compact")
11195
11255
  },
11196
11256
  {
11197
11257
  latexTrigger: ["\\scriptstyle"],
11198
- parse: () => "Nothing"
11199
- // @todo: parse as ['Annotated'...]
11258
+ parse: parseMathStyleSwitch("script")
11200
11259
  },
11201
11260
  {
11202
11261
  latexTrigger: ["\\scriptscriptstyle"],
11203
- parse: () => "Nothing"
11204
- // @todo: parse as ['Annotated'...]
11262
+ parse: parseMathStyleSwitch("scriptscript")
11205
11263
  },
11206
11264
  {
11207
11265
  latexTrigger: ["\\color"],
11208
11266
  parse: (parser) => {
11209
- parser.parseGroup();
11267
+ const color = parser.parseStringGroup();
11268
+ if (color !== null) {
11269
+ const body = parser.parseExpression();
11270
+ if (body !== null && !isEmptySequence(body))
11271
+ return ["Annotated", body, { dict: { color } }];
11272
+ }
11210
11273
  return "Nothing";
11211
11274
  }
11212
11275
  },
11213
11276
  {
11214
11277
  latexTrigger: ["\\tiny"],
11215
- parse: () => "Nothing"
11216
- // @todo: parse as ['Annotated'...]
11278
+ parse: parseSizeSwitch(1)
11217
11279
  },
11218
11280
  {
11219
11281
  latexTrigger: ["\\scriptsize"],
11220
- parse: () => "Nothing"
11221
- // @todo: parse as ['Annotated'...]
11282
+ parse: parseSizeSwitch(2)
11222
11283
  },
11223
11284
  {
11224
11285
  latexTrigger: ["\\footnotesize"],
11225
- parse: () => "Nothing"
11226
- // @todo: parse as ['Annotated'...]
11286
+ parse: parseSizeSwitch(3)
11227
11287
  },
11228
11288
  {
11229
11289
  latexTrigger: ["\\small"],
11230
- parse: () => "Nothing"
11231
- // @todo: parse as ['Annotated'...]
11290
+ parse: parseSizeSwitch(4)
11232
11291
  },
11233
11292
  {
11234
11293
  latexTrigger: ["\\normalsize"],
11235
- parse: () => "Nothing"
11236
- // @todo: parse as ['Annotated'...]
11294
+ parse: parseSizeSwitch(5)
11237
11295
  },
11238
11296
  {
11239
11297
  latexTrigger: ["\\large"],
11240
- parse: () => "Nothing"
11241
- // @todo: parse as ['Annotated'...]
11298
+ parse: parseSizeSwitch(6)
11242
11299
  },
11243
11300
  {
11244
11301
  latexTrigger: ["\\Large"],
11245
- parse: () => "Nothing"
11246
- // @todo: parse as ['Annotated'...]
11302
+ parse: parseSizeSwitch(7)
11247
11303
  },
11248
11304
  {
11249
11305
  latexTrigger: ["\\LARGE"],
11250
- parse: () => "Nothing"
11251
- // @todo: parse as ['Annotated'...]
11306
+ parse: parseSizeSwitch(8)
11252
11307
  },
11253
11308
  {
11254
11309
  latexTrigger: ["\\huge"],
11255
- parse: () => "Nothing"
11256
- // @todo: parse as ['Annotated'...]
11310
+ parse: parseSizeSwitch(9)
11257
11311
  },
11258
11312
  {
11259
11313
  latexTrigger: ["\\Huge"],
11260
- parse: () => "Nothing"
11261
- // @todo: parse as ['Annotated'...]
11314
+ parse: parseSizeSwitch(10)
11262
11315
  },
11263
11316
  {
11264
11317
  name: "Annotated",
@@ -11270,6 +11323,10 @@ var Compile = (() => {
11270
11323
  result = joinLatex(["{\\displaystyle", result, "}"]);
11271
11324
  else if (dict.dict.mathStyle === "compact")
11272
11325
  result = joinLatex(["{\\textstyle", result, "}"]);
11326
+ else if (dict.dict.mathStyle === "script")
11327
+ result = joinLatex(["{\\scriptstyle", result, "}"]);
11328
+ else if (dict.dict.mathStyle === "scriptscript")
11329
+ result = joinLatex(["{\\scriptscriptstyle", result, "}"]);
11273
11330
  const v = dict.dict.size;
11274
11331
  if (v !== null && v >= 1 && v <= 10) {
11275
11332
  result = joinLatex([
@@ -11357,6 +11414,28 @@ var Compile = (() => {
11357
11414
  latexTrigger: ["\\enspace"],
11358
11415
  parse: () => ["HorizontalSpacing", 9]
11359
11416
  },
11417
+ {
11418
+ latexTrigger: ["\\hspace"],
11419
+ parse: (parser) => {
11420
+ if (parser.peek === "*") parser.nextToken();
11421
+ parser.parseStringGroup();
11422
+ return ["HorizontalSpacing", 0];
11423
+ }
11424
+ },
11425
+ {
11426
+ latexTrigger: ["\\hskip"],
11427
+ parse: (parser) => {
11428
+ skipTexDimension(parser);
11429
+ return ["HorizontalSpacing", 0];
11430
+ }
11431
+ },
11432
+ {
11433
+ latexTrigger: ["\\kern"],
11434
+ parse: (parser) => {
11435
+ skipTexDimension(parser);
11436
+ return ["HorizontalSpacing", 0];
11437
+ }
11438
+ },
11360
11439
  {
11361
11440
  latexTrigger: ["\\phantom"],
11362
11441
  parse: (parser) => {
@@ -11407,7 +11486,17 @@ var Compile = (() => {
11407
11486
  // `["HorizontalSpacing", expr, 'op'|'bin'|rel]` -> indicate a spacing around and expression, i.e. `\mathbin{x}`, etc...
11408
11487
  serialize: (serializer, expr) => {
11409
11488
  if (operand(expr, 2) !== null) {
11410
- return serializer.serialize(operand(expr, 1));
11489
+ const cls = stringValue(operand(expr, 2));
11490
+ const inner = serializer.serialize(operand(expr, 1));
11491
+ if (cls === "bin") return `\\mathbin{${inner}}`;
11492
+ if (cls === "op") return `\\mathop{${inner}}`;
11493
+ if (cls === "rel") return `\\mathrel{${inner}}`;
11494
+ if (cls === "ord") return `\\mathord{${inner}}`;
11495
+ if (cls === "open") return `\\mathopen{${inner}}`;
11496
+ if (cls === "close") return `\\mathclose{${inner}}`;
11497
+ if (cls === "punct") return `\\mathpunct{${inner}}`;
11498
+ if (cls === "inner") return `\\mathinner{${inner}}`;
11499
+ return inner;
11411
11500
  }
11412
11501
  const v = machineValue(operand(expr, 1));
11413
11502
  if (v === null) return "";
@@ -11422,7 +11511,7 @@ var Compile = (() => {
11422
11511
  36: "\\qquad"
11423
11512
  }[v] ?? "";
11424
11513
  }
11425
- }
11514
+ },
11426
11515
  // if (
11427
11516
  // [
11428
11517
  // '\\!',
@@ -11446,6 +11535,121 @@ var Compile = (() => {
11446
11535
  // name: '',
11447
11536
  // trigger: '\\check',
11448
11537
  // },
11538
+ // ---------------------------------------------------------------------------
11539
+ // Function-style aliases for collection / random operators that some
11540
+ // notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
11541
+ // The capitalized library entries already exist; these are pure parse
11542
+ // aliases so the lowercase names don't land in `unsupported-operator`.
11543
+ // ---------------------------------------------------------------------------
11544
+ { latexTrigger: "\\operatorname{random}", parse: "Random" },
11545
+ { latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
11546
+ { latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
11547
+ { latexTrigger: "\\operatorname{join}", parse: "Join" },
11548
+ // ---------------------------------------------------------------------------
11549
+ // Geometric primitive heads. Registered as known typed heads so consumers
11550
+ // can branch on the operator name; CE itself doesn't render them. The
11551
+ // library entries (with no evaluator) live in `library/core.ts`.
11552
+ // ---------------------------------------------------------------------------
11553
+ {
11554
+ name: "Triangle",
11555
+ latexTrigger: ["\\operatorname{triangle}"],
11556
+ kind: "function",
11557
+ serialize: (serializer, expr) => "\\operatorname{triangle}" + serializer.wrapArguments(expr)
11558
+ },
11559
+ // Desmos's geometric `vector(p1, p2)` — a directed segment between two
11560
+ // points. Routed to a dedicated head (not the existing column-vector
11561
+ // `Vector`, which has a narrower `(number+) -> vector` signature).
11562
+ {
11563
+ name: "GeometricVector",
11564
+ latexTrigger: ["\\operatorname{vector}"],
11565
+ kind: "function",
11566
+ serialize: (serializer, expr) => "\\operatorname{vector}" + serializer.wrapArguments(expr)
11567
+ },
11568
+ {
11569
+ name: "Sphere",
11570
+ latexTrigger: ["\\operatorname{sphere}"],
11571
+ kind: "function",
11572
+ serialize: (serializer, expr) => "\\operatorname{sphere}" + serializer.wrapArguments(expr)
11573
+ },
11574
+ {
11575
+ name: "Segment",
11576
+ latexTrigger: ["\\operatorname{segment}"],
11577
+ kind: "function",
11578
+ serialize: (serializer, expr) => "\\operatorname{segment}" + serializer.wrapArguments(expr)
11579
+ }
11580
+ ];
11581
+
11582
+ // src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
11583
+ var DEFINITIONS_COLORS = [
11584
+ // Color constructors (one per colorspace, preserves space on evaluation)
11585
+ {
11586
+ name: "Rgb",
11587
+ latexTrigger: ["\\operatorname{rgb}"],
11588
+ kind: "function",
11589
+ serialize: (serializer, expr) => "\\operatorname{rgb}" + serializer.wrapArguments(expr)
11590
+ },
11591
+ {
11592
+ name: "Hsv",
11593
+ latexTrigger: ["\\operatorname{hsv}"],
11594
+ kind: "function",
11595
+ serialize: (serializer, expr) => "\\operatorname{hsv}" + serializer.wrapArguments(expr)
11596
+ },
11597
+ {
11598
+ name: "Hsl",
11599
+ latexTrigger: ["\\operatorname{hsl}"],
11600
+ kind: "function",
11601
+ serialize: (serializer, expr) => "\\operatorname{hsl}" + serializer.wrapArguments(expr)
11602
+ },
11603
+ {
11604
+ name: "Oklab",
11605
+ latexTrigger: ["\\operatorname{oklab}"],
11606
+ kind: "function",
11607
+ serialize: (serializer, expr) => "\\operatorname{oklab}" + serializer.wrapArguments(expr)
11608
+ },
11609
+ {
11610
+ name: "Oklch",
11611
+ latexTrigger: ["\\operatorname{oklch}"],
11612
+ kind: "function",
11613
+ serialize: (serializer, expr) => "\\operatorname{oklch}" + serializer.wrapArguments(expr)
11614
+ },
11615
+ // Conversion functions (color → color in the named space)
11616
+ {
11617
+ name: "AsRgb",
11618
+ latexTrigger: ["\\operatorname{asRgb}"],
11619
+ kind: "function",
11620
+ serialize: (serializer, expr) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr)
11621
+ },
11622
+ {
11623
+ name: "AsHsv",
11624
+ latexTrigger: ["\\operatorname{asHsv}"],
11625
+ kind: "function",
11626
+ serialize: (serializer, expr) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr)
11627
+ },
11628
+ {
11629
+ name: "AsHsl",
11630
+ latexTrigger: ["\\operatorname{asHsl}"],
11631
+ kind: "function",
11632
+ serialize: (serializer, expr) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr)
11633
+ },
11634
+ {
11635
+ name: "AsOklab",
11636
+ latexTrigger: ["\\operatorname{asOklab}"],
11637
+ kind: "function",
11638
+ serialize: (serializer, expr) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr)
11639
+ },
11640
+ {
11641
+ name: "AsOklch",
11642
+ latexTrigger: ["\\operatorname{asOklch}"],
11643
+ kind: "function",
11644
+ serialize: (serializer, expr) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr)
11645
+ },
11646
+ // Perceptual difference (returns a scalar in [0, ~1])
11647
+ {
11648
+ name: "ColorDelta",
11649
+ latexTrigger: ["\\operatorname{colorDelta}"],
11650
+ kind: "function",
11651
+ serialize: (serializer, expr) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr)
11652
+ }
11449
11653
  ];
11450
11654
 
11451
11655
  // src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
@@ -11476,7 +11680,8 @@ var Compile = (() => {
11476
11680
  ...DEFINITIONS_STATISTICS,
11477
11681
  ...DEFINITIONS_UNITS,
11478
11682
  ...DEFINITIONS_OTHERS,
11479
- ...DEFINITIONS_PHYSICS
11683
+ ...DEFINITIONS_PHYSICS,
11684
+ ...DEFINITIONS_COLORS
11480
11685
  ];
11481
11686
 
11482
11687
  // src/math-json/symbols.ts
@@ -15099,8 +15304,7 @@ ${lines.join("\n")}`;
15099
15304
  vars: options?.vars,
15100
15305
  imports: options?.imports,
15101
15306
  preamble: options?.preamble,
15102
- realOnly: options?.realOnly,
15103
- hints: options?.hints
15307
+ realOnly: options?.realOnly
15104
15308
  });
15105
15309
  } catch (e) {
15106
15310
  if (options?.fallback ?? true) {
@@ -15112,8 +15316,7 @@ ${lines.join("\n")}`;
15112
15316
  ce.pushScope();
15113
15317
  try {
15114
15318
  if (vars && typeof vars === "object") {
15115
- for (const [k, v] of Object.entries(vars))
15116
- ce.assign(k, v);
15319
+ for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
15117
15320
  }
15118
15321
  return expr.evaluate().re;
15119
15322
  } finally {
@@ -15200,8 +15403,7 @@ ${lines.join("\n")}`;
15200
15403
  return { re: null, im: formatFloat(iScale) };
15201
15404
  }
15202
15405
  const compiledFactors = remaining.map((r) => compile2(r));
15203
- if (iScale !== 1)
15204
- compiledFactors.unshift(formatFloat(iScale));
15406
+ if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
15205
15407
  const imCode = foldTerms(compiledFactors, "1.0", "*");
15206
15408
  return { re: null, im: imCode };
15207
15409
  }
@@ -15266,6 +15468,40 @@ ${lines.join("\n")}`;
15266
15468
  else h = ((r - g) / d + 4) / 6;
15267
15469
  return { h: h * 360, s, l };
15268
15470
  }
15471
+ function hsvToRgb(h, s, v) {
15472
+ h = (h % 360 + 360) % 360;
15473
+ s = Math.max(0, Math.min(1, s));
15474
+ v = Math.max(0, Math.min(1, v));
15475
+ const c = v * s;
15476
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
15477
+ const m = v - c;
15478
+ let r = 0, g = 0, b = 0;
15479
+ if (h < 60) [r, g, b] = [c, x, 0];
15480
+ else if (h < 120) [r, g, b] = [x, c, 0];
15481
+ else if (h < 180) [r, g, b] = [0, c, x];
15482
+ else if (h < 240) [r, g, b] = [0, x, c];
15483
+ else if (h < 300) [r, g, b] = [x, 0, c];
15484
+ else [r, g, b] = [c, 0, x];
15485
+ return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
15486
+ }
15487
+ function rgbToHsv(r, g, b) {
15488
+ r /= 255;
15489
+ g /= 255;
15490
+ b /= 255;
15491
+ const max2 = Math.max(r, g, b);
15492
+ const min2 = Math.min(r, g, b);
15493
+ const d = max2 - min2;
15494
+ let h = 0;
15495
+ if (d > 0) {
15496
+ if (max2 === r) h = (g - b) / d % 6;
15497
+ else if (max2 === g) h = (b - r) / d + 2;
15498
+ else h = (r - g) / d + 4;
15499
+ h *= 60;
15500
+ if (h < 0) h += 360;
15501
+ }
15502
+ const s = max2 === 0 ? 0 : d / max2;
15503
+ return { h, s, v: max2 };
15504
+ }
15269
15505
  function parseHexColor(s) {
15270
15506
  const hex = s.startsWith("#") ? s.substring(1) : s;
15271
15507
  let r, g, b;
@@ -15721,6 +15957,13 @@ ${lines.join("\n")}`;
15721
15957
  };
15722
15958
  function parseColor(s, darkMode) {
15723
15959
  const str = s.trim().toLowerCase();
15960
+ const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
15961
+ if (opacityMatch) {
15962
+ const base = parseColor(opacityMatch[1].trim(), darkMode);
15963
+ const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
15964
+ const alpha = Math.round(opacity / 100 * 255);
15965
+ return base & 4294967040 | alpha;
15966
+ }
15724
15967
  if (str.startsWith("#")) {
15725
15968
  const hex = str.substring(1);
15726
15969
  let r, g, b, a = 255;
@@ -15853,14 +16096,6 @@ ${lines.join("\n")}`;
15853
16096
  console.warn(`parseColor: unrecognized color "${s}"`);
15854
16097
  return 0;
15855
16098
  }
15856
- function parseColorToRgb01(s, darkMode) {
15857
- const color = parseColor(s, darkMode);
15858
- return [
15859
- (color >>> 24 & 255) / 255,
15860
- (color >>> 16 & 255) / 255,
15861
- (color >>> 8 & 255) / 255
15862
- ];
15863
- }
15864
16099
  function apca(bgColor, fgColor) {
15865
16100
  const bgRgb = asRgb(bgColor);
15866
16101
  const fgRgb = asRgb(fgColor);
@@ -15919,6 +16154,12 @@ ${lines.join("\n")}`;
15919
16154
  const contrast2 = Math.abs(apca(fg2, bg));
15920
16155
  return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
15921
16156
  }
16157
+ function oklabDeltaE(a, b) {
16158
+ const dL = a.L - b.L;
16159
+ const da = a.a - b.a;
16160
+ const db = a.b - b.b;
16161
+ return Math.sqrt(dL * dL + da * da + db * db);
16162
+ }
15922
16163
  var TYCHO_11 = [
15923
16164
  "#4e79a7",
15924
16165
  // Blue
@@ -20130,39 +20371,130 @@ ${lines.join("\n")}`;
20130
20371
  if (args.length >= 2)
20131
20372
  return `_SYS.colormap(${compile2(args[0])}, ${compile2(args[1])})`;
20132
20373
  return `_SYS.colormap(${compile2(args[0])})`;
20374
+ },
20375
+ // -----------------------------------------------------------------------
20376
+ // Color constructor heads. All compile to OKLCh arrays at runtime — the
20377
+ // canonical color representation in this target. The constructors take
20378
+ // their own colorspace's components and convert internally.
20379
+ // (Mirrors the GPU target's design: color values are vec3 OKLCh.)
20380
+ // -----------------------------------------------------------------------
20381
+ Rgb: (args, compile2) => {
20382
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
20383
+ return `_SYS.rgb(${args.map(compile2).join(", ")})`;
20384
+ },
20385
+ Hsv: (args, compile2) => {
20386
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
20387
+ return `_SYS.hsv(${args.map(compile2).join(", ")})`;
20388
+ },
20389
+ Hsl: (args, compile2) => {
20390
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
20391
+ return `_SYS.hsl(${args.map(compile2).join(", ")})`;
20392
+ },
20393
+ Oklab: (args, compile2) => {
20394
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
20395
+ return `_SYS.oklab(${args.map(compile2).join(", ")})`;
20396
+ },
20397
+ Oklch: (args, compile2) => {
20398
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
20399
+ return `_SYS.oklch(${args.map(compile2).join(", ")})`;
20400
+ },
20401
+ // -----------------------------------------------------------------------
20402
+ // As* converters. Compile-time output convention matches the engine and
20403
+ // the GPU target: each returns components in the named space as a 3- or
20404
+ // 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
20405
+ // layers). `AsOklch` is the identity (canonical form).
20406
+ // -----------------------------------------------------------------------
20407
+ AsRgb: ([c], compile2) => {
20408
+ if (c === null) throw new Error("AsRgb: no argument");
20409
+ return `_SYS.asRgb(${compile2(c)})`;
20410
+ },
20411
+ AsHsv: ([c], compile2) => {
20412
+ if (c === null) throw new Error("AsHsv: no argument");
20413
+ return `_SYS.asHsv(${compile2(c)})`;
20414
+ },
20415
+ AsHsl: ([c], compile2) => {
20416
+ if (c === null) throw new Error("AsHsl: no argument");
20417
+ return `_SYS.asHsl(${compile2(c)})`;
20418
+ },
20419
+ AsOklab: ([c], compile2) => {
20420
+ if (c === null) throw new Error("AsOklab: no argument");
20421
+ return `_SYS.asOklab(${compile2(c)})`;
20422
+ },
20423
+ AsOklch: ([c], compile2) => {
20424
+ if (c === null) throw new Error("AsOklch: no argument");
20425
+ return compile2(c);
20426
+ },
20427
+ // Perceptual color difference (ΔE_OK).
20428
+ ColorDelta: ([a, b], compile2) => {
20429
+ if (a === null || b === null)
20430
+ throw new Error("ColorDelta: need two colors");
20431
+ return `_SYS.colorDelta(${compile2(a)}, ${compile2(b)})`;
20432
+ },
20433
+ // Euclidean distance between two tuples (any positive dimension).
20434
+ // The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
20435
+ // (vec-only); this JS handler works on plain arrays of any length.
20436
+ Distance: ([a, b], compile2) => {
20437
+ if (a === null || b === null) throw new Error("Distance: need two points");
20438
+ return `_SYS.distance(${compile2(a)}, ${compile2(b)})`;
20133
20439
  }
20134
20440
  };
20135
20441
  function toRI(c) {
20136
20442
  return { re: c.re, im: c.im };
20137
20443
  }
20444
+ function normalizeAlpha(a) {
20445
+ if (a === void 0) return void 0;
20446
+ if (!Number.isFinite(a)) return void 0;
20447
+ if (Math.abs(a - 1) < 1e-9) return void 0;
20448
+ return a;
20449
+ }
20138
20450
  function toRgb255(input) {
20139
20451
  if (typeof input === "string") {
20140
20452
  const c = parseColor(input);
20141
- return {
20453
+ const rgb2 = {
20142
20454
  r: c >>> 24 & 255,
20143
20455
  g: c >>> 16 & 255,
20144
- b: c >>> 8 & 255,
20145
- alpha: (c & 255) / 255
20456
+ b: c >>> 8 & 255
20146
20457
  };
20458
+ const alpha = normalizeAlpha((c & 255) / 255);
20459
+ if (alpha !== void 0) rgb2.alpha = alpha;
20460
+ return rgb2;
20461
+ }
20462
+ const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
20463
+ if (input.length >= 4) {
20464
+ const alpha = normalizeAlpha(input[3]);
20465
+ if (alpha !== void 0) rgb.alpha = alpha;
20147
20466
  }
20148
- const rgb = {
20149
- r: input[0] * 255,
20150
- g: input[1] * 255,
20151
- b: input[2] * 255
20152
- };
20153
- if (input.length >= 4) rgb.alpha = input[3];
20154
20467
  return rgb;
20155
20468
  }
20156
- function packedToArray(c) {
20157
- const r = (c >>> 24 & 255) / 255;
20158
- const g = (c >>> 16 & 255) / 255;
20159
- const b = (c >>> 8 & 255) / 255;
20160
- const a = (c & 255) / 255;
20161
- return Math.abs(a - 1) < 1e-4 ? [r, g, b] : [r, g, b, a];
20469
+ function toOklch(input) {
20470
+ if (typeof input === "string") {
20471
+ const c = parseColor(input);
20472
+ const r = c >>> 24 & 255;
20473
+ const g = c >>> 16 & 255;
20474
+ const b = c >>> 8 & 255;
20475
+ const oklch2 = rgbToOklch({ r, g, b });
20476
+ const alpha = normalizeAlpha((c & 255) / 255);
20477
+ if (alpha !== void 0) oklch2.alpha = alpha;
20478
+ return oklch2;
20479
+ }
20480
+ return {
20481
+ L: input[0],
20482
+ C: input[1],
20483
+ H: input[2],
20484
+ alpha: input.length >= 4 ? normalizeAlpha(input[3]) : void 0
20485
+ };
20486
+ }
20487
+ function packedToOklch(c) {
20488
+ const r = c >>> 24 & 255;
20489
+ const g = c >>> 16 & 255;
20490
+ const b = c >>> 8 & 255;
20491
+ const oklch2 = rgbToOklch({ r, g, b });
20492
+ const alpha = normalizeAlpha((c & 255) / 255);
20493
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
20162
20494
  }
20163
20495
  var colorHelpers = {
20164
20496
  color(input) {
20165
- return packedToArray(parseColor(input));
20497
+ return packedToOklch(parseColor(input));
20166
20498
  },
20167
20499
  colorToString(input, format) {
20168
20500
  const rgb = toRgb255(input);
@@ -20173,7 +20505,7 @@ ${lines.join("\n")}`;
20173
20505
  const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
20174
20506
  const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
20175
20507
  let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
20176
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4) {
20508
+ if (rgb.alpha !== void 0) {
20177
20509
  const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
20178
20510
  hex += a.toString(16).padStart(2, "0");
20179
20511
  }
@@ -20183,7 +20515,7 @@ ${lines.join("\n")}`;
20183
20515
  const r = Math.round(rgb.r);
20184
20516
  const g = Math.round(rgb.g);
20185
20517
  const b = Math.round(rgb.b);
20186
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20518
+ if (rgb.alpha !== void 0)
20187
20519
  return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
20188
20520
  return `rgb(${r} ${g} ${b})`;
20189
20521
  }
@@ -20192,7 +20524,7 @@ ${lines.join("\n")}`;
20192
20524
  const h = Math.round(hsl.h * 10) / 10;
20193
20525
  const s = Math.round(hsl.s * 1e3) / 10;
20194
20526
  const l = Math.round(hsl.l * 1e3) / 10;
20195
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20527
+ if (rgb.alpha !== void 0)
20196
20528
  return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
20197
20529
  return `hsl(${h} ${s}% ${l}%)`;
20198
20530
  }
@@ -20201,7 +20533,7 @@ ${lines.join("\n")}`;
20201
20533
  const L = Math.round(c.L * 1e3) / 1e3;
20202
20534
  const C = Math.round(c.C * 1e3) / 1e3;
20203
20535
  const H = Math.round(c.H * 10) / 10;
20204
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
20536
+ if (rgb.alpha !== void 0)
20205
20537
  return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
20206
20538
  return `oklch(${L} ${C} ${H})`;
20207
20539
  }
@@ -20210,29 +20542,29 @@ ${lines.join("\n")}`;
20210
20542
  }
20211
20543
  },
20212
20544
  colorMix(input1, input2, ratio = 0.5) {
20213
- const rgb1 = toRgb255(input1);
20214
- const rgb2 = toRgb255(input2);
20545
+ const c1 = toOklch(input1);
20546
+ const c2 = toOklch(input2);
20215
20547
  ratio = Math.max(0, Math.min(1, ratio));
20216
- const c1 = rgbToOklch(rgb1);
20217
- const c2 = rgbToOklch(rgb2);
20218
- let dh = c2.H - c1.H;
20219
- if (dh > 180) dh -= 360;
20220
- if (dh < -180) dh += 360;
20221
- let H = c1.H + dh * ratio;
20222
- if (H < 0) H += 360;
20223
- if (H >= 360) H -= 360;
20224
- const mixed = oklchToRgb({
20225
- L: c1.L + (c2.L - c1.L) * ratio,
20226
- C: c1.C + (c2.C - c1.C) * ratio,
20227
- H
20228
- });
20229
- const r = mixed.r / 255;
20230
- const g = mixed.g / 255;
20231
- const b = mixed.b / 255;
20232
- const a1 = rgb1.alpha ?? 1;
20233
- const a2 = rgb2.alpha ?? 1;
20234
- const alpha = a1 + (a2 - a1) * ratio;
20235
- return Math.abs(alpha - 1) > 1e-4 ? [r, g, b, alpha] : [r, g, b];
20548
+ const c1Achromatic = c1.C < 1e-6;
20549
+ const c2Achromatic = c2.C < 1e-6;
20550
+ let H;
20551
+ if (c1Achromatic && c2Achromatic) H = c1.H;
20552
+ else if (c1Achromatic) H = c2.H;
20553
+ else if (c2Achromatic) H = c1.H;
20554
+ else {
20555
+ let dh = c2.H - c1.H;
20556
+ if (dh > 180) dh -= 360;
20557
+ if (dh < -180) dh += 360;
20558
+ H = c1.H + dh * ratio;
20559
+ if (H < 0) H += 360;
20560
+ if (H >= 360) H -= 360;
20561
+ }
20562
+ const L = c1.L + (c2.L - c1.L) * ratio;
20563
+ const C = c1.C + (c2.C - c1.C) * ratio;
20564
+ const a1 = c1.alpha ?? 1;
20565
+ const a2 = c2.alpha ?? 1;
20566
+ const alpha = normalizeAlpha(a1 + (a2 - a1) * ratio);
20567
+ return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
20236
20568
  },
20237
20569
  colorContrast(bg, fg) {
20238
20570
  return apca(toRgb255(bg), toRgb255(fg));
@@ -20240,11 +20572,11 @@ ${lines.join("\n")}`;
20240
20572
  contrastingColor(bg, fg1, fg2) {
20241
20573
  const bgRgb = toRgb255(bg);
20242
20574
  if (fg1 !== void 0 && fg2 !== void 0) {
20243
- return packedToArray(
20575
+ return packedToOklch(
20244
20576
  contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
20245
20577
  );
20246
20578
  }
20247
- return packedToArray(contrastingColor(bgRgb));
20579
+ return packedToOklch(contrastingColor(bgRgb));
20248
20580
  },
20249
20581
  colorToColorspace(input, space) {
20250
20582
  const rgb = toRgb255(input);
@@ -20273,7 +20605,7 @@ ${lines.join("\n")}`;
20273
20605
  default:
20274
20606
  throw new Error(`Unknown color space: ${space}`);
20275
20607
  }
20276
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
20608
+ if (alpha !== void 0) result.push(alpha);
20277
20609
  return result;
20278
20610
  },
20279
20611
  colormap(name, arg) {
@@ -20285,7 +20617,7 @@ ${lines.join("\n")}`;
20285
20617
  const palette = allPalettes[name];
20286
20618
  if (!palette) throw new Error(`Unknown palette: ${name}`);
20287
20619
  const colors = palette.map(
20288
- (hex) => parseColorToRgb01(hex)
20620
+ (hex) => packedToOklch(parseColor(hex))
20289
20621
  );
20290
20622
  if (arg === void 0) return colors;
20291
20623
  if (Number.isInteger(arg) && arg >= 2) {
@@ -20309,62 +20641,128 @@ ${lines.join("\n")}`;
20309
20641
  const frac = pos - i;
20310
20642
  if (frac === 0 || i >= colors.length - 1)
20311
20643
  return [...colors[Math.min(i, colors.length - 1)]];
20312
- const rgb1 = {
20313
- r: colors[i][0] * 255,
20314
- g: colors[i][1] * 255,
20315
- b: colors[i][2] * 255
20316
- };
20317
- const rgb2 = {
20318
- r: colors[i + 1][0] * 255,
20319
- g: colors[i + 1][1] * 255,
20320
- b: colors[i + 1][2] * 255
20321
- };
20322
- const c1 = rgbToOklch(rgb1);
20323
- const c2 = rgbToOklch(rgb2);
20324
- let dh = c2.H - c1.H;
20325
- if (dh > 180) dh -= 360;
20326
- if (dh < -180) dh += 360;
20327
- let H = c1.H + dh * frac;
20328
- if (H < 0) H += 360;
20329
- if (H >= 360) H -= 360;
20330
- const mixed = oklchToRgb({
20331
- L: c1.L + (c2.L - c1.L) * frac,
20332
- C: c1.C + (c2.C - c1.C) * frac,
20333
- H
20334
- });
20335
- return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
20644
+ const [L1, C1, H1] = colors[i];
20645
+ const [L2, C2, H2] = colors[i + 1];
20646
+ const c1Achromatic = C1 < 1e-6;
20647
+ const c2Achromatic = C2 < 1e-6;
20648
+ let H;
20649
+ if (c1Achromatic && c2Achromatic) H = H1;
20650
+ else if (c1Achromatic) H = H2;
20651
+ else if (c2Achromatic) H = H1;
20652
+ else {
20653
+ let dh = H2 - H1;
20654
+ if (dh > 180) dh -= 360;
20655
+ if (dh < -180) dh += 360;
20656
+ H = H1 + dh * frac;
20657
+ if (H < 0) H += 360;
20658
+ if (H >= 360) H -= 360;
20659
+ }
20660
+ return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
20336
20661
  },
20337
20662
  colorFromColorspace(components, space) {
20338
20663
  const c0 = components[0];
20339
20664
  const c1 = components[1];
20340
20665
  const c2 = components[2];
20341
20666
  const alpha = components.length >= 4 ? components[3] : void 0;
20342
- let result;
20667
+ let oklch2;
20343
20668
  switch (space.toLowerCase()) {
20344
20669
  case "rgb":
20345
- result = [c0, c1, c2];
20670
+ oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
20346
20671
  break;
20347
20672
  case "hsl": {
20348
- const r = hslToRgb(c0, c1, c2);
20349
- result = [r.r / 255, r.g / 255, r.b / 255];
20673
+ const rgb = hslToRgb(c0, c1, c2);
20674
+ oklch2 = rgbToOklch(rgb);
20350
20675
  break;
20351
20676
  }
20352
- case "oklch": {
20353
- const r = oklchToRgb({ L: c0, C: c1, H: c2 });
20354
- result = [r.r / 255, r.g / 255, r.b / 255];
20677
+ case "oklch":
20678
+ oklch2 = { L: c0, C: c1, H: c2 };
20355
20679
  break;
20356
- }
20357
20680
  case "oklab":
20358
- case "lab": {
20359
- const r = oklabToRgb({ L: c0, a: c1, b: c2 });
20360
- result = [r.r / 255, r.g / 255, r.b / 255];
20681
+ case "lab":
20682
+ oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
20361
20683
  break;
20362
- }
20363
20684
  default:
20364
20685
  throw new Error(`Unknown color space: ${space}`);
20365
20686
  }
20366
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
20367
- return result;
20687
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
20688
+ },
20689
+ // -----------------------------------------------------------------------
20690
+ // Color constructors. Each accepts components in its colorspace's natural
20691
+ // units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
20692
+ // -----------------------------------------------------------------------
20693
+ rgb(r, g, b, alpha) {
20694
+ const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
20695
+ const a = normalizeAlpha(alpha);
20696
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20697
+ },
20698
+ hsv(h, s, v, alpha) {
20699
+ const rgb = hsvToRgb(h, s, v);
20700
+ const c = rgbToOklch(rgb);
20701
+ const a = normalizeAlpha(alpha);
20702
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20703
+ },
20704
+ hsl(h, s, l, alpha) {
20705
+ const rgb = hslToRgb(h, s, l);
20706
+ const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
20707
+ const a = normalizeAlpha(alpha);
20708
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
20709
+ },
20710
+ oklab(L, a, b, alpha) {
20711
+ const c = oklabToOklch({ L, a, b });
20712
+ const al = normalizeAlpha(alpha);
20713
+ return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
20714
+ },
20715
+ oklch(L, C, H, alpha) {
20716
+ const a = normalizeAlpha(alpha);
20717
+ return a !== void 0 ? [L, C, H, a] : [L, C, H];
20718
+ },
20719
+ // -----------------------------------------------------------------------
20720
+ // As* converters. Inputs are anything `toOklch` accepts (string, packed
20721
+ // int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
20722
+ // space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
20723
+ // consistency with the GPU target's shader convention.
20724
+ // -----------------------------------------------------------------------
20725
+ asRgb(input) {
20726
+ const rgb = toRgb255(input);
20727
+ const r = rgb.r / 255;
20728
+ const g = rgb.g / 255;
20729
+ const b = rgb.b / 255;
20730
+ return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
20731
+ },
20732
+ asHsv(input) {
20733
+ const rgb = toRgb255(input);
20734
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
20735
+ return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
20736
+ },
20737
+ asHsl(input) {
20738
+ const rgb = toRgb255(input);
20739
+ const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
20740
+ return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
20741
+ },
20742
+ asOklab(input) {
20743
+ const c = toOklch(input);
20744
+ const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
20745
+ return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
20746
+ },
20747
+ // asOklch is identity — handled at compile time as a pass-through
20748
+ // Perceptual color difference (ΔE_OK).
20749
+ colorDelta(a, b) {
20750
+ const labA = oklchToOklab(toOklch(a));
20751
+ const labB = oklchToOklab(toOklch(b));
20752
+ return oklabDeltaE(labA, labB);
20753
+ },
20754
+ // Euclidean distance between two tuples. Plain numeric — not a color
20755
+ // operation despite living in the same helpers block.
20756
+ distance(a, b) {
20757
+ if (!Array.isArray(a) || !Array.isArray(b))
20758
+ throw new Error("Distance: expected two arrays");
20759
+ if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
20760
+ let sumSq = 0;
20761
+ for (let i = 0; i < a.length; i++) {
20762
+ const d = a[i] - b[i];
20763
+ sumSq += d * d;
20764
+ }
20765
+ return Math.sqrt(sumSq);
20368
20766
  }
20369
20767
  };
20370
20768
  var SYS_HELPERS = {
@@ -20782,43 +21180,6 @@ ${lines.join("\n")}`;
20782
21180
  return b;
20783
21181
  }
20784
21182
 
20785
- // src/compute-engine/compilation/fractal-orbit.ts
20786
- function toBigDecimal(v) {
20787
- if (typeof v === "object" && "hi" in v)
20788
- return new BigDecimal(v.hi).add(new BigDecimal(v.lo));
20789
- return new BigDecimal(v);
20790
- }
20791
- function hpToNumber(v) {
20792
- if (typeof v === "number") return v;
20793
- if (typeof v === "string") return Number(v);
20794
- return v.hi + v.lo;
20795
- }
20796
- function computeReferenceOrbit(center, maxIter, precision) {
20797
- const prevPrecision = BigDecimal.precision;
20798
- BigDecimal.precision = precision;
20799
- try {
20800
- const cr = toBigDecimal(center[0]);
20801
- const ci = toBigDecimal(center[1]);
20802
- let zr = BigDecimal.ZERO;
20803
- let zi = BigDecimal.ZERO;
20804
- const ESCAPE = new BigDecimal(256);
20805
- const points = [];
20806
- for (let i = 0; i < maxIter; i++) {
20807
- points.push(zr.toNumber(), zi.toNumber());
20808
- const zr2 = zr.mul(zr).toPrecision(precision);
20809
- const zi2 = zi.mul(zi).toPrecision(precision);
20810
- const mag2 = zr2.add(zi2);
20811
- if (mag2.cmp(ESCAPE) > 0) break;
20812
- const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
20813
- zr = zr2.sub(zi2).add(cr);
20814
- zi = new_zi;
20815
- }
20816
- return new Float32Array(points);
20817
- } finally {
20818
- BigDecimal.precision = prevPrecision;
20819
- }
20820
- }
20821
-
20822
21183
  // src/compute-engine/compilation/gpu-target.ts
20823
21184
  var GPU_OPERATORS = {
20824
21185
  Add: ["+", 11],
@@ -20840,6 +21201,13 @@ ${lines.join("\n")}`;
20840
21201
  function gpuVec2(target) {
20841
21202
  return target?.language === "wgsl" ? "vec2f" : "vec2";
20842
21203
  }
21204
+ function gpuVec3(target) {
21205
+ return target?.language === "wgsl" ? "vec3f" : "vec3";
21206
+ }
21207
+ function readStringLiteral(expr) {
21208
+ if (!isString(expr)) return null;
21209
+ return expr.string?.toLowerCase() ?? null;
21210
+ }
20843
21211
  function compileIntArg(expr, compile2, target) {
20844
21212
  const c = tryGetConstant(expr);
20845
21213
  if (c !== void 0 && Number.isInteger(c)) return c.toString();
@@ -20898,17 +21266,10 @@ ${lines.join("\n")}`;
20898
21266
  `for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
20899
21267
  ` ${acc} ${op}= ${body};`,
20900
21268
  `}`,
20901
- `return ${acc}`
21269
+ `return ${acc};`
20902
21270
  ];
20903
21271
  return lines.join("\n");
20904
21272
  }
20905
- function selectFractalStrategy(target) {
20906
- const radius = target.hints?.viewport?.radius;
20907
- if (radius === void 0) return "single";
20908
- if (radius > 1e-6) return "single";
20909
- if (radius > 1e-14) return "double";
20910
- return "perturbation";
20911
- }
20912
21273
  var GPU_FUNCTIONS = {
20913
21274
  // Variadic arithmetic (for function-call form, e.g., with vectors)
20914
21275
  Add: (args, compile2, target) => {
@@ -20959,8 +21320,7 @@ ${lines.join("\n")}`;
20959
21320
  const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
20960
21321
  const realFactors = args.filter((_, i) => i !== iIndex);
20961
21322
  const v2 = gpuVec2(target);
20962
- if (realFactors.length === 0)
20963
- return `${v2}(0.0, ${formatFloat(iScale)})`;
21323
+ if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
20964
21324
  const factors = realFactors.map((f) => compile2(f));
20965
21325
  if (iScale !== 1) factors.unshift(formatFloat(iScale));
20966
21326
  const imCode = foldTerms(factors, "1.0", "*");
@@ -21013,8 +21373,7 @@ ${lines.join("\n")}`;
21013
21373
  if (isNumber(x) && x.im !== 0) {
21014
21374
  return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
21015
21375
  }
21016
- if (isSymbol2(x, "ImaginaryUnit"))
21017
- return `${gpuVec2(target)}(0.0, -1.0)`;
21376
+ if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
21018
21377
  return `(-${compile2(x)})`;
21019
21378
  },
21020
21379
  // Standard math functions with complex dispatch
@@ -21387,49 +21746,139 @@ ${lines.join("\n")}`;
21387
21746
  }
21388
21747
  const isWGSL = target?.language === "wgsl";
21389
21748
  const v3 = isWGSL ? "vec3f" : "vec3";
21390
- return `((_gpu_apca(${bg}, ${v3}(0.0)) > 50.0) ? ${v3}(0.0) : ${v3}(1.0))`;
21749
+ const black = `${v3}(0.0)`;
21750
+ const white = `${v3}(1.0, 0.0, 0.0)`;
21751
+ return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
21391
21752
  },
21392
21753
  ColorToColorspace: ([color, space], compile2) => {
21393
21754
  if (color === null || space === null)
21394
21755
  throw new Error("ColorToColorspace: need color and space");
21395
- return `_gpu_srgb_to_oklab(${compile2(color)})`;
21756
+ const spaceName = readStringLiteral(space);
21757
+ if (spaceName === null)
21758
+ throw new Error("ColorToColorspace: space must be a string literal");
21759
+ const c = compile2(color);
21760
+ switch (spaceName) {
21761
+ case "oklch":
21762
+ return c;
21763
+ case "oklab":
21764
+ case "lab":
21765
+ return `_gpu_oklch_to_oklab(${c})`;
21766
+ case "rgb":
21767
+ return `_gpu_oklch_to_srgb(${c})`;
21768
+ case "hsl":
21769
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
21770
+ case "hsv":
21771
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
21772
+ default:
21773
+ throw new Error(
21774
+ `ColorToColorspace: unsupported space "${spaceName}" on GPU target`
21775
+ );
21776
+ }
21396
21777
  },
21397
21778
  ColorFromColorspace: ([components, space], compile2) => {
21398
21779
  if (components === null || space === null)
21399
21780
  throw new Error("ColorFromColorspace: need components and space");
21400
- return `_gpu_oklab_to_srgb(${compile2(components)})`;
21781
+ const spaceName = readStringLiteral(space);
21782
+ if (spaceName === null)
21783
+ throw new Error("ColorFromColorspace: space must be a string literal");
21784
+ const c = compile2(components);
21785
+ switch (spaceName) {
21786
+ case "oklch":
21787
+ return c;
21788
+ case "oklab":
21789
+ case "lab":
21790
+ return `_gpu_oklab_to_oklch(${c})`;
21791
+ case "rgb":
21792
+ return `_gpu_srgb_to_oklch(${c})`;
21793
+ case "hsl":
21794
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
21795
+ case "hsv":
21796
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
21797
+ default:
21798
+ throw new Error(
21799
+ `ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
21800
+ );
21801
+ }
21802
+ },
21803
+ // ---------------------------------------------------------------------------
21804
+ // Color literals. Each typed head compiles to a canonical OKLCh vec3.
21805
+ // Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
21806
+ // alpha as a separate uniform if it's needed at the framebuffer boundary.
21807
+ // ---------------------------------------------------------------------------
21808
+ Color: ([s], _compile, target) => {
21809
+ if (s === null) throw new Error("Color: no argument");
21810
+ const str = readStringLiteral(s);
21811
+ if (str === null)
21812
+ throw new Error("Color: argument must be a string literal on GPU target");
21813
+ const packed = parseColor(str);
21814
+ if (packed === 0 && str.trim().toLowerCase() !== "transparent")
21815
+ throw new Error(`Color: invalid color string "${str}"`);
21816
+ const r = packed >>> 24 & 255;
21817
+ const g = packed >>> 16 & 255;
21818
+ const b = packed >>> 8 & 255;
21819
+ const oklch2 = rgbToOklch({ r, g, b });
21820
+ return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
21821
+ },
21822
+ Rgb: (args, compile2, target) => {
21823
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
21824
+ const v3 = gpuVec3(target);
21825
+ return `_gpu_srgb_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
21826
+ },
21827
+ Hsv: (args, compile2, target) => {
21828
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
21829
+ const v3 = gpuVec3(target);
21830
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
21831
+ },
21832
+ Hsl: (args, compile2, target) => {
21833
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
21834
+ const v3 = gpuVec3(target);
21835
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
21836
+ },
21837
+ Oklab: (args, compile2, target) => {
21838
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
21839
+ const v3 = gpuVec3(target);
21840
+ return `_gpu_oklab_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
21841
+ },
21842
+ Oklch: (args, compile2, target) => {
21843
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
21844
+ const v3 = gpuVec3(target);
21845
+ return `${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})`;
21846
+ },
21847
+ // ---------------------------------------------------------------------------
21848
+ // As* operators. AsOklch is identity (canonical). The other As* return
21849
+ // components in the named space, equivalent to ColorToColorspace(c, 'x').
21850
+ // ---------------------------------------------------------------------------
21851
+ AsOklch: ([c], compile2) => {
21852
+ if (c === null) throw new Error("AsOklch: no argument");
21853
+ return compile2(c);
21854
+ },
21855
+ AsOklab: ([c], compile2) => {
21856
+ if (c === null) throw new Error("AsOklab: no argument");
21857
+ return `_gpu_oklch_to_oklab(${compile2(c)})`;
21858
+ },
21859
+ AsRgb: ([c], compile2) => {
21860
+ if (c === null) throw new Error("AsRgb: no argument");
21861
+ return `_gpu_oklch_to_srgb(${compile2(c)})`;
21862
+ },
21863
+ AsHsv: ([c], compile2) => {
21864
+ if (c === null) throw new Error("AsHsv: no argument");
21865
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile2(c)}))`;
21866
+ },
21867
+ AsHsl: ([c], compile2) => {
21868
+ if (c === null) throw new Error("AsHsl: no argument");
21869
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile2(c)}))`;
21401
21870
  },
21402
21871
  // Fractal functions
21403
21872
  Mandelbrot: ([c, maxIter], compile2, target) => {
21404
21873
  if (c === null || maxIter === null)
21405
21874
  throw new Error("Mandelbrot: missing arguments");
21406
21875
  const iterCode = compileIntArg(maxIter, compile2, target);
21407
- const strategy = selectFractalStrategy(target);
21408
- if (strategy === "double") {
21409
- const dpCoord = target?.language === "wgsl" ? "_dp_coord(v_uv)" : "_dp_coord()";
21410
- return `_fractal_mandelbrot_dp(${dpCoord}, ${iterCode})`;
21411
- }
21412
- if (strategy === "perturbation") {
21413
- const ptDelta = target?.language === "wgsl" ? "_pt_delta(v_uv)" : "_pt_delta()";
21414
- return `_fractal_mandelbrot_pt(${ptDelta}, ${iterCode})`;
21415
- }
21416
21876
  return `_fractal_mandelbrot(${compile2(c)}, ${iterCode})`;
21417
21877
  },
21418
21878
  Julia: ([z, c, maxIter], compile2, target) => {
21419
21879
  if (z === null || c === null || maxIter === null)
21420
21880
  throw new Error("Julia: missing arguments");
21421
21881
  const iterCode = compileIntArg(maxIter, compile2, target);
21422
- const strategy = selectFractalStrategy(target);
21423
- if (strategy === "double") {
21424
- const dpCoord = target?.language === "wgsl" ? "_dp_coord(v_uv)" : "_dp_coord()";
21425
- const cCode = compile2(c);
21426
- return `_fractal_julia_dp(${dpCoord}, vec4(${cCode}, vec2(0.0)), ${iterCode})`;
21427
- }
21428
- if (strategy === "perturbation") {
21429
- const ptDelta = target?.language === "wgsl" ? "_pt_delta(v_uv)" : "_pt_delta()";
21430
- const cCode = compile2(c);
21431
- return `_fractal_julia_pt(${ptDelta}, ${cCode}, ${iterCode})`;
21432
- }
21433
21882
  return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${iterCode})`;
21434
21883
  },
21435
21884
  // Vector/Matrix operations
@@ -22026,232 +22475,6 @@ fn _gpu_besselJ(n_in: i32, x_in: f32) -> f32 {
22026
22475
  for (var k2: i32 = 2; k2 <= M; k2 += 2) { norm += 2.0 * vals[k2]; }
22027
22476
  return sgn * vals[n] / norm;
22028
22477
  }
22029
- `;
22030
- var GPU_DS_ARITHMETIC_PREAMBLE_GLSL = `
22031
- // Split a float into high and low parts for exact multiplication
22032
- vec2 ds_split(float a) {
22033
- const float SPLIT = 4097.0; // 2^12 + 1
22034
- float t = SPLIT * a;
22035
- float hi = t - (t - a);
22036
- float lo = a - hi;
22037
- return vec2(hi, lo);
22038
- }
22039
-
22040
- // Create a double-single from a single float
22041
- vec2 ds_from(float a) {
22042
- return vec2(a, 0.0);
22043
- }
22044
-
22045
- // Error-free addition (Knuth TwoSum)
22046
- vec2 ds_add(vec2 a, vec2 b) {
22047
- float s = a.x + b.x;
22048
- float v = s - a.x;
22049
- float e = (a.x - (s - v)) + (b.x - v);
22050
- float lo = (a.y + b.y) + e;
22051
- float hi = s + lo;
22052
- lo = lo - (hi - s);
22053
- return vec2(hi, lo);
22054
- }
22055
-
22056
- // Double-single subtraction
22057
- vec2 ds_sub(vec2 a, vec2 b) {
22058
- return ds_add(a, vec2(-b.x, -b.y));
22059
- }
22060
-
22061
- // Error-free multiplication (Dekker TwoProduct)
22062
- vec2 ds_mul(vec2 a, vec2 b) {
22063
- float p = a.x * b.x;
22064
- vec2 sa = ds_split(a.x);
22065
- vec2 sb = ds_split(b.x);
22066
- float err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22067
- err += a.x * b.y + a.y * b.x;
22068
- float hi = p + err;
22069
- float lo = err - (hi - p);
22070
- return vec2(hi, lo);
22071
- }
22072
-
22073
- // Optimized self-multiply
22074
- vec2 ds_sqr(vec2 a) {
22075
- float p = a.x * a.x;
22076
- vec2 sa = ds_split(a.x);
22077
- float err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22078
- err += 2.0 * a.x * a.y;
22079
- float hi = p + err;
22080
- float lo = err - (hi - p);
22081
- return vec2(hi, lo);
22082
- }
22083
-
22084
- // Compare magnitude: returns -1, 0, or 1
22085
- float ds_cmp(vec2 a, vec2 b) {
22086
- float d = a.x - b.x;
22087
- if (d != 0.0) return sign(d);
22088
- return sign(a.y - b.y);
22089
- }
22090
- `;
22091
- var GPU_DS_ARITHMETIC_PREAMBLE_WGSL = `
22092
- fn ds_split(a: f32) -> vec2f {
22093
- const SPLIT: f32 = 4097.0;
22094
- let t = SPLIT * a;
22095
- let hi = t - (t - a);
22096
- let lo = a - hi;
22097
- return vec2f(hi, lo);
22098
- }
22099
-
22100
- fn ds_from(a: f32) -> vec2f {
22101
- return vec2f(a, 0.0);
22102
- }
22103
-
22104
- fn ds_add(a: vec2f, b: vec2f) -> vec2f {
22105
- let s = a.x + b.x;
22106
- let v = s - a.x;
22107
- let e = (a.x - (s - v)) + (b.x - v);
22108
- let lo_t = (a.y + b.y) + e;
22109
- let hi = s + lo_t;
22110
- let lo = lo_t - (hi - s);
22111
- return vec2f(hi, lo);
22112
- }
22113
-
22114
- fn ds_sub(a: vec2f, b: vec2f) -> vec2f {
22115
- return ds_add(a, vec2f(-b.x, -b.y));
22116
- }
22117
-
22118
- fn ds_mul(a: vec2f, b: vec2f) -> vec2f {
22119
- let p = a.x * b.x;
22120
- let sa = ds_split(a.x);
22121
- let sb = ds_split(b.x);
22122
- var err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
22123
- err += a.x * b.y + a.y * b.x;
22124
- let hi = p + err;
22125
- let lo = err - (hi - p);
22126
- return vec2f(hi, lo);
22127
- }
22128
-
22129
- fn ds_sqr(a: vec2f) -> vec2f {
22130
- let p = a.x * a.x;
22131
- let sa = ds_split(a.x);
22132
- var err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
22133
- err += 2.0 * a.x * a.y;
22134
- let hi = p + err;
22135
- let lo = err - (hi - p);
22136
- return vec2f(hi, lo);
22137
- }
22138
-
22139
- fn ds_cmp(a: vec2f, b: vec2f) -> f32 {
22140
- let d = a.x - b.x;
22141
- if (d != 0.0) { return sign(d); }
22142
- return sign(a.y - b.y);
22143
- }
22144
- `;
22145
- var GPU_FRACTAL_DP_PREAMBLE_GLSL = `
22146
- uniform float _dp_cx_hi;
22147
- uniform float _dp_cx_lo;
22148
- uniform float _dp_cy_hi;
22149
- uniform float _dp_cy_lo;
22150
- uniform float _dp_w;
22151
- uniform float _dp_h;
22152
-
22153
- vec4 _dp_coord() {
22154
- // Per-pixel offset from center \u2014 small, so float-precise
22155
- float dx = (v_uv.x - 0.5) * _dp_w;
22156
- float dy = (v_uv.y - 0.5) * _dp_h;
22157
- // Combine center (hi+lo) + delta with emulated double precision
22158
- vec2 cre = ds_add(vec2(_dp_cx_hi, _dp_cx_lo), ds_from(dx));
22159
- vec2 cim = ds_add(vec2(_dp_cy_hi, _dp_cy_lo), ds_from(dy));
22160
- return vec4(cre.x, cim.x, cre.y, cim.y);
22161
- }
22162
-
22163
- float _fractal_mandelbrot_dp(vec4 c, int maxIter) {
22164
- // c = (re_hi, im_hi, re_lo, im_lo)
22165
- vec2 cr = vec2(c.x, c.z); // real part as ds
22166
- vec2 ci = vec2(c.y, c.w); // imag part as ds
22167
- vec2 zr = vec2(0.0, 0.0);
22168
- vec2 zi = vec2(0.0, 0.0);
22169
- for (int i = 0; i < maxIter; i++) {
22170
- vec2 zr2 = ds_sqr(zr);
22171
- vec2 zi2 = ds_sqr(zi);
22172
- // |z|^2 > 4.0 ?
22173
- vec2 mag2 = ds_add(zr2, zi2);
22174
- if (mag2.x > 4.0)
22175
- return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22176
- // z = z^2 + c
22177
- vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci); // 2*zr*zi + ci
22178
- zr = ds_add(ds_sub(zr2, zi2), cr); // zr^2 - zi^2 + cr
22179
- zi = new_zi;
22180
- }
22181
- return 1.0;
22182
- }
22183
-
22184
- float _fractal_julia_dp(vec4 z_in, vec4 c, int maxIter) {
22185
- vec2 zr = vec2(z_in.x, z_in.z);
22186
- vec2 zi = vec2(z_in.y, z_in.w);
22187
- vec2 cr = vec2(c.x, c.z);
22188
- vec2 ci = vec2(c.y, c.w);
22189
- for (int i = 0; i < maxIter; i++) {
22190
- vec2 zr2 = ds_sqr(zr);
22191
- vec2 zi2 = ds_sqr(zi);
22192
- vec2 mag2 = ds_add(zr2, zi2);
22193
- if (mag2.x > 4.0)
22194
- return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
22195
- vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22196
- zr = ds_add(ds_sub(zr2, zi2), cr);
22197
- zi = new_zi;
22198
- }
22199
- return 1.0;
22200
- }
22201
- `;
22202
- var GPU_FRACTAL_DP_PREAMBLE_WGSL = `
22203
- @group(0) @binding(10) var<uniform> _dp_cx_hi: f32;
22204
- @group(0) @binding(11) var<uniform> _dp_cx_lo: f32;
22205
- @group(0) @binding(12) var<uniform> _dp_cy_hi: f32;
22206
- @group(0) @binding(13) var<uniform> _dp_cy_lo: f32;
22207
- @group(0) @binding(14) var<uniform> _dp_w: f32;
22208
- @group(0) @binding(15) var<uniform> _dp_h: f32;
22209
-
22210
- fn _dp_coord(uv: vec2f) -> vec4f {
22211
- let dx = (uv.x - 0.5) * _dp_w;
22212
- let dy = (uv.y - 0.5) * _dp_h;
22213
- let cre = ds_add(vec2f(_dp_cx_hi, _dp_cx_lo), ds_from(dx));
22214
- let cim = ds_add(vec2f(_dp_cy_hi, _dp_cy_lo), ds_from(dy));
22215
- return vec4f(cre.x, cim.x, cre.y, cim.y);
22216
- }
22217
-
22218
- fn _fractal_mandelbrot_dp(c: vec4f, maxIter: i32) -> f32 {
22219
- let cr = vec2f(c.x, c.z);
22220
- let ci = vec2f(c.y, c.w);
22221
- var zr = vec2f(0.0, 0.0);
22222
- var zi = vec2f(0.0, 0.0);
22223
- for (var i: i32 = 0; i < maxIter; i++) {
22224
- let zr2 = ds_sqr(zr);
22225
- let zi2 = ds_sqr(zi);
22226
- let mag2 = ds_add(zr2, zi2);
22227
- if (mag2.x > 4.0) {
22228
- return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22229
- }
22230
- let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22231
- zr = ds_add(ds_sub(zr2, zi2), cr);
22232
- zi = new_zi;
22233
- }
22234
- return 1.0;
22235
- }
22236
-
22237
- fn _fractal_julia_dp(z_in: vec4f, c: vec4f, maxIter: i32) -> f32 {
22238
- var zr = vec2f(z_in.x, z_in.z);
22239
- var zi = vec2f(z_in.y, z_in.w);
22240
- let cr = vec2f(c.x, c.z);
22241
- let ci = vec2f(c.y, c.w);
22242
- for (var i: i32 = 0; i < maxIter; i++) {
22243
- let zr2 = ds_sqr(zr);
22244
- let zi2 = ds_sqr(zi);
22245
- let mag2 = ds_add(zr2, zi2);
22246
- if (mag2.x > 4.0) {
22247
- return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
22248
- }
22249
- let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
22250
- zr = ds_add(ds_sub(zr2, zi2), cr);
22251
- zi = new_zi;
22252
- }
22253
- return 1.0;
22254
- }
22255
22478
  `;
22256
22479
  var GPU_FRACTAL_PREAMBLE_GLSL = `
22257
22480
  float _fractal_mandelbrot(vec2 c, int maxIter) {
@@ -22295,208 +22518,6 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
22295
22518
  }
22296
22519
  return 1.0;
22297
22520
  }
22298
- `;
22299
- var GPU_FRACTAL_PT_PREAMBLE_GLSL = `
22300
- uniform sampler2D _refOrbit;
22301
- uniform int _refOrbitLen;
22302
- uniform int _refOrbitTexWidth;
22303
- uniform float _pt_offset_x;
22304
- uniform float _pt_offset_y;
22305
- uniform float _pt_w;
22306
- uniform float _pt_h;
22307
-
22308
- vec2 _pt_delta() {
22309
- float dx = _pt_offset_x + (v_uv.x - 0.5) * _pt_w;
22310
- float dy = _pt_offset_y + (v_uv.y - 0.5) * _pt_h;
22311
- return vec2(dx, dy);
22312
- }
22313
-
22314
- vec2 _pt_fetch_orbit(int i) {
22315
- int y = i / _refOrbitTexWidth;
22316
- int x = i - y * _refOrbitTexWidth;
22317
- return texelFetch(_refOrbit, ivec2(x, y), 0).rg;
22318
- }
22319
-
22320
- float _fractal_mandelbrot_pt(vec2 delta_c, int maxIter) {
22321
- float dr = 0.0;
22322
- float di = 0.0;
22323
- int orbitLen = min(maxIter, _refOrbitLen);
22324
- for (int i = 0; i < orbitLen; i++) {
22325
- vec2 Zn = _pt_fetch_orbit(i);
22326
- // delta_{n+1} = 2*Z_n*delta_n + delta_n^2 + delta_c
22327
- float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22328
- float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22329
- dr = new_dr;
22330
- di = new_di;
22331
- // Full z = Z_{n+1} + delta for escape check
22332
- vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22333
- float zr = Zn1.x + dr;
22334
- float zi = Zn1.y + di;
22335
- float mag2 = zr * zr + zi * zi;
22336
- if (mag2 > 4.0)
22337
- return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22338
- // Glitch detection: |delta|^2 > |Z|^2
22339
- float dmag2 = dr * dr + di * di;
22340
- float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22341
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22342
- // Rebase to absolute coordinates and continue with single-float
22343
- float abs_zr = Zn1.x + dr;
22344
- float abs_zi = Zn1.y + di;
22345
- // Reconstruct absolute c from reference + delta
22346
- // (Use ds_from for the concept, but single-float suffices for fallback)
22347
- float cx = abs_zr - dr + delta_c.x;
22348
- float cy = abs_zi - di + delta_c.y;
22349
- for (int j = i + 1; j < maxIter; j++) {
22350
- float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22351
- abs_zi = 2.0 * abs_zr * abs_zi + cy;
22352
- abs_zr = new_zr;
22353
- mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22354
- if (mag2 > 4.0)
22355
- return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22356
- }
22357
- return 1.0;
22358
- }
22359
- }
22360
- return 1.0;
22361
- }
22362
-
22363
- float _fractal_julia_pt(vec2 z_delta, vec2 delta_c, int maxIter) {
22364
- float dr = z_delta.x;
22365
- float di = z_delta.y;
22366
- int orbitLen = min(maxIter, _refOrbitLen);
22367
- for (int i = 0; i < orbitLen; i++) {
22368
- vec2 Zn = _pt_fetch_orbit(i);
22369
- float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22370
- float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22371
- dr = new_dr;
22372
- di = new_di;
22373
- vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
22374
- float zr = Zn1.x + dr;
22375
- float zi = Zn1.y + di;
22376
- float mag2 = zr * zr + zi * zi;
22377
- if (mag2 > 4.0)
22378
- return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22379
- float dmag2 = dr * dr + di * di;
22380
- float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22381
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22382
- float abs_zr = Zn1.x + dr;
22383
- float abs_zi = Zn1.y + di;
22384
- float cx = delta_c.x;
22385
- float cy = delta_c.y;
22386
- for (int j = i + 1; j < maxIter; j++) {
22387
- float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
22388
- abs_zi = 2.0 * abs_zr * abs_zi + cy;
22389
- abs_zr = new_zr;
22390
- mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
22391
- if (mag2 > 4.0)
22392
- return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
22393
- }
22394
- return 1.0;
22395
- }
22396
- }
22397
- return 1.0;
22398
- }
22399
- `;
22400
- var GPU_FRACTAL_PT_PREAMBLE_WGSL = `
22401
- @group(0) @binding(1) var _refOrbit: texture_2d<f32>;
22402
- var<uniform> _refOrbitLen: i32;
22403
- var<uniform> _refOrbitTexWidth: i32;
22404
- var<uniform> _pt_offset_x: f32;
22405
- var<uniform> _pt_offset_y: f32;
22406
- var<uniform> _pt_w: f32;
22407
- var<uniform> _pt_h: f32;
22408
-
22409
- fn _pt_delta(uv: vec2f) -> vec2f {
22410
- let dx = _pt_offset_x + (uv.x - 0.5) * _pt_w;
22411
- let dy = _pt_offset_y + (uv.y - 0.5) * _pt_h;
22412
- return vec2f(dx, dy);
22413
- }
22414
-
22415
- fn _pt_fetch_orbit(i: i32) -> vec2f {
22416
- let y = i / _refOrbitTexWidth;
22417
- let x = i - y * _refOrbitTexWidth;
22418
- return textureLoad(_refOrbit, vec2i(x, y), 0).rg;
22419
- }
22420
-
22421
- fn _fractal_mandelbrot_pt(delta_c: vec2f, maxIter: i32) -> f32 {
22422
- var dr: f32 = 0.0;
22423
- var di: f32 = 0.0;
22424
- let orbitLen = min(maxIter, _refOrbitLen);
22425
- for (var i: i32 = 0; i < orbitLen; i++) {
22426
- let Zn = _pt_fetch_orbit(i);
22427
- let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22428
- let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22429
- dr = new_dr;
22430
- di = new_di;
22431
- var Zn1 = vec2f(0.0);
22432
- if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22433
- let zr = Zn1.x + dr;
22434
- let zi = Zn1.y + di;
22435
- var mag2 = zr * zr + zi * zi;
22436
- if (mag2 > 4.0) {
22437
- return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22438
- }
22439
- let dmag2 = dr * dr + di * di;
22440
- let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22441
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22442
- var f_zr = Zn1.x + dr;
22443
- var f_zi = Zn1.y + di;
22444
- let cx = delta_c.x;
22445
- let cy = delta_c.y;
22446
- for (var j: i32 = i + 1; j < maxIter; j++) {
22447
- let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22448
- f_zi = 2.0 * f_zr * f_zi + cy;
22449
- f_zr = t_zr;
22450
- mag2 = f_zr * f_zr + f_zi * f_zi;
22451
- if (mag2 > 4.0) {
22452
- return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22453
- }
22454
- }
22455
- return 1.0;
22456
- }
22457
- }
22458
- return 1.0;
22459
- }
22460
-
22461
- fn _fractal_julia_pt(z_delta: vec2f, delta_c: vec2f, maxIter: i32) -> f32 {
22462
- var dr = z_delta.x;
22463
- var di = z_delta.y;
22464
- let orbitLen = min(maxIter, _refOrbitLen);
22465
- for (var i: i32 = 0; i < orbitLen; i++) {
22466
- let Zn = _pt_fetch_orbit(i);
22467
- let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
22468
- let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
22469
- dr = new_dr;
22470
- di = new_di;
22471
- var Zn1 = vec2f(0.0);
22472
- if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
22473
- let zr = Zn1.x + dr;
22474
- let zi = Zn1.y + di;
22475
- var mag2 = zr * zr + zi * zi;
22476
- if (mag2 > 4.0) {
22477
- return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22478
- }
22479
- let dmag2 = dr * dr + di * di;
22480
- let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
22481
- if (dmag2 > Zmag2 && Zmag2 > 0.0) {
22482
- var f_zr = Zn1.x + dr;
22483
- var f_zi = Zn1.y + di;
22484
- let cx = delta_c.x;
22485
- let cy = delta_c.y;
22486
- for (var j: i32 = i + 1; j < maxIter; j++) {
22487
- let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
22488
- f_zi = 2.0 * f_zr * f_zi + cy;
22489
- f_zr = t_zr;
22490
- mag2 = f_zr * f_zr + f_zi * f_zi;
22491
- if (mag2 > 4.0) {
22492
- return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
22493
- }
22494
- }
22495
- return 1.0;
22496
- }
22497
- }
22498
- return 1.0;
22499
- }
22500
22521
  `;
22501
22522
  var GPU_COLOR_PREAMBLE_GLSL = `
22502
22523
  float _gpu_srgb_to_linear(float c) {
@@ -22538,28 +22559,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
22538
22559
 
22539
22560
  vec3 _gpu_oklab_to_oklch(vec3 lab) {
22540
22561
  float C = length(lab.yz);
22541
- float H = atan(lab.z, lab.y);
22562
+ float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
22563
+ if (H < 0.0) H += 360.0;
22542
22564
  return vec3(lab.x, C, H);
22543
22565
  }
22544
22566
 
22545
22567
  vec3 _gpu_oklch_to_oklab(vec3 lch) {
22546
- return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
22568
+ float h_rad = lch.z * (3.14159265359 / 180.0);
22569
+ return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
22570
+ }
22571
+
22572
+ vec3 _gpu_srgb_to_oklch(vec3 rgb) {
22573
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
22547
22574
  }
22548
22575
 
22549
- vec3 _gpu_color_mix(vec3 rgb1, vec3 rgb2, float t) {
22550
- vec3 lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
22551
- vec3 lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
22576
+ vec3 _gpu_oklch_to_srgb(vec3 lch) {
22577
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
22578
+ }
22579
+
22580
+ // HSL conversion. Hue in degrees, saturation/lightness in 0-1.
22581
+ vec3 _gpu_hsl_to_rgb(vec3 hsl) {
22582
+ float h = hsl.x;
22583
+ float s = hsl.y;
22584
+ float l = hsl.z;
22585
+ float c = (1.0 - abs(2.0 * l - 1.0)) * s;
22586
+ float h6 = h / 60.0;
22587
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
22588
+ float r = 0.0;
22589
+ float g = 0.0;
22590
+ float b = 0.0;
22591
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22592
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22593
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22594
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22595
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22596
+ else { r = c; g = 0.0; b = x; }
22597
+ float m = l - c / 2.0;
22598
+ return vec3(r + m, g + m, b + m);
22599
+ }
22600
+
22601
+ vec3 _gpu_rgb_to_hsl(vec3 rgb) {
22602
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
22603
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
22604
+ float l = (maxc + minc) / 2.0;
22605
+ float d = maxc - minc;
22606
+ if (d < 1e-6) return vec3(0.0, 0.0, l);
22607
+ float s = d / (1.0 - abs(2.0 * l - 1.0));
22608
+ float h;
22609
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
22610
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
22611
+ else h = (rgb.x - rgb.y) / d + 4.0;
22612
+ h *= 60.0;
22613
+ if (h < 0.0) h += 360.0;
22614
+ return vec3(h, s, l);
22615
+ }
22616
+
22617
+ // HSV conversion. Hue in degrees, saturation/value in 0-1.
22618
+ vec3 _gpu_hsv_to_rgb(vec3 hsv) {
22619
+ float h = hsv.x;
22620
+ float s = hsv.y;
22621
+ float v = hsv.z;
22622
+ float c = v * s;
22623
+ float h6 = h / 60.0;
22624
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
22625
+ float r = 0.0;
22626
+ float g = 0.0;
22627
+ float b = 0.0;
22628
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22629
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22630
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22631
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22632
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22633
+ else { r = c; g = 0.0; b = x; }
22634
+ float m = v - c;
22635
+ return vec3(r + m, g + m, b + m);
22636
+ }
22637
+
22638
+ vec3 _gpu_rgb_to_hsv(vec3 rgb) {
22639
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
22640
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
22641
+ float v = maxc;
22642
+ float d = maxc - minc;
22643
+ if (d < 1e-6) return vec3(0.0, 0.0, v);
22644
+ float s = (maxc < 1e-6) ? 0.0 : d / maxc;
22645
+ float h;
22646
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
22647
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
22648
+ else h = (rgb.x - rgb.y) / d + 4.0;
22649
+ h *= 60.0;
22650
+ if (h < 0.0) h += 360.0;
22651
+ return vec3(h, s, v);
22652
+ }
22653
+
22654
+ vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
22552
22655
  float L = mix(lch1.x, lch2.x, t);
22553
22656
  float C = mix(lch1.y, lch2.y, t);
22554
- float dh = lch2.z - lch1.z;
22555
- const float PI = 3.14159265359;
22556
- if (dh > PI) dh -= 2.0 * PI;
22557
- if (dh < -PI) dh += 2.0 * PI;
22558
- float H = lch1.z + dh * t;
22559
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3(L, C, H)));
22657
+ bool a1 = lch1.y < 1e-6;
22658
+ bool a2 = lch2.y < 1e-6;
22659
+ float H;
22660
+ if (a1 && a2) {
22661
+ H = lch1.z;
22662
+ } else if (a1) {
22663
+ H = lch2.z;
22664
+ } else if (a2) {
22665
+ H = lch1.z;
22666
+ } else {
22667
+ float dh = lch2.z - lch1.z;
22668
+ if (dh > 180.0) dh -= 360.0;
22669
+ if (dh < -180.0) dh += 360.0;
22670
+ H = lch1.z + dh * t;
22671
+ if (H < 0.0) H += 360.0;
22672
+ if (H >= 360.0) H -= 360.0;
22673
+ }
22674
+ return vec3(L, C, H);
22560
22675
  }
22561
22676
 
22562
- float _gpu_apca(vec3 bg, vec3 fg) {
22677
+ float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
22678
+ vec3 bg = _gpu_oklch_to_srgb(lch_bg);
22679
+ vec3 fg = _gpu_oklch_to_srgb(lch_fg);
22563
22680
  float bgR = _gpu_srgb_to_linear(bg.x);
22564
22681
  float bgG = _gpu_srgb_to_linear(bg.y);
22565
22682
  float bgB = _gpu_srgb_to_linear(bg.z);
@@ -22570,9 +22687,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
22570
22687
  float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
22571
22688
  float bgC = pow(bgY, 0.56);
22572
22689
  float fgC = pow(fgY, 0.57);
22573
- float contrast = (bgC > fgC)
22574
- ? (bgC - fgC) * 1.14
22575
- : (bgC - fgC) * 1.14;
22690
+ float contrast = (bgC - fgC) * 1.14;
22576
22691
  return contrast * 100.0;
22577
22692
  }
22578
22693
  `;
@@ -22616,28 +22731,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
22616
22731
 
22617
22732
  fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
22618
22733
  let C = length(lab.yz);
22619
- let H = atan2(lab.z, lab.y);
22734
+ var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
22735
+ if (H < 0.0) { H = H + 360.0; }
22620
22736
  return vec3f(lab.x, C, H);
22621
22737
  }
22622
22738
 
22623
22739
  fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
22624
- return vec3f(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
22740
+ let h_rad = lch.z * (3.14159265359 / 180.0);
22741
+ return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
22625
22742
  }
22626
22743
 
22627
- fn _gpu_color_mix(rgb1: vec3f, rgb2: vec3f, t: f32) -> vec3f {
22628
- let lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
22629
- let lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
22744
+ fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
22745
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
22746
+ }
22747
+
22748
+ fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
22749
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
22750
+ }
22751
+
22752
+ fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
22753
+ let h = hsl.x;
22754
+ let s = hsl.y;
22755
+ let l = hsl.z;
22756
+ let c = (1.0 - abs(2.0 * l - 1.0)) * s;
22757
+ let h6 = h / 60.0;
22758
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
22759
+ var r: f32 = 0.0;
22760
+ var g: f32 = 0.0;
22761
+ var b: f32 = 0.0;
22762
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22763
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22764
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22765
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22766
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22767
+ else { r = c; g = 0.0; b = x; }
22768
+ let m = l - c / 2.0;
22769
+ return vec3f(r + m, g + m, b + m);
22770
+ }
22771
+
22772
+ fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
22773
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
22774
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
22775
+ let l = (maxc + minc) / 2.0;
22776
+ let d = maxc - minc;
22777
+ if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
22778
+ let s = d / (1.0 - abs(2.0 * l - 1.0));
22779
+ var h: f32;
22780
+ if (maxc == rgb.x) {
22781
+ let v = (rgb.y - rgb.z) / d;
22782
+ h = v - 6.0 * floor(v / 6.0);
22783
+ } else if (maxc == rgb.y) {
22784
+ h = (rgb.z - rgb.x) / d + 2.0;
22785
+ } else {
22786
+ h = (rgb.x - rgb.y) / d + 4.0;
22787
+ }
22788
+ h = h * 60.0;
22789
+ if (h < 0.0) { h = h + 360.0; }
22790
+ return vec3f(h, s, l);
22791
+ }
22792
+
22793
+ fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
22794
+ let h = hsv.x;
22795
+ let s = hsv.y;
22796
+ let v = hsv.z;
22797
+ let c = v * s;
22798
+ let h6 = h / 60.0;
22799
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
22800
+ var r: f32 = 0.0;
22801
+ var g: f32 = 0.0;
22802
+ var b: f32 = 0.0;
22803
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
22804
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
22805
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
22806
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
22807
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
22808
+ else { r = c; g = 0.0; b = x; }
22809
+ let m = v - c;
22810
+ return vec3f(r + m, g + m, b + m);
22811
+ }
22812
+
22813
+ fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
22814
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
22815
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
22816
+ let v = maxc;
22817
+ let d = maxc - minc;
22818
+ if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
22819
+ var s: f32 = 0.0;
22820
+ if (maxc >= 1e-6) { s = d / maxc; }
22821
+ var h: f32;
22822
+ if (maxc == rgb.x) {
22823
+ let q = (rgb.y - rgb.z) / d;
22824
+ h = q - 6.0 * floor(q / 6.0);
22825
+ } else if (maxc == rgb.y) {
22826
+ h = (rgb.z - rgb.x) / d + 2.0;
22827
+ } else {
22828
+ h = (rgb.x - rgb.y) / d + 4.0;
22829
+ }
22830
+ h = h * 60.0;
22831
+ if (h < 0.0) { h = h + 360.0; }
22832
+ return vec3f(h, s, v);
22833
+ }
22834
+
22835
+ fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
22630
22836
  let L = mix(lch1.x, lch2.x, t);
22631
22837
  let C = mix(lch1.y, lch2.y, t);
22632
- let PI = 3.14159265359;
22633
- var dh = lch2.z - lch1.z;
22634
- if (dh > PI) { dh -= 2.0 * PI; }
22635
- if (dh < -PI) { dh += 2.0 * PI; }
22636
- let H = lch1.z + dh * t;
22637
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3f(L, C, H)));
22838
+ let a1 = lch1.y < 1e-6;
22839
+ let a2 = lch2.y < 1e-6;
22840
+ var H: f32;
22841
+ if (a1 && a2) {
22842
+ H = lch1.z;
22843
+ } else if (a1) {
22844
+ H = lch2.z;
22845
+ } else if (a2) {
22846
+ H = lch1.z;
22847
+ } else {
22848
+ var dh = lch2.z - lch1.z;
22849
+ if (dh > 180.0) { dh = dh - 360.0; }
22850
+ if (dh < -180.0) { dh = dh + 360.0; }
22851
+ H = lch1.z + dh * t;
22852
+ if (H < 0.0) { H = H + 360.0; }
22853
+ if (H >= 360.0) { H = H - 360.0; }
22854
+ }
22855
+ return vec3f(L, C, H);
22638
22856
  }
22639
22857
 
22640
- fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22858
+ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
22859
+ let bg = _gpu_oklch_to_srgb(lch_bg);
22860
+ let fg = _gpu_oklch_to_srgb(lch_fg);
22641
22861
  let bgR = _gpu_srgb_to_linear(bg.x);
22642
22862
  let bgG = _gpu_srgb_to_linear(bg.y);
22643
22863
  let bgB = _gpu_srgb_to_linear(bg.z);
@@ -22925,7 +23145,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22925
23145
  if (stmts.length === 0) return "";
22926
23146
  const last = stmts.length - 1;
22927
23147
  stmts[last] = `return ${stmts[last]}`;
22928
- return stmts.join(";\n");
23148
+ return stmts.join(";\n") + ";";
22929
23149
  },
22930
23150
  ...options
22931
23151
  };
@@ -22936,7 +23156,6 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22936
23156
  const constants = this.getConstants();
22937
23157
  const v2 = this.languageId === "wgsl" ? "vec2f" : "vec2";
22938
23158
  const target = this.createTarget({
22939
- hints: options.hints,
22940
23159
  functions: (id) => {
22941
23160
  if (userFunctions && id in userFunctions) {
22942
23161
  const fn = userFunctions[id];
@@ -22975,89 +23194,12 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
22975
23194
  if (code.includes("_gpu_besselJ"))
22976
23195
  preamble += this.languageId === "wgsl" ? GPU_BESSELJ_PREAMBLE_WGSL : GPU_BESSELJ_PREAMBLE_GLSL;
22977
23196
  if (code.includes("_fractal_")) {
22978
- if (code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) {
22979
- preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22980
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PT_PREAMBLE_WGSL : GPU_FRACTAL_PT_PREAMBLE_GLSL;
22981
- } else if (code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) {
22982
- preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
22983
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_DP_PREAMBLE_WGSL : GPU_FRACTAL_DP_PREAMBLE_GLSL;
22984
- } else {
22985
- preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22986
- }
23197
+ preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
22987
23198
  }
22988
23199
  if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
22989
23200
  preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
22990
23201
  }
22991
23202
  if (preamble) result.preamble = preamble;
22992
- if (code.includes("_fractal_") && options.hints?.viewport) {
22993
- const strategy = selectFractalStrategy(target);
22994
- const radius = options.hints.viewport.radius;
22995
- switch (strategy) {
22996
- case "single":
22997
- result.staleWhen = { radiusBelow: 1e-6 };
22998
- break;
22999
- case "double":
23000
- result.staleWhen = { radiusBelow: 1e-14, radiusAbove: 1e-5 };
23001
- break;
23002
- case "perturbation":
23003
- result.staleWhen = {
23004
- radiusAbove: 1e-5,
23005
- radiusBelow: radius * 0.01,
23006
- centerDistance: radius * 2
23007
- };
23008
- break;
23009
- }
23010
- }
23011
- if ((code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) && options.hints?.viewport) {
23012
- const cx = hpToNumber(options.hints.viewport.center[0]);
23013
- const cy = hpToNumber(options.hints.viewport.center[1]);
23014
- const size = options.hints.viewport.radius * 2;
23015
- const cx_hi = Math.fround(cx);
23016
- const cy_hi = Math.fround(cy);
23017
- result.uniforms = {
23018
- ...result.uniforms,
23019
- _dp_cx_hi: cx_hi,
23020
- _dp_cx_lo: cx - cx_hi,
23021
- _dp_cy_hi: cy_hi,
23022
- _dp_cy_lo: cy - cy_hi,
23023
- _dp_w: size,
23024
- _dp_h: size
23025
- };
23026
- }
23027
- if ((code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) && options.hints?.viewport) {
23028
- const viewport = options.hints.viewport;
23029
- const size = viewport.radius * 2;
23030
- result.uniforms = {
23031
- ...result.uniforms,
23032
- _pt_offset_x: 0,
23033
- _pt_offset_y: 0,
23034
- _pt_w: size,
23035
- _pt_h: size
23036
- };
23037
- const digits = Math.max(50, Math.ceil(-Math.log10(viewport.radius)) + 10);
23038
- const maxIter = 1e3;
23039
- const orbit = computeReferenceOrbit(
23040
- viewport.center,
23041
- maxIter,
23042
- digits
23043
- );
23044
- const orbitLen = orbit.length / 2;
23045
- const texWidth = Math.min(orbitLen, 4096);
23046
- const texHeight = Math.ceil(orbitLen / texWidth);
23047
- result.textures = {
23048
- _refOrbit: {
23049
- data: orbit,
23050
- width: texWidth,
23051
- height: texHeight,
23052
- format: "rg32f"
23053
- }
23054
- };
23055
- result.uniforms = {
23056
- ...result.uniforms,
23057
- _refOrbitLen: orbitLen,
23058
- _refOrbitTexWidth: texWidth
23059
- };
23060
- }
23061
23203
  return result;
23062
23204
  }
23063
23205
  compileToSource(expr, _options = {}) {
@@ -23102,7 +23244,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
23102
23244
  if (body.includes("\n")) {
23103
23245
  const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
23104
23246
  return `${returnType} ${functionName}(${params}) {
23105
- ${indented};
23247
+ ${indented}
23106
23248
  }`;
23107
23249
  }
23108
23250
  return `${returnType} ${functionName}(${params}) {
@@ -23213,7 +23355,7 @@ ${indented};
23213
23355
  return `fn ${functionName}(${params}) -> ${toWGSLType(
23214
23356
  returnType
23215
23357
  )} {
23216
- ${indented};
23358
+ ${indented}
23217
23359
  }`;
23218
23360
  }
23219
23361
  return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
@@ -25392,7 +25534,7 @@ ${code}`;
25392
25534
  }
25393
25535
 
25394
25536
  // src/compile.ts
25395
- var version = "0.55.5";
25537
+ var version = "0.56.0";
25396
25538
  return __toCommonJS(compile_exports);
25397
25539
  })();
25398
25540
  /*! Bundled license information: