@cortex-js/compute-engine 0.55.6 → 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 (258) hide show
  1. package/dist/compile.esm.js +776 -139
  2. package/dist/compile.min.esm.js +277 -78
  3. package/dist/compile.min.umd.cjs +277 -78
  4. package/dist/compile.umd.cjs +776 -139
  5. package/dist/compute-engine.esm.js +1299 -260
  6. package/dist/compute-engine.min.esm.js +298 -99
  7. package/dist/compute-engine.min.umd.cjs +298 -99
  8. package/dist/compute-engine.umd.cjs +1299 -260
  9. package/dist/core.esm.js +1298 -259
  10. package/dist/core.min.esm.js +297 -98
  11. package/dist/core.min.umd.cjs +297 -98
  12. package/dist/core.umd.cjs +1298 -259
  13. package/dist/interval.esm.js +134 -5
  14. package/dist/interval.min.esm.js +6 -6
  15. package/dist/interval.min.umd.cjs +6 -6
  16. package/dist/interval.umd.cjs +134 -5
  17. package/dist/latex-syntax.esm.js +160 -11
  18. package/dist/latex-syntax.min.esm.js +7 -7
  19. package/dist/latex-syntax.min.umd.cjs +7 -7
  20. package/dist/latex-syntax.umd.cjs +160 -11
  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 +1 -1
  106. package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
  107. package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
  108. package/dist/types/compute-engine/compilation/gpu-target.d.ts +15 -5
  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 -1
  113. package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
  114. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  115. package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
  116. package/dist/types/compute-engine/engine-cache.d.ts +1 -1
  117. package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
  118. package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
  119. package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
  120. package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
  121. package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
  122. package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
  123. package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
  124. package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
  125. package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
  126. package/dist/types/compute-engine/engine-scope.d.ts +1 -1
  127. package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
  128. package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
  129. package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
  130. package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
  131. package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
  132. package/dist/types/compute-engine/free-functions.d.ts +1 -1
  133. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  134. package/dist/types/compute-engine/global-types.d.ts +1 -1
  135. package/dist/types/compute-engine/index.d.ts +22 -2
  136. package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
  137. package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
  138. package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
  139. package/dist/types/compute-engine/interval/index.d.ts +1 -1
  140. package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
  141. package/dist/types/compute-engine/interval/types.d.ts +1 -1
  142. package/dist/types/compute-engine/interval/util.d.ts +1 -1
  143. package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +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 +1 -1
  169. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  170. package/dist/types/compute-engine/latex-syntax/types.d.ts +1 -1
  171. package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
  172. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  173. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  174. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  175. package/dist/types/compute-engine/library/colors.d.ts +1 -1
  176. package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
  177. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  178. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  179. package/dist/types/compute-engine/library/core.d.ts +1 -1
  180. package/dist/types/compute-engine/library/fractals.d.ts +1 -1
  181. package/dist/types/compute-engine/library/library.d.ts +1 -1
  182. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  183. package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
  184. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  185. package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
  186. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  187. package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
  188. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  189. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  190. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  191. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  192. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  193. package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
  194. package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
  195. package/dist/types/compute-engine/library/units.d.ts +1 -1
  196. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  197. package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
  198. package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
  199. package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
  200. package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
  201. package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
  202. package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
  203. package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
  204. package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
  205. package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
  206. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  207. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  208. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  209. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  210. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  211. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  212. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  213. package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
  214. package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
  215. package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
  216. package/dist/types/compute-engine/numerics/types.d.ts +1 -1
  217. package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
  218. package/dist/types/compute-engine/oeis.d.ts +1 -1
  219. package/dist/types/compute-engine/sequence.d.ts +1 -1
  220. package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
  221. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  222. package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
  223. package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
  224. package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
  225. package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
  226. package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
  227. package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
  228. package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
  229. package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
  230. package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
  231. package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
  232. package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
  233. package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
  234. package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
  235. package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
  236. package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
  237. package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
  238. package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
  239. package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
  240. package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
  241. package/dist/types/compute-engine/types-definitions.d.ts +1 -1
  242. package/dist/types/compute-engine/types-engine.d.ts +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 +1 -2
  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
@@ -1,4 +1,4 @@
1
- /** Compute Engine 0.55.6 */
1
+ /** Compute Engine 0.56.0 */
2
2
 
3
3
  // node_modules/complex-esm/dist/src/complex.js
4
4
  var cosh = Math.cosh || function(x) {
@@ -2240,6 +2240,7 @@ var SCALAR_TYPES = [
2240
2240
  ];
2241
2241
  var VALUE_TYPES = [
2242
2242
  "value",
2243
+ "color",
2243
2244
  ...COLLECTION_TYPES,
2244
2245
  ...SCALAR_TYPES
2245
2246
  ];
@@ -3939,6 +3940,7 @@ var PRIMITIVE_SUBTYPES = {
3939
3940
  symbol: [],
3940
3941
  boolean: [],
3941
3942
  string: [],
3943
+ color: [],
3942
3944
  expression: EXPRESSION_TYPES
3943
3945
  };
3944
3946
  function isPrimitiveSubtype(lhs, rhs) {
@@ -7822,9 +7824,10 @@ var _BoxedExpression = class __BoxedExpression {
7822
7824
  if (!materialized.isLazyCollection) return materialized.latex;
7823
7825
  }
7824
7826
  const syntax = this.engine._requireLatexSyntax();
7825
- return syntax.serialize(
7826
- this.toMathJson({ prettify: true, fractionalDigits: "auto" })
7827
- );
7827
+ const json = this.toMathJson({ prettify: true, fractionalDigits: "auto" });
7828
+ const latexOpts = this.engine.latexOptions;
7829
+ if (Object.keys(latexOpts).length === 0) return syntax.serialize(json);
7830
+ return syntax.serialize(json, { ...latexOpts });
7828
7831
  }
7829
7832
  /**
7830
7833
  * Return a LaTeX representation of this expression with custom
@@ -7848,9 +7851,13 @@ var _BoxedExpression = class __BoxedExpression {
7848
7851
  fractionalDigits: "auto"
7849
7852
  });
7850
7853
  const syntax = this.engine._requireLatexSyntax();
7851
- if (!options || Object.keys(options).length === 0)
7852
- return syntax.serialize(json);
7853
- return syntax.serialize(json, options);
7854
+ const latexOpts = this.engine.latexOptions;
7855
+ const haveEngineOpts = Object.keys(latexOpts).length > 0;
7856
+ const haveCallOpts = options && Object.keys(options).length > 0;
7857
+ if (!haveEngineOpts && !haveCallOpts) return syntax.serialize(json);
7858
+ if (!haveEngineOpts) return syntax.serialize(json, options);
7859
+ if (!haveCallOpts) return syntax.serialize(json, { ...latexOpts });
7860
+ return syntax.serialize(json, { ...latexOpts, ...options });
7854
7861
  }
7855
7862
  /** Called by `JSON.stringify()` when serializing to json.
7856
7863
  *
@@ -7894,11 +7901,13 @@ var _BoxedExpression = class __BoxedExpression {
7894
7901
  "number",
7895
7902
  "dictionary"
7896
7903
  ];
7897
- }
7898
- if (Array.isArray(options.shorthands))
7904
+ } else if (Array.isArray(options.shorthands)) {
7899
7905
  defaultOptions.shorthands = options.shorthands;
7906
+ }
7900
7907
  if (typeof options.metadata === "string" && options.metadata === "all" || options.metadata?.includes("all")) {
7901
7908
  defaultOptions.metadata = ["latex", "wikidata"];
7909
+ } else if (Array.isArray(options.metadata)) {
7910
+ defaultOptions.metadata = options.metadata;
7902
7911
  }
7903
7912
  if (options.fractionalDigits === "auto")
7904
7913
  defaultOptions.fractionalDigits = -this.engine.precision;
@@ -13620,6 +13629,8 @@ var DEFINITIONS_ARITHMETIC = [
13620
13629
  precedence: DIVISION_PRECEDENCE,
13621
13630
  parse: "Mod"
13622
13631
  },
13632
+ // Function-style alias: `\operatorname{mod}(a, b)`
13633
+ { latexTrigger: "\\operatorname{mod}", parse: "Mod" },
13623
13634
  {
13624
13635
  latexTrigger: "\\pmod",
13625
13636
  kind: "prefix",
@@ -13860,6 +13871,13 @@ var DEFINITIONS_ARITHMETIC = [
13860
13871
  const rhs = serializer.wrap(operand(expr2, 2), ADDITION_PRECEDENCE + 3);
13861
13872
  return joinLatex([lhs, "-", rhs]);
13862
13873
  }
13874
+ },
13875
+ // Euclidean distance between two points (tuples of numbers).
13876
+ {
13877
+ name: "Distance",
13878
+ latexTrigger: ["\\operatorname{distance}"],
13879
+ kind: "function",
13880
+ serialize: (serializer, expr2) => "\\operatorname{distance}" + serializer.wrapArguments(expr2)
13863
13881
  }
13864
13882
  ];
13865
13883
  function getIndexAssignment(expr2, upper) {
@@ -15284,7 +15302,9 @@ var DEFINITIONS_STATISTICS = [
15284
15302
  if (!expr2 || !symbol(expr2)) return null;
15285
15303
  return ["Mean", expr2];
15286
15304
  }
15287
- }
15305
+ },
15306
+ // Function-style alias: `\operatorname{var}(...)`
15307
+ { latexTrigger: "\\operatorname{var}", parse: "Variance" }
15288
15308
  ];
15289
15309
 
15290
15310
  // src/compute-engine/numerics/unit-data.ts
@@ -16385,7 +16405,7 @@ var DEFINITIONS_OTHERS = [
16385
16405
  36: "\\qquad"
16386
16406
  }[v] ?? "";
16387
16407
  }
16388
- }
16408
+ },
16389
16409
  // if (
16390
16410
  // [
16391
16411
  // '\\!',
@@ -16409,6 +16429,121 @@ var DEFINITIONS_OTHERS = [
16409
16429
  // name: '',
16410
16430
  // trigger: '\\check',
16411
16431
  // },
16432
+ // ---------------------------------------------------------------------------
16433
+ // Function-style aliases for collection / random operators that some
16434
+ // notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
16435
+ // The capitalized library entries already exist; these are pure parse
16436
+ // aliases so the lowercase names don't land in `unsupported-operator`.
16437
+ // ---------------------------------------------------------------------------
16438
+ { latexTrigger: "\\operatorname{random}", parse: "Random" },
16439
+ { latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
16440
+ { latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
16441
+ { latexTrigger: "\\operatorname{join}", parse: "Join" },
16442
+ // ---------------------------------------------------------------------------
16443
+ // Geometric primitive heads. Registered as known typed heads so consumers
16444
+ // can branch on the operator name; CE itself doesn't render them. The
16445
+ // library entries (with no evaluator) live in `library/core.ts`.
16446
+ // ---------------------------------------------------------------------------
16447
+ {
16448
+ name: "Triangle",
16449
+ latexTrigger: ["\\operatorname{triangle}"],
16450
+ kind: "function",
16451
+ serialize: (serializer, expr2) => "\\operatorname{triangle}" + serializer.wrapArguments(expr2)
16452
+ },
16453
+ // Desmos's geometric `vector(p1, p2)` — a directed segment between two
16454
+ // points. Routed to a dedicated head (not the existing column-vector
16455
+ // `Vector`, which has a narrower `(number+) -> vector` signature).
16456
+ {
16457
+ name: "GeometricVector",
16458
+ latexTrigger: ["\\operatorname{vector}"],
16459
+ kind: "function",
16460
+ serialize: (serializer, expr2) => "\\operatorname{vector}" + serializer.wrapArguments(expr2)
16461
+ },
16462
+ {
16463
+ name: "Sphere",
16464
+ latexTrigger: ["\\operatorname{sphere}"],
16465
+ kind: "function",
16466
+ serialize: (serializer, expr2) => "\\operatorname{sphere}" + serializer.wrapArguments(expr2)
16467
+ },
16468
+ {
16469
+ name: "Segment",
16470
+ latexTrigger: ["\\operatorname{segment}"],
16471
+ kind: "function",
16472
+ serialize: (serializer, expr2) => "\\operatorname{segment}" + serializer.wrapArguments(expr2)
16473
+ }
16474
+ ];
16475
+
16476
+ // src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
16477
+ var DEFINITIONS_COLORS = [
16478
+ // Color constructors (one per colorspace, preserves space on evaluation)
16479
+ {
16480
+ name: "Rgb",
16481
+ latexTrigger: ["\\operatorname{rgb}"],
16482
+ kind: "function",
16483
+ serialize: (serializer, expr2) => "\\operatorname{rgb}" + serializer.wrapArguments(expr2)
16484
+ },
16485
+ {
16486
+ name: "Hsv",
16487
+ latexTrigger: ["\\operatorname{hsv}"],
16488
+ kind: "function",
16489
+ serialize: (serializer, expr2) => "\\operatorname{hsv}" + serializer.wrapArguments(expr2)
16490
+ },
16491
+ {
16492
+ name: "Hsl",
16493
+ latexTrigger: ["\\operatorname{hsl}"],
16494
+ kind: "function",
16495
+ serialize: (serializer, expr2) => "\\operatorname{hsl}" + serializer.wrapArguments(expr2)
16496
+ },
16497
+ {
16498
+ name: "Oklab",
16499
+ latexTrigger: ["\\operatorname{oklab}"],
16500
+ kind: "function",
16501
+ serialize: (serializer, expr2) => "\\operatorname{oklab}" + serializer.wrapArguments(expr2)
16502
+ },
16503
+ {
16504
+ name: "Oklch",
16505
+ latexTrigger: ["\\operatorname{oklch}"],
16506
+ kind: "function",
16507
+ serialize: (serializer, expr2) => "\\operatorname{oklch}" + serializer.wrapArguments(expr2)
16508
+ },
16509
+ // Conversion functions (color → color in the named space)
16510
+ {
16511
+ name: "AsRgb",
16512
+ latexTrigger: ["\\operatorname{asRgb}"],
16513
+ kind: "function",
16514
+ serialize: (serializer, expr2) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr2)
16515
+ },
16516
+ {
16517
+ name: "AsHsv",
16518
+ latexTrigger: ["\\operatorname{asHsv}"],
16519
+ kind: "function",
16520
+ serialize: (serializer, expr2) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr2)
16521
+ },
16522
+ {
16523
+ name: "AsHsl",
16524
+ latexTrigger: ["\\operatorname{asHsl}"],
16525
+ kind: "function",
16526
+ serialize: (serializer, expr2) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr2)
16527
+ },
16528
+ {
16529
+ name: "AsOklab",
16530
+ latexTrigger: ["\\operatorname{asOklab}"],
16531
+ kind: "function",
16532
+ serialize: (serializer, expr2) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr2)
16533
+ },
16534
+ {
16535
+ name: "AsOklch",
16536
+ latexTrigger: ["\\operatorname{asOklch}"],
16537
+ kind: "function",
16538
+ serialize: (serializer, expr2) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr2)
16539
+ },
16540
+ // Perceptual difference (returns a scalar in [0, ~1])
16541
+ {
16542
+ name: "ColorDelta",
16543
+ latexTrigger: ["\\operatorname{colorDelta}"],
16544
+ kind: "function",
16545
+ serialize: (serializer, expr2) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr2)
16546
+ }
16412
16547
  ];
16413
16548
 
16414
16549
  // src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
@@ -16439,7 +16574,8 @@ var LATEX_DICTIONARY = [
16439
16574
  ...DEFINITIONS_STATISTICS,
16440
16575
  ...DEFINITIONS_UNITS,
16441
16576
  ...DEFINITIONS_OTHERS,
16442
- ...DEFINITIONS_PHYSICS
16577
+ ...DEFINITIONS_PHYSICS,
16578
+ ...DEFINITIONS_COLORS
16443
16579
  ];
16444
16580
 
16445
16581
  // src/math-json/symbols.ts
@@ -16604,6 +16740,17 @@ function addEntry(result, entry, onError) {
16604
16740
  } else if (Array.isArray(openTrigger) && openTrigger.length > 0) {
16605
16741
  openTokens.push(openTrigger[0]);
16606
16742
  }
16743
+ const closeTrigger = indexedEntry.closeTrigger;
16744
+ const closeTokens = /* @__PURE__ */ new Set();
16745
+ if (typeof closeTrigger === "string") {
16746
+ const variants = DELIMITER_SHORTHAND[closeTrigger];
16747
+ if (variants) for (const v of variants) closeTokens.add(v);
16748
+ else closeTokens.add(closeTrigger);
16749
+ if (closeTrigger === "||") closeTokens.add("|");
16750
+ } else if (Array.isArray(closeTrigger) && closeTrigger.length > 0) {
16751
+ closeTokens.add(closeTrigger[0]);
16752
+ }
16753
+ indexedEntry.closeTokens = closeTokens;
16607
16754
  for (const token of openTokens) {
16608
16755
  const existing = result.matchfixByOpen.get(token);
16609
16756
  if (existing) {
@@ -16795,11 +16942,7 @@ function makeSerializeHandler(entry, latexTrigger, idTrigger) {
16795
16942
  if (style === "scaled")
16796
16943
  return joinLatex([`\\left${openDelim}`, inner, `\\right${closeDelim}`]);
16797
16944
  if (style === "big")
16798
- return joinLatex([
16799
- `\\Bigl${openDelim}`,
16800
- inner,
16801
- `\\Bigr${closeDelim}`
16802
- ]);
16945
+ return joinLatex([`\\Bigl${openDelim}`, inner, `\\Bigr${closeDelim}`]);
16803
16946
  return joinLatex([openDelim, inner, closeDelim]);
16804
16947
  };
16805
16948
  }
@@ -18150,7 +18293,7 @@ var _Parser = class __Parser {
18150
18293
  }
18151
18294
  if (this.match("\\hskip") || this.match("\\kern")) {
18152
18295
  this.skipSpace();
18153
- this.match("-") || this.match("+");
18296
+ if (!this.match("-")) this.match("+");
18154
18297
  while (/^[\d.]$/.test(this.peek)) this.nextToken();
18155
18298
  for (const unit of [
18156
18299
  "pt",
@@ -18664,6 +18807,19 @@ var _Parser = class __Parser {
18664
18807
  }
18665
18808
  for (const def of defs) {
18666
18809
  this.index = start;
18810
+ if (def.closeTokens.size > 0) {
18811
+ let found = false;
18812
+ const tokens = this._tokens;
18813
+ for (let i = start; i < tokens.length; i++) {
18814
+ if (def.closeTokens.has(tokens[i])) {
18815
+ found = true;
18816
+ break;
18817
+ }
18818
+ }
18819
+ if (!found) continue;
18820
+ }
18821
+ if (typeof def.openTrigger === "string" && def.openTrigger === "." && !OPEN_DELIMITER_PREFIX[currentToken])
18822
+ continue;
18667
18823
  const matched = this.matchDelimiter(def.openTrigger, def.closeTrigger);
18668
18824
  if (!matched) continue;
18669
18825
  const bodyStart = this.index;
@@ -32226,6 +32382,29 @@ var ARITHMETIC_LIBRARY = [
32226
32382
  signature: "(value*) -> number | list",
32227
32383
  evaluate: (xs, { engine }) => evaluateMinMax(engine, xs, "Infimum")
32228
32384
  },
32385
+ Distance: {
32386
+ description: "Euclidean distance between two points (tuples of numbers).",
32387
+ complexity: 6e3,
32388
+ signature: "(tuple, tuple) -> number",
32389
+ evaluate: ([a, b], { engine: ce }) => {
32390
+ if (!isFunction2(a) || !isFunction2(b))
32391
+ return ce.error("incompatible-type");
32392
+ if (a.operator !== "Tuple" || b.operator !== "Tuple")
32393
+ return ce.error("incompatible-type");
32394
+ if (a.ops.length !== b.ops.length || a.ops.length === 0)
32395
+ return ce.error("incompatible-type");
32396
+ let sumSq = 0;
32397
+ for (let i = 0; i < a.ops.length; i++) {
32398
+ const ai = a.ops[i].re;
32399
+ const bi = b.ops[i].re;
32400
+ if (!Number.isFinite(ai) || !Number.isFinite(bi))
32401
+ return ce.error("expected-value");
32402
+ const d = ai - bi;
32403
+ sumSq += d * d;
32404
+ }
32405
+ return ce.number(Math.sqrt(sumSq));
32406
+ }
32407
+ },
32229
32408
  Product: {
32230
32409
  description: "`Product(f, a, b)` computes the product of `f` from `a` to `b`",
32231
32410
  wikidata: "Q901718",
@@ -32758,16 +32937,11 @@ function boxRule(ce, rule, options) {
32758
32937
  );
32759
32938
  let condFn;
32760
32939
  if (typeof condition === "string") {
32761
- const latex = asLatexString(condition);
32762
- if (latex) {
32763
- const condPattern = ce.parse(latex, {
32764
- form: options?.canonical ? "canonical" : "raw"
32765
- }) ?? ce.expr("Nothing");
32766
- condFn = (x, _ce) => {
32767
- const evaluated = condPattern.subs(x).evaluate();
32768
- return isSymbol2(evaluated, "True");
32769
- };
32770
- }
32940
+ const condPattern = ce.parse(condition) ?? ce.expr("Nothing");
32941
+ condFn = (x, _ce) => {
32942
+ const evaluated = condPattern.subs(x).evaluate();
32943
+ return isSymbol2(evaluated, "True");
32944
+ };
32771
32945
  } else {
32772
32946
  if (condition !== void 0 && typeof condition !== "function")
32773
32947
  throw new Error(
@@ -32869,6 +33043,15 @@ ${e.message}
32869
33043
  function applyRule(rule, expr2, substitution, options) {
32870
33044
  if (!rule) return null;
32871
33045
  let canonical2 = options?.canonical ?? (expr2.isCanonical || expr2.isStructural);
33046
+ let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
33047
+ const because = id ?? "";
33048
+ const ce = expr2.engine;
33049
+ if (canonical2 && match2) {
33050
+ const awc = getWildcards(match2);
33051
+ const canonicalMatch = match2.canonical;
33052
+ const bwc = getWildcards(canonicalMatch);
33053
+ if (!awc.every((x) => bwc.includes(x))) return null;
33054
+ }
32872
33055
  let operandsMatched = false;
32873
33056
  if (isFunction2(expr2) && options?.recursive) {
32874
33057
  const newOps = expr2.ops.map((op) => {
@@ -32880,20 +33063,11 @@ function applyRule(rule, expr2, substitution, options) {
32880
33063
  if (operandsMatched) {
32881
33064
  if (!canonical2 && options?.canonical === void 0 && newOps.every((x) => x.isCanonical))
32882
33065
  canonical2 = true;
32883
- expr2 = expr2.engine.function(expr2.operator, newOps, {
33066
+ expr2 = ce.function(expr2.operator, newOps, {
32884
33067
  form: canonical2 ? "canonical" : "raw"
32885
33068
  });
32886
33069
  }
32887
33070
  }
32888
- let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
32889
- const because = id ?? "";
32890
- if (canonical2 && match2) {
32891
- const awc = getWildcards(match2);
32892
- const canonicalMatch = match2.canonical;
32893
- const bwc = getWildcards(canonicalMatch);
32894
- if (!awc.every((x) => bwc.includes(x)))
32895
- return operandsMatched ? { value: expr2, because } : null;
32896
- }
32897
33071
  const useVariations = rule.useVariations ?? options?.useVariations ?? false;
32898
33072
  const matchPermutations = options?.matchPermutations ?? true;
32899
33073
  onBeforeMatch?.(rule, expr2);
@@ -32912,7 +33086,7 @@ function applyRule(rule, expr2, substitution, options) {
32912
33086
  ...sub2
32913
33087
  };
32914
33088
  try {
32915
- if (!condition(conditionSub, expr2.engine))
33089
+ if (!condition(conditionSub, ce))
32916
33090
  return operandsMatched ? { value: expr2, because } : null;
32917
33091
  } catch (e) {
32918
33092
  console.error(
@@ -32927,7 +33101,8 @@ function applyRule(rule, expr2, substitution, options) {
32927
33101
  if (!canonical2 && options?.canonical === void 0 && replace2 instanceof _BoxedExpression && replace2.isCanonical)
32928
33102
  canonical2 = true;
32929
33103
  const result = typeof replace2 === "function" ? replace2(expr2, sub2) : replace2.subs(sub2, { canonical: canonical2 });
32930
- if (!result) return null;
33104
+ if (!result)
33105
+ return operandsMatched ? { value: canonical2 ? expr2.canonical : expr2, because } : null;
32931
33106
  onMatch?.(rule, expr2, result);
32932
33107
  if (isRuleStep(result))
32933
33108
  return canonical2 ? { ...result, value: result.value.canonical } : result;
@@ -38501,6 +38676,40 @@ function rgbToHsl(r, g, b) {
38501
38676
  else h = ((r - g) / d + 4) / 6;
38502
38677
  return { h: h * 360, s, l };
38503
38678
  }
38679
+ function hsvToRgb(h, s, v) {
38680
+ h = (h % 360 + 360) % 360;
38681
+ s = Math.max(0, Math.min(1, s));
38682
+ v = Math.max(0, Math.min(1, v));
38683
+ const c = v * s;
38684
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
38685
+ const m = v - c;
38686
+ let r = 0, g = 0, b = 0;
38687
+ if (h < 60) [r, g, b] = [c, x, 0];
38688
+ else if (h < 120) [r, g, b] = [x, c, 0];
38689
+ else if (h < 180) [r, g, b] = [0, c, x];
38690
+ else if (h < 240) [r, g, b] = [0, x, c];
38691
+ else if (h < 300) [r, g, b] = [x, 0, c];
38692
+ else [r, g, b] = [c, 0, x];
38693
+ return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
38694
+ }
38695
+ function rgbToHsv(r, g, b) {
38696
+ r /= 255;
38697
+ g /= 255;
38698
+ b /= 255;
38699
+ const max2 = Math.max(r, g, b);
38700
+ const min2 = Math.min(r, g, b);
38701
+ const d = max2 - min2;
38702
+ let h = 0;
38703
+ if (d > 0) {
38704
+ if (max2 === r) h = (g - b) / d % 6;
38705
+ else if (max2 === g) h = (b - r) / d + 2;
38706
+ else h = (r - g) / d + 4;
38707
+ h *= 60;
38708
+ if (h < 0) h += 360;
38709
+ }
38710
+ const s = max2 === 0 ? 0 : d / max2;
38711
+ return { h, s, v: max2 };
38712
+ }
38504
38713
  function parseHexColor(s) {
38505
38714
  const hex = s.startsWith("#") ? s.substring(1) : s;
38506
38715
  let r, g, b;
@@ -38525,6 +38734,12 @@ function parseHexColor(s) {
38525
38734
  if (alpha !== void 0) result.alpha = alpha;
38526
38735
  return result;
38527
38736
  }
38737
+ function asOklch(color) {
38738
+ if (typeof color === "string") return rgbToOklch(parseHexColor(color));
38739
+ if ("C" in color) return color;
38740
+ if ("a" in color && "b" in color) return oklabToOklch(color);
38741
+ return rgbToOklch(color);
38742
+ }
38528
38743
  function asRgb(color) {
38529
38744
  if (typeof color === "number") {
38530
38745
  return {
@@ -38956,6 +39171,13 @@ var NAMED_COLORS = {
38956
39171
  };
38957
39172
  function parseColor(s, darkMode) {
38958
39173
  const str = s.trim().toLowerCase();
39174
+ const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
39175
+ if (opacityMatch) {
39176
+ const base = parseColor(opacityMatch[1].trim(), darkMode);
39177
+ const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
39178
+ const alpha = Math.round(opacity / 100 * 255);
39179
+ return base & 4294967040 | alpha;
39180
+ }
38959
39181
  if (str.startsWith("#")) {
38960
39182
  const hex = str.substring(1);
38961
39183
  let r, g, b, a = 255;
@@ -39088,14 +39310,6 @@ function parseColor(s, darkMode) {
39088
39310
  console.warn(`parseColor: unrecognized color "${s}"`);
39089
39311
  return 0;
39090
39312
  }
39091
- function parseColorToRgb01(s, darkMode) {
39092
- const color = parseColor(s, darkMode);
39093
- return [
39094
- (color >>> 24 & 255) / 255,
39095
- (color >>> 16 & 255) / 255,
39096
- (color >>> 8 & 255) / 255
39097
- ];
39098
- }
39099
39313
  function apca(bgColor, fgColor) {
39100
39314
  const bgRgb = asRgb(bgColor);
39101
39315
  const fgRgb = asRgb(fgColor);
@@ -39154,6 +39368,12 @@ function contrastingColor(arg) {
39154
39368
  const contrast2 = Math.abs(apca(fg2, bg));
39155
39369
  return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
39156
39370
  }
39371
+ function oklabDeltaE(a, b) {
39372
+ const dL = a.L - b.L;
39373
+ const da = a.a - b.a;
39374
+ const db = a.b - b.b;
39375
+ return Math.sqrt(dL * dL + da * da + db * db);
39376
+ }
39157
39377
  function lerpOklch(c1, c2, f) {
39158
39378
  const L = c1.L + (c2.L - c1.L) * f;
39159
39379
  const C = c1.C + (c2.C - c1.C) * f;
@@ -41915,14 +42135,30 @@ var SEQUENTIAL_PALETTES = {
41915
42135
  };
41916
42136
 
41917
42137
  // src/compute-engine/library/colors.ts
41918
- function colorNumberToTuple(ce, color) {
41919
- const r = (color >>> 24 & 255) / 255;
41920
- const g = (color >>> 16 & 255) / 255;
41921
- const b = (color >>> 8 & 255) / 255;
41922
- const a = (color & 255) / 255;
41923
- if (Math.abs(a - 1) < 1e-4)
41924
- return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
41925
- return ce.tuple(ce.number(r), ce.number(g), ce.number(b), ce.number(a));
42138
+ function normalizeAlpha(a) {
42139
+ if (a === void 0) return void 0;
42140
+ if (!Number.isFinite(a)) return void 0;
42141
+ if (Math.abs(a - 1) < 1e-9) return void 0;
42142
+ return a;
42143
+ }
42144
+ function normalizeColorHead(ce, expr2) {
42145
+ if (!isFunction2(expr2) || !expr2.ops || expr2.ops.length < 4) return expr2;
42146
+ const alphaExpr = expr2.ops[3];
42147
+ if (!isNumber(alphaExpr)) return expr2;
42148
+ if (normalizeAlpha(alphaExpr.re) === void 0) {
42149
+ return ce.function(expr2.operator, [expr2.ops[0], expr2.ops[1], expr2.ops[2]]);
42150
+ }
42151
+ return expr2;
42152
+ }
42153
+ function colorNumberToOklch(ce, color) {
42154
+ const r = color >>> 24 & 255;
42155
+ const g = color >>> 16 & 255;
42156
+ const b = color >>> 8 & 255;
42157
+ const a = normalizeAlpha((color & 255) / 255);
42158
+ const c = rgbToOklch({ r, g, b });
42159
+ const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
42160
+ if (a !== void 0) args.push(ce.number(a));
42161
+ return ce.function("Oklch", args);
41926
42162
  }
41927
42163
  var ALL_PALETTES = {
41928
42164
  ...SEQUENTIAL_PALETTES,
@@ -41933,45 +42169,139 @@ function samplePalette(ce, palette, t) {
41933
42169
  t = Math.max(0, Math.min(1, t));
41934
42170
  const n = palette.length;
41935
42171
  if (n === 0) return ce.error("expected-value");
41936
- if (n === 1) return colorNumberToTuple(ce, parseColor(palette[0]));
42172
+ if (n === 1) return colorNumberToOklch(ce, parseColor(palette[0]));
41937
42173
  const pos = t * (n - 1);
41938
42174
  const i = Math.floor(pos);
41939
42175
  const frac = pos - i;
41940
- if (i >= n - 1) return colorNumberToTuple(ce, parseColor(palette[n - 1]));
41941
- if (frac < 1e-9) return colorNumberToTuple(ce, parseColor(palette[i]));
41942
- const rgb = interpolateOklch(palette[i], palette[i + 1], frac);
41943
- const r = rgb.r / 255;
41944
- const g = rgb.g / 255;
41945
- const b = rgb.b / 255;
41946
- return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
42176
+ if (i >= n - 1) return colorNumberToOklch(ce, parseColor(palette[n - 1]));
42177
+ if (frac < 1e-9) return colorNumberToOklch(ce, parseColor(palette[i]));
42178
+ return oklchToExpr(
42179
+ ce,
42180
+ asOklch(interpolateOklch(palette[i], palette[i + 1], frac))
42181
+ );
42182
+ }
42183
+ var COLOR_OPERATORS = /* @__PURE__ */ new Set(["Rgb", "Hsv", "Hsl", "Oklab", "Oklch"]);
42184
+ function readColorExpr(arg) {
42185
+ if (!isFunction2(arg)) return null;
42186
+ if (!COLOR_OPERATORS.has(arg.operator)) return null;
42187
+ if (!arg.ops || arg.ops.length < 3) return null;
42188
+ const c0 = arg.ops[0].re;
42189
+ const c1 = arg.ops[1].re;
42190
+ const c2 = arg.ops[2].re;
42191
+ if (!Number.isFinite(c0) || !Number.isFinite(c1) || !Number.isFinite(c2))
42192
+ return null;
42193
+ const alpha = arg.ops.length >= 4 ? normalizeAlpha(arg.ops[3].re) : void 0;
42194
+ return { space: arg.operator, c0, c1, c2, alpha };
42195
+ }
42196
+ function colorExprToRgb(arg) {
42197
+ const c = readColorExpr(arg);
42198
+ if (!c) return null;
42199
+ const withAlpha = (rgb) => c.alpha !== void 0 ? { ...rgb, alpha: c.alpha } : rgb;
42200
+ switch (c.space) {
42201
+ case "Rgb":
42202
+ return withAlpha({ r: c.c0 * 255, g: c.c1 * 255, b: c.c2 * 255 });
42203
+ case "Hsv":
42204
+ return withAlpha(hsvToRgb(c.c0, c.c1, c.c2));
42205
+ case "Hsl":
42206
+ return withAlpha(hslToRgb(c.c0, c.c1, c.c2));
42207
+ case "Oklab":
42208
+ return withAlpha(oklabToRgb({ L: c.c0, a: c.c1, b: c.c2 }));
42209
+ case "Oklch":
42210
+ return withAlpha(oklchToRgb({ L: c.c0, C: c.c1, H: c.c2 }));
42211
+ }
42212
+ return null;
42213
+ }
42214
+ function colorExprToOklch(arg) {
42215
+ const c = readColorExpr(arg);
42216
+ if (!c) return null;
42217
+ switch (c.space) {
42218
+ case "Oklch":
42219
+ return asOklch({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
42220
+ case "Oklab":
42221
+ return asOklch({ L: c.c0, a: c.c1, b: c.c2, alpha: c.alpha });
42222
+ case "Rgb":
42223
+ return asOklch({
42224
+ r: c.c0 * 255,
42225
+ g: c.c1 * 255,
42226
+ b: c.c2 * 255,
42227
+ alpha: c.alpha
42228
+ });
42229
+ case "Hsv": {
42230
+ const rgb = hsvToRgb(c.c0, c.c1, c.c2);
42231
+ return asOklch({ ...rgb, alpha: c.alpha });
42232
+ }
42233
+ case "Hsl": {
42234
+ const rgb = hslToRgb(c.c0, c.c1, c.c2);
42235
+ return asOklch({ r: rgb.r, g: rgb.g, b: rgb.b, alpha: c.alpha });
42236
+ }
42237
+ }
42238
+ return null;
42239
+ }
42240
+ function toOklch(ce, arg) {
42241
+ const direct = colorExprToOklch(arg);
42242
+ if (direct) return direct;
42243
+ const rgb = extractRgb(ce, arg);
42244
+ return rgb ? asOklch(rgb) : null;
42245
+ }
42246
+ function lerpOklchColor(a, b, t) {
42247
+ const L = a.L + (b.L - a.L) * t;
42248
+ const C = a.C + (b.C - a.C) * t;
42249
+ const aAchromatic = a.C < 1e-6;
42250
+ const bAchromatic = b.C < 1e-6;
42251
+ let H;
42252
+ if (aAchromatic && bAchromatic) H = a.H;
42253
+ else if (aAchromatic) H = b.H;
42254
+ else if (bAchromatic) H = a.H;
42255
+ else {
42256
+ let dH = b.H - a.H;
42257
+ if (dH > 180) dH -= 360;
42258
+ if (dH < -180) dH += 360;
42259
+ H = a.H + dH * t;
42260
+ if (H < 0) H += 360;
42261
+ if (H >= 360) H -= 360;
42262
+ }
42263
+ const alphaA = a.alpha ?? 1;
42264
+ const alphaB = b.alpha ?? 1;
42265
+ return { L, C, H, alpha: normalizeAlpha(alphaA + (alphaB - alphaA) * t) };
42266
+ }
42267
+ function oklchToExpr(ce, c) {
42268
+ const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
42269
+ if (c.alpha !== void 0) args.push(ce.number(c.alpha));
42270
+ return ce.function("Oklch", args);
41947
42271
  }
41948
42272
  function extractRgb(ce, arg) {
41949
42273
  if (isString(arg)) {
41950
42274
  const s = arg.string;
41951
42275
  if (!s) return void 0;
41952
42276
  const color = parseColor(s);
41953
- return {
42277
+ const rgb = {
41954
42278
  r: color >>> 24 & 255,
41955
42279
  g: color >>> 16 & 255,
41956
- b: color >>> 8 & 255,
41957
- alpha: (color & 255) / 255
42280
+ b: color >>> 8 & 255
41958
42281
  };
42282
+ const alpha = normalizeAlpha((color & 255) / 255);
42283
+ if (alpha !== void 0) rgb.alpha = alpha;
42284
+ return rgb;
41959
42285
  }
42286
+ const fromTyped = colorExprToRgb(arg);
42287
+ if (fromTyped) return fromTyped;
41960
42288
  if (arg.operator === "Tuple" && arg.ops && arg.ops.length >= 3) {
41961
42289
  const rgb = {
41962
42290
  r: arg.ops[0].re * 255,
41963
42291
  g: arg.ops[1].re * 255,
41964
42292
  b: arg.ops[2].re * 255
41965
42293
  };
41966
- if (arg.ops.length >= 4) rgb.alpha = arg.ops[3].re;
42294
+ if (arg.ops.length >= 4) {
42295
+ const alpha = normalizeAlpha(arg.ops[3].re);
42296
+ if (alpha !== void 0) rgb.alpha = alpha;
42297
+ }
41967
42298
  return rgb;
41968
42299
  }
41969
42300
  return void 0;
41970
42301
  }
41971
42302
  function componentsTuple(ce, components, alpha) {
41972
42303
  const args = components.map((v) => ce.number(v));
41973
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4)
41974
- args.push(ce.number(alpha));
42304
+ if (alpha !== void 0) args.push(ce.number(alpha));
41975
42305
  return ce.tuple(...args);
41976
42306
  }
41977
42307
  function rgbToHex(rgb) {
@@ -41979,7 +42309,7 @@ function rgbToHex(rgb) {
41979
42309
  const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
41980
42310
  const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
41981
42311
  const hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
41982
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4) {
42312
+ if (rgb.alpha !== void 0) {
41983
42313
  const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
41984
42314
  return hex + a.toString(16).padStart(2, "0");
41985
42315
  }
@@ -41987,22 +42317,29 @@ function rgbToHex(rgb) {
41987
42317
  }
41988
42318
  var COLORS_LIBRARY = {
41989
42319
  Color: {
41990
- description: "Convert a color string to a canonical sRGB tuple",
42320
+ description: "Parse a CSS-style color string to an Oklch color",
41991
42321
  complexity: 8e3,
41992
- signature: "(string) -> tuple",
42322
+ signature: "(string) -> color",
41993
42323
  evaluate: (ops, { engine: ce }) => {
41994
42324
  const input = isString(ops[0]) ? ops[0].string : void 0;
41995
42325
  if (!input) return ce.error("incompatible-type");
41996
42326
  const color = parseColor(input);
41997
42327
  if (color === 0 && input.trim().toLowerCase() !== "transparent")
41998
42328
  return ce.error("incompatible-type");
41999
- return colorNumberToTuple(ce, color);
42329
+ const r = color >>> 24 & 255;
42330
+ const g = color >>> 16 & 255;
42331
+ const b = color >>> 8 & 255;
42332
+ const a = normalizeAlpha((color & 255) / 255);
42333
+ const c = rgbToOklch({ r, g, b });
42334
+ const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
42335
+ if (a !== void 0) args.push(ce.number(a));
42336
+ return ce.function("Oklch", args);
42000
42337
  }
42001
42338
  },
42002
42339
  ColorToString: {
42003
42340
  description: "Convert a color to a string in the specified format",
42004
42341
  complexity: 8e3,
42005
- signature: "(any, string?) -> string",
42342
+ signature: "(color | string | tuple, string?) -> string",
42006
42343
  evaluate: (ops, { engine: ce }) => {
42007
42344
  const rgb = extractRgb(ce, ops[0]);
42008
42345
  if (!rgb) return ce.error("incompatible-type");
@@ -42014,7 +42351,7 @@ var COLORS_LIBRARY = {
42014
42351
  const r = Math.round(rgb.r);
42015
42352
  const g = Math.round(rgb.g);
42016
42353
  const b = Math.round(rgb.b);
42017
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
42354
+ if (rgb.alpha !== void 0)
42018
42355
  return ce.string(`rgb(${r} ${g} ${b} / ${rgb.alpha})`);
42019
42356
  return ce.string(`rgb(${r} ${g} ${b})`);
42020
42357
  }
@@ -42023,17 +42360,17 @@ var COLORS_LIBRARY = {
42023
42360
  const h = Math.round(hsl.h * 10) / 10;
42024
42361
  const s = Math.round(hsl.s * 1e3) / 10;
42025
42362
  const l = Math.round(hsl.l * 1e3) / 10;
42026
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
42363
+ if (rgb.alpha !== void 0)
42027
42364
  return ce.string(`hsl(${h} ${s}% ${l}% / ${rgb.alpha})`);
42028
42365
  return ce.string(`hsl(${h} ${s}% ${l}%)`);
42029
42366
  }
42030
42367
  case "oklch": {
42031
- const c = rgbToOklch(rgb);
42368
+ const c = colorExprToOklch(ops[0]) ?? asOklch(rgb);
42032
42369
  const L = Math.round(c.L * 1e3) / 1e3;
42033
42370
  const C = Math.round(c.C * 1e3) / 1e3;
42034
42371
  const H = Math.round(c.H * 10) / 10;
42035
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
42036
- return ce.string(`oklch(${L} ${C} ${H} / ${rgb.alpha})`);
42372
+ if (c.alpha !== void 0)
42373
+ return ce.string(`oklch(${L} ${C} ${H} / ${c.alpha})`);
42037
42374
  return ce.string(`oklch(${L} ${C} ${H})`);
42038
42375
  }
42039
42376
  default:
@@ -42044,60 +42381,44 @@ var COLORS_LIBRARY = {
42044
42381
  ColorMix: {
42045
42382
  description: "Mix two colors in OKLCh space",
42046
42383
  complexity: 8e3,
42047
- signature: "(any, any, number?) -> tuple",
42384
+ signature: "(color | string | tuple, color | string | tuple, number?) -> color",
42048
42385
  evaluate: (ops, { engine: ce }) => {
42049
- const rgb1 = extractRgb(ce, ops[0]);
42050
- const rgb2 = extractRgb(ce, ops[1]);
42051
- if (!rgb1 || !rgb2) return ce.error("incompatible-type");
42052
42386
  let ratio = 0.5;
42053
42387
  if (ops.length >= 3 && ops[2] !== void 0) {
42054
42388
  ratio = ops[2].re;
42055
42389
  if (!Number.isFinite(ratio)) return ce.error("expected-value");
42056
42390
  ratio = Math.max(0, Math.min(1, ratio));
42057
42391
  }
42058
- const c1 = rgbToOklch(rgb1);
42059
- const c2 = rgbToOklch(rgb2);
42060
- const mixed = oklchToRgb(lerpOklch(c1, c2, ratio));
42061
- const r = mixed.r / 255;
42062
- const g = mixed.g / 255;
42063
- const b = mixed.b / 255;
42064
- const a1 = rgb1.alpha ?? 1;
42065
- const a2 = rgb2.alpha ?? 1;
42066
- const alpha = a1 + (a2 - a1) * ratio;
42067
- if (Math.abs(alpha - 1) > 1e-4)
42068
- return ce.tuple(
42069
- ce.number(r),
42070
- ce.number(g),
42071
- ce.number(b),
42072
- ce.number(alpha)
42073
- );
42074
- return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
42392
+ const oklch1 = toOklch(ce, ops[0]);
42393
+ const oklch2 = toOklch(ce, ops[1]);
42394
+ if (!oklch1 || !oklch2) return ce.error("incompatible-type");
42395
+ return oklchToExpr(ce, lerpOklchColor(oklch1, oklch2, ratio));
42075
42396
  }
42076
42397
  },
42077
42398
  Colormap: {
42078
42399
  description: "Sample colors from a named palette",
42079
42400
  complexity: 8e3,
42080
- signature: "(string, number?) -> any",
42401
+ signature: "(string, number?) -> color | list<color>",
42081
42402
  evaluate: (ops, { engine: ce }) => {
42082
42403
  const name = isString(ops[0]) ? ops[0].string : void 0;
42083
42404
  if (!name) return ce.error("incompatible-type");
42084
42405
  const palette = ALL_PALETTES[name];
42085
42406
  if (!palette) return ce.error("expected-value", name);
42086
42407
  if (ops.length < 2 || ops[1] === void 0) {
42087
- const tuples = palette.map(
42088
- (hex) => colorNumberToTuple(ce, parseColor(hex))
42408
+ const colors = palette.map(
42409
+ (hex) => colorNumberToOklch(ce, parseColor(hex))
42089
42410
  );
42090
- return ce.function("List", tuples);
42411
+ return ce.function("List", colors);
42091
42412
  }
42092
42413
  const val = ops[1].re;
42093
42414
  if (!Number.isFinite(val)) return ce.error("expected-value");
42094
42415
  if (Number.isInteger(val) && val >= 2) {
42095
42416
  const n = val;
42096
- const tuples = [];
42417
+ const colors = [];
42097
42418
  for (let i = 0; i < n; i++) {
42098
- tuples.push(samplePalette(ce, palette, i / (n - 1)));
42419
+ colors.push(samplePalette(ce, palette, i / (n - 1)));
42099
42420
  }
42100
- return ce.function("List", tuples);
42421
+ return ce.function("List", colors);
42101
42422
  }
42102
42423
  return samplePalette(ce, palette, val);
42103
42424
  }
@@ -42105,12 +42426,25 @@ var COLORS_LIBRARY = {
42105
42426
  ColorToColorspace: {
42106
42427
  description: "Convert a color to components in a target color space",
42107
42428
  complexity: 8e3,
42108
- signature: "(any, string) -> tuple",
42429
+ signature: "(color | string | tuple, string) -> tuple",
42109
42430
  evaluate: (ops, { engine: ce }) => {
42110
- const rgb = extractRgb(ce, ops[0]);
42111
- if (!rgb) return ce.error("incompatible-type");
42112
42431
  const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
42113
42432
  if (!space) return ce.error("incompatible-type");
42433
+ if (space === "oklch" || space === "oklab" || space === "lab") {
42434
+ const oklch2 = colorExprToOklch(ops[0]);
42435
+ if (oklch2) {
42436
+ if (space === "oklch")
42437
+ return componentsTuple(
42438
+ ce,
42439
+ [oklch2.L, oklch2.C, oklch2.H],
42440
+ oklch2.alpha
42441
+ );
42442
+ const lab = oklchToOklab(oklch2);
42443
+ return componentsTuple(ce, [lab.L, lab.a, lab.b], lab.alpha);
42444
+ }
42445
+ }
42446
+ const rgb = extractRgb(ce, ops[0]);
42447
+ if (!rgb) return ce.error("incompatible-type");
42114
42448
  const alpha = rgb.alpha;
42115
42449
  switch (space) {
42116
42450
  case "rgb":
@@ -42140,17 +42474,27 @@ var COLORS_LIBRARY = {
42140
42474
  ColorFromColorspace: {
42141
42475
  description: "Convert color space components to a canonical sRGB tuple",
42142
42476
  complexity: 8e3,
42143
- signature: "(tuple, string) -> tuple",
42477
+ signature: "(color | tuple, string) -> tuple",
42144
42478
  evaluate: (ops, { engine: ce }) => {
42145
- const tuple = ops[0];
42146
- if (!isFunction2(tuple) || tuple.operator !== "Tuple" || tuple.ops.length < 3)
42147
- return ce.error("incompatible-type");
42148
- const c0 = tuple.ops[0].re;
42149
- const c1 = tuple.ops[1].re;
42150
- const c2 = tuple.ops[2].re;
42151
- const alpha = tuple.ops.length >= 4 ? tuple.ops[3].re : void 0;
42152
42479
  const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
42153
42480
  if (!space) return ce.error("incompatible-type");
42481
+ let c0, c1, c2;
42482
+ let alpha;
42483
+ const arg = ops[0];
42484
+ const typed = readColorExpr(arg);
42485
+ if (typed) {
42486
+ c0 = typed.c0;
42487
+ c1 = typed.c1;
42488
+ c2 = typed.c2;
42489
+ alpha = typed.alpha;
42490
+ } else if (isFunction2(arg) && arg.operator === "Tuple" && arg.ops.length >= 3) {
42491
+ c0 = arg.ops[0].re;
42492
+ c1 = arg.ops[1].re;
42493
+ c2 = arg.ops[2].re;
42494
+ alpha = arg.ops.length >= 4 ? arg.ops[3].re : void 0;
42495
+ } else {
42496
+ return ce.error("incompatible-type");
42497
+ }
42154
42498
  let rgb;
42155
42499
  switch (space) {
42156
42500
  case "rgb":
@@ -42186,7 +42530,7 @@ var COLORS_LIBRARY = {
42186
42530
  ColorContrast: {
42187
42531
  description: "APCA contrast ratio between two colors",
42188
42532
  complexity: 8e3,
42189
- signature: "(any, any) -> number",
42533
+ signature: "(color | string | tuple, color | string | tuple) -> number",
42190
42534
  evaluate: (ops, { engine: ce }) => {
42191
42535
  const bgRgb = extractRgb(ce, ops[0]);
42192
42536
  const fgRgb = extractRgb(ce, ops[1]);
@@ -42197,19 +42541,186 @@ var COLORS_LIBRARY = {
42197
42541
  ContrastingColor: {
42198
42542
  description: "Choose the foreground color with better APCA contrast against a background",
42199
42543
  complexity: 8e3,
42200
- signature: "(any, any?, any?) -> tuple",
42544
+ signature: "(color | string | tuple, (color | string | tuple)?, (color | string | tuple)?) -> color",
42201
42545
  evaluate: (ops, { engine: ce }) => {
42202
42546
  const bgRgb = extractRgb(ce, ops[0]);
42203
42547
  if (!bgRgb) return ce.error("incompatible-type");
42548
+ let packed;
42204
42549
  if (ops.length >= 3 && ops[1] !== void 0 && ops[2] !== void 0) {
42205
42550
  const fg1 = extractRgb(ce, ops[1]);
42206
42551
  const fg2 = extractRgb(ce, ops[2]);
42207
42552
  if (!fg1 || !fg2) return ce.error("incompatible-type");
42208
- const result2 = contrastingColor({ bg: bgRgb, fg1, fg2 });
42209
- return colorNumberToTuple(ce, result2);
42553
+ packed = contrastingColor({ bg: bgRgb, fg1, fg2 });
42554
+ } else {
42555
+ packed = contrastingColor(bgRgb);
42556
+ }
42557
+ const r = (packed >>> 24 & 255) / 255;
42558
+ const g = (packed >>> 16 & 255) / 255;
42559
+ const b = (packed >>> 8 & 255) / 255;
42560
+ const alpha = normalizeAlpha((packed & 255) / 255);
42561
+ const args = [ce.number(r), ce.number(g), ce.number(b)];
42562
+ if (alpha !== void 0) args.push(ce.number(alpha));
42563
+ return ce.function("Rgb", args);
42564
+ }
42565
+ },
42566
+ // ---------------------------------------------------------------------------
42567
+ // Color constructors. Each preserves its colorspace on evaluation; the
42568
+ // operator name is the discriminator. Components are interpreted per
42569
+ // colorspace conventions (Rgb channels 0-1, Hsv/Hsl hue in degrees with
42570
+ // sat/value 0-1, Oklab/Oklch L 0-1 with standard a/b/C/H ranges). The
42571
+ // optional 4th argument is alpha in [0, 1]. No clamping at evaluation time.
42572
+ // ---------------------------------------------------------------------------
42573
+ Rgb: {
42574
+ description: "sRGB color (channels 0-1, optional alpha 0-1)",
42575
+ complexity: 8e3,
42576
+ signature: "(number, number, number, number?) -> color"
42577
+ },
42578
+ Hsv: {
42579
+ description: "HSV color (hue degrees, saturation/value 0-1, optional alpha)",
42580
+ complexity: 8e3,
42581
+ signature: "(number, number, number, number?) -> color"
42582
+ },
42583
+ Hsl: {
42584
+ description: "HSL color (hue degrees, saturation/lightness 0-1, optional alpha)",
42585
+ complexity: 8e3,
42586
+ signature: "(number, number, number, number?) -> color"
42587
+ },
42588
+ Oklab: {
42589
+ description: "OKLab color (L 0-1, a/b ~ -0.4..0.4, optional alpha)",
42590
+ complexity: 8e3,
42591
+ signature: "(number, number, number, number?) -> color"
42592
+ },
42593
+ Oklch: {
42594
+ description: "OKLCh color (L 0-1, C 0-~0.4, hue degrees, optional alpha)",
42595
+ complexity: 8e3,
42596
+ signature: "(number, number, number, number?) -> color"
42597
+ },
42598
+ // ---------------------------------------------------------------------------
42599
+ // Color-space conversions. Each accepts any of the five color heads and
42600
+ // returns the same color in the named space. If the input is already in
42601
+ // the target space, returns the input unchanged.
42602
+ // ---------------------------------------------------------------------------
42603
+ AsRgb: {
42604
+ description: "Convert any color to sRGB (channels 0-1)",
42605
+ complexity: 8e3,
42606
+ signature: "(color) -> color",
42607
+ evaluate: (ops, { engine: ce }) => {
42608
+ const arg = ops[0];
42609
+ if (isFunction2(arg) && arg.operator === "Rgb")
42610
+ return normalizeColorHead(ce, arg);
42611
+ const rgb = colorExprToRgb(arg);
42612
+ if (!rgb) return ce.error("incompatible-type");
42613
+ const args = [
42614
+ ce.number(rgb.r / 255),
42615
+ ce.number(rgb.g / 255),
42616
+ ce.number(rgb.b / 255)
42617
+ ];
42618
+ if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
42619
+ return ce.function("Rgb", args);
42620
+ }
42621
+ },
42622
+ AsHsv: {
42623
+ description: "Convert any color to HSV (hue degrees, s/v 0-1)",
42624
+ complexity: 8e3,
42625
+ signature: "(color) -> color",
42626
+ evaluate: (ops, { engine: ce }) => {
42627
+ const arg = ops[0];
42628
+ if (isFunction2(arg) && arg.operator === "Hsv")
42629
+ return normalizeColorHead(ce, arg);
42630
+ const rgb = colorExprToRgb(arg);
42631
+ if (!rgb) return ce.error("incompatible-type");
42632
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
42633
+ const args = [ce.number(hsv.h), ce.number(hsv.s), ce.number(hsv.v)];
42634
+ if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
42635
+ return ce.function("Hsv", args);
42636
+ }
42637
+ },
42638
+ AsHsl: {
42639
+ description: "Convert any color to HSL (hue degrees, s/l 0-1)",
42640
+ complexity: 8e3,
42641
+ signature: "(color) -> color",
42642
+ evaluate: (ops, { engine: ce }) => {
42643
+ const arg = ops[0];
42644
+ if (isFunction2(arg) && arg.operator === "Hsl")
42645
+ return normalizeColorHead(ce, arg);
42646
+ const rgb = colorExprToRgb(arg);
42647
+ if (!rgb) return ce.error("incompatible-type");
42648
+ const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
42649
+ const args = [ce.number(hsl.h), ce.number(hsl.s), ce.number(hsl.l)];
42650
+ if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
42651
+ return ce.function("Hsl", args);
42652
+ }
42653
+ },
42654
+ AsOklab: {
42655
+ description: "Convert any color to OKLab",
42656
+ complexity: 8e3,
42657
+ signature: "(color) -> color",
42658
+ evaluate: (ops, { engine: ce }) => {
42659
+ const arg = ops[0];
42660
+ if (isFunction2(arg) && arg.operator === "Oklab")
42661
+ return normalizeColorHead(ce, arg);
42662
+ if (isFunction2(arg) && arg.operator === "Oklch") {
42663
+ const c = readColorExpr(arg);
42664
+ if (!c) return ce.error("incompatible-type");
42665
+ const lab2 = oklchToOklab({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
42666
+ const args2 = [ce.number(lab2.L), ce.number(lab2.a), ce.number(lab2.b)];
42667
+ if (lab2.alpha !== void 0) args2.push(ce.number(lab2.alpha));
42668
+ return ce.function("Oklab", args2);
42669
+ }
42670
+ const rgb = colorExprToRgb(arg);
42671
+ if (!rgb) return ce.error("incompatible-type");
42672
+ const lab = rgbToOklab(rgb);
42673
+ const args = [ce.number(lab.L), ce.number(lab.a), ce.number(lab.b)];
42674
+ if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
42675
+ return ce.function("Oklab", args);
42676
+ }
42677
+ },
42678
+ AsOklch: {
42679
+ description: "Convert any color to OKLCh",
42680
+ complexity: 8e3,
42681
+ signature: "(color) -> color",
42682
+ evaluate: (ops, { engine: ce }) => {
42683
+ const arg = ops[0];
42684
+ if (isFunction2(arg) && arg.operator === "Oklch")
42685
+ return normalizeColorHead(ce, arg);
42686
+ if (isFunction2(arg) && arg.operator === "Oklab") {
42687
+ const c2 = readColorExpr(arg);
42688
+ if (!c2) return ce.error("incompatible-type");
42689
+ const oklch2 = oklabToOklch({
42690
+ L: c2.c0,
42691
+ a: c2.c1,
42692
+ b: c2.c2,
42693
+ alpha: c2.alpha
42694
+ });
42695
+ const args2 = [
42696
+ ce.number(oklch2.L),
42697
+ ce.number(oklch2.C),
42698
+ ce.number(oklch2.H)
42699
+ ];
42700
+ if (oklch2.alpha !== void 0) args2.push(ce.number(oklch2.alpha));
42701
+ return ce.function("Oklch", args2);
42210
42702
  }
42211
- const result = contrastingColor(bgRgb);
42212
- return colorNumberToTuple(ce, result);
42703
+ const rgb = colorExprToRgb(arg);
42704
+ if (!rgb) return ce.error("incompatible-type");
42705
+ const c = rgbToOklch(rgb);
42706
+ const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
42707
+ if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
42708
+ return ce.function("Oklch", args);
42709
+ }
42710
+ },
42711
+ // ---------------------------------------------------------------------------
42712
+ // Perceptual difference. Returns ΔE_OK (Euclidean distance in OKLab),
42713
+ // an approximately perceptually uniform scalar.
42714
+ // ---------------------------------------------------------------------------
42715
+ ColorDelta: {
42716
+ description: "Perceptual color difference (\u0394E_OK) between two colors",
42717
+ complexity: 8e3,
42718
+ signature: "(color | string | tuple, color | string | tuple) -> number",
42719
+ evaluate: (ops, { engine: ce }) => {
42720
+ const a = toOklch(ce, ops[0]);
42721
+ const b = toOklch(ce, ops[1]);
42722
+ if (!a || !b) return ce.error("incompatible-type");
42723
+ return ce.number(oklabDeltaE(oklchToOklab(a), oklchToOklab(b)));
42213
42724
  }
42214
42725
  }
42215
42726
  };
@@ -44689,6 +45200,34 @@ var CORE_LIBRARY = [
44689
45200
  signature: "() -> expression",
44690
45201
  evaluate: (_ops, { engine }) => engine.expr(randomExpression())
44691
45202
  }
45203
+ },
45204
+ // ---------------------------------------------------------------------------
45205
+ // Opaque typed heads — registered so the names are in the standard set
45206
+ // (consumers can branch on the operator name); CE itself does not evaluate
45207
+ // them. Geometric primitives `Triangle`/`Sphere`/`Segment` and the action
45208
+ // arrow `To` (`a \to b`).
45209
+ // ---------------------------------------------------------------------------
45210
+ {
45211
+ Triangle: {
45212
+ description: "Triangle primitive \u2014 opaque typed head.",
45213
+ signature: "(any+) -> expression"
45214
+ },
45215
+ GeometricVector: {
45216
+ description: "Geometric vector (directed segment between two points) \u2014 opaque typed head. Distinct from the column-vector `Vector` operator.",
45217
+ signature: "(any, any) -> expression"
45218
+ },
45219
+ Sphere: {
45220
+ description: "Sphere primitive \u2014 opaque typed head.",
45221
+ signature: "(any+) -> expression"
45222
+ },
45223
+ Segment: {
45224
+ description: "Segment primitive \u2014 opaque typed head.",
45225
+ signature: "(any+) -> expression"
45226
+ },
45227
+ To: {
45228
+ description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
45229
+ signature: "(any, any) -> nothing"
45230
+ }
44692
45231
  }
44693
45232
  ];
44694
45233
 
@@ -51825,6 +52364,7 @@ function orderConvexHull(points) {
51825
52364
 
51826
52365
  // src/compute-engine/boxed-expression/cache.ts
51827
52366
  function cachedValue(v, generation, fn) {
52367
+ if (v.generation === generation && v.value !== null) return v.value;
51828
52368
  v.generation = generation;
51829
52369
  v.value = fn();
51830
52370
  return v.value;
@@ -53602,6 +54142,12 @@ function _setProduct(fn) {
53602
54142
  function _escapeJsonString(s) {
53603
54143
  return s;
53604
54144
  }
54145
+ function _serializeLatexMetadata(ce, expr2) {
54146
+ const syntax = ce.latexSyntax;
54147
+ const opts = ce.latexOptions;
54148
+ if (Object.keys(opts).length === 0) return syntax.serialize(expr2);
54149
+ return syntax.serialize(expr2, { ...opts });
54150
+ }
53605
54151
  function serializeSubtract(ce, a, b, options, metadata) {
53606
54152
  if (isNumber(a) && a.isNegative) {
53607
54153
  const v = a.numericValue;
@@ -53906,7 +54452,7 @@ function serializeJsonFunction(ce, name, args, options, metadata) {
53906
54452
  ];
53907
54453
  const md = { ...metadata ?? {} };
53908
54454
  if (options.metadata.includes("latex") && ce.latexSyntax) {
53909
- md.latex = _escapeJsonString(md.latex ?? ce.latexSyntax.serialize(fn));
54455
+ md.latex = _escapeJsonString(md.latex ?? _serializeLatexMetadata(ce, fn));
53910
54456
  } else md.latex = "";
53911
54457
  if (!options.metadata.includes("wikidata")) md.wikidata = "";
53912
54458
  if (!md.latex && !md.wikidata && options.shorthands.includes("function"))
@@ -53931,7 +54477,7 @@ function serializeJsonSymbol(ce, sym2, options, metadata) {
53931
54477
  }
53932
54478
  metadata = { ...metadata };
53933
54479
  if (options.metadata.includes("latex") && ce.latexSyntax) {
53934
- metadata.latex = metadata.latex ?? ce.latexSyntax.serialize(sym2);
54480
+ metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, sym2);
53935
54481
  if (metadata.latex !== void 0)
53936
54482
  metadata.latex = _escapeJsonString(metadata.latex);
53937
54483
  } else metadata.latex = void 0;
@@ -54093,7 +54639,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
54093
54639
  }
54094
54640
  }
54095
54641
  if (options.metadata.includes("latex") && ce.latexSyntax)
54096
- metadata.latex = metadata.latex ?? ce.latexSyntax.serialize(result2 ?? { num });
54642
+ metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, result2 ?? { num });
54097
54643
  if (result2) {
54098
54644
  if (metadata.latex !== void 0)
54099
54645
  return { sym: result2, latex: metadata.latex };
@@ -54109,7 +54655,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
54109
54655
  if (value.isNaN()) {
54110
54656
  num = "NaN";
54111
54657
  if (options.metadata.includes("latex") && ce.latexSyntax)
54112
- metadata.latex = metadata.latex ?? ce.latexSyntax.serialize({ num });
54658
+ metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
54113
54659
  return metadata.latex !== void 0 ? { num, latex: metadata.latex } : { num };
54114
54660
  }
54115
54661
  return serializeJsonFunction(
@@ -54143,7 +54689,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
54143
54689
  value = Number(value);
54144
54690
  } else {
54145
54691
  if (options.metadata.includes("latex") && ce.latexSyntax)
54146
- metadata.latex = metadata.latex ?? ce.latexSyntax.serialize({
54692
+ metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, {
54147
54693
  num: value.toString()
54148
54694
  });
54149
54695
  if (metadata.latex !== void 0)
@@ -54157,7 +54703,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
54157
54703
  result = value > 0 ? "PositiveInfinity" : "NegativeInfinity";
54158
54704
  else num = serializeRepeatingDecimals(value.toString(), options);
54159
54705
  if (options.metadata.includes("latex") && ce.latexSyntax)
54160
- metadata.latex = metadata.latex ?? ce.latexSyntax.serialize({ num });
54706
+ metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
54161
54707
  if (result) {
54162
54708
  if (metadata.latex !== void 0)
54163
54709
  return { sym: result, latex: metadata.latex };
@@ -54922,8 +55468,7 @@ function compile(expr2, options) {
54922
55468
  ce.pushScope();
54923
55469
  try {
54924
55470
  if (vars && typeof vars === "object") {
54925
- for (const [k, v] of Object.entries(vars))
54926
- ce.assign(k, v);
55471
+ for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
54927
55472
  }
54928
55473
  return expr2.evaluate().re;
54929
55474
  } finally {
@@ -60153,8 +60698,7 @@ function tryGetComplexParts(expr2, compile3) {
60153
60698
  return { re: null, im: formatFloat(iScale) };
60154
60699
  }
60155
60700
  const compiledFactors = remaining.map((r) => compile3(r));
60156
- if (iScale !== 1)
60157
- compiledFactors.unshift(formatFloat(iScale));
60701
+ if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
60158
60702
  const imCode = foldTerms(compiledFactors, "1.0", "*");
60159
60703
  return { re: null, im: imCode };
60160
60704
  }
@@ -60758,39 +61302,130 @@ var JAVASCRIPT_FUNCTIONS = {
60758
61302
  if (args.length >= 2)
60759
61303
  return `_SYS.colormap(${compile3(args[0])}, ${compile3(args[1])})`;
60760
61304
  return `_SYS.colormap(${compile3(args[0])})`;
61305
+ },
61306
+ // -----------------------------------------------------------------------
61307
+ // Color constructor heads. All compile to OKLCh arrays at runtime — the
61308
+ // canonical color representation in this target. The constructors take
61309
+ // their own colorspace's components and convert internally.
61310
+ // (Mirrors the GPU target's design: color values are vec3 OKLCh.)
61311
+ // -----------------------------------------------------------------------
61312
+ Rgb: (args, compile3) => {
61313
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
61314
+ return `_SYS.rgb(${args.map(compile3).join(", ")})`;
61315
+ },
61316
+ Hsv: (args, compile3) => {
61317
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
61318
+ return `_SYS.hsv(${args.map(compile3).join(", ")})`;
61319
+ },
61320
+ Hsl: (args, compile3) => {
61321
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
61322
+ return `_SYS.hsl(${args.map(compile3).join(", ")})`;
61323
+ },
61324
+ Oklab: (args, compile3) => {
61325
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
61326
+ return `_SYS.oklab(${args.map(compile3).join(", ")})`;
61327
+ },
61328
+ Oklch: (args, compile3) => {
61329
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
61330
+ return `_SYS.oklch(${args.map(compile3).join(", ")})`;
61331
+ },
61332
+ // -----------------------------------------------------------------------
61333
+ // As* converters. Compile-time output convention matches the engine and
61334
+ // the GPU target: each returns components in the named space as a 3- or
61335
+ // 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
61336
+ // layers). `AsOklch` is the identity (canonical form).
61337
+ // -----------------------------------------------------------------------
61338
+ AsRgb: ([c], compile3) => {
61339
+ if (c === null) throw new Error("AsRgb: no argument");
61340
+ return `_SYS.asRgb(${compile3(c)})`;
61341
+ },
61342
+ AsHsv: ([c], compile3) => {
61343
+ if (c === null) throw new Error("AsHsv: no argument");
61344
+ return `_SYS.asHsv(${compile3(c)})`;
61345
+ },
61346
+ AsHsl: ([c], compile3) => {
61347
+ if (c === null) throw new Error("AsHsl: no argument");
61348
+ return `_SYS.asHsl(${compile3(c)})`;
61349
+ },
61350
+ AsOklab: ([c], compile3) => {
61351
+ if (c === null) throw new Error("AsOklab: no argument");
61352
+ return `_SYS.asOklab(${compile3(c)})`;
61353
+ },
61354
+ AsOklch: ([c], compile3) => {
61355
+ if (c === null) throw new Error("AsOklch: no argument");
61356
+ return compile3(c);
61357
+ },
61358
+ // Perceptual color difference (ΔE_OK).
61359
+ ColorDelta: ([a, b], compile3) => {
61360
+ if (a === null || b === null)
61361
+ throw new Error("ColorDelta: need two colors");
61362
+ return `_SYS.colorDelta(${compile3(a)}, ${compile3(b)})`;
61363
+ },
61364
+ // Euclidean distance between two tuples (any positive dimension).
61365
+ // The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
61366
+ // (vec-only); this JS handler works on plain arrays of any length.
61367
+ Distance: ([a, b], compile3) => {
61368
+ if (a === null || b === null) throw new Error("Distance: need two points");
61369
+ return `_SYS.distance(${compile3(a)}, ${compile3(b)})`;
60761
61370
  }
60762
61371
  };
60763
61372
  function toRI(c) {
60764
61373
  return { re: c.re, im: c.im };
60765
61374
  }
61375
+ function normalizeAlpha2(a) {
61376
+ if (a === void 0) return void 0;
61377
+ if (!Number.isFinite(a)) return void 0;
61378
+ if (Math.abs(a - 1) < 1e-9) return void 0;
61379
+ return a;
61380
+ }
60766
61381
  function toRgb255(input) {
60767
61382
  if (typeof input === "string") {
60768
61383
  const c = parseColor(input);
60769
- return {
61384
+ const rgb2 = {
60770
61385
  r: c >>> 24 & 255,
60771
61386
  g: c >>> 16 & 255,
60772
- b: c >>> 8 & 255,
60773
- alpha: (c & 255) / 255
61387
+ b: c >>> 8 & 255
60774
61388
  };
61389
+ const alpha = normalizeAlpha2((c & 255) / 255);
61390
+ if (alpha !== void 0) rgb2.alpha = alpha;
61391
+ return rgb2;
61392
+ }
61393
+ const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
61394
+ if (input.length >= 4) {
61395
+ const alpha = normalizeAlpha2(input[3]);
61396
+ if (alpha !== void 0) rgb.alpha = alpha;
60775
61397
  }
60776
- const rgb = {
60777
- r: input[0] * 255,
60778
- g: input[1] * 255,
60779
- b: input[2] * 255
60780
- };
60781
- if (input.length >= 4) rgb.alpha = input[3];
60782
61398
  return rgb;
60783
61399
  }
60784
- function packedToArray(c) {
60785
- const r = (c >>> 24 & 255) / 255;
60786
- const g = (c >>> 16 & 255) / 255;
60787
- const b = (c >>> 8 & 255) / 255;
60788
- const a = (c & 255) / 255;
60789
- return Math.abs(a - 1) < 1e-4 ? [r, g, b] : [r, g, b, a];
61400
+ function toOklch2(input) {
61401
+ if (typeof input === "string") {
61402
+ const c = parseColor(input);
61403
+ const r = c >>> 24 & 255;
61404
+ const g = c >>> 16 & 255;
61405
+ const b = c >>> 8 & 255;
61406
+ const oklch2 = rgbToOklch({ r, g, b });
61407
+ const alpha = normalizeAlpha2((c & 255) / 255);
61408
+ if (alpha !== void 0) oklch2.alpha = alpha;
61409
+ return oklch2;
61410
+ }
61411
+ return {
61412
+ L: input[0],
61413
+ C: input[1],
61414
+ H: input[2],
61415
+ alpha: input.length >= 4 ? normalizeAlpha2(input[3]) : void 0
61416
+ };
61417
+ }
61418
+ function packedToOklch(c) {
61419
+ const r = c >>> 24 & 255;
61420
+ const g = c >>> 16 & 255;
61421
+ const b = c >>> 8 & 255;
61422
+ const oklch2 = rgbToOklch({ r, g, b });
61423
+ const alpha = normalizeAlpha2((c & 255) / 255);
61424
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
60790
61425
  }
60791
61426
  var colorHelpers = {
60792
61427
  color(input) {
60793
- return packedToArray(parseColor(input));
61428
+ return packedToOklch(parseColor(input));
60794
61429
  },
60795
61430
  colorToString(input, format) {
60796
61431
  const rgb = toRgb255(input);
@@ -60801,7 +61436,7 @@ var colorHelpers = {
60801
61436
  const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
60802
61437
  const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
60803
61438
  let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
60804
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4) {
61439
+ if (rgb.alpha !== void 0) {
60805
61440
  const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
60806
61441
  hex += a.toString(16).padStart(2, "0");
60807
61442
  }
@@ -60811,7 +61446,7 @@ var colorHelpers = {
60811
61446
  const r = Math.round(rgb.r);
60812
61447
  const g = Math.round(rgb.g);
60813
61448
  const b = Math.round(rgb.b);
60814
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
61449
+ if (rgb.alpha !== void 0)
60815
61450
  return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
60816
61451
  return `rgb(${r} ${g} ${b})`;
60817
61452
  }
@@ -60820,7 +61455,7 @@ var colorHelpers = {
60820
61455
  const h = Math.round(hsl.h * 10) / 10;
60821
61456
  const s = Math.round(hsl.s * 1e3) / 10;
60822
61457
  const l = Math.round(hsl.l * 1e3) / 10;
60823
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
61458
+ if (rgb.alpha !== void 0)
60824
61459
  return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
60825
61460
  return `hsl(${h} ${s}% ${l}%)`;
60826
61461
  }
@@ -60829,7 +61464,7 @@ var colorHelpers = {
60829
61464
  const L = Math.round(c.L * 1e3) / 1e3;
60830
61465
  const C = Math.round(c.C * 1e3) / 1e3;
60831
61466
  const H = Math.round(c.H * 10) / 10;
60832
- if (rgb.alpha !== void 0 && Math.abs(rgb.alpha - 1) > 1e-4)
61467
+ if (rgb.alpha !== void 0)
60833
61468
  return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
60834
61469
  return `oklch(${L} ${C} ${H})`;
60835
61470
  }
@@ -60838,29 +61473,29 @@ var colorHelpers = {
60838
61473
  }
60839
61474
  },
60840
61475
  colorMix(input1, input2, ratio = 0.5) {
60841
- const rgb1 = toRgb255(input1);
60842
- const rgb2 = toRgb255(input2);
61476
+ const c1 = toOklch2(input1);
61477
+ const c2 = toOklch2(input2);
60843
61478
  ratio = Math.max(0, Math.min(1, ratio));
60844
- const c1 = rgbToOklch(rgb1);
60845
- const c2 = rgbToOklch(rgb2);
60846
- let dh = c2.H - c1.H;
60847
- if (dh > 180) dh -= 360;
60848
- if (dh < -180) dh += 360;
60849
- let H = c1.H + dh * ratio;
60850
- if (H < 0) H += 360;
60851
- if (H >= 360) H -= 360;
60852
- const mixed = oklchToRgb({
60853
- L: c1.L + (c2.L - c1.L) * ratio,
60854
- C: c1.C + (c2.C - c1.C) * ratio,
60855
- H
60856
- });
60857
- const r = mixed.r / 255;
60858
- const g = mixed.g / 255;
60859
- const b = mixed.b / 255;
60860
- const a1 = rgb1.alpha ?? 1;
60861
- const a2 = rgb2.alpha ?? 1;
60862
- const alpha = a1 + (a2 - a1) * ratio;
60863
- return Math.abs(alpha - 1) > 1e-4 ? [r, g, b, alpha] : [r, g, b];
61479
+ const c1Achromatic = c1.C < 1e-6;
61480
+ const c2Achromatic = c2.C < 1e-6;
61481
+ let H;
61482
+ if (c1Achromatic && c2Achromatic) H = c1.H;
61483
+ else if (c1Achromatic) H = c2.H;
61484
+ else if (c2Achromatic) H = c1.H;
61485
+ else {
61486
+ let dh = c2.H - c1.H;
61487
+ if (dh > 180) dh -= 360;
61488
+ if (dh < -180) dh += 360;
61489
+ H = c1.H + dh * ratio;
61490
+ if (H < 0) H += 360;
61491
+ if (H >= 360) H -= 360;
61492
+ }
61493
+ const L = c1.L + (c2.L - c1.L) * ratio;
61494
+ const C = c1.C + (c2.C - c1.C) * ratio;
61495
+ const a1 = c1.alpha ?? 1;
61496
+ const a2 = c2.alpha ?? 1;
61497
+ const alpha = normalizeAlpha2(a1 + (a2 - a1) * ratio);
61498
+ return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
60864
61499
  },
60865
61500
  colorContrast(bg, fg) {
60866
61501
  return apca(toRgb255(bg), toRgb255(fg));
@@ -60868,11 +61503,11 @@ var colorHelpers = {
60868
61503
  contrastingColor(bg, fg1, fg2) {
60869
61504
  const bgRgb = toRgb255(bg);
60870
61505
  if (fg1 !== void 0 && fg2 !== void 0) {
60871
- return packedToArray(
61506
+ return packedToOklch(
60872
61507
  contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
60873
61508
  );
60874
61509
  }
60875
- return packedToArray(contrastingColor(bgRgb));
61510
+ return packedToOklch(contrastingColor(bgRgb));
60876
61511
  },
60877
61512
  colorToColorspace(input, space) {
60878
61513
  const rgb = toRgb255(input);
@@ -60901,7 +61536,7 @@ var colorHelpers = {
60901
61536
  default:
60902
61537
  throw new Error(`Unknown color space: ${space}`);
60903
61538
  }
60904
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
61539
+ if (alpha !== void 0) result.push(alpha);
60905
61540
  return result;
60906
61541
  },
60907
61542
  colormap(name, arg) {
@@ -60913,7 +61548,7 @@ var colorHelpers = {
60913
61548
  const palette = allPalettes[name];
60914
61549
  if (!palette) throw new Error(`Unknown palette: ${name}`);
60915
61550
  const colors = palette.map(
60916
- (hex) => parseColorToRgb01(hex)
61551
+ (hex) => packedToOklch(parseColor(hex))
60917
61552
  );
60918
61553
  if (arg === void 0) return colors;
60919
61554
  if (Number.isInteger(arg) && arg >= 2) {
@@ -60937,62 +61572,128 @@ var colorHelpers = {
60937
61572
  const frac = pos - i;
60938
61573
  if (frac === 0 || i >= colors.length - 1)
60939
61574
  return [...colors[Math.min(i, colors.length - 1)]];
60940
- const rgb1 = {
60941
- r: colors[i][0] * 255,
60942
- g: colors[i][1] * 255,
60943
- b: colors[i][2] * 255
60944
- };
60945
- const rgb2 = {
60946
- r: colors[i + 1][0] * 255,
60947
- g: colors[i + 1][1] * 255,
60948
- b: colors[i + 1][2] * 255
60949
- };
60950
- const c1 = rgbToOklch(rgb1);
60951
- const c2 = rgbToOklch(rgb2);
60952
- let dh = c2.H - c1.H;
60953
- if (dh > 180) dh -= 360;
60954
- if (dh < -180) dh += 360;
60955
- let H = c1.H + dh * frac;
60956
- if (H < 0) H += 360;
60957
- if (H >= 360) H -= 360;
60958
- const mixed = oklchToRgb({
60959
- L: c1.L + (c2.L - c1.L) * frac,
60960
- C: c1.C + (c2.C - c1.C) * frac,
60961
- H
60962
- });
60963
- return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
61575
+ const [L1, C1, H1] = colors[i];
61576
+ const [L2, C2, H2] = colors[i + 1];
61577
+ const c1Achromatic = C1 < 1e-6;
61578
+ const c2Achromatic = C2 < 1e-6;
61579
+ let H;
61580
+ if (c1Achromatic && c2Achromatic) H = H1;
61581
+ else if (c1Achromatic) H = H2;
61582
+ else if (c2Achromatic) H = H1;
61583
+ else {
61584
+ let dh = H2 - H1;
61585
+ if (dh > 180) dh -= 360;
61586
+ if (dh < -180) dh += 360;
61587
+ H = H1 + dh * frac;
61588
+ if (H < 0) H += 360;
61589
+ if (H >= 360) H -= 360;
61590
+ }
61591
+ return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
60964
61592
  },
60965
61593
  colorFromColorspace(components, space) {
60966
61594
  const c0 = components[0];
60967
61595
  const c1 = components[1];
60968
61596
  const c2 = components[2];
60969
61597
  const alpha = components.length >= 4 ? components[3] : void 0;
60970
- let result;
61598
+ let oklch2;
60971
61599
  switch (space.toLowerCase()) {
60972
61600
  case "rgb":
60973
- result = [c0, c1, c2];
61601
+ oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
60974
61602
  break;
60975
61603
  case "hsl": {
60976
- const r = hslToRgb(c0, c1, c2);
60977
- result = [r.r / 255, r.g / 255, r.b / 255];
61604
+ const rgb = hslToRgb(c0, c1, c2);
61605
+ oklch2 = rgbToOklch(rgb);
60978
61606
  break;
60979
61607
  }
60980
- case "oklch": {
60981
- const r = oklchToRgb({ L: c0, C: c1, H: c2 });
60982
- result = [r.r / 255, r.g / 255, r.b / 255];
61608
+ case "oklch":
61609
+ oklch2 = { L: c0, C: c1, H: c2 };
60983
61610
  break;
60984
- }
60985
61611
  case "oklab":
60986
- case "lab": {
60987
- const r = oklabToRgb({ L: c0, a: c1, b: c2 });
60988
- result = [r.r / 255, r.g / 255, r.b / 255];
61612
+ case "lab":
61613
+ oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
60989
61614
  break;
60990
- }
60991
61615
  default:
60992
61616
  throw new Error(`Unknown color space: ${space}`);
60993
61617
  }
60994
- if (alpha !== void 0 && Math.abs(alpha - 1) > 1e-4) result.push(alpha);
60995
- return result;
61618
+ return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
61619
+ },
61620
+ // -----------------------------------------------------------------------
61621
+ // Color constructors. Each accepts components in its colorspace's natural
61622
+ // units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
61623
+ // -----------------------------------------------------------------------
61624
+ rgb(r, g, b, alpha) {
61625
+ const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
61626
+ const a = normalizeAlpha2(alpha);
61627
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
61628
+ },
61629
+ hsv(h, s, v, alpha) {
61630
+ const rgb = hsvToRgb(h, s, v);
61631
+ const c = rgbToOklch(rgb);
61632
+ const a = normalizeAlpha2(alpha);
61633
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
61634
+ },
61635
+ hsl(h, s, l, alpha) {
61636
+ const rgb = hslToRgb(h, s, l);
61637
+ const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
61638
+ const a = normalizeAlpha2(alpha);
61639
+ return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
61640
+ },
61641
+ oklab(L, a, b, alpha) {
61642
+ const c = oklabToOklch({ L, a, b });
61643
+ const al = normalizeAlpha2(alpha);
61644
+ return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
61645
+ },
61646
+ oklch(L, C, H, alpha) {
61647
+ const a = normalizeAlpha2(alpha);
61648
+ return a !== void 0 ? [L, C, H, a] : [L, C, H];
61649
+ },
61650
+ // -----------------------------------------------------------------------
61651
+ // As* converters. Inputs are anything `toOklch` accepts (string, packed
61652
+ // int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
61653
+ // space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
61654
+ // consistency with the GPU target's shader convention.
61655
+ // -----------------------------------------------------------------------
61656
+ asRgb(input) {
61657
+ const rgb = toRgb255(input);
61658
+ const r = rgb.r / 255;
61659
+ const g = rgb.g / 255;
61660
+ const b = rgb.b / 255;
61661
+ return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
61662
+ },
61663
+ asHsv(input) {
61664
+ const rgb = toRgb255(input);
61665
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
61666
+ return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
61667
+ },
61668
+ asHsl(input) {
61669
+ const rgb = toRgb255(input);
61670
+ const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
61671
+ return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
61672
+ },
61673
+ asOklab(input) {
61674
+ const c = toOklch2(input);
61675
+ const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
61676
+ return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
61677
+ },
61678
+ // asOklch is identity — handled at compile time as a pass-through
61679
+ // Perceptual color difference (ΔE_OK).
61680
+ colorDelta(a, b) {
61681
+ const labA = oklchToOklab(toOklch2(a));
61682
+ const labB = oklchToOklab(toOklch2(b));
61683
+ return oklabDeltaE(labA, labB);
61684
+ },
61685
+ // Euclidean distance between two tuples. Plain numeric — not a color
61686
+ // operation despite living in the same helpers block.
61687
+ distance(a, b) {
61688
+ if (!Array.isArray(a) || !Array.isArray(b))
61689
+ throw new Error("Distance: expected two arrays");
61690
+ if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
61691
+ let sumSq = 0;
61692
+ for (let i = 0; i < a.length; i++) {
61693
+ const d = a[i] - b[i];
61694
+ sumSq += d * d;
61695
+ }
61696
+ return Math.sqrt(sumSq);
60996
61697
  }
60997
61698
  };
60998
61699
  var SYS_HELPERS = {
@@ -61431,6 +62132,13 @@ var GPU_OPERATORS = {
61431
62132
  function gpuVec2(target) {
61432
62133
  return target?.language === "wgsl" ? "vec2f" : "vec2";
61433
62134
  }
62135
+ function gpuVec3(target) {
62136
+ return target?.language === "wgsl" ? "vec3f" : "vec3";
62137
+ }
62138
+ function readStringLiteral(expr2) {
62139
+ if (!isString(expr2)) return null;
62140
+ return expr2.string?.toLowerCase() ?? null;
62141
+ }
61434
62142
  function compileIntArg(expr2, compile3, target) {
61435
62143
  const c = tryGetConstant(expr2);
61436
62144
  if (c !== void 0 && Number.isInteger(c)) return c.toString();
@@ -61489,7 +62197,7 @@ function compileGPUSumProduct(kind, args, _compile2, target) {
61489
62197
  `for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
61490
62198
  ` ${acc} ${op}= ${body};`,
61491
62199
  `}`,
61492
- `return ${acc}`
62200
+ `return ${acc};`
61493
62201
  ];
61494
62202
  return lines.join("\n");
61495
62203
  }
@@ -61543,8 +62251,7 @@ var GPU_FUNCTIONS = {
61543
62251
  const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
61544
62252
  const realFactors = args.filter((_, i) => i !== iIndex);
61545
62253
  const v2 = gpuVec2(target);
61546
- if (realFactors.length === 0)
61547
- return `${v2}(0.0, ${formatFloat(iScale)})`;
62254
+ if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
61548
62255
  const factors = realFactors.map((f) => compile3(f));
61549
62256
  if (iScale !== 1) factors.unshift(formatFloat(iScale));
61550
62257
  const imCode = foldTerms(factors, "1.0", "*");
@@ -61597,8 +62304,7 @@ var GPU_FUNCTIONS = {
61597
62304
  if (isNumber(x) && x.im !== 0) {
61598
62305
  return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
61599
62306
  }
61600
- if (isSymbol2(x, "ImaginaryUnit"))
61601
- return `${gpuVec2(target)}(0.0, -1.0)`;
62307
+ if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
61602
62308
  return `(-${compile3(x)})`;
61603
62309
  },
61604
62310
  // Standard math functions with complex dispatch
@@ -61971,17 +62677,127 @@ var GPU_FUNCTIONS = {
61971
62677
  }
61972
62678
  const isWGSL = target?.language === "wgsl";
61973
62679
  const v3 = isWGSL ? "vec3f" : "vec3";
61974
- return `((_gpu_apca(${bg}, ${v3}(0.0)) > 50.0) ? ${v3}(0.0) : ${v3}(1.0))`;
62680
+ const black = `${v3}(0.0)`;
62681
+ const white = `${v3}(1.0, 0.0, 0.0)`;
62682
+ return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
61975
62683
  },
61976
62684
  ColorToColorspace: ([color, space], compile3) => {
61977
62685
  if (color === null || space === null)
61978
62686
  throw new Error("ColorToColorspace: need color and space");
61979
- return `_gpu_srgb_to_oklab(${compile3(color)})`;
62687
+ const spaceName = readStringLiteral(space);
62688
+ if (spaceName === null)
62689
+ throw new Error("ColorToColorspace: space must be a string literal");
62690
+ const c = compile3(color);
62691
+ switch (spaceName) {
62692
+ case "oklch":
62693
+ return c;
62694
+ case "oklab":
62695
+ case "lab":
62696
+ return `_gpu_oklch_to_oklab(${c})`;
62697
+ case "rgb":
62698
+ return `_gpu_oklch_to_srgb(${c})`;
62699
+ case "hsl":
62700
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
62701
+ case "hsv":
62702
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
62703
+ default:
62704
+ throw new Error(
62705
+ `ColorToColorspace: unsupported space "${spaceName}" on GPU target`
62706
+ );
62707
+ }
61980
62708
  },
61981
62709
  ColorFromColorspace: ([components, space], compile3) => {
61982
62710
  if (components === null || space === null)
61983
62711
  throw new Error("ColorFromColorspace: need components and space");
61984
- return `_gpu_oklab_to_srgb(${compile3(components)})`;
62712
+ const spaceName = readStringLiteral(space);
62713
+ if (spaceName === null)
62714
+ throw new Error("ColorFromColorspace: space must be a string literal");
62715
+ const c = compile3(components);
62716
+ switch (spaceName) {
62717
+ case "oklch":
62718
+ return c;
62719
+ case "oklab":
62720
+ case "lab":
62721
+ return `_gpu_oklab_to_oklch(${c})`;
62722
+ case "rgb":
62723
+ return `_gpu_srgb_to_oklch(${c})`;
62724
+ case "hsl":
62725
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
62726
+ case "hsv":
62727
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
62728
+ default:
62729
+ throw new Error(
62730
+ `ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
62731
+ );
62732
+ }
62733
+ },
62734
+ // ---------------------------------------------------------------------------
62735
+ // Color literals. Each typed head compiles to a canonical OKLCh vec3.
62736
+ // Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
62737
+ // alpha as a separate uniform if it's needed at the framebuffer boundary.
62738
+ // ---------------------------------------------------------------------------
62739
+ Color: ([s], _compile2, target) => {
62740
+ if (s === null) throw new Error("Color: no argument");
62741
+ const str = readStringLiteral(s);
62742
+ if (str === null)
62743
+ throw new Error("Color: argument must be a string literal on GPU target");
62744
+ const packed = parseColor(str);
62745
+ if (packed === 0 && str.trim().toLowerCase() !== "transparent")
62746
+ throw new Error(`Color: invalid color string "${str}"`);
62747
+ const r = packed >>> 24 & 255;
62748
+ const g = packed >>> 16 & 255;
62749
+ const b = packed >>> 8 & 255;
62750
+ const oklch2 = rgbToOklch({ r, g, b });
62751
+ return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
62752
+ },
62753
+ Rgb: (args, compile3, target) => {
62754
+ if (args.length < 3) throw new Error("Rgb: need 3 components");
62755
+ const v3 = gpuVec3(target);
62756
+ return `_gpu_srgb_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
62757
+ },
62758
+ Hsv: (args, compile3, target) => {
62759
+ if (args.length < 3) throw new Error("Hsv: need 3 components");
62760
+ const v3 = gpuVec3(target);
62761
+ return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
62762
+ },
62763
+ Hsl: (args, compile3, target) => {
62764
+ if (args.length < 3) throw new Error("Hsl: need 3 components");
62765
+ const v3 = gpuVec3(target);
62766
+ return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
62767
+ },
62768
+ Oklab: (args, compile3, target) => {
62769
+ if (args.length < 3) throw new Error("Oklab: need 3 components");
62770
+ const v3 = gpuVec3(target);
62771
+ return `_gpu_oklab_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
62772
+ },
62773
+ Oklch: (args, compile3, target) => {
62774
+ if (args.length < 3) throw new Error("Oklch: need 3 components");
62775
+ const v3 = gpuVec3(target);
62776
+ return `${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})`;
62777
+ },
62778
+ // ---------------------------------------------------------------------------
62779
+ // As* operators. AsOklch is identity (canonical). The other As* return
62780
+ // components in the named space, equivalent to ColorToColorspace(c, 'x').
62781
+ // ---------------------------------------------------------------------------
62782
+ AsOklch: ([c], compile3) => {
62783
+ if (c === null) throw new Error("AsOklch: no argument");
62784
+ return compile3(c);
62785
+ },
62786
+ AsOklab: ([c], compile3) => {
62787
+ if (c === null) throw new Error("AsOklab: no argument");
62788
+ return `_gpu_oklch_to_oklab(${compile3(c)})`;
62789
+ },
62790
+ AsRgb: ([c], compile3) => {
62791
+ if (c === null) throw new Error("AsRgb: no argument");
62792
+ return `_gpu_oklch_to_srgb(${compile3(c)})`;
62793
+ },
62794
+ AsHsv: ([c], compile3) => {
62795
+ if (c === null) throw new Error("AsHsv: no argument");
62796
+ return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile3(c)}))`;
62797
+ },
62798
+ AsHsl: ([c], compile3) => {
62799
+ if (c === null) throw new Error("AsHsl: no argument");
62800
+ return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile3(c)}))`;
61985
62801
  },
61986
62802
  // Fractal functions
61987
62803
  Mandelbrot: ([c, maxIter], compile3, target) => {
@@ -62674,28 +63490,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
62674
63490
 
62675
63491
  vec3 _gpu_oklab_to_oklch(vec3 lab) {
62676
63492
  float C = length(lab.yz);
62677
- float H = atan(lab.z, lab.y);
63493
+ float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
63494
+ if (H < 0.0) H += 360.0;
62678
63495
  return vec3(lab.x, C, H);
62679
63496
  }
62680
63497
 
62681
63498
  vec3 _gpu_oklch_to_oklab(vec3 lch) {
62682
- return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
63499
+ float h_rad = lch.z * (3.14159265359 / 180.0);
63500
+ return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
63501
+ }
63502
+
63503
+ vec3 _gpu_srgb_to_oklch(vec3 rgb) {
63504
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
63505
+ }
63506
+
63507
+ vec3 _gpu_oklch_to_srgb(vec3 lch) {
63508
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
63509
+ }
63510
+
63511
+ // HSL conversion. Hue in degrees, saturation/lightness in 0-1.
63512
+ vec3 _gpu_hsl_to_rgb(vec3 hsl) {
63513
+ float h = hsl.x;
63514
+ float s = hsl.y;
63515
+ float l = hsl.z;
63516
+ float c = (1.0 - abs(2.0 * l - 1.0)) * s;
63517
+ float h6 = h / 60.0;
63518
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
63519
+ float r = 0.0;
63520
+ float g = 0.0;
63521
+ float b = 0.0;
63522
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
63523
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
63524
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
63525
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
63526
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
63527
+ else { r = c; g = 0.0; b = x; }
63528
+ float m = l - c / 2.0;
63529
+ return vec3(r + m, g + m, b + m);
63530
+ }
63531
+
63532
+ vec3 _gpu_rgb_to_hsl(vec3 rgb) {
63533
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
63534
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
63535
+ float l = (maxc + minc) / 2.0;
63536
+ float d = maxc - minc;
63537
+ if (d < 1e-6) return vec3(0.0, 0.0, l);
63538
+ float s = d / (1.0 - abs(2.0 * l - 1.0));
63539
+ float h;
63540
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
63541
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
63542
+ else h = (rgb.x - rgb.y) / d + 4.0;
63543
+ h *= 60.0;
63544
+ if (h < 0.0) h += 360.0;
63545
+ return vec3(h, s, l);
63546
+ }
63547
+
63548
+ // HSV conversion. Hue in degrees, saturation/value in 0-1.
63549
+ vec3 _gpu_hsv_to_rgb(vec3 hsv) {
63550
+ float h = hsv.x;
63551
+ float s = hsv.y;
63552
+ float v = hsv.z;
63553
+ float c = v * s;
63554
+ float h6 = h / 60.0;
63555
+ float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
63556
+ float r = 0.0;
63557
+ float g = 0.0;
63558
+ float b = 0.0;
63559
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
63560
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
63561
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
63562
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
63563
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
63564
+ else { r = c; g = 0.0; b = x; }
63565
+ float m = v - c;
63566
+ return vec3(r + m, g + m, b + m);
63567
+ }
63568
+
63569
+ vec3 _gpu_rgb_to_hsv(vec3 rgb) {
63570
+ float maxc = max(max(rgb.x, rgb.y), rgb.z);
63571
+ float minc = min(min(rgb.x, rgb.y), rgb.z);
63572
+ float v = maxc;
63573
+ float d = maxc - minc;
63574
+ if (d < 1e-6) return vec3(0.0, 0.0, v);
63575
+ float s = (maxc < 1e-6) ? 0.0 : d / maxc;
63576
+ float h;
63577
+ if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
63578
+ else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
63579
+ else h = (rgb.x - rgb.y) / d + 4.0;
63580
+ h *= 60.0;
63581
+ if (h < 0.0) h += 360.0;
63582
+ return vec3(h, s, v);
62683
63583
  }
62684
63584
 
62685
- vec3 _gpu_color_mix(vec3 rgb1, vec3 rgb2, float t) {
62686
- vec3 lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
62687
- vec3 lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
63585
+ vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
62688
63586
  float L = mix(lch1.x, lch2.x, t);
62689
63587
  float C = mix(lch1.y, lch2.y, t);
62690
- float dh = lch2.z - lch1.z;
62691
- const float PI = 3.14159265359;
62692
- if (dh > PI) dh -= 2.0 * PI;
62693
- if (dh < -PI) dh += 2.0 * PI;
62694
- float H = lch1.z + dh * t;
62695
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3(L, C, H)));
63588
+ bool a1 = lch1.y < 1e-6;
63589
+ bool a2 = lch2.y < 1e-6;
63590
+ float H;
63591
+ if (a1 && a2) {
63592
+ H = lch1.z;
63593
+ } else if (a1) {
63594
+ H = lch2.z;
63595
+ } else if (a2) {
63596
+ H = lch1.z;
63597
+ } else {
63598
+ float dh = lch2.z - lch1.z;
63599
+ if (dh > 180.0) dh -= 360.0;
63600
+ if (dh < -180.0) dh += 360.0;
63601
+ H = lch1.z + dh * t;
63602
+ if (H < 0.0) H += 360.0;
63603
+ if (H >= 360.0) H -= 360.0;
63604
+ }
63605
+ return vec3(L, C, H);
62696
63606
  }
62697
63607
 
62698
- float _gpu_apca(vec3 bg, vec3 fg) {
63608
+ float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
63609
+ vec3 bg = _gpu_oklch_to_srgb(lch_bg);
63610
+ vec3 fg = _gpu_oklch_to_srgb(lch_fg);
62699
63611
  float bgR = _gpu_srgb_to_linear(bg.x);
62700
63612
  float bgG = _gpu_srgb_to_linear(bg.y);
62701
63613
  float bgB = _gpu_srgb_to_linear(bg.z);
@@ -62706,9 +63618,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
62706
63618
  float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
62707
63619
  float bgC = pow(bgY, 0.56);
62708
63620
  float fgC = pow(fgY, 0.57);
62709
- float contrast = (bgC > fgC)
62710
- ? (bgC - fgC) * 1.14
62711
- : (bgC - fgC) * 1.14;
63621
+ float contrast = (bgC - fgC) * 1.14;
62712
63622
  return contrast * 100.0;
62713
63623
  }
62714
63624
  `;
@@ -62752,28 +63662,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
62752
63662
 
62753
63663
  fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
62754
63664
  let C = length(lab.yz);
62755
- let H = atan2(lab.z, lab.y);
63665
+ var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
63666
+ if (H < 0.0) { H = H + 360.0; }
62756
63667
  return vec3f(lab.x, C, H);
62757
63668
  }
62758
63669
 
62759
63670
  fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
62760
- return vec3f(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));
63671
+ let h_rad = lch.z * (3.14159265359 / 180.0);
63672
+ return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
63673
+ }
63674
+
63675
+ fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
63676
+ return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
63677
+ }
63678
+
63679
+ fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
63680
+ return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
63681
+ }
63682
+
63683
+ fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
63684
+ let h = hsl.x;
63685
+ let s = hsl.y;
63686
+ let l = hsl.z;
63687
+ let c = (1.0 - abs(2.0 * l - 1.0)) * s;
63688
+ let h6 = h / 60.0;
63689
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
63690
+ var r: f32 = 0.0;
63691
+ var g: f32 = 0.0;
63692
+ var b: f32 = 0.0;
63693
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
63694
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
63695
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
63696
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
63697
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
63698
+ else { r = c; g = 0.0; b = x; }
63699
+ let m = l - c / 2.0;
63700
+ return vec3f(r + m, g + m, b + m);
63701
+ }
63702
+
63703
+ fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
63704
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
63705
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
63706
+ let l = (maxc + minc) / 2.0;
63707
+ let d = maxc - minc;
63708
+ if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
63709
+ let s = d / (1.0 - abs(2.0 * l - 1.0));
63710
+ var h: f32;
63711
+ if (maxc == rgb.x) {
63712
+ let v = (rgb.y - rgb.z) / d;
63713
+ h = v - 6.0 * floor(v / 6.0);
63714
+ } else if (maxc == rgb.y) {
63715
+ h = (rgb.z - rgb.x) / d + 2.0;
63716
+ } else {
63717
+ h = (rgb.x - rgb.y) / d + 4.0;
63718
+ }
63719
+ h = h * 60.0;
63720
+ if (h < 0.0) { h = h + 360.0; }
63721
+ return vec3f(h, s, l);
63722
+ }
63723
+
63724
+ fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
63725
+ let h = hsv.x;
63726
+ let s = hsv.y;
63727
+ let v = hsv.z;
63728
+ let c = v * s;
63729
+ let h6 = h / 60.0;
63730
+ let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
63731
+ var r: f32 = 0.0;
63732
+ var g: f32 = 0.0;
63733
+ var b: f32 = 0.0;
63734
+ if (h6 < 1.0) { r = c; g = x; b = 0.0; }
63735
+ else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
63736
+ else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
63737
+ else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
63738
+ else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
63739
+ else { r = c; g = 0.0; b = x; }
63740
+ let m = v - c;
63741
+ return vec3f(r + m, g + m, b + m);
63742
+ }
63743
+
63744
+ fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
63745
+ let maxc = max(max(rgb.x, rgb.y), rgb.z);
63746
+ let minc = min(min(rgb.x, rgb.y), rgb.z);
63747
+ let v = maxc;
63748
+ let d = maxc - minc;
63749
+ if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
63750
+ var s: f32 = 0.0;
63751
+ if (maxc >= 1e-6) { s = d / maxc; }
63752
+ var h: f32;
63753
+ if (maxc == rgb.x) {
63754
+ let q = (rgb.y - rgb.z) / d;
63755
+ h = q - 6.0 * floor(q / 6.0);
63756
+ } else if (maxc == rgb.y) {
63757
+ h = (rgb.z - rgb.x) / d + 2.0;
63758
+ } else {
63759
+ h = (rgb.x - rgb.y) / d + 4.0;
63760
+ }
63761
+ h = h * 60.0;
63762
+ if (h < 0.0) { h = h + 360.0; }
63763
+ return vec3f(h, s, v);
62761
63764
  }
62762
63765
 
62763
- fn _gpu_color_mix(rgb1: vec3f, rgb2: vec3f, t: f32) -> vec3f {
62764
- let lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
62765
- let lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
63766
+ fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
62766
63767
  let L = mix(lch1.x, lch2.x, t);
62767
63768
  let C = mix(lch1.y, lch2.y, t);
62768
- let PI = 3.14159265359;
62769
- var dh = lch2.z - lch1.z;
62770
- if (dh > PI) { dh -= 2.0 * PI; }
62771
- if (dh < -PI) { dh += 2.0 * PI; }
62772
- let H = lch1.z + dh * t;
62773
- return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(vec3f(L, C, H)));
63769
+ let a1 = lch1.y < 1e-6;
63770
+ let a2 = lch2.y < 1e-6;
63771
+ var H: f32;
63772
+ if (a1 && a2) {
63773
+ H = lch1.z;
63774
+ } else if (a1) {
63775
+ H = lch2.z;
63776
+ } else if (a2) {
63777
+ H = lch1.z;
63778
+ } else {
63779
+ var dh = lch2.z - lch1.z;
63780
+ if (dh > 180.0) { dh = dh - 360.0; }
63781
+ if (dh < -180.0) { dh = dh + 360.0; }
63782
+ H = lch1.z + dh * t;
63783
+ if (H < 0.0) { H = H + 360.0; }
63784
+ if (H >= 360.0) { H = H - 360.0; }
63785
+ }
63786
+ return vec3f(L, C, H);
62774
63787
  }
62775
63788
 
62776
- fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
63789
+ fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
63790
+ let bg = _gpu_oklch_to_srgb(lch_bg);
63791
+ let fg = _gpu_oklch_to_srgb(lch_fg);
62777
63792
  let bgR = _gpu_srgb_to_linear(bg.x);
62778
63793
  let bgG = _gpu_srgb_to_linear(bg.y);
62779
63794
  let bgB = _gpu_srgb_to_linear(bg.z);
@@ -63061,7 +64076,7 @@ var GPUShaderTarget = class {
63061
64076
  if (stmts.length === 0) return "";
63062
64077
  const last = stmts.length - 1;
63063
64078
  stmts[last] = `return ${stmts[last]}`;
63064
- return stmts.join(";\n");
64079
+ return stmts.join(";\n") + ";";
63065
64080
  },
63066
64081
  ...options
63067
64082
  };
@@ -63160,7 +64175,7 @@ var GLSLTarget = class extends GPUShaderTarget {
63160
64175
  if (body.includes("\n")) {
63161
64176
  const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
63162
64177
  return `${returnType} ${functionName}(${params}) {
63163
- ${indented};
64178
+ ${indented}
63164
64179
  }`;
63165
64180
  }
63166
64181
  return `${returnType} ${functionName}(${params}) {
@@ -63271,7 +64286,7 @@ var WGSLTarget = class extends GPUShaderTarget {
63271
64286
  return `fn ${functionName}(${params}) -> ${toWGSLType(
63272
64287
  returnType
63273
64288
  )} {
63274
- ${indented};
64289
+ ${indented}
63275
64290
  }`;
63276
64291
  }
63277
64292
  return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
@@ -67678,6 +68693,7 @@ var ComputeEngine = class _ComputeEngine {
67678
68693
  this.pushScope(void 0, "global");
67679
68694
  this._compilationTargets.registerDefaults();
67680
68695
  if (options?.latexSyntax) this._latexSyntax = options.latexSyntax;
68696
+ if (options?.latexOptions) this._latexOptions = { ...options.latexOptions };
67681
68697
  hidePrivateProperties(this);
67682
68698
  }
67683
68699
  toJSON() {
@@ -68338,6 +69354,29 @@ var ComputeEngine = class _ComputeEngine {
68338
69354
  );
68339
69355
  return this._latexSyntax;
68340
69356
  }
69357
+ /** @internal Engine-wide LaTeX parse/serialize options (e.g. decimalSeparator).
69358
+ * Merged into every `parse()` and `toLatex()` call between the LatexSyntax
69359
+ * instance defaults and any per-call overrides. */
69360
+ _latexOptions = {};
69361
+ /** Engine-wide LaTeX parse/serialize options.
69362
+ *
69363
+ * These options are merged into every `parse()` and `toLatex()` call.
69364
+ * Precedence (most-specific wins):
69365
+ * 1. LatexSyntax instance defaults (set at its construction)
69366
+ * 2. `ce.latexOptions` (this property)
69367
+ * 3. Per-call options passed to `ce.parse()` / `expr.toLatex()`
69368
+ *
69369
+ * Assigning replaces the whole bag. Use spread to merge:
69370
+ * ```ts
69371
+ * ce.latexOptions = { ...ce.latexOptions, decimalSeparator: '{,}' };
69372
+ * ```
69373
+ */
69374
+ get latexOptions() {
69375
+ return this._latexOptions;
69376
+ }
69377
+ set latexOptions(options) {
69378
+ this._latexOptions = { ...options };
69379
+ }
68341
69380
  parse(latex, options) {
68342
69381
  if (latex === null || latex === void 0) return null;
68343
69382
  if (typeof latex !== "string")
@@ -68345,7 +69384,6 @@ var ComputeEngine = class _ComputeEngine {
68345
69384
  const syntax = this._requireLatexSyntax();
68346
69385
  const { form, ...parseOpts } = options ?? {};
68347
69386
  const result = syntax.parse(latex, {
68348
- decimalSeparator: ".",
68349
69387
  getSymbolType: (id) => {
68350
69388
  const def = this.lookupDefinition(id);
68351
69389
  if (!def) return BoxedType.unknown;
@@ -68357,6 +69395,7 @@ var ComputeEngine = class _ComputeEngine {
68357
69395
  const def = this.lookupDefinition(id);
68358
69396
  return !!(isValueDef(def) && def.value.subscriptEvaluate);
68359
69397
  },
69398
+ ...this._latexOptions,
68360
69399
  ...parseOpts
68361
69400
  });
68362
69401
  if (result === null) return null;
@@ -68520,14 +69559,14 @@ var ComputeEngine = class _ComputeEngine {
68520
69559
  _setDefaultEngineFactory(() => new ComputeEngine());
68521
69560
 
68522
69561
  // src/compute-engine.ts
68523
- var version = "0.55.6";
69562
+ var version = "0.56.0";
68524
69563
  ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
68525
69564
  _setDefaultEngineFactory(
68526
69565
  () => new ComputeEngine({ latexSyntax: new LatexSyntax() })
68527
69566
  );
68528
69567
  globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
68529
69568
  ComputeEngine: ComputeEngine.prototype.constructor,
68530
- version: "0.55.6"
69569
+ version: "0.56.0"
68531
69570
  };
68532
69571
  export {
68533
69572
  DEFINITIONS_ALGEBRA as ALGEBRA_DICTIONARY,