@cortex-js/compute-engine 0.55.6 → 0.57.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.
- package/dist/compile.esm.js +1224 -179
- package/dist/compile.min.esm.js +290 -91
- package/dist/compile.min.umd.cjs +291 -92
- package/dist/compile.umd.cjs +1224 -179
- package/dist/compute-engine.esm.js +1973 -306
- package/dist/compute-engine.min.esm.js +301 -102
- package/dist/compute-engine.min.umd.cjs +301 -102
- package/dist/compute-engine.umd.cjs +1973 -306
- package/dist/core.esm.js +1972 -305
- package/dist/core.min.esm.js +300 -101
- package/dist/core.min.umd.cjs +300 -101
- package/dist/core.umd.cjs +1972 -305
- package/dist/interval.esm.js +360 -19
- package/dist/interval.min.esm.js +6 -6
- package/dist/interval.min.umd.cjs +6 -6
- package/dist/interval.umd.cjs +360 -19
- package/dist/latex-syntax.esm.js +427 -25
- package/dist/latex-syntax.min.esm.js +7 -7
- package/dist/latex-syntax.min.umd.cjs +7 -7
- package/dist/latex-syntax.umd.cjs +427 -25
- package/dist/math-json.esm.js +2 -2
- package/dist/math-json.min.esm.js +2 -2
- package/dist/math-json.min.umd.cjs +2 -2
- package/dist/math-json.umd.cjs +2 -2
- package/dist/numerics.esm.js +4 -2
- package/dist/numerics.min.esm.js +3 -3
- package/dist/numerics.min.umd.cjs +3 -3
- package/dist/numerics.umd.cjs +4 -2
- package/dist/types/big-decimal/big-decimal.d.ts +1 -1
- package/dist/types/big-decimal/index.d.ts +1 -1
- package/dist/types/big-decimal/transcendentals.d.ts +1 -1
- package/dist/types/big-decimal/utils.d.ts +1 -1
- package/dist/types/common/ansi-codes.d.ts +1 -1
- package/dist/types/common/configuration-change.d.ts +1 -1
- package/dist/types/common/fuzzy-string-match.d.ts +1 -1
- package/dist/types/common/grapheme-splitter.d.ts +1 -1
- package/dist/types/common/interruptible.d.ts +1 -1
- package/dist/types/common/one-of.d.ts +1 -1
- package/dist/types/common/signals.d.ts +1 -1
- package/dist/types/common/type/ast-nodes.d.ts +1 -1
- package/dist/types/common/type/boxed-type.d.ts +1 -1
- package/dist/types/common/type/lexer.d.ts +1 -1
- package/dist/types/common/type/parse.d.ts +1 -1
- package/dist/types/common/type/parser.d.ts +1 -1
- package/dist/types/common/type/primitive.d.ts +1 -1
- package/dist/types/common/type/reduce.d.ts +1 -1
- package/dist/types/common/type/serialize.d.ts +1 -1
- package/dist/types/common/type/subtype.d.ts +1 -1
- package/dist/types/common/type/type-builder.d.ts +1 -1
- package/dist/types/common/type/types.d.ts +2 -2
- package/dist/types/common/type/utils.d.ts +1 -1
- package/dist/types/common/utils.d.ts +1 -1
- package/dist/types/compile.d.ts +1 -1
- package/dist/types/compute-engine/assume.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +6 -1
- package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/rules.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
- package/dist/types/compute-engine/collection-utils.d.ts +1 -1
- package/dist/types/compute-engine/compilation/base-compiler.d.ts +55 -6
- package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
- package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
- package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/gpu-target.d.ts +15 -5
- package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/javascript-target.d.ts +25 -3
- package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/types.d.ts +1 -1
- package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
- package/dist/types/compute-engine/cost-function.d.ts +1 -1
- package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
- package/dist/types/compute-engine/engine-cache.d.ts +1 -1
- package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
- package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
- package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
- package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
- package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
- package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
- package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
- package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
- package/dist/types/compute-engine/engine-scope.d.ts +1 -1
- package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
- package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
- package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
- package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
- package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/free-functions.d.ts +1 -1
- package/dist/types/compute-engine/function-utils.d.ts +1 -1
- package/dist/types/compute-engine/global-types.d.ts +1 -1
- package/dist/types/compute-engine/index.d.ts +24 -3
- package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
- package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
- package/dist/types/compute-engine/interval/index.d.ts +1 -1
- package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
- package/dist/types/compute-engine/interval/types.d.ts +1 -1
- package/dist/types/compute-engine/interval/util.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +4 -3
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +10 -0
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +9 -1
- package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/types.d.ts +40 -1
- package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/calculus.d.ts +1 -1
- package/dist/types/compute-engine/library/collections.d.ts +5 -3
- package/dist/types/compute-engine/library/colors.d.ts +1 -1
- package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
- package/dist/types/compute-engine/library/complex.d.ts +1 -1
- package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
- package/dist/types/compute-engine/library/core.d.ts +1 -1
- package/dist/types/compute-engine/library/fractals.d.ts +1 -1
- package/dist/types/compute-engine/library/library.d.ts +1 -1
- package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
- package/dist/types/compute-engine/library/logic.d.ts +1 -1
- package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
- package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
- package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
- package/dist/types/compute-engine/library/sets.d.ts +1 -1
- package/dist/types/compute-engine/library/statistics.d.ts +1 -1
- package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
- package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/library/units.d.ts +1 -1
- package/dist/types/compute-engine/library/utils.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
- package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
- package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
- package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
- package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
- package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
- package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
- package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
- package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
- package/dist/types/compute-engine/numerics/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/oeis.d.ts +1 -1
- package/dist/types/compute-engine/sequence.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
- package/dist/types/compute-engine/types-definitions.d.ts +1 -1
- package/dist/types/compute-engine/types-engine.d.ts +23 -2
- package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-expression.d.ts +1 -1
- package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
- package/dist/types/compute-engine/types-serialization.d.ts +1 -1
- package/dist/types/compute-engine/types.d.ts +1 -1
- package/dist/types/compute-engine.d.ts +1 -2
- package/dist/types/core.d.ts +1 -1
- package/dist/types/interval.d.ts +1 -1
- package/dist/types/latex-syntax.d.ts +2 -2
- package/dist/types/math-json/symbols.d.ts +1 -1
- package/dist/types/math-json/types.d.ts +1 -1
- package/dist/types/math-json/utils.d.ts +1 -1
- package/dist/types/math-json.d.ts +2 -2
- package/dist/types/numerics.d.ts +1 -1
- package/package.json +2 -2
package/dist/core.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** ComputeEngineCore 0.
|
|
1
|
+
/** ComputeEngineCore 0.57.0 */
|
|
2
2
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngineCore = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var ComputeEngineCore = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -2287,6 +2287,7 @@ var ComputeEngineCore = (() => {
|
|
|
2287
2287
|
];
|
|
2288
2288
|
var VALUE_TYPES = [
|
|
2289
2289
|
"value",
|
|
2290
|
+
"color",
|
|
2290
2291
|
...COLLECTION_TYPES,
|
|
2291
2292
|
...SCALAR_TYPES
|
|
2292
2293
|
];
|
|
@@ -3986,6 +3987,7 @@ var ComputeEngineCore = (() => {
|
|
|
3986
3987
|
symbol: [],
|
|
3987
3988
|
boolean: [],
|
|
3988
3989
|
string: [],
|
|
3990
|
+
color: [],
|
|
3989
3991
|
expression: EXPRESSION_TYPES
|
|
3990
3992
|
};
|
|
3991
3993
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
@@ -7869,9 +7871,10 @@ var ComputeEngineCore = (() => {
|
|
|
7869
7871
|
if (!materialized.isLazyCollection) return materialized.latex;
|
|
7870
7872
|
}
|
|
7871
7873
|
const syntax = this.engine._requireLatexSyntax();
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
);
|
|
7874
|
+
const json = this.toMathJson({ prettify: true, fractionalDigits: "auto" });
|
|
7875
|
+
const latexOpts = this.engine.latexOptions;
|
|
7876
|
+
if (Object.keys(latexOpts).length === 0) return syntax.serialize(json);
|
|
7877
|
+
return syntax.serialize(json, { ...latexOpts });
|
|
7875
7878
|
}
|
|
7876
7879
|
/**
|
|
7877
7880
|
* Return a LaTeX representation of this expression with custom
|
|
@@ -7882,8 +7885,15 @@ var ComputeEngineCore = (() => {
|
|
|
7882
7885
|
*
|
|
7883
7886
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7884
7887
|
* (via `fractionalDigits: 'auto'`).
|
|
7888
|
+
*
|
|
7889
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
7890
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
7891
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
7892
|
+
* re-serialization if no verbatim is available.
|
|
7885
7893
|
*/
|
|
7886
7894
|
toLatex(options) {
|
|
7895
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
7896
|
+
return this.verbatimLatex;
|
|
7887
7897
|
if (this.isLazyCollection) {
|
|
7888
7898
|
const materialized = this.evaluate({
|
|
7889
7899
|
materialization: options?.materialization ?? true
|
|
@@ -7895,9 +7905,13 @@ var ComputeEngineCore = (() => {
|
|
|
7895
7905
|
fractionalDigits: "auto"
|
|
7896
7906
|
});
|
|
7897
7907
|
const syntax = this.engine._requireLatexSyntax();
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7908
|
+
const latexOpts = this.engine.latexOptions;
|
|
7909
|
+
const haveEngineOpts = Object.keys(latexOpts).length > 0;
|
|
7910
|
+
const haveCallOpts = options && Object.keys(options).length > 0;
|
|
7911
|
+
if (!haveEngineOpts && !haveCallOpts) return syntax.serialize(json);
|
|
7912
|
+
if (!haveEngineOpts) return syntax.serialize(json, options);
|
|
7913
|
+
if (!haveCallOpts) return syntax.serialize(json, { ...latexOpts });
|
|
7914
|
+
return syntax.serialize(json, { ...latexOpts, ...options });
|
|
7901
7915
|
}
|
|
7902
7916
|
/** Called by `JSON.stringify()` when serializing to json.
|
|
7903
7917
|
*
|
|
@@ -7941,11 +7955,13 @@ var ComputeEngineCore = (() => {
|
|
|
7941
7955
|
"number",
|
|
7942
7956
|
"dictionary"
|
|
7943
7957
|
];
|
|
7944
|
-
}
|
|
7945
|
-
if (Array.isArray(options.shorthands))
|
|
7958
|
+
} else if (Array.isArray(options.shorthands)) {
|
|
7946
7959
|
defaultOptions.shorthands = options.shorthands;
|
|
7960
|
+
}
|
|
7947
7961
|
if (typeof options.metadata === "string" && options.metadata === "all" || options.metadata?.includes("all")) {
|
|
7948
7962
|
defaultOptions.metadata = ["latex", "wikidata"];
|
|
7963
|
+
} else if (Array.isArray(options.metadata)) {
|
|
7964
|
+
defaultOptions.metadata = options.metadata;
|
|
7949
7965
|
}
|
|
7950
7966
|
if (options.fractionalDigits === "auto")
|
|
7951
7967
|
defaultOptions.fractionalDigits = -this.engine.precision;
|
|
@@ -10020,6 +10036,64 @@ var ComputeEngineCore = (() => {
|
|
|
10020
10036
|
}
|
|
10021
10037
|
|
|
10022
10038
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
10039
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
10040
|
+
x: "First",
|
|
10041
|
+
y: "Second",
|
|
10042
|
+
z: "Third",
|
|
10043
|
+
real: "Real",
|
|
10044
|
+
re: "Real",
|
|
10045
|
+
imag: "Imaginary",
|
|
10046
|
+
im: "Imaginary",
|
|
10047
|
+
count: "Length",
|
|
10048
|
+
total: "Sum",
|
|
10049
|
+
max: "Max",
|
|
10050
|
+
min: "Min"
|
|
10051
|
+
};
|
|
10052
|
+
function memberHead(name) {
|
|
10053
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10054
|
+
}
|
|
10055
|
+
function parseComponentAccess(parser, lhs) {
|
|
10056
|
+
parser.skipVisualSpace();
|
|
10057
|
+
if (parser.match("\\operatorname")) {
|
|
10058
|
+
const name = parser.parseStringGroup();
|
|
10059
|
+
if (name === null) return null;
|
|
10060
|
+
const head = memberHead(name.trim());
|
|
10061
|
+
if (head === null) return null;
|
|
10062
|
+
return [head, lhs];
|
|
10063
|
+
}
|
|
10064
|
+
const tok = parser.peek;
|
|
10065
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10066
|
+
const bare = tok.slice(1);
|
|
10067
|
+
const head = memberHead(bare);
|
|
10068
|
+
if (head !== null) {
|
|
10069
|
+
parser.nextToken();
|
|
10070
|
+
return [head, lhs];
|
|
10071
|
+
}
|
|
10072
|
+
return null;
|
|
10073
|
+
}
|
|
10074
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10075
|
+
const head = memberHead(tok);
|
|
10076
|
+
if (head === null) return null;
|
|
10077
|
+
parser.nextToken();
|
|
10078
|
+
return [head, lhs];
|
|
10079
|
+
}
|
|
10080
|
+
return null;
|
|
10081
|
+
}
|
|
10082
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10083
|
+
parser.addBoundary(close);
|
|
10084
|
+
parser.skipVisualSpace();
|
|
10085
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10086
|
+
if (cond === null) {
|
|
10087
|
+
parser.removeBoundary();
|
|
10088
|
+
return null;
|
|
10089
|
+
}
|
|
10090
|
+
parser.skipVisualSpace();
|
|
10091
|
+
if (!parser.matchBoundary()) {
|
|
10092
|
+
parser.removeBoundary();
|
|
10093
|
+
return null;
|
|
10094
|
+
}
|
|
10095
|
+
return ["When", lhs, cond];
|
|
10096
|
+
}
|
|
10023
10097
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
10024
10098
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
10025
10099
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10491,6 +10565,15 @@ var ComputeEngineCore = (() => {
|
|
|
10491
10565
|
}
|
|
10492
10566
|
},
|
|
10493
10567
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10568
|
+
// Component-access postfix: expr.member (C3)
|
|
10569
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10570
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10571
|
+
{
|
|
10572
|
+
kind: "postfix",
|
|
10573
|
+
precedence: 850,
|
|
10574
|
+
latexTrigger: ["."],
|
|
10575
|
+
parse: parseComponentAccess
|
|
10576
|
+
},
|
|
10494
10577
|
{
|
|
10495
10578
|
name: "At",
|
|
10496
10579
|
kind: "postfix",
|
|
@@ -10511,6 +10594,29 @@ var ComputeEngineCore = (() => {
|
|
|
10511
10594
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10512
10595
|
parse: parseAt("\\right", "\\rbrack")
|
|
10513
10596
|
},
|
|
10597
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10598
|
+
{
|
|
10599
|
+
name: "When",
|
|
10600
|
+
kind: "postfix",
|
|
10601
|
+
precedence: 800,
|
|
10602
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10603
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10604
|
+
serialize: (serializer, expr2) => {
|
|
10605
|
+
const e = operand(expr2, 1);
|
|
10606
|
+
const cond = operand(expr2, 2);
|
|
10607
|
+
if (!e || !cond) return "";
|
|
10608
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10609
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10610
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10611
|
+
}
|
|
10612
|
+
},
|
|
10613
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10614
|
+
{
|
|
10615
|
+
kind: "postfix",
|
|
10616
|
+
precedence: 800,
|
|
10617
|
+
latexTrigger: ["\\{"],
|
|
10618
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10619
|
+
},
|
|
10514
10620
|
{
|
|
10515
10621
|
kind: "postfix",
|
|
10516
10622
|
latexTrigger: ["_"],
|
|
@@ -10593,6 +10699,29 @@ var ComputeEngineCore = (() => {
|
|
|
10593
10699
|
return "";
|
|
10594
10700
|
}
|
|
10595
10701
|
},
|
|
10702
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10703
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10704
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10705
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10706
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10707
|
+
{
|
|
10708
|
+
latexTrigger: [".", ".", "."],
|
|
10709
|
+
kind: "infix",
|
|
10710
|
+
precedence: 800,
|
|
10711
|
+
parse: parseRange
|
|
10712
|
+
},
|
|
10713
|
+
{
|
|
10714
|
+
latexTrigger: ["\\ldots"],
|
|
10715
|
+
kind: "infix",
|
|
10716
|
+
precedence: 800,
|
|
10717
|
+
parse: parseRange
|
|
10718
|
+
},
|
|
10719
|
+
{
|
|
10720
|
+
latexTrigger: ["\\dots"],
|
|
10721
|
+
kind: "infix",
|
|
10722
|
+
precedence: 800,
|
|
10723
|
+
parse: parseRange
|
|
10724
|
+
},
|
|
10596
10725
|
{
|
|
10597
10726
|
latexTrigger: [";"],
|
|
10598
10727
|
kind: "infix",
|
|
@@ -10777,13 +10906,24 @@ var ComputeEngineCore = (() => {
|
|
|
10777
10906
|
const args = operands(expr2);
|
|
10778
10907
|
if (!args || args.length < 2) return "";
|
|
10779
10908
|
const body = args[0];
|
|
10780
|
-
const
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10909
|
+
const elements = args.slice(1);
|
|
10910
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
10911
|
+
if (!allElements) {
|
|
10912
|
+
return joinLatex([
|
|
10913
|
+
"\\operatorname{Loop}(",
|
|
10914
|
+
serializer.serialize(body),
|
|
10915
|
+
", ",
|
|
10916
|
+
serializer.serialize(elements[0]),
|
|
10917
|
+
")"
|
|
10918
|
+
]);
|
|
10919
|
+
}
|
|
10920
|
+
if (elements.length === 1) {
|
|
10921
|
+
const elem = elements[0];
|
|
10922
|
+
const index = operand(elem, 1);
|
|
10923
|
+
const coll = operand(elem, 2);
|
|
10924
|
+
if (operator(coll) === "Range") {
|
|
10925
|
+
const lo = operand(coll, 1);
|
|
10926
|
+
const hi = operand(coll, 2);
|
|
10787
10927
|
return joinLatex([
|
|
10788
10928
|
"\\text{for }",
|
|
10789
10929
|
serializer.serialize(index),
|
|
@@ -10795,13 +10935,27 @@ var ComputeEngineCore = (() => {
|
|
|
10795
10935
|
serializer.serialize(body)
|
|
10796
10936
|
]);
|
|
10797
10937
|
}
|
|
10938
|
+
return joinLatex([
|
|
10939
|
+
serializer.serialize(body),
|
|
10940
|
+
" \\operatorname{for} ",
|
|
10941
|
+
serializer.serialize(index),
|
|
10942
|
+
" = ",
|
|
10943
|
+
serializer.serialize(coll)
|
|
10944
|
+
]);
|
|
10798
10945
|
}
|
|
10946
|
+
const bindings = elements.map((elem) => {
|
|
10947
|
+
const name = operand(elem, 1);
|
|
10948
|
+
const coll = operand(elem, 2);
|
|
10949
|
+
return joinLatex([
|
|
10950
|
+
serializer.serialize(name),
|
|
10951
|
+
" = ",
|
|
10952
|
+
serializer.serialize(coll)
|
|
10953
|
+
]);
|
|
10954
|
+
}).join(", ");
|
|
10799
10955
|
return joinLatex([
|
|
10800
|
-
"\\operatorname{Loop}(",
|
|
10801
10956
|
serializer.serialize(body),
|
|
10802
|
-
"
|
|
10803
|
-
|
|
10804
|
-
")"
|
|
10957
|
+
" \\operatorname{for} ",
|
|
10958
|
+
bindings
|
|
10805
10959
|
]);
|
|
10806
10960
|
}
|
|
10807
10961
|
},
|
|
@@ -10834,6 +10988,18 @@ var ComputeEngineCore = (() => {
|
|
|
10834
10988
|
precedence: 245,
|
|
10835
10989
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10836
10990
|
},
|
|
10991
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
10992
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
10993
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
10994
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
10995
|
+
// bindings can be comma-separated below us.
|
|
10996
|
+
{
|
|
10997
|
+
symbolTrigger: "for",
|
|
10998
|
+
kind: "infix",
|
|
10999
|
+
associativity: "none",
|
|
11000
|
+
precedence: 19,
|
|
11001
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
11002
|
+
},
|
|
10837
11003
|
// \operatorname{break}
|
|
10838
11004
|
{
|
|
10839
11005
|
symbolTrigger: "break",
|
|
@@ -11038,7 +11204,10 @@ var ComputeEngineCore = (() => {
|
|
|
11038
11204
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
11039
11205
|
parser.addBoundary([")"]);
|
|
11040
11206
|
const expr2 = parser.parseExpression(until);
|
|
11041
|
-
if (!parser.matchBoundary())
|
|
11207
|
+
if (!parser.matchBoundary()) {
|
|
11208
|
+
parser.removeBoundary();
|
|
11209
|
+
return null;
|
|
11210
|
+
}
|
|
11042
11211
|
if (!parser.match("<}>")) return null;
|
|
11043
11212
|
return ["Derivative", lhs, expr2];
|
|
11044
11213
|
}
|
|
@@ -11479,7 +11648,12 @@ var ComputeEngineCore = (() => {
|
|
|
11479
11648
|
if (isEmptySequence(body)) return ["List"];
|
|
11480
11649
|
const h = operator(body);
|
|
11481
11650
|
if (h === "Range" || h === "Linspace") return body;
|
|
11482
|
-
if (h === "Sequence")
|
|
11651
|
+
if (h === "Sequence") {
|
|
11652
|
+
const elems = operands(body);
|
|
11653
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11654
|
+
if (inferred) return inferred;
|
|
11655
|
+
return ["List", ...elems];
|
|
11656
|
+
}
|
|
11483
11657
|
if (h === "Delimiter") {
|
|
11484
11658
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11485
11659
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11492,12 +11666,37 @@ var ComputeEngineCore = (() => {
|
|
|
11492
11666
|
}
|
|
11493
11667
|
if (delim === "," || delim === ".,.") {
|
|
11494
11668
|
body = operand(body, 1);
|
|
11495
|
-
if (operator(body) === "Sequence")
|
|
11669
|
+
if (operator(body) === "Sequence") {
|
|
11670
|
+
const elems = operands(body);
|
|
11671
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11672
|
+
if (inferred) return inferred;
|
|
11673
|
+
return ["List", ...elems];
|
|
11674
|
+
}
|
|
11496
11675
|
return ["List", body ?? "Nothing"];
|
|
11497
11676
|
}
|
|
11498
11677
|
}
|
|
11499
11678
|
return ["List", body];
|
|
11500
11679
|
}
|
|
11680
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11681
|
+
if (elems.length < 4) return null;
|
|
11682
|
+
const penultimate = elems[elems.length - 2];
|
|
11683
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11684
|
+
const samples = elems.slice(0, -2);
|
|
11685
|
+
const endExpr = elems[elems.length - 1];
|
|
11686
|
+
if (samples.length < 2) return null;
|
|
11687
|
+
const sampleNums = samples.map(machineValue);
|
|
11688
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11689
|
+
const nums = sampleNums;
|
|
11690
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11691
|
+
const tol = parser.options.tolerance;
|
|
11692
|
+
if (Math.abs(step) < tol)
|
|
11693
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11694
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11695
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11696
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11697
|
+
}
|
|
11698
|
+
return ["Range", nums[0], endExpr, step];
|
|
11699
|
+
}
|
|
11501
11700
|
function serializeList(serializer, expr2) {
|
|
11502
11701
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11503
11702
|
const op = operator(x);
|
|
@@ -11749,6 +11948,35 @@ var ComputeEngineCore = (() => {
|
|
|
11749
11948
|
["Element", index, ["Range", lower, upper]]
|
|
11750
11949
|
];
|
|
11751
11950
|
}
|
|
11951
|
+
function parseForComprehension(parser, lhs, until) {
|
|
11952
|
+
const bindingTerminator = {
|
|
11953
|
+
minPrec: 21,
|
|
11954
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
11955
|
+
condition: (p) => {
|
|
11956
|
+
if (until?.condition?.(p)) return true;
|
|
11957
|
+
const saved = p.index;
|
|
11958
|
+
p.skipVisualSpace();
|
|
11959
|
+
const isComma = p.peek === ",";
|
|
11960
|
+
p.index = saved;
|
|
11961
|
+
return isComma;
|
|
11962
|
+
}
|
|
11963
|
+
};
|
|
11964
|
+
const elements = [];
|
|
11965
|
+
do {
|
|
11966
|
+
parser.skipVisualSpace();
|
|
11967
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
11968
|
+
if (binding === null) break;
|
|
11969
|
+
const op = operator(binding);
|
|
11970
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
11971
|
+
const name = operand(binding, 1);
|
|
11972
|
+
const list = operand(binding, 2);
|
|
11973
|
+
if (!name || !list) return null;
|
|
11974
|
+
elements.push(["Element", name, list]);
|
|
11975
|
+
parser.skipVisualSpace();
|
|
11976
|
+
} while (parser.match(","));
|
|
11977
|
+
if (elements.length === 0) return null;
|
|
11978
|
+
return ["Loop", lhs, ...elements];
|
|
11979
|
+
}
|
|
11752
11980
|
function parseWhereExpression(parser, lhs, until) {
|
|
11753
11981
|
const bindingTerminator = {
|
|
11754
11982
|
minPrec: 21,
|
|
@@ -13667,6 +13895,8 @@ var ComputeEngineCore = (() => {
|
|
|
13667
13895
|
precedence: DIVISION_PRECEDENCE,
|
|
13668
13896
|
parse: "Mod"
|
|
13669
13897
|
},
|
|
13898
|
+
// Function-style alias: `\operatorname{mod}(a, b)`
|
|
13899
|
+
{ latexTrigger: "\\operatorname{mod}", parse: "Mod" },
|
|
13670
13900
|
{
|
|
13671
13901
|
latexTrigger: "\\pmod",
|
|
13672
13902
|
kind: "prefix",
|
|
@@ -13907,6 +14137,13 @@ var ComputeEngineCore = (() => {
|
|
|
13907
14137
|
const rhs = serializer.wrap(operand(expr2, 2), ADDITION_PRECEDENCE + 3);
|
|
13908
14138
|
return joinLatex([lhs, "-", rhs]);
|
|
13909
14139
|
}
|
|
14140
|
+
},
|
|
14141
|
+
// Euclidean distance between two points (tuples of numbers).
|
|
14142
|
+
{
|
|
14143
|
+
name: "Distance",
|
|
14144
|
+
latexTrigger: ["\\operatorname{distance}"],
|
|
14145
|
+
kind: "function",
|
|
14146
|
+
serialize: (serializer, expr2) => "\\operatorname{distance}" + serializer.wrapArguments(expr2)
|
|
13910
14147
|
}
|
|
13911
14148
|
];
|
|
13912
14149
|
function getIndexAssignment(expr2, upper) {
|
|
@@ -15331,7 +15568,9 @@ var ComputeEngineCore = (() => {
|
|
|
15331
15568
|
if (!expr2 || !symbol(expr2)) return null;
|
|
15332
15569
|
return ["Mean", expr2];
|
|
15333
15570
|
}
|
|
15334
|
-
}
|
|
15571
|
+
},
|
|
15572
|
+
// Function-style alias: `\operatorname{var}(...)`
|
|
15573
|
+
{ latexTrigger: "\\operatorname{var}", parse: "Variance" }
|
|
15335
15574
|
];
|
|
15336
15575
|
|
|
15337
15576
|
// src/compute-engine/numerics/unit-data.ts
|
|
@@ -16432,7 +16671,7 @@ var ComputeEngineCore = (() => {
|
|
|
16432
16671
|
36: "\\qquad"
|
|
16433
16672
|
}[v] ?? "";
|
|
16434
16673
|
}
|
|
16435
|
-
}
|
|
16674
|
+
},
|
|
16436
16675
|
// if (
|
|
16437
16676
|
// [
|
|
16438
16677
|
// '\\!',
|
|
@@ -16456,6 +16695,121 @@ var ComputeEngineCore = (() => {
|
|
|
16456
16695
|
// name: '',
|
|
16457
16696
|
// trigger: '\\check',
|
|
16458
16697
|
// },
|
|
16698
|
+
// ---------------------------------------------------------------------------
|
|
16699
|
+
// Function-style aliases for collection / random operators that some
|
|
16700
|
+
// notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
|
|
16701
|
+
// The capitalized library entries already exist; these are pure parse
|
|
16702
|
+
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16703
|
+
// ---------------------------------------------------------------------------
|
|
16704
|
+
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16705
|
+
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16706
|
+
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16707
|
+
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16708
|
+
// ---------------------------------------------------------------------------
|
|
16709
|
+
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16710
|
+
// can branch on the operator name; CE itself doesn't render them. The
|
|
16711
|
+
// library entries (with no evaluator) live in `library/core.ts`.
|
|
16712
|
+
// ---------------------------------------------------------------------------
|
|
16713
|
+
{
|
|
16714
|
+
name: "Triangle",
|
|
16715
|
+
latexTrigger: ["\\operatorname{triangle}"],
|
|
16716
|
+
kind: "function",
|
|
16717
|
+
serialize: (serializer, expr2) => "\\operatorname{triangle}" + serializer.wrapArguments(expr2)
|
|
16718
|
+
},
|
|
16719
|
+
// Desmos's geometric `vector(p1, p2)` — a directed segment between two
|
|
16720
|
+
// points. Routed to a dedicated head (not the existing column-vector
|
|
16721
|
+
// `Vector`, which has a narrower `(number+) -> vector` signature).
|
|
16722
|
+
{
|
|
16723
|
+
name: "GeometricVector",
|
|
16724
|
+
latexTrigger: ["\\operatorname{vector}"],
|
|
16725
|
+
kind: "function",
|
|
16726
|
+
serialize: (serializer, expr2) => "\\operatorname{vector}" + serializer.wrapArguments(expr2)
|
|
16727
|
+
},
|
|
16728
|
+
{
|
|
16729
|
+
name: "Sphere",
|
|
16730
|
+
latexTrigger: ["\\operatorname{sphere}"],
|
|
16731
|
+
kind: "function",
|
|
16732
|
+
serialize: (serializer, expr2) => "\\operatorname{sphere}" + serializer.wrapArguments(expr2)
|
|
16733
|
+
},
|
|
16734
|
+
{
|
|
16735
|
+
name: "Segment",
|
|
16736
|
+
latexTrigger: ["\\operatorname{segment}"],
|
|
16737
|
+
kind: "function",
|
|
16738
|
+
serialize: (serializer, expr2) => "\\operatorname{segment}" + serializer.wrapArguments(expr2)
|
|
16739
|
+
}
|
|
16740
|
+
];
|
|
16741
|
+
|
|
16742
|
+
// src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
|
|
16743
|
+
var DEFINITIONS_COLORS = [
|
|
16744
|
+
// Color constructors (one per colorspace, preserves space on evaluation)
|
|
16745
|
+
{
|
|
16746
|
+
name: "Rgb",
|
|
16747
|
+
latexTrigger: ["\\operatorname{rgb}"],
|
|
16748
|
+
kind: "function",
|
|
16749
|
+
serialize: (serializer, expr2) => "\\operatorname{rgb}" + serializer.wrapArguments(expr2)
|
|
16750
|
+
},
|
|
16751
|
+
{
|
|
16752
|
+
name: "Hsv",
|
|
16753
|
+
latexTrigger: ["\\operatorname{hsv}"],
|
|
16754
|
+
kind: "function",
|
|
16755
|
+
serialize: (serializer, expr2) => "\\operatorname{hsv}" + serializer.wrapArguments(expr2)
|
|
16756
|
+
},
|
|
16757
|
+
{
|
|
16758
|
+
name: "Hsl",
|
|
16759
|
+
latexTrigger: ["\\operatorname{hsl}"],
|
|
16760
|
+
kind: "function",
|
|
16761
|
+
serialize: (serializer, expr2) => "\\operatorname{hsl}" + serializer.wrapArguments(expr2)
|
|
16762
|
+
},
|
|
16763
|
+
{
|
|
16764
|
+
name: "Oklab",
|
|
16765
|
+
latexTrigger: ["\\operatorname{oklab}"],
|
|
16766
|
+
kind: "function",
|
|
16767
|
+
serialize: (serializer, expr2) => "\\operatorname{oklab}" + serializer.wrapArguments(expr2)
|
|
16768
|
+
},
|
|
16769
|
+
{
|
|
16770
|
+
name: "Oklch",
|
|
16771
|
+
latexTrigger: ["\\operatorname{oklch}"],
|
|
16772
|
+
kind: "function",
|
|
16773
|
+
serialize: (serializer, expr2) => "\\operatorname{oklch}" + serializer.wrapArguments(expr2)
|
|
16774
|
+
},
|
|
16775
|
+
// Conversion functions (color → color in the named space)
|
|
16776
|
+
{
|
|
16777
|
+
name: "AsRgb",
|
|
16778
|
+
latexTrigger: ["\\operatorname{asRgb}"],
|
|
16779
|
+
kind: "function",
|
|
16780
|
+
serialize: (serializer, expr2) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr2)
|
|
16781
|
+
},
|
|
16782
|
+
{
|
|
16783
|
+
name: "AsHsv",
|
|
16784
|
+
latexTrigger: ["\\operatorname{asHsv}"],
|
|
16785
|
+
kind: "function",
|
|
16786
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr2)
|
|
16787
|
+
},
|
|
16788
|
+
{
|
|
16789
|
+
name: "AsHsl",
|
|
16790
|
+
latexTrigger: ["\\operatorname{asHsl}"],
|
|
16791
|
+
kind: "function",
|
|
16792
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr2)
|
|
16793
|
+
},
|
|
16794
|
+
{
|
|
16795
|
+
name: "AsOklab",
|
|
16796
|
+
latexTrigger: ["\\operatorname{asOklab}"],
|
|
16797
|
+
kind: "function",
|
|
16798
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr2)
|
|
16799
|
+
},
|
|
16800
|
+
{
|
|
16801
|
+
name: "AsOklch",
|
|
16802
|
+
latexTrigger: ["\\operatorname{asOklch}"],
|
|
16803
|
+
kind: "function",
|
|
16804
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr2)
|
|
16805
|
+
},
|
|
16806
|
+
// Perceptual difference (returns a scalar in [0, ~1])
|
|
16807
|
+
{
|
|
16808
|
+
name: "ColorDelta",
|
|
16809
|
+
latexTrigger: ["\\operatorname{colorDelta}"],
|
|
16810
|
+
kind: "function",
|
|
16811
|
+
serialize: (serializer, expr2) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr2)
|
|
16812
|
+
}
|
|
16459
16813
|
];
|
|
16460
16814
|
|
|
16461
16815
|
// src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
|
|
@@ -16486,7 +16840,8 @@ var ComputeEngineCore = (() => {
|
|
|
16486
16840
|
...DEFINITIONS_STATISTICS,
|
|
16487
16841
|
...DEFINITIONS_UNITS,
|
|
16488
16842
|
...DEFINITIONS_OTHERS,
|
|
16489
|
-
...DEFINITIONS_PHYSICS
|
|
16843
|
+
...DEFINITIONS_PHYSICS,
|
|
16844
|
+
...DEFINITIONS_COLORS
|
|
16490
16845
|
];
|
|
16491
16846
|
|
|
16492
16847
|
// src/math-json/symbols.ts
|
|
@@ -16651,6 +17006,17 @@ var ComputeEngineCore = (() => {
|
|
|
16651
17006
|
} else if (Array.isArray(openTrigger) && openTrigger.length > 0) {
|
|
16652
17007
|
openTokens.push(openTrigger[0]);
|
|
16653
17008
|
}
|
|
17009
|
+
const closeTrigger = indexedEntry.closeTrigger;
|
|
17010
|
+
const closeTokens = /* @__PURE__ */ new Set();
|
|
17011
|
+
if (typeof closeTrigger === "string") {
|
|
17012
|
+
const variants = DELIMITER_SHORTHAND[closeTrigger];
|
|
17013
|
+
if (variants) for (const v of variants) closeTokens.add(v);
|
|
17014
|
+
else closeTokens.add(closeTrigger);
|
|
17015
|
+
if (closeTrigger === "||") closeTokens.add("|");
|
|
17016
|
+
} else if (Array.isArray(closeTrigger) && closeTrigger.length > 0) {
|
|
17017
|
+
closeTokens.add(closeTrigger[0]);
|
|
17018
|
+
}
|
|
17019
|
+
indexedEntry.closeTokens = closeTokens;
|
|
16654
17020
|
for (const token of openTokens) {
|
|
16655
17021
|
const existing = result.matchfixByOpen.get(token);
|
|
16656
17022
|
if (existing) {
|
|
@@ -16842,11 +17208,7 @@ var ComputeEngineCore = (() => {
|
|
|
16842
17208
|
if (style === "scaled")
|
|
16843
17209
|
return joinLatex([`\\left${openDelim}`, inner, `\\right${closeDelim}`]);
|
|
16844
17210
|
if (style === "big")
|
|
16845
|
-
return joinLatex([
|
|
16846
|
-
`\\Bigl${openDelim}`,
|
|
16847
|
-
inner,
|
|
16848
|
-
`\\Bigr${closeDelim}`
|
|
16849
|
-
]);
|
|
17211
|
+
return joinLatex([`\\Bigl${openDelim}`, inner, `\\Bigr${closeDelim}`]);
|
|
16850
17212
|
return joinLatex([openDelim, inner, closeDelim]);
|
|
16851
17213
|
};
|
|
16852
17214
|
}
|
|
@@ -18197,7 +18559,7 @@ var ComputeEngineCore = (() => {
|
|
|
18197
18559
|
}
|
|
18198
18560
|
if (this.match("\\hskip") || this.match("\\kern")) {
|
|
18199
18561
|
this.skipSpace();
|
|
18200
|
-
this.match("-")
|
|
18562
|
+
if (!this.match("-")) this.match("+");
|
|
18201
18563
|
while (/^[\d.]$/.test(this.peek)) this.nextToken();
|
|
18202
18564
|
for (const unit of [
|
|
18203
18565
|
"pt",
|
|
@@ -18711,6 +19073,19 @@ var ComputeEngineCore = (() => {
|
|
|
18711
19073
|
}
|
|
18712
19074
|
for (const def of defs) {
|
|
18713
19075
|
this.index = start;
|
|
19076
|
+
if (def.closeTokens.size > 0) {
|
|
19077
|
+
let found = false;
|
|
19078
|
+
const tokens = this._tokens;
|
|
19079
|
+
for (let i = start; i < tokens.length; i++) {
|
|
19080
|
+
if (def.closeTokens.has(tokens[i])) {
|
|
19081
|
+
found = true;
|
|
19082
|
+
break;
|
|
19083
|
+
}
|
|
19084
|
+
}
|
|
19085
|
+
if (!found) continue;
|
|
19086
|
+
}
|
|
19087
|
+
if (typeof def.openTrigger === "string" && def.openTrigger === "." && !OPEN_DELIMITER_PREFIX[currentToken])
|
|
19088
|
+
continue;
|
|
18714
19089
|
const matched = this.matchDelimiter(def.openTrigger, def.closeTrigger);
|
|
18715
19090
|
if (!matched) continue;
|
|
18716
19091
|
const bodyStart = this.index;
|
|
@@ -19373,6 +19748,19 @@ var ComputeEngineCore = (() => {
|
|
|
19373
19748
|
} while (postfix !== null);
|
|
19374
19749
|
}
|
|
19375
19750
|
if (result !== null) result = this.parseSupsub(result);
|
|
19751
|
+
if (result !== null) {
|
|
19752
|
+
let postfix = null;
|
|
19753
|
+
let index = this.index;
|
|
19754
|
+
do {
|
|
19755
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
19756
|
+
result = postfix ?? result;
|
|
19757
|
+
if (this.index === index && postfix !== null) {
|
|
19758
|
+
console.assert(this.index !== index, "No token consumed");
|
|
19759
|
+
break;
|
|
19760
|
+
}
|
|
19761
|
+
index = this.index;
|
|
19762
|
+
} while (postfix !== null);
|
|
19763
|
+
}
|
|
19376
19764
|
if (result === null) {
|
|
19377
19765
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19378
19766
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -19881,6 +20269,28 @@ var ComputeEngineCore = (() => {
|
|
|
19881
20269
|
}
|
|
19882
20270
|
|
|
19883
20271
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20272
|
+
var DOT_NOTATION_MAP = {
|
|
20273
|
+
First: ".x",
|
|
20274
|
+
Second: ".y",
|
|
20275
|
+
Third: ".z",
|
|
20276
|
+
Real: ".\\operatorname{real}",
|
|
20277
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20278
|
+
Length: ".\\operatorname{count}",
|
|
20279
|
+
Sum: ".\\operatorname{total}",
|
|
20280
|
+
Max: ".\\max",
|
|
20281
|
+
Min: ".\\min"
|
|
20282
|
+
};
|
|
20283
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20284
|
+
if (!serializer.options.dotNotation) return null;
|
|
20285
|
+
const ops = operands(expr2);
|
|
20286
|
+
if (!ops || ops.length !== 1) return null;
|
|
20287
|
+
const head = operator(expr2);
|
|
20288
|
+
if (!head) return null;
|
|
20289
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20290
|
+
if (suffix === void 0) return null;
|
|
20291
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20292
|
+
return `${lhs}${suffix}`;
|
|
20293
|
+
}
|
|
19884
20294
|
var ACCENT_MODIFIERS = {
|
|
19885
20295
|
deg: (s) => `${s}\\degree`,
|
|
19886
20296
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -19924,6 +20334,7 @@ var ComputeEngineCore = (() => {
|
|
|
19924
20334
|
constructor(dictionary, options) {
|
|
19925
20335
|
this.dictionary = dictionary;
|
|
19926
20336
|
this.options = {
|
|
20337
|
+
dotNotation: false,
|
|
19927
20338
|
dmsFormat: false,
|
|
19928
20339
|
angleNormalization: "none",
|
|
19929
20340
|
...options
|
|
@@ -20022,6 +20433,8 @@ var ComputeEngineCore = (() => {
|
|
|
20022
20433
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
20023
20434
|
}
|
|
20024
20435
|
serializeFunction(expr2, def) {
|
|
20436
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20437
|
+
if (dotResult !== null) return dotResult;
|
|
20025
20438
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
20026
20439
|
const h = operator(expr2);
|
|
20027
20440
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20264,6 +20677,8 @@ var ComputeEngineCore = (() => {
|
|
|
20264
20677
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20265
20678
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20266
20679
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20680
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20681
|
+
tolerance: 1e-7,
|
|
20267
20682
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20268
20683
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20269
20684
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20296,6 +20711,7 @@ var ComputeEngineCore = (() => {
|
|
|
20296
20711
|
invisiblePlus: "",
|
|
20297
20712
|
multiply: "\\times",
|
|
20298
20713
|
missingSymbol: "\\blacksquare",
|
|
20714
|
+
dotNotation: false,
|
|
20299
20715
|
dmsFormat: false,
|
|
20300
20716
|
angleNormalization: "none",
|
|
20301
20717
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -27266,7 +27682,11 @@ ${lines.join("\n")}`;
|
|
|
27266
27682
|
//
|
|
27267
27683
|
Range: {
|
|
27268
27684
|
complexity: 8200,
|
|
27269
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27685
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27686
|
+
type: (ops) => {
|
|
27687
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27688
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27689
|
+
},
|
|
27270
27690
|
canonical: (ops, { engine: ce }) => {
|
|
27271
27691
|
if (ops.length === 0) return null;
|
|
27272
27692
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27290,19 +27710,26 @@ ${lines.join("\n")}`;
|
|
|
27290
27710
|
const [lower, upper, step] = range(expr2);
|
|
27291
27711
|
if (step === 0) return 0;
|
|
27292
27712
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27293
|
-
return
|
|
27713
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27294
27714
|
},
|
|
27295
27715
|
contains: (expr2, target) => {
|
|
27296
|
-
if (!target.type.matches("integer")) return false;
|
|
27297
27716
|
const t = target.re;
|
|
27717
|
+
if (!isFinite(t)) return false;
|
|
27298
27718
|
const [lower, upper, step] = range(expr2);
|
|
27299
27719
|
if (step === 0) return false;
|
|
27300
|
-
if (step > 0)
|
|
27301
|
-
|
|
27720
|
+
if (step > 0) {
|
|
27721
|
+
if (t < lower || t > upper) return false;
|
|
27722
|
+
} else {
|
|
27723
|
+
if (t > lower || t < upper) return false;
|
|
27724
|
+
}
|
|
27725
|
+
const k = (t - lower) / step;
|
|
27726
|
+
const tol = expr2.engine.tolerance;
|
|
27727
|
+
const kRounded = Math.round(k);
|
|
27728
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27302
27729
|
},
|
|
27303
27730
|
iterator: (expr2) => {
|
|
27304
27731
|
const [lower, upper, step] = range(expr2);
|
|
27305
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
27732
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27306
27733
|
let index = 1;
|
|
27307
27734
|
return {
|
|
27308
27735
|
next: () => {
|
|
@@ -27320,7 +27747,9 @@ ${lines.join("\n")}`;
|
|
|
27320
27747
|
at: (expr2, index) => {
|
|
27321
27748
|
if (typeof index !== "number") return void 0;
|
|
27322
27749
|
const [lower, upper, step] = range(expr2);
|
|
27323
|
-
if (
|
|
27750
|
+
if (step === 0) return void 0;
|
|
27751
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27752
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27324
27753
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27325
27754
|
},
|
|
27326
27755
|
indexWhere: void 0,
|
|
@@ -27345,7 +27774,13 @@ ${lines.join("\n")}`;
|
|
|
27345
27774
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27346
27775
|
return lower >= upper ? "positive" : "negative";
|
|
27347
27776
|
},
|
|
27348
|
-
elttype: (
|
|
27777
|
+
elttype: (expr2) => {
|
|
27778
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
27779
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
27780
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
27781
|
+
}
|
|
27782
|
+
return "finite_integer";
|
|
27783
|
+
}
|
|
27349
27784
|
}
|
|
27350
27785
|
},
|
|
27351
27786
|
Interval: {
|
|
@@ -27943,15 +28378,45 @@ ${lines.join("\n")}`;
|
|
|
27943
28378
|
},
|
|
27944
28379
|
First: {
|
|
27945
28380
|
complexity: 8200,
|
|
27946
|
-
signature: "(
|
|
28381
|
+
signature: "(any) -> any",
|
|
27947
28382
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27948
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28383
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28384
|
+
if (!xs.isCollection)
|
|
28385
|
+
return ce.error([
|
|
28386
|
+
"incompatible-type",
|
|
28387
|
+
`'collection'`,
|
|
28388
|
+
xs.type.toString()
|
|
28389
|
+
]);
|
|
28390
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28391
|
+
}
|
|
27949
28392
|
},
|
|
27950
28393
|
Second: {
|
|
27951
28394
|
complexity: 8200,
|
|
27952
|
-
signature: "(
|
|
28395
|
+
signature: "(any) -> any",
|
|
27953
28396
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27954
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28397
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28398
|
+
if (!xs.isCollection)
|
|
28399
|
+
return ce.error([
|
|
28400
|
+
"incompatible-type",
|
|
28401
|
+
`'collection'`,
|
|
28402
|
+
xs.type.toString()
|
|
28403
|
+
]);
|
|
28404
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28405
|
+
}
|
|
28406
|
+
},
|
|
28407
|
+
Third: {
|
|
28408
|
+
complexity: 8200,
|
|
28409
|
+
signature: "(any) -> any",
|
|
28410
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28411
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28412
|
+
if (!xs.isCollection)
|
|
28413
|
+
return ce.error([
|
|
28414
|
+
"incompatible-type",
|
|
28415
|
+
`'collection'`,
|
|
28416
|
+
xs.type.toString()
|
|
28417
|
+
]);
|
|
28418
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28419
|
+
}
|
|
27955
28420
|
},
|
|
27956
28421
|
Last: {
|
|
27957
28422
|
complexity: 8200,
|
|
@@ -28930,17 +29395,14 @@ ${lines.join("\n")}`;
|
|
|
28930
29395
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
28931
29396
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
28932
29397
|
let op1 = expr2.op1.re;
|
|
28933
|
-
if (!isFinite(op1)) op1 = 1;
|
|
28934
|
-
else op1 = Math.round(op1);
|
|
29398
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
28935
29399
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
28936
29400
|
let op2 = expr2.op2.re;
|
|
28937
29401
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
28938
|
-
|
|
28939
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29402
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
28940
29403
|
let op3 = expr2.op3.re;
|
|
28941
|
-
if (!isFinite(op3)) op3 = 1;
|
|
28942
|
-
|
|
28943
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29404
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29405
|
+
return [op1, op2, op3];
|
|
28944
29406
|
}
|
|
28945
29407
|
function rangeLast(r) {
|
|
28946
29408
|
const [lower, upper, step] = r;
|
|
@@ -32273,6 +32735,29 @@ ${lines.join("\n")}`;
|
|
|
32273
32735
|
signature: "(value*) -> number | list",
|
|
32274
32736
|
evaluate: (xs, { engine }) => evaluateMinMax(engine, xs, "Infimum")
|
|
32275
32737
|
},
|
|
32738
|
+
Distance: {
|
|
32739
|
+
description: "Euclidean distance between two points (tuples of numbers).",
|
|
32740
|
+
complexity: 6e3,
|
|
32741
|
+
signature: "(tuple, tuple) -> number",
|
|
32742
|
+
evaluate: ([a, b], { engine: ce }) => {
|
|
32743
|
+
if (!isFunction2(a) || !isFunction2(b))
|
|
32744
|
+
return ce.error("incompatible-type");
|
|
32745
|
+
if (a.operator !== "Tuple" || b.operator !== "Tuple")
|
|
32746
|
+
return ce.error("incompatible-type");
|
|
32747
|
+
if (a.ops.length !== b.ops.length || a.ops.length === 0)
|
|
32748
|
+
return ce.error("incompatible-type");
|
|
32749
|
+
let sumSq = 0;
|
|
32750
|
+
for (let i = 0; i < a.ops.length; i++) {
|
|
32751
|
+
const ai = a.ops[i].re;
|
|
32752
|
+
const bi = b.ops[i].re;
|
|
32753
|
+
if (!Number.isFinite(ai) || !Number.isFinite(bi))
|
|
32754
|
+
return ce.error("expected-value");
|
|
32755
|
+
const d = ai - bi;
|
|
32756
|
+
sumSq += d * d;
|
|
32757
|
+
}
|
|
32758
|
+
return ce.number(Math.sqrt(sumSq));
|
|
32759
|
+
}
|
|
32760
|
+
},
|
|
32276
32761
|
Product: {
|
|
32277
32762
|
description: "`Product(f, a, b)` computes the product of `f` from `a` to `b`",
|
|
32278
32763
|
wikidata: "Q901718",
|
|
@@ -32805,16 +33290,11 @@ ${lines.join("\n")}`;
|
|
|
32805
33290
|
);
|
|
32806
33291
|
let condFn;
|
|
32807
33292
|
if (typeof condition === "string") {
|
|
32808
|
-
const
|
|
32809
|
-
|
|
32810
|
-
const
|
|
32811
|
-
|
|
32812
|
-
|
|
32813
|
-
condFn = (x, _ce) => {
|
|
32814
|
-
const evaluated = condPattern.subs(x).evaluate();
|
|
32815
|
-
return isSymbol2(evaluated, "True");
|
|
32816
|
-
};
|
|
32817
|
-
}
|
|
33293
|
+
const condPattern = ce.parse(condition) ?? ce.expr("Nothing");
|
|
33294
|
+
condFn = (x, _ce) => {
|
|
33295
|
+
const evaluated = condPattern.subs(x).evaluate();
|
|
33296
|
+
return isSymbol2(evaluated, "True");
|
|
33297
|
+
};
|
|
32818
33298
|
} else {
|
|
32819
33299
|
if (condition !== void 0 && typeof condition !== "function")
|
|
32820
33300
|
throw new Error(
|
|
@@ -32916,6 +33396,15 @@ ${e.message}
|
|
|
32916
33396
|
function applyRule(rule, expr2, substitution, options) {
|
|
32917
33397
|
if (!rule) return null;
|
|
32918
33398
|
let canonical2 = options?.canonical ?? (expr2.isCanonical || expr2.isStructural);
|
|
33399
|
+
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
33400
|
+
const because = id ?? "";
|
|
33401
|
+
const ce = expr2.engine;
|
|
33402
|
+
if (canonical2 && match2) {
|
|
33403
|
+
const awc = getWildcards(match2);
|
|
33404
|
+
const canonicalMatch = match2.canonical;
|
|
33405
|
+
const bwc = getWildcards(canonicalMatch);
|
|
33406
|
+
if (!awc.every((x) => bwc.includes(x))) return null;
|
|
33407
|
+
}
|
|
32919
33408
|
let operandsMatched = false;
|
|
32920
33409
|
if (isFunction2(expr2) && options?.recursive) {
|
|
32921
33410
|
const newOps = expr2.ops.map((op) => {
|
|
@@ -32927,20 +33416,11 @@ ${e.message}
|
|
|
32927
33416
|
if (operandsMatched) {
|
|
32928
33417
|
if (!canonical2 && options?.canonical === void 0 && newOps.every((x) => x.isCanonical))
|
|
32929
33418
|
canonical2 = true;
|
|
32930
|
-
expr2 =
|
|
33419
|
+
expr2 = ce.function(expr2.operator, newOps, {
|
|
32931
33420
|
form: canonical2 ? "canonical" : "raw"
|
|
32932
33421
|
});
|
|
32933
33422
|
}
|
|
32934
33423
|
}
|
|
32935
|
-
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
32936
|
-
const because = id ?? "";
|
|
32937
|
-
if (canonical2 && match2) {
|
|
32938
|
-
const awc = getWildcards(match2);
|
|
32939
|
-
const canonicalMatch = match2.canonical;
|
|
32940
|
-
const bwc = getWildcards(canonicalMatch);
|
|
32941
|
-
if (!awc.every((x) => bwc.includes(x)))
|
|
32942
|
-
return operandsMatched ? { value: expr2, because } : null;
|
|
32943
|
-
}
|
|
32944
33424
|
const useVariations = rule.useVariations ?? options?.useVariations ?? false;
|
|
32945
33425
|
const matchPermutations = options?.matchPermutations ?? true;
|
|
32946
33426
|
onBeforeMatch?.(rule, expr2);
|
|
@@ -32959,7 +33439,7 @@ ${e.message}
|
|
|
32959
33439
|
...sub2
|
|
32960
33440
|
};
|
|
32961
33441
|
try {
|
|
32962
|
-
if (!condition(conditionSub,
|
|
33442
|
+
if (!condition(conditionSub, ce))
|
|
32963
33443
|
return operandsMatched ? { value: expr2, because } : null;
|
|
32964
33444
|
} catch (e) {
|
|
32965
33445
|
console.error(
|
|
@@ -32974,7 +33454,8 @@ ${e.message}
|
|
|
32974
33454
|
if (!canonical2 && options?.canonical === void 0 && replace2 instanceof _BoxedExpression && replace2.isCanonical)
|
|
32975
33455
|
canonical2 = true;
|
|
32976
33456
|
const result = typeof replace2 === "function" ? replace2(expr2, sub2) : replace2.subs(sub2, { canonical: canonical2 });
|
|
32977
|
-
if (!result)
|
|
33457
|
+
if (!result)
|
|
33458
|
+
return operandsMatched ? { value: canonical2 ? expr2.canonical : expr2, because } : null;
|
|
32978
33459
|
onMatch?.(rule, expr2, result);
|
|
32979
33460
|
if (isRuleStep(result))
|
|
32980
33461
|
return canonical2 ? { ...result, value: result.value.canonical } : result;
|
|
@@ -38548,6 +39029,40 @@ ${e.message}
|
|
|
38548
39029
|
else h = ((r - g) / d + 4) / 6;
|
|
38549
39030
|
return { h: h * 360, s, l };
|
|
38550
39031
|
}
|
|
39032
|
+
function hsvToRgb(h, s, v) {
|
|
39033
|
+
h = (h % 360 + 360) % 360;
|
|
39034
|
+
s = Math.max(0, Math.min(1, s));
|
|
39035
|
+
v = Math.max(0, Math.min(1, v));
|
|
39036
|
+
const c = v * s;
|
|
39037
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
39038
|
+
const m = v - c;
|
|
39039
|
+
let r = 0, g = 0, b = 0;
|
|
39040
|
+
if (h < 60) [r, g, b] = [c, x, 0];
|
|
39041
|
+
else if (h < 120) [r, g, b] = [x, c, 0];
|
|
39042
|
+
else if (h < 180) [r, g, b] = [0, c, x];
|
|
39043
|
+
else if (h < 240) [r, g, b] = [0, x, c];
|
|
39044
|
+
else if (h < 300) [r, g, b] = [x, 0, c];
|
|
39045
|
+
else [r, g, b] = [c, 0, x];
|
|
39046
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
39047
|
+
}
|
|
39048
|
+
function rgbToHsv(r, g, b) {
|
|
39049
|
+
r /= 255;
|
|
39050
|
+
g /= 255;
|
|
39051
|
+
b /= 255;
|
|
39052
|
+
const max2 = Math.max(r, g, b);
|
|
39053
|
+
const min2 = Math.min(r, g, b);
|
|
39054
|
+
const d = max2 - min2;
|
|
39055
|
+
let h = 0;
|
|
39056
|
+
if (d > 0) {
|
|
39057
|
+
if (max2 === r) h = (g - b) / d % 6;
|
|
39058
|
+
else if (max2 === g) h = (b - r) / d + 2;
|
|
39059
|
+
else h = (r - g) / d + 4;
|
|
39060
|
+
h *= 60;
|
|
39061
|
+
if (h < 0) h += 360;
|
|
39062
|
+
}
|
|
39063
|
+
const s = max2 === 0 ? 0 : d / max2;
|
|
39064
|
+
return { h, s, v: max2 };
|
|
39065
|
+
}
|
|
38551
39066
|
function parseHexColor(s) {
|
|
38552
39067
|
const hex = s.startsWith("#") ? s.substring(1) : s;
|
|
38553
39068
|
let r, g, b;
|
|
@@ -38572,6 +39087,12 @@ ${e.message}
|
|
|
38572
39087
|
if (alpha !== void 0) result.alpha = alpha;
|
|
38573
39088
|
return result;
|
|
38574
39089
|
}
|
|
39090
|
+
function asOklch(color) {
|
|
39091
|
+
if (typeof color === "string") return rgbToOklch(parseHexColor(color));
|
|
39092
|
+
if ("C" in color) return color;
|
|
39093
|
+
if ("a" in color && "b" in color) return oklabToOklch(color);
|
|
39094
|
+
return rgbToOklch(color);
|
|
39095
|
+
}
|
|
38575
39096
|
function asRgb(color) {
|
|
38576
39097
|
if (typeof color === "number") {
|
|
38577
39098
|
return {
|
|
@@ -39003,6 +39524,13 @@ ${e.message}
|
|
|
39003
39524
|
};
|
|
39004
39525
|
function parseColor(s, darkMode) {
|
|
39005
39526
|
const str = s.trim().toLowerCase();
|
|
39527
|
+
const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
|
|
39528
|
+
if (opacityMatch) {
|
|
39529
|
+
const base = parseColor(opacityMatch[1].trim(), darkMode);
|
|
39530
|
+
const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
|
|
39531
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
39532
|
+
return base & 4294967040 | alpha;
|
|
39533
|
+
}
|
|
39006
39534
|
if (str.startsWith("#")) {
|
|
39007
39535
|
const hex = str.substring(1);
|
|
39008
39536
|
let r, g, b, a = 255;
|
|
@@ -39135,14 +39663,6 @@ ${e.message}
|
|
|
39135
39663
|
console.warn(`parseColor: unrecognized color "${s}"`);
|
|
39136
39664
|
return 0;
|
|
39137
39665
|
}
|
|
39138
|
-
function parseColorToRgb01(s, darkMode) {
|
|
39139
|
-
const color = parseColor(s, darkMode);
|
|
39140
|
-
return [
|
|
39141
|
-
(color >>> 24 & 255) / 255,
|
|
39142
|
-
(color >>> 16 & 255) / 255,
|
|
39143
|
-
(color >>> 8 & 255) / 255
|
|
39144
|
-
];
|
|
39145
|
-
}
|
|
39146
39666
|
function apca(bgColor, fgColor) {
|
|
39147
39667
|
const bgRgb = asRgb(bgColor);
|
|
39148
39668
|
const fgRgb = asRgb(fgColor);
|
|
@@ -39201,6 +39721,12 @@ ${e.message}
|
|
|
39201
39721
|
const contrast2 = Math.abs(apca(fg2, bg));
|
|
39202
39722
|
return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
|
|
39203
39723
|
}
|
|
39724
|
+
function oklabDeltaE(a, b) {
|
|
39725
|
+
const dL = a.L - b.L;
|
|
39726
|
+
const da = a.a - b.a;
|
|
39727
|
+
const db = a.b - b.b;
|
|
39728
|
+
return Math.sqrt(dL * dL + da * da + db * db);
|
|
39729
|
+
}
|
|
39204
39730
|
function lerpOklch(c1, c2, f) {
|
|
39205
39731
|
const L = c1.L + (c2.L - c1.L) * f;
|
|
39206
39732
|
const C = c1.C + (c2.C - c1.C) * f;
|
|
@@ -41962,14 +42488,30 @@ ${e.message}
|
|
|
41962
42488
|
};
|
|
41963
42489
|
|
|
41964
42490
|
// src/compute-engine/library/colors.ts
|
|
41965
|
-
function
|
|
41966
|
-
|
|
41967
|
-
|
|
41968
|
-
|
|
41969
|
-
|
|
41970
|
-
|
|
41971
|
-
|
|
41972
|
-
|
|
42491
|
+
function normalizeAlpha(a) {
|
|
42492
|
+
if (a === void 0) return void 0;
|
|
42493
|
+
if (!Number.isFinite(a)) return void 0;
|
|
42494
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
42495
|
+
return a;
|
|
42496
|
+
}
|
|
42497
|
+
function normalizeColorHead(ce, expr2) {
|
|
42498
|
+
if (!isFunction2(expr2) || !expr2.ops || expr2.ops.length < 4) return expr2;
|
|
42499
|
+
const alphaExpr = expr2.ops[3];
|
|
42500
|
+
if (!isNumber(alphaExpr)) return expr2;
|
|
42501
|
+
if (normalizeAlpha(alphaExpr.re) === void 0) {
|
|
42502
|
+
return ce.function(expr2.operator, [expr2.ops[0], expr2.ops[1], expr2.ops[2]]);
|
|
42503
|
+
}
|
|
42504
|
+
return expr2;
|
|
42505
|
+
}
|
|
42506
|
+
function colorNumberToOklch(ce, color) {
|
|
42507
|
+
const r = color >>> 24 & 255;
|
|
42508
|
+
const g = color >>> 16 & 255;
|
|
42509
|
+
const b = color >>> 8 & 255;
|
|
42510
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42511
|
+
const c = rgbToOklch({ r, g, b });
|
|
42512
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42513
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42514
|
+
return ce.function("Oklch", args);
|
|
41973
42515
|
}
|
|
41974
42516
|
var ALL_PALETTES = {
|
|
41975
42517
|
...SEQUENTIAL_PALETTES,
|
|
@@ -41980,45 +42522,139 @@ ${e.message}
|
|
|
41980
42522
|
t = Math.max(0, Math.min(1, t));
|
|
41981
42523
|
const n = palette.length;
|
|
41982
42524
|
if (n === 0) return ce.error("expected-value");
|
|
41983
|
-
if (n === 1) return
|
|
42525
|
+
if (n === 1) return colorNumberToOklch(ce, parseColor(palette[0]));
|
|
41984
42526
|
const pos = t * (n - 1);
|
|
41985
42527
|
const i = Math.floor(pos);
|
|
41986
42528
|
const frac = pos - i;
|
|
41987
|
-
if (i >= n - 1) return
|
|
41988
|
-
if (frac < 1e-9) return
|
|
41989
|
-
|
|
41990
|
-
|
|
41991
|
-
|
|
41992
|
-
|
|
41993
|
-
|
|
42529
|
+
if (i >= n - 1) return colorNumberToOklch(ce, parseColor(palette[n - 1]));
|
|
42530
|
+
if (frac < 1e-9) return colorNumberToOklch(ce, parseColor(palette[i]));
|
|
42531
|
+
return oklchToExpr(
|
|
42532
|
+
ce,
|
|
42533
|
+
asOklch(interpolateOklch(palette[i], palette[i + 1], frac))
|
|
42534
|
+
);
|
|
42535
|
+
}
|
|
42536
|
+
var COLOR_OPERATORS = /* @__PURE__ */ new Set(["Rgb", "Hsv", "Hsl", "Oklab", "Oklch"]);
|
|
42537
|
+
function readColorExpr(arg) {
|
|
42538
|
+
if (!isFunction2(arg)) return null;
|
|
42539
|
+
if (!COLOR_OPERATORS.has(arg.operator)) return null;
|
|
42540
|
+
if (!arg.ops || arg.ops.length < 3) return null;
|
|
42541
|
+
const c0 = arg.ops[0].re;
|
|
42542
|
+
const c1 = arg.ops[1].re;
|
|
42543
|
+
const c2 = arg.ops[2].re;
|
|
42544
|
+
if (!Number.isFinite(c0) || !Number.isFinite(c1) || !Number.isFinite(c2))
|
|
42545
|
+
return null;
|
|
42546
|
+
const alpha = arg.ops.length >= 4 ? normalizeAlpha(arg.ops[3].re) : void 0;
|
|
42547
|
+
return { space: arg.operator, c0, c1, c2, alpha };
|
|
42548
|
+
}
|
|
42549
|
+
function colorExprToRgb(arg) {
|
|
42550
|
+
const c = readColorExpr(arg);
|
|
42551
|
+
if (!c) return null;
|
|
42552
|
+
const withAlpha = (rgb) => c.alpha !== void 0 ? { ...rgb, alpha: c.alpha } : rgb;
|
|
42553
|
+
switch (c.space) {
|
|
42554
|
+
case "Rgb":
|
|
42555
|
+
return withAlpha({ r: c.c0 * 255, g: c.c1 * 255, b: c.c2 * 255 });
|
|
42556
|
+
case "Hsv":
|
|
42557
|
+
return withAlpha(hsvToRgb(c.c0, c.c1, c.c2));
|
|
42558
|
+
case "Hsl":
|
|
42559
|
+
return withAlpha(hslToRgb(c.c0, c.c1, c.c2));
|
|
42560
|
+
case "Oklab":
|
|
42561
|
+
return withAlpha(oklabToRgb({ L: c.c0, a: c.c1, b: c.c2 }));
|
|
42562
|
+
case "Oklch":
|
|
42563
|
+
return withAlpha(oklchToRgb({ L: c.c0, C: c.c1, H: c.c2 }));
|
|
42564
|
+
}
|
|
42565
|
+
return null;
|
|
42566
|
+
}
|
|
42567
|
+
function colorExprToOklch(arg) {
|
|
42568
|
+
const c = readColorExpr(arg);
|
|
42569
|
+
if (!c) return null;
|
|
42570
|
+
switch (c.space) {
|
|
42571
|
+
case "Oklch":
|
|
42572
|
+
return asOklch({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
42573
|
+
case "Oklab":
|
|
42574
|
+
return asOklch({ L: c.c0, a: c.c1, b: c.c2, alpha: c.alpha });
|
|
42575
|
+
case "Rgb":
|
|
42576
|
+
return asOklch({
|
|
42577
|
+
r: c.c0 * 255,
|
|
42578
|
+
g: c.c1 * 255,
|
|
42579
|
+
b: c.c2 * 255,
|
|
42580
|
+
alpha: c.alpha
|
|
42581
|
+
});
|
|
42582
|
+
case "Hsv": {
|
|
42583
|
+
const rgb = hsvToRgb(c.c0, c.c1, c.c2);
|
|
42584
|
+
return asOklch({ ...rgb, alpha: c.alpha });
|
|
42585
|
+
}
|
|
42586
|
+
case "Hsl": {
|
|
42587
|
+
const rgb = hslToRgb(c.c0, c.c1, c.c2);
|
|
42588
|
+
return asOklch({ r: rgb.r, g: rgb.g, b: rgb.b, alpha: c.alpha });
|
|
42589
|
+
}
|
|
42590
|
+
}
|
|
42591
|
+
return null;
|
|
42592
|
+
}
|
|
42593
|
+
function toOklch(ce, arg) {
|
|
42594
|
+
const direct = colorExprToOklch(arg);
|
|
42595
|
+
if (direct) return direct;
|
|
42596
|
+
const rgb = extractRgb(ce, arg);
|
|
42597
|
+
return rgb ? asOklch(rgb) : null;
|
|
42598
|
+
}
|
|
42599
|
+
function lerpOklchColor(a, b, t) {
|
|
42600
|
+
const L = a.L + (b.L - a.L) * t;
|
|
42601
|
+
const C = a.C + (b.C - a.C) * t;
|
|
42602
|
+
const aAchromatic = a.C < 1e-6;
|
|
42603
|
+
const bAchromatic = b.C < 1e-6;
|
|
42604
|
+
let H;
|
|
42605
|
+
if (aAchromatic && bAchromatic) H = a.H;
|
|
42606
|
+
else if (aAchromatic) H = b.H;
|
|
42607
|
+
else if (bAchromatic) H = a.H;
|
|
42608
|
+
else {
|
|
42609
|
+
let dH = b.H - a.H;
|
|
42610
|
+
if (dH > 180) dH -= 360;
|
|
42611
|
+
if (dH < -180) dH += 360;
|
|
42612
|
+
H = a.H + dH * t;
|
|
42613
|
+
if (H < 0) H += 360;
|
|
42614
|
+
if (H >= 360) H -= 360;
|
|
42615
|
+
}
|
|
42616
|
+
const alphaA = a.alpha ?? 1;
|
|
42617
|
+
const alphaB = b.alpha ?? 1;
|
|
42618
|
+
return { L, C, H, alpha: normalizeAlpha(alphaA + (alphaB - alphaA) * t) };
|
|
42619
|
+
}
|
|
42620
|
+
function oklchToExpr(ce, c) {
|
|
42621
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42622
|
+
if (c.alpha !== void 0) args.push(ce.number(c.alpha));
|
|
42623
|
+
return ce.function("Oklch", args);
|
|
41994
42624
|
}
|
|
41995
42625
|
function extractRgb(ce, arg) {
|
|
41996
42626
|
if (isString(arg)) {
|
|
41997
42627
|
const s = arg.string;
|
|
41998
42628
|
if (!s) return void 0;
|
|
41999
42629
|
const color = parseColor(s);
|
|
42000
|
-
|
|
42630
|
+
const rgb = {
|
|
42001
42631
|
r: color >>> 24 & 255,
|
|
42002
42632
|
g: color >>> 16 & 255,
|
|
42003
|
-
b: color >>> 8 & 255
|
|
42004
|
-
alpha: (color & 255) / 255
|
|
42633
|
+
b: color >>> 8 & 255
|
|
42005
42634
|
};
|
|
42635
|
+
const alpha = normalizeAlpha((color & 255) / 255);
|
|
42636
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42637
|
+
return rgb;
|
|
42006
42638
|
}
|
|
42639
|
+
const fromTyped = colorExprToRgb(arg);
|
|
42640
|
+
if (fromTyped) return fromTyped;
|
|
42007
42641
|
if (arg.operator === "Tuple" && arg.ops && arg.ops.length >= 3) {
|
|
42008
42642
|
const rgb = {
|
|
42009
42643
|
r: arg.ops[0].re * 255,
|
|
42010
42644
|
g: arg.ops[1].re * 255,
|
|
42011
42645
|
b: arg.ops[2].re * 255
|
|
42012
42646
|
};
|
|
42013
|
-
if (arg.ops.length >= 4)
|
|
42647
|
+
if (arg.ops.length >= 4) {
|
|
42648
|
+
const alpha = normalizeAlpha(arg.ops[3].re);
|
|
42649
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42650
|
+
}
|
|
42014
42651
|
return rgb;
|
|
42015
42652
|
}
|
|
42016
42653
|
return void 0;
|
|
42017
42654
|
}
|
|
42018
42655
|
function componentsTuple(ce, components, alpha) {
|
|
42019
42656
|
const args = components.map((v) => ce.number(v));
|
|
42020
|
-
if (alpha !== void 0
|
|
42021
|
-
args.push(ce.number(alpha));
|
|
42657
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
42022
42658
|
return ce.tuple(...args);
|
|
42023
42659
|
}
|
|
42024
42660
|
function rgbToHex(rgb) {
|
|
@@ -42026,7 +42662,7 @@ ${e.message}
|
|
|
42026
42662
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
42027
42663
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
42028
42664
|
const hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
42029
|
-
if (rgb.alpha !== void 0
|
|
42665
|
+
if (rgb.alpha !== void 0) {
|
|
42030
42666
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
42031
42667
|
return hex + a.toString(16).padStart(2, "0");
|
|
42032
42668
|
}
|
|
@@ -42034,22 +42670,29 @@ ${e.message}
|
|
|
42034
42670
|
}
|
|
42035
42671
|
var COLORS_LIBRARY = {
|
|
42036
42672
|
Color: {
|
|
42037
|
-
description: "
|
|
42673
|
+
description: "Parse a CSS-style color string to an Oklch color",
|
|
42038
42674
|
complexity: 8e3,
|
|
42039
|
-
signature: "(string) ->
|
|
42675
|
+
signature: "(string) -> color",
|
|
42040
42676
|
evaluate: (ops, { engine: ce }) => {
|
|
42041
42677
|
const input = isString(ops[0]) ? ops[0].string : void 0;
|
|
42042
42678
|
if (!input) return ce.error("incompatible-type");
|
|
42043
42679
|
const color = parseColor(input);
|
|
42044
42680
|
if (color === 0 && input.trim().toLowerCase() !== "transparent")
|
|
42045
42681
|
return ce.error("incompatible-type");
|
|
42046
|
-
|
|
42682
|
+
const r = color >>> 24 & 255;
|
|
42683
|
+
const g = color >>> 16 & 255;
|
|
42684
|
+
const b = color >>> 8 & 255;
|
|
42685
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42686
|
+
const c = rgbToOklch({ r, g, b });
|
|
42687
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42688
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42689
|
+
return ce.function("Oklch", args);
|
|
42047
42690
|
}
|
|
42048
42691
|
},
|
|
42049
42692
|
ColorToString: {
|
|
42050
42693
|
description: "Convert a color to a string in the specified format",
|
|
42051
42694
|
complexity: 8e3,
|
|
42052
|
-
signature: "(
|
|
42695
|
+
signature: "(color | string | tuple, string?) -> string",
|
|
42053
42696
|
evaluate: (ops, { engine: ce }) => {
|
|
42054
42697
|
const rgb = extractRgb(ce, ops[0]);
|
|
42055
42698
|
if (!rgb) return ce.error("incompatible-type");
|
|
@@ -42061,7 +42704,7 @@ ${e.message}
|
|
|
42061
42704
|
const r = Math.round(rgb.r);
|
|
42062
42705
|
const g = Math.round(rgb.g);
|
|
42063
42706
|
const b = Math.round(rgb.b);
|
|
42064
|
-
if (rgb.alpha !== void 0
|
|
42707
|
+
if (rgb.alpha !== void 0)
|
|
42065
42708
|
return ce.string(`rgb(${r} ${g} ${b} / ${rgb.alpha})`);
|
|
42066
42709
|
return ce.string(`rgb(${r} ${g} ${b})`);
|
|
42067
42710
|
}
|
|
@@ -42070,17 +42713,17 @@ ${e.message}
|
|
|
42070
42713
|
const h = Math.round(hsl.h * 10) / 10;
|
|
42071
42714
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
42072
42715
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
42073
|
-
if (rgb.alpha !== void 0
|
|
42716
|
+
if (rgb.alpha !== void 0)
|
|
42074
42717
|
return ce.string(`hsl(${h} ${s}% ${l}% / ${rgb.alpha})`);
|
|
42075
42718
|
return ce.string(`hsl(${h} ${s}% ${l}%)`);
|
|
42076
42719
|
}
|
|
42077
42720
|
case "oklch": {
|
|
42078
|
-
const c =
|
|
42721
|
+
const c = colorExprToOklch(ops[0]) ?? asOklch(rgb);
|
|
42079
42722
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
42080
42723
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
42081
42724
|
const H = Math.round(c.H * 10) / 10;
|
|
42082
|
-
if (
|
|
42083
|
-
return ce.string(`oklch(${L} ${C} ${H} / ${
|
|
42725
|
+
if (c.alpha !== void 0)
|
|
42726
|
+
return ce.string(`oklch(${L} ${C} ${H} / ${c.alpha})`);
|
|
42084
42727
|
return ce.string(`oklch(${L} ${C} ${H})`);
|
|
42085
42728
|
}
|
|
42086
42729
|
default:
|
|
@@ -42091,60 +42734,44 @@ ${e.message}
|
|
|
42091
42734
|
ColorMix: {
|
|
42092
42735
|
description: "Mix two colors in OKLCh space",
|
|
42093
42736
|
complexity: 8e3,
|
|
42094
|
-
signature: "(
|
|
42737
|
+
signature: "(color | string | tuple, color | string | tuple, number?) -> color",
|
|
42095
42738
|
evaluate: (ops, { engine: ce }) => {
|
|
42096
|
-
const rgb1 = extractRgb(ce, ops[0]);
|
|
42097
|
-
const rgb2 = extractRgb(ce, ops[1]);
|
|
42098
|
-
if (!rgb1 || !rgb2) return ce.error("incompatible-type");
|
|
42099
42739
|
let ratio = 0.5;
|
|
42100
42740
|
if (ops.length >= 3 && ops[2] !== void 0) {
|
|
42101
42741
|
ratio = ops[2].re;
|
|
42102
42742
|
if (!Number.isFinite(ratio)) return ce.error("expected-value");
|
|
42103
42743
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
42104
42744
|
}
|
|
42105
|
-
const
|
|
42106
|
-
const
|
|
42107
|
-
|
|
42108
|
-
|
|
42109
|
-
const g = mixed.g / 255;
|
|
42110
|
-
const b = mixed.b / 255;
|
|
42111
|
-
const a1 = rgb1.alpha ?? 1;
|
|
42112
|
-
const a2 = rgb2.alpha ?? 1;
|
|
42113
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
42114
|
-
if (Math.abs(alpha - 1) > 1e-4)
|
|
42115
|
-
return ce.tuple(
|
|
42116
|
-
ce.number(r),
|
|
42117
|
-
ce.number(g),
|
|
42118
|
-
ce.number(b),
|
|
42119
|
-
ce.number(alpha)
|
|
42120
|
-
);
|
|
42121
|
-
return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
|
|
42745
|
+
const oklch1 = toOklch(ce, ops[0]);
|
|
42746
|
+
const oklch2 = toOklch(ce, ops[1]);
|
|
42747
|
+
if (!oklch1 || !oklch2) return ce.error("incompatible-type");
|
|
42748
|
+
return oklchToExpr(ce, lerpOklchColor(oklch1, oklch2, ratio));
|
|
42122
42749
|
}
|
|
42123
42750
|
},
|
|
42124
42751
|
Colormap: {
|
|
42125
42752
|
description: "Sample colors from a named palette",
|
|
42126
42753
|
complexity: 8e3,
|
|
42127
|
-
signature: "(string, number?) ->
|
|
42754
|
+
signature: "(string, number?) -> color | list<color>",
|
|
42128
42755
|
evaluate: (ops, { engine: ce }) => {
|
|
42129
42756
|
const name = isString(ops[0]) ? ops[0].string : void 0;
|
|
42130
42757
|
if (!name) return ce.error("incompatible-type");
|
|
42131
42758
|
const palette = ALL_PALETTES[name];
|
|
42132
42759
|
if (!palette) return ce.error("expected-value", name);
|
|
42133
42760
|
if (ops.length < 2 || ops[1] === void 0) {
|
|
42134
|
-
const
|
|
42135
|
-
(hex) =>
|
|
42761
|
+
const colors = palette.map(
|
|
42762
|
+
(hex) => colorNumberToOklch(ce, parseColor(hex))
|
|
42136
42763
|
);
|
|
42137
|
-
return ce.function("List",
|
|
42764
|
+
return ce.function("List", colors);
|
|
42138
42765
|
}
|
|
42139
42766
|
const val = ops[1].re;
|
|
42140
42767
|
if (!Number.isFinite(val)) return ce.error("expected-value");
|
|
42141
42768
|
if (Number.isInteger(val) && val >= 2) {
|
|
42142
42769
|
const n = val;
|
|
42143
|
-
const
|
|
42770
|
+
const colors = [];
|
|
42144
42771
|
for (let i = 0; i < n; i++) {
|
|
42145
|
-
|
|
42772
|
+
colors.push(samplePalette(ce, palette, i / (n - 1)));
|
|
42146
42773
|
}
|
|
42147
|
-
return ce.function("List",
|
|
42774
|
+
return ce.function("List", colors);
|
|
42148
42775
|
}
|
|
42149
42776
|
return samplePalette(ce, palette, val);
|
|
42150
42777
|
}
|
|
@@ -42152,12 +42779,25 @@ ${e.message}
|
|
|
42152
42779
|
ColorToColorspace: {
|
|
42153
42780
|
description: "Convert a color to components in a target color space",
|
|
42154
42781
|
complexity: 8e3,
|
|
42155
|
-
signature: "(
|
|
42782
|
+
signature: "(color | string | tuple, string) -> tuple",
|
|
42156
42783
|
evaluate: (ops, { engine: ce }) => {
|
|
42157
|
-
const rgb = extractRgb(ce, ops[0]);
|
|
42158
|
-
if (!rgb) return ce.error("incompatible-type");
|
|
42159
42784
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42160
42785
|
if (!space) return ce.error("incompatible-type");
|
|
42786
|
+
if (space === "oklch" || space === "oklab" || space === "lab") {
|
|
42787
|
+
const oklch2 = colorExprToOklch(ops[0]);
|
|
42788
|
+
if (oklch2) {
|
|
42789
|
+
if (space === "oklch")
|
|
42790
|
+
return componentsTuple(
|
|
42791
|
+
ce,
|
|
42792
|
+
[oklch2.L, oklch2.C, oklch2.H],
|
|
42793
|
+
oklch2.alpha
|
|
42794
|
+
);
|
|
42795
|
+
const lab = oklchToOklab(oklch2);
|
|
42796
|
+
return componentsTuple(ce, [lab.L, lab.a, lab.b], lab.alpha);
|
|
42797
|
+
}
|
|
42798
|
+
}
|
|
42799
|
+
const rgb = extractRgb(ce, ops[0]);
|
|
42800
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42161
42801
|
const alpha = rgb.alpha;
|
|
42162
42802
|
switch (space) {
|
|
42163
42803
|
case "rgb":
|
|
@@ -42187,17 +42827,27 @@ ${e.message}
|
|
|
42187
42827
|
ColorFromColorspace: {
|
|
42188
42828
|
description: "Convert color space components to a canonical sRGB tuple",
|
|
42189
42829
|
complexity: 8e3,
|
|
42190
|
-
signature: "(tuple, string) -> tuple",
|
|
42830
|
+
signature: "(color | tuple, string) -> tuple",
|
|
42191
42831
|
evaluate: (ops, { engine: ce }) => {
|
|
42192
|
-
const tuple = ops[0];
|
|
42193
|
-
if (!isFunction2(tuple) || tuple.operator !== "Tuple" || tuple.ops.length < 3)
|
|
42194
|
-
return ce.error("incompatible-type");
|
|
42195
|
-
const c0 = tuple.ops[0].re;
|
|
42196
|
-
const c1 = tuple.ops[1].re;
|
|
42197
|
-
const c2 = tuple.ops[2].re;
|
|
42198
|
-
const alpha = tuple.ops.length >= 4 ? tuple.ops[3].re : void 0;
|
|
42199
42832
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42200
42833
|
if (!space) return ce.error("incompatible-type");
|
|
42834
|
+
let c0, c1, c2;
|
|
42835
|
+
let alpha;
|
|
42836
|
+
const arg = ops[0];
|
|
42837
|
+
const typed = readColorExpr(arg);
|
|
42838
|
+
if (typed) {
|
|
42839
|
+
c0 = typed.c0;
|
|
42840
|
+
c1 = typed.c1;
|
|
42841
|
+
c2 = typed.c2;
|
|
42842
|
+
alpha = typed.alpha;
|
|
42843
|
+
} else if (isFunction2(arg) && arg.operator === "Tuple" && arg.ops.length >= 3) {
|
|
42844
|
+
c0 = arg.ops[0].re;
|
|
42845
|
+
c1 = arg.ops[1].re;
|
|
42846
|
+
c2 = arg.ops[2].re;
|
|
42847
|
+
alpha = arg.ops.length >= 4 ? arg.ops[3].re : void 0;
|
|
42848
|
+
} else {
|
|
42849
|
+
return ce.error("incompatible-type");
|
|
42850
|
+
}
|
|
42201
42851
|
let rgb;
|
|
42202
42852
|
switch (space) {
|
|
42203
42853
|
case "rgb":
|
|
@@ -42233,7 +42883,7 @@ ${e.message}
|
|
|
42233
42883
|
ColorContrast: {
|
|
42234
42884
|
description: "APCA contrast ratio between two colors",
|
|
42235
42885
|
complexity: 8e3,
|
|
42236
|
-
signature: "(
|
|
42886
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
42237
42887
|
evaluate: (ops, { engine: ce }) => {
|
|
42238
42888
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42239
42889
|
const fgRgb = extractRgb(ce, ops[1]);
|
|
@@ -42244,19 +42894,186 @@ ${e.message}
|
|
|
42244
42894
|
ContrastingColor: {
|
|
42245
42895
|
description: "Choose the foreground color with better APCA contrast against a background",
|
|
42246
42896
|
complexity: 8e3,
|
|
42247
|
-
signature: "(
|
|
42897
|
+
signature: "(color | string | tuple, (color | string | tuple)?, (color | string | tuple)?) -> color",
|
|
42248
42898
|
evaluate: (ops, { engine: ce }) => {
|
|
42249
42899
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42250
42900
|
if (!bgRgb) return ce.error("incompatible-type");
|
|
42901
|
+
let packed;
|
|
42251
42902
|
if (ops.length >= 3 && ops[1] !== void 0 && ops[2] !== void 0) {
|
|
42252
42903
|
const fg1 = extractRgb(ce, ops[1]);
|
|
42253
42904
|
const fg2 = extractRgb(ce, ops[2]);
|
|
42254
42905
|
if (!fg1 || !fg2) return ce.error("incompatible-type");
|
|
42255
|
-
|
|
42256
|
-
|
|
42906
|
+
packed = contrastingColor({ bg: bgRgb, fg1, fg2 });
|
|
42907
|
+
} else {
|
|
42908
|
+
packed = contrastingColor(bgRgb);
|
|
42909
|
+
}
|
|
42910
|
+
const r = (packed >>> 24 & 255) / 255;
|
|
42911
|
+
const g = (packed >>> 16 & 255) / 255;
|
|
42912
|
+
const b = (packed >>> 8 & 255) / 255;
|
|
42913
|
+
const alpha = normalizeAlpha((packed & 255) / 255);
|
|
42914
|
+
const args = [ce.number(r), ce.number(g), ce.number(b)];
|
|
42915
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
42916
|
+
return ce.function("Rgb", args);
|
|
42917
|
+
}
|
|
42918
|
+
},
|
|
42919
|
+
// ---------------------------------------------------------------------------
|
|
42920
|
+
// Color constructors. Each preserves its colorspace on evaluation; the
|
|
42921
|
+
// operator name is the discriminator. Components are interpreted per
|
|
42922
|
+
// colorspace conventions (Rgb channels 0-1, Hsv/Hsl hue in degrees with
|
|
42923
|
+
// sat/value 0-1, Oklab/Oklch L 0-1 with standard a/b/C/H ranges). The
|
|
42924
|
+
// optional 4th argument is alpha in [0, 1]. No clamping at evaluation time.
|
|
42925
|
+
// ---------------------------------------------------------------------------
|
|
42926
|
+
Rgb: {
|
|
42927
|
+
description: "sRGB color (channels 0-1, optional alpha 0-1)",
|
|
42928
|
+
complexity: 8e3,
|
|
42929
|
+
signature: "(number, number, number, number?) -> color"
|
|
42930
|
+
},
|
|
42931
|
+
Hsv: {
|
|
42932
|
+
description: "HSV color (hue degrees, saturation/value 0-1, optional alpha)",
|
|
42933
|
+
complexity: 8e3,
|
|
42934
|
+
signature: "(number, number, number, number?) -> color"
|
|
42935
|
+
},
|
|
42936
|
+
Hsl: {
|
|
42937
|
+
description: "HSL color (hue degrees, saturation/lightness 0-1, optional alpha)",
|
|
42938
|
+
complexity: 8e3,
|
|
42939
|
+
signature: "(number, number, number, number?) -> color"
|
|
42940
|
+
},
|
|
42941
|
+
Oklab: {
|
|
42942
|
+
description: "OKLab color (L 0-1, a/b ~ -0.4..0.4, optional alpha)",
|
|
42943
|
+
complexity: 8e3,
|
|
42944
|
+
signature: "(number, number, number, number?) -> color"
|
|
42945
|
+
},
|
|
42946
|
+
Oklch: {
|
|
42947
|
+
description: "OKLCh color (L 0-1, C 0-~0.4, hue degrees, optional alpha)",
|
|
42948
|
+
complexity: 8e3,
|
|
42949
|
+
signature: "(number, number, number, number?) -> color"
|
|
42950
|
+
},
|
|
42951
|
+
// ---------------------------------------------------------------------------
|
|
42952
|
+
// Color-space conversions. Each accepts any of the five color heads and
|
|
42953
|
+
// returns the same color in the named space. If the input is already in
|
|
42954
|
+
// the target space, returns the input unchanged.
|
|
42955
|
+
// ---------------------------------------------------------------------------
|
|
42956
|
+
AsRgb: {
|
|
42957
|
+
description: "Convert any color to sRGB (channels 0-1)",
|
|
42958
|
+
complexity: 8e3,
|
|
42959
|
+
signature: "(color) -> color",
|
|
42960
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42961
|
+
const arg = ops[0];
|
|
42962
|
+
if (isFunction2(arg) && arg.operator === "Rgb")
|
|
42963
|
+
return normalizeColorHead(ce, arg);
|
|
42964
|
+
const rgb = colorExprToRgb(arg);
|
|
42965
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42966
|
+
const args = [
|
|
42967
|
+
ce.number(rgb.r / 255),
|
|
42968
|
+
ce.number(rgb.g / 255),
|
|
42969
|
+
ce.number(rgb.b / 255)
|
|
42970
|
+
];
|
|
42971
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42972
|
+
return ce.function("Rgb", args);
|
|
42973
|
+
}
|
|
42974
|
+
},
|
|
42975
|
+
AsHsv: {
|
|
42976
|
+
description: "Convert any color to HSV (hue degrees, s/v 0-1)",
|
|
42977
|
+
complexity: 8e3,
|
|
42978
|
+
signature: "(color) -> color",
|
|
42979
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42980
|
+
const arg = ops[0];
|
|
42981
|
+
if (isFunction2(arg) && arg.operator === "Hsv")
|
|
42982
|
+
return normalizeColorHead(ce, arg);
|
|
42983
|
+
const rgb = colorExprToRgb(arg);
|
|
42984
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42985
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
42986
|
+
const args = [ce.number(hsv.h), ce.number(hsv.s), ce.number(hsv.v)];
|
|
42987
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42988
|
+
return ce.function("Hsv", args);
|
|
42989
|
+
}
|
|
42990
|
+
},
|
|
42991
|
+
AsHsl: {
|
|
42992
|
+
description: "Convert any color to HSL (hue degrees, s/l 0-1)",
|
|
42993
|
+
complexity: 8e3,
|
|
42994
|
+
signature: "(color) -> color",
|
|
42995
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42996
|
+
const arg = ops[0];
|
|
42997
|
+
if (isFunction2(arg) && arg.operator === "Hsl")
|
|
42998
|
+
return normalizeColorHead(ce, arg);
|
|
42999
|
+
const rgb = colorExprToRgb(arg);
|
|
43000
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43001
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
43002
|
+
const args = [ce.number(hsl.h), ce.number(hsl.s), ce.number(hsl.l)];
|
|
43003
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43004
|
+
return ce.function("Hsl", args);
|
|
43005
|
+
}
|
|
43006
|
+
},
|
|
43007
|
+
AsOklab: {
|
|
43008
|
+
description: "Convert any color to OKLab",
|
|
43009
|
+
complexity: 8e3,
|
|
43010
|
+
signature: "(color) -> color",
|
|
43011
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43012
|
+
const arg = ops[0];
|
|
43013
|
+
if (isFunction2(arg) && arg.operator === "Oklab")
|
|
43014
|
+
return normalizeColorHead(ce, arg);
|
|
43015
|
+
if (isFunction2(arg) && arg.operator === "Oklch") {
|
|
43016
|
+
const c = readColorExpr(arg);
|
|
43017
|
+
if (!c) return ce.error("incompatible-type");
|
|
43018
|
+
const lab2 = oklchToOklab({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
43019
|
+
const args2 = [ce.number(lab2.L), ce.number(lab2.a), ce.number(lab2.b)];
|
|
43020
|
+
if (lab2.alpha !== void 0) args2.push(ce.number(lab2.alpha));
|
|
43021
|
+
return ce.function("Oklab", args2);
|
|
43022
|
+
}
|
|
43023
|
+
const rgb = colorExprToRgb(arg);
|
|
43024
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43025
|
+
const lab = rgbToOklab(rgb);
|
|
43026
|
+
const args = [ce.number(lab.L), ce.number(lab.a), ce.number(lab.b)];
|
|
43027
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43028
|
+
return ce.function("Oklab", args);
|
|
43029
|
+
}
|
|
43030
|
+
},
|
|
43031
|
+
AsOklch: {
|
|
43032
|
+
description: "Convert any color to OKLCh",
|
|
43033
|
+
complexity: 8e3,
|
|
43034
|
+
signature: "(color) -> color",
|
|
43035
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43036
|
+
const arg = ops[0];
|
|
43037
|
+
if (isFunction2(arg) && arg.operator === "Oklch")
|
|
43038
|
+
return normalizeColorHead(ce, arg);
|
|
43039
|
+
if (isFunction2(arg) && arg.operator === "Oklab") {
|
|
43040
|
+
const c2 = readColorExpr(arg);
|
|
43041
|
+
if (!c2) return ce.error("incompatible-type");
|
|
43042
|
+
const oklch2 = oklabToOklch({
|
|
43043
|
+
L: c2.c0,
|
|
43044
|
+
a: c2.c1,
|
|
43045
|
+
b: c2.c2,
|
|
43046
|
+
alpha: c2.alpha
|
|
43047
|
+
});
|
|
43048
|
+
const args2 = [
|
|
43049
|
+
ce.number(oklch2.L),
|
|
43050
|
+
ce.number(oklch2.C),
|
|
43051
|
+
ce.number(oklch2.H)
|
|
43052
|
+
];
|
|
43053
|
+
if (oklch2.alpha !== void 0) args2.push(ce.number(oklch2.alpha));
|
|
43054
|
+
return ce.function("Oklch", args2);
|
|
42257
43055
|
}
|
|
42258
|
-
const
|
|
42259
|
-
return
|
|
43056
|
+
const rgb = colorExprToRgb(arg);
|
|
43057
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43058
|
+
const c = rgbToOklch(rgb);
|
|
43059
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
43060
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43061
|
+
return ce.function("Oklch", args);
|
|
43062
|
+
}
|
|
43063
|
+
},
|
|
43064
|
+
// ---------------------------------------------------------------------------
|
|
43065
|
+
// Perceptual difference. Returns ΔE_OK (Euclidean distance in OKLab),
|
|
43066
|
+
// an approximately perceptually uniform scalar.
|
|
43067
|
+
// ---------------------------------------------------------------------------
|
|
43068
|
+
ColorDelta: {
|
|
43069
|
+
description: "Perceptual color difference (\u0394E_OK) between two colors",
|
|
43070
|
+
complexity: 8e3,
|
|
43071
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
43072
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43073
|
+
const a = toOklch(ce, ops[0]);
|
|
43074
|
+
const b = toOklch(ce, ops[1]);
|
|
43075
|
+
if (!a || !b) return ce.error("incompatible-type");
|
|
43076
|
+
return ce.number(oklabDeltaE(oklchToOklab(a), oklchToOklab(b)));
|
|
42260
43077
|
}
|
|
42261
43078
|
}
|
|
42262
43079
|
};
|
|
@@ -42315,12 +43132,42 @@ ${e.message}
|
|
|
42315
43132
|
}
|
|
42316
43133
|
},
|
|
42317
43134
|
Loop: {
|
|
42318
|
-
description: "Evaluate a body expression over
|
|
43135
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
42319
43136
|
lazy: true,
|
|
42320
|
-
signature: "(body:expression,
|
|
42321
|
-
type: ([body]) =>
|
|
42322
|
-
|
|
42323
|
-
|
|
43137
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43138
|
+
type: ([body]) => {
|
|
43139
|
+
if (!body) return "nothing";
|
|
43140
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43141
|
+
},
|
|
43142
|
+
canonical: canonicalLoop,
|
|
43143
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43144
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43145
|
+
},
|
|
43146
|
+
When: {
|
|
43147
|
+
description: "Conditional value: returns expr when cond holds, undefined otherwise.",
|
|
43148
|
+
lazy: true,
|
|
43149
|
+
signature: "(expression, boolean) -> any",
|
|
43150
|
+
type: ([expr2]) => expr2.type,
|
|
43151
|
+
canonical: (args, { engine: ce }) => {
|
|
43152
|
+
if (args.length !== 2) return null;
|
|
43153
|
+
const [expr2, cond] = args;
|
|
43154
|
+
if (isFunction2(expr2, "When")) {
|
|
43155
|
+
const inner = expr2.op1.canonical;
|
|
43156
|
+
const innerCond = expr2.op2.canonical;
|
|
43157
|
+
return ce._fn("When", [
|
|
43158
|
+
inner,
|
|
43159
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43160
|
+
]);
|
|
43161
|
+
}
|
|
43162
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43163
|
+
},
|
|
43164
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43165
|
+
const c = cond.evaluate();
|
|
43166
|
+
const cs = sym(c);
|
|
43167
|
+
if (cs === "True") return expr2.evaluate();
|
|
43168
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43169
|
+
return ce._fn("When", [expr2, c]);
|
|
43170
|
+
}
|
|
42324
43171
|
},
|
|
42325
43172
|
Which: {
|
|
42326
43173
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42380,9 +43227,141 @@ ${e.message}
|
|
|
42380
43227
|
);
|
|
42381
43228
|
return result;
|
|
42382
43229
|
}
|
|
42383
|
-
function
|
|
43230
|
+
function canonicalLoop(ops, options) {
|
|
43231
|
+
const { engine: ce, scope } = options;
|
|
43232
|
+
if (ops.length === 0) return null;
|
|
43233
|
+
if (ops.length === 1) {
|
|
43234
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43235
|
+
}
|
|
43236
|
+
const body = ops[0];
|
|
43237
|
+
const iterators = ops.slice(1);
|
|
43238
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43239
|
+
if (!allElement) {
|
|
43240
|
+
return ce._fn(
|
|
43241
|
+
"Loop",
|
|
43242
|
+
ops.map((op) => op.canonical)
|
|
43243
|
+
);
|
|
43244
|
+
}
|
|
43245
|
+
const loopScope = scope ?? {
|
|
43246
|
+
parent: ce.context.lexicalScope,
|
|
43247
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43248
|
+
};
|
|
43249
|
+
loopScope.noAutoDeclare = true;
|
|
43250
|
+
ce.pushScope(loopScope);
|
|
43251
|
+
let canonicalIterators;
|
|
43252
|
+
let canonicalBody;
|
|
43253
|
+
try {
|
|
43254
|
+
canonicalIterators = iterators.map((it) => {
|
|
43255
|
+
if (!isFunction2(it, "Element")) {
|
|
43256
|
+
return ce._fn("Element", [
|
|
43257
|
+
ce.error("missing").canonical,
|
|
43258
|
+
ce.error("missing").canonical
|
|
43259
|
+
]);
|
|
43260
|
+
}
|
|
43261
|
+
const indexExpr = it.ops[0];
|
|
43262
|
+
const collExpr = it.ops[1];
|
|
43263
|
+
if (!indexExpr || !collExpr) {
|
|
43264
|
+
return ce._fn("Element", [
|
|
43265
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43266
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43267
|
+
]);
|
|
43268
|
+
}
|
|
43269
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43270
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43271
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43272
|
+
}
|
|
43273
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43274
|
+
});
|
|
43275
|
+
canonicalBody = body.canonical;
|
|
43276
|
+
} finally {
|
|
43277
|
+
ce.popScope();
|
|
43278
|
+
loopScope.noAutoDeclare = false;
|
|
43279
|
+
}
|
|
43280
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43281
|
+
scope: loopScope
|
|
43282
|
+
});
|
|
43283
|
+
}
|
|
43284
|
+
function* runLoop(body, elements, ce) {
|
|
42384
43285
|
body ??= ce.Nothing;
|
|
42385
43286
|
if (sym(body) === "Nothing") return body;
|
|
43287
|
+
if (elements.length === 0) {
|
|
43288
|
+
const result = body.evaluate();
|
|
43289
|
+
yield result;
|
|
43290
|
+
return result;
|
|
43291
|
+
}
|
|
43292
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43293
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43294
|
+
}
|
|
43295
|
+
const results = [];
|
|
43296
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43297
|
+
const freshScope = {
|
|
43298
|
+
parent: ce.context.lexicalScope,
|
|
43299
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43300
|
+
};
|
|
43301
|
+
ce._pushEvalContext(freshScope);
|
|
43302
|
+
try {
|
|
43303
|
+
for (const elem of elements) {
|
|
43304
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43305
|
+
const idx = elem.ops[0];
|
|
43306
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43307
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43308
|
+
ce.declare(idx.symbol, "unknown");
|
|
43309
|
+
}
|
|
43310
|
+
}
|
|
43311
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43312
|
+
} finally {
|
|
43313
|
+
ce._popEvalContext();
|
|
43314
|
+
}
|
|
43315
|
+
if (state.stopped && state.value !== void 0) {
|
|
43316
|
+
if (!state.broke) return state.value;
|
|
43317
|
+
return state.value;
|
|
43318
|
+
}
|
|
43319
|
+
return ce.function("List", results);
|
|
43320
|
+
}
|
|
43321
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43322
|
+
if (state.stopped) return;
|
|
43323
|
+
if (index === elements.length) {
|
|
43324
|
+
const result = body.evaluate();
|
|
43325
|
+
state.count += 1;
|
|
43326
|
+
if (state.count > ce.iterationLimit)
|
|
43327
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43328
|
+
if (isFunction2(result, "Break")) {
|
|
43329
|
+
state.stopped = true;
|
|
43330
|
+
state.broke = true;
|
|
43331
|
+
state.value = result.op1;
|
|
43332
|
+
return;
|
|
43333
|
+
}
|
|
43334
|
+
if (result.operator === "Return") {
|
|
43335
|
+
state.stopped = true;
|
|
43336
|
+
state.value = result;
|
|
43337
|
+
return;
|
|
43338
|
+
}
|
|
43339
|
+
results.push(result);
|
|
43340
|
+
yield result;
|
|
43341
|
+
return;
|
|
43342
|
+
}
|
|
43343
|
+
const elem = elements[index];
|
|
43344
|
+
if (!isFunction2(elem, "Element")) {
|
|
43345
|
+
return;
|
|
43346
|
+
}
|
|
43347
|
+
const indexExpr = elem.ops[0];
|
|
43348
|
+
const collExpr = elem.ops[1];
|
|
43349
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43350
|
+
return;
|
|
43351
|
+
}
|
|
43352
|
+
const name = indexExpr.symbol;
|
|
43353
|
+
const collection = collExpr.evaluate();
|
|
43354
|
+
if (!collection?.isCollection) {
|
|
43355
|
+
return;
|
|
43356
|
+
}
|
|
43357
|
+
const skipAssign = name === "Nothing";
|
|
43358
|
+
for (const value of collection.each()) {
|
|
43359
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43360
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43361
|
+
if (state.stopped) return;
|
|
43362
|
+
}
|
|
43363
|
+
}
|
|
43364
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42386
43365
|
if (collection?.isCollection) {
|
|
42387
43366
|
let result = void 0;
|
|
42388
43367
|
const fn = applicable(body);
|
|
@@ -44736,6 +45715,34 @@ ${e.message}
|
|
|
44736
45715
|
signature: "() -> expression",
|
|
44737
45716
|
evaluate: (_ops, { engine }) => engine.expr(randomExpression())
|
|
44738
45717
|
}
|
|
45718
|
+
},
|
|
45719
|
+
// ---------------------------------------------------------------------------
|
|
45720
|
+
// Opaque typed heads — registered so the names are in the standard set
|
|
45721
|
+
// (consumers can branch on the operator name); CE itself does not evaluate
|
|
45722
|
+
// them. Geometric primitives `Triangle`/`Sphere`/`Segment` and the action
|
|
45723
|
+
// arrow `To` (`a \to b`).
|
|
45724
|
+
// ---------------------------------------------------------------------------
|
|
45725
|
+
{
|
|
45726
|
+
Triangle: {
|
|
45727
|
+
description: "Triangle primitive \u2014 opaque typed head.",
|
|
45728
|
+
signature: "(any+) -> expression"
|
|
45729
|
+
},
|
|
45730
|
+
GeometricVector: {
|
|
45731
|
+
description: "Geometric vector (directed segment between two points) \u2014 opaque typed head. Distinct from the column-vector `Vector` operator.",
|
|
45732
|
+
signature: "(any, any) -> expression"
|
|
45733
|
+
},
|
|
45734
|
+
Sphere: {
|
|
45735
|
+
description: "Sphere primitive \u2014 opaque typed head.",
|
|
45736
|
+
signature: "(any+) -> expression"
|
|
45737
|
+
},
|
|
45738
|
+
Segment: {
|
|
45739
|
+
description: "Segment primitive \u2014 opaque typed head.",
|
|
45740
|
+
signature: "(any+) -> expression"
|
|
45741
|
+
},
|
|
45742
|
+
To: {
|
|
45743
|
+
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45744
|
+
signature: "(any, any) -> nothing"
|
|
45745
|
+
}
|
|
44739
45746
|
}
|
|
44740
45747
|
];
|
|
44741
45748
|
|
|
@@ -51872,6 +52879,7 @@ Error in definition of "${name}"`,
|
|
|
51872
52879
|
|
|
51873
52880
|
// src/compute-engine/boxed-expression/cache.ts
|
|
51874
52881
|
function cachedValue(v, generation, fn) {
|
|
52882
|
+
if (v.generation === generation && v.value !== null) return v.value;
|
|
51875
52883
|
v.generation = generation;
|
|
51876
52884
|
v.value = fn();
|
|
51877
52885
|
return v.value;
|
|
@@ -53649,6 +54657,12 @@ Error in definition of "${name}"`,
|
|
|
53649
54657
|
function _escapeJsonString(s) {
|
|
53650
54658
|
return s;
|
|
53651
54659
|
}
|
|
54660
|
+
function _serializeLatexMetadata(ce, expr2) {
|
|
54661
|
+
const syntax = ce.latexSyntax;
|
|
54662
|
+
const opts = ce.latexOptions;
|
|
54663
|
+
if (Object.keys(opts).length === 0) return syntax.serialize(expr2);
|
|
54664
|
+
return syntax.serialize(expr2, { ...opts });
|
|
54665
|
+
}
|
|
53652
54666
|
function serializeSubtract(ce, a, b, options, metadata) {
|
|
53653
54667
|
if (isNumber(a) && a.isNegative) {
|
|
53654
54668
|
const v = a.numericValue;
|
|
@@ -53953,7 +54967,7 @@ Error in definition of "${name}"`,
|
|
|
53953
54967
|
];
|
|
53954
54968
|
const md = { ...metadata ?? {} };
|
|
53955
54969
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
53956
|
-
md.latex = _escapeJsonString(md.latex ?? ce
|
|
54970
|
+
md.latex = _escapeJsonString(md.latex ?? _serializeLatexMetadata(ce, fn));
|
|
53957
54971
|
} else md.latex = "";
|
|
53958
54972
|
if (!options.metadata.includes("wikidata")) md.wikidata = "";
|
|
53959
54973
|
if (!md.latex && !md.wikidata && options.shorthands.includes("function"))
|
|
@@ -53978,7 +54992,7 @@ Error in definition of "${name}"`,
|
|
|
53978
54992
|
}
|
|
53979
54993
|
metadata = { ...metadata };
|
|
53980
54994
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
53981
|
-
metadata.latex = metadata.latex ?? ce
|
|
54995
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, sym2);
|
|
53982
54996
|
if (metadata.latex !== void 0)
|
|
53983
54997
|
metadata.latex = _escapeJsonString(metadata.latex);
|
|
53984
54998
|
} else metadata.latex = void 0;
|
|
@@ -54140,7 +55154,7 @@ Error in definition of "${name}"`,
|
|
|
54140
55154
|
}
|
|
54141
55155
|
}
|
|
54142
55156
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54143
|
-
metadata.latex = metadata.latex ?? ce
|
|
55157
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, result2 ?? { num });
|
|
54144
55158
|
if (result2) {
|
|
54145
55159
|
if (metadata.latex !== void 0)
|
|
54146
55160
|
return { sym: result2, latex: metadata.latex };
|
|
@@ -54156,7 +55170,7 @@ Error in definition of "${name}"`,
|
|
|
54156
55170
|
if (value.isNaN()) {
|
|
54157
55171
|
num = "NaN";
|
|
54158
55172
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54159
|
-
metadata.latex = metadata.latex ?? ce
|
|
55173
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54160
55174
|
return metadata.latex !== void 0 ? { num, latex: metadata.latex } : { num };
|
|
54161
55175
|
}
|
|
54162
55176
|
return serializeJsonFunction(
|
|
@@ -54190,7 +55204,7 @@ Error in definition of "${name}"`,
|
|
|
54190
55204
|
value = Number(value);
|
|
54191
55205
|
} else {
|
|
54192
55206
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54193
|
-
metadata.latex = metadata.latex ?? ce
|
|
55207
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, {
|
|
54194
55208
|
num: value.toString()
|
|
54195
55209
|
});
|
|
54196
55210
|
if (metadata.latex !== void 0)
|
|
@@ -54204,7 +55218,7 @@ Error in definition of "${name}"`,
|
|
|
54204
55218
|
result = value > 0 ? "PositiveInfinity" : "NegativeInfinity";
|
|
54205
55219
|
else num = serializeRepeatingDecimals(value.toString(), options);
|
|
54206
55220
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54207
|
-
metadata.latex = metadata.latex ?? ce
|
|
55221
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54208
55222
|
if (result) {
|
|
54209
55223
|
if (metadata.latex !== void 0)
|
|
54210
55224
|
return { sym: result, latex: metadata.latex };
|
|
@@ -54430,6 +55444,23 @@ Error in definition of "${name}"`,
|
|
|
54430
55444
|
};
|
|
54431
55445
|
return compilePair(0);
|
|
54432
55446
|
}
|
|
55447
|
+
if (h === "When") {
|
|
55448
|
+
if (args.length !== 2)
|
|
55449
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55450
|
+
const fn2 = target.functions?.(h);
|
|
55451
|
+
if (fn2) {
|
|
55452
|
+
if (typeof fn2 === "function") {
|
|
55453
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55454
|
+
}
|
|
55455
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55456
|
+
}
|
|
55457
|
+
if (isSymbol2(args[1], "True"))
|
|
55458
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55459
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55460
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55461
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55462
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55463
|
+
}
|
|
54433
55464
|
if (h === "Block") {
|
|
54434
55465
|
return _BaseCompiler.compileBlock(args, target);
|
|
54435
55466
|
}
|
|
@@ -54504,17 +55535,91 @@ Error in definition of "${name}"`,
|
|
|
54504
55535
|
)}${target.ws("\n")}})()`;
|
|
54505
55536
|
}
|
|
54506
55537
|
/**
|
|
54507
|
-
* Compile a Loop expression
|
|
54508
|
-
*
|
|
55538
|
+
* Compile a Loop expression.
|
|
55539
|
+
*
|
|
55540
|
+
* Two forms are supported:
|
|
55541
|
+
*
|
|
55542
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
55543
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
55544
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
55545
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
55546
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
55547
|
+
* references to the loop index inside the body are re-wrapped via
|
|
55548
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
54509
55549
|
*
|
|
54510
|
-
*
|
|
54511
|
-
*
|
|
54512
|
-
*
|
|
55550
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
55551
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
55552
|
+
* When two or more `Element` clauses are present — or when the single
|
|
55553
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
55554
|
+
* comprehension that collects results into an array. Each clause
|
|
55555
|
+
* produces a `for (const name of collection)` loop, nested
|
|
55556
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
55557
|
+
*
|
|
55558
|
+
* Example output (JS):
|
|
55559
|
+
* ```js
|
|
55560
|
+
* (() => { const result = [];
|
|
55561
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
55562
|
+
* return result; })()
|
|
55563
|
+
* ```
|
|
55564
|
+
*
|
|
55565
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
55566
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
55567
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
55568
|
+
* array or by unrolling when bounds are known at compile time.
|
|
54513
55569
|
*/
|
|
54514
55570
|
static compileForLoop(args, target) {
|
|
54515
55571
|
if (!args[0]) throw new Error("Loop: no body");
|
|
54516
55572
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
54517
|
-
const
|
|
55573
|
+
const body = args[0];
|
|
55574
|
+
const elements = args.slice(1);
|
|
55575
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
55576
|
+
if (useComprehension) {
|
|
55577
|
+
const lang = target.language ?? "";
|
|
55578
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
55579
|
+
throw new Error(
|
|
55580
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
55581
|
+
);
|
|
55582
|
+
}
|
|
55583
|
+
const narrowedElements = [];
|
|
55584
|
+
for (let i = 0; i < elements.length; i++) {
|
|
55585
|
+
const elem = elements[i];
|
|
55586
|
+
if (!isFunction2(elem, "Element"))
|
|
55587
|
+
throw new Error(
|
|
55588
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
55589
|
+
);
|
|
55590
|
+
if (!isSymbol2(elem.ops[0]))
|
|
55591
|
+
throw new Error(
|
|
55592
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
55593
|
+
);
|
|
55594
|
+
narrowedElements.push(elem);
|
|
55595
|
+
}
|
|
55596
|
+
const loopVarSet = new Set(
|
|
55597
|
+
narrowedElements.map(
|
|
55598
|
+
(e) => e.ops[0].symbol
|
|
55599
|
+
)
|
|
55600
|
+
);
|
|
55601
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
55602
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
55603
|
+
...target,
|
|
55604
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
55605
|
+
} : target;
|
|
55606
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
55607
|
+
let inner = `result.push(${bodyCode});`;
|
|
55608
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
55609
|
+
const elem = narrowedElements[i];
|
|
55610
|
+
const name = elem.ops[0].symbol;
|
|
55611
|
+
const collExpr = elem.ops[1];
|
|
55612
|
+
let collection;
|
|
55613
|
+
if (isFunction2(collExpr, "Range")) {
|
|
55614
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
55615
|
+
} else {
|
|
55616
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
55617
|
+
}
|
|
55618
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
55619
|
+
}
|
|
55620
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
55621
|
+
}
|
|
55622
|
+
const indexing = elements[0];
|
|
54518
55623
|
if (!isFunction2(indexing, "Element"))
|
|
54519
55624
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
54520
55625
|
const indexExpr = indexing.ops[0];
|
|
@@ -54532,13 +55637,72 @@ Error in definition of "${name}"`,
|
|
|
54532
55637
|
...target,
|
|
54533
55638
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
54534
55639
|
};
|
|
54535
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
55640
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
54536
55641
|
return `(() => {${target.ws(
|
|
54537
55642
|
"\n"
|
|
54538
55643
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
54539
55644
|
"\n"
|
|
54540
55645
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
54541
55646
|
}
|
|
55647
|
+
/**
|
|
55648
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
55649
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
55650
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
55651
|
+
*
|
|
55652
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
55653
|
+
* are not statically numeric we accept the Range (the historical
|
|
55654
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
55655
|
+
* left as a known limitation; callers can force the iterable path by
|
|
55656
|
+
* supplying an explicit step.
|
|
55657
|
+
*/
|
|
55658
|
+
static isLegacyCompatibleRange(coll) {
|
|
55659
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
55660
|
+
if (coll.ops.length >= 3) {
|
|
55661
|
+
const stepExpr = coll.ops[2];
|
|
55662
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
55663
|
+
}
|
|
55664
|
+
const lo = coll.ops[0];
|
|
55665
|
+
const hi = coll.ops[1];
|
|
55666
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
55667
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
55668
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
55669
|
+
return true;
|
|
55670
|
+
}
|
|
55671
|
+
/**
|
|
55672
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
55673
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
55674
|
+
* `library/collections.ts` Range:
|
|
55675
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
55676
|
+
* element = lo + step * k (0-indexed)
|
|
55677
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
55678
|
+
*
|
|
55679
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
55680
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
55681
|
+
*/
|
|
55682
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
55683
|
+
const loExpr = rangeExpr.ops[0];
|
|
55684
|
+
const hiExpr = rangeExpr.ops[1];
|
|
55685
|
+
const stepExpr = rangeExpr.ops[2];
|
|
55686
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
55687
|
+
const lo2 = loExpr.re;
|
|
55688
|
+
const hi2 = hiExpr.re;
|
|
55689
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
55690
|
+
if (step2 === 0) return "[]";
|
|
55691
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
55692
|
+
if (step2 === 1) {
|
|
55693
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
55694
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
55695
|
+
}
|
|
55696
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
55697
|
+
}
|
|
55698
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
55699
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
55700
|
+
if (stepExpr === void 0) {
|
|
55701
|
+
return `((_lo,_hi)=>{const _st=_hi>=_lo?1:-1;return Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k);})(${lo},${hi})`;
|
|
55702
|
+
}
|
|
55703
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
55704
|
+
return `((_lo,_hi,_st)=>_st===0?[]:Array.from({length:Math.max(0,Math.floor((_hi-_lo)/_st)+1)},(_,k)=>_lo+_st*k))(${lo},${hi},${step})`;
|
|
55705
|
+
}
|
|
54542
55706
|
/**
|
|
54543
55707
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
54544
55708
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -54969,8 +56133,7 @@ Error in definition of "${name}"`,
|
|
|
54969
56133
|
ce.pushScope();
|
|
54970
56134
|
try {
|
|
54971
56135
|
if (vars && typeof vars === "object") {
|
|
54972
|
-
for (const [k, v] of Object.entries(vars))
|
|
54973
|
-
ce.assign(k, v);
|
|
56136
|
+
for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
|
|
54974
56137
|
}
|
|
54975
56138
|
return expr2.evaluate().re;
|
|
54976
56139
|
} finally {
|
|
@@ -60200,8 +61363,7 @@ Error in definition of "${name}"`,
|
|
|
60200
61363
|
return { re: null, im: formatFloat(iScale) };
|
|
60201
61364
|
}
|
|
60202
61365
|
const compiledFactors = remaining.map((r) => compile3(r));
|
|
60203
|
-
if (iScale !== 1)
|
|
60204
|
-
compiledFactors.unshift(formatFloat(iScale));
|
|
61366
|
+
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
60205
61367
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
60206
61368
|
return { re: null, im: imCode };
|
|
60207
61369
|
}
|
|
@@ -60805,39 +61967,130 @@ Error in definition of "${name}"`,
|
|
|
60805
61967
|
if (args.length >= 2)
|
|
60806
61968
|
return `_SYS.colormap(${compile3(args[0])}, ${compile3(args[1])})`;
|
|
60807
61969
|
return `_SYS.colormap(${compile3(args[0])})`;
|
|
61970
|
+
},
|
|
61971
|
+
// -----------------------------------------------------------------------
|
|
61972
|
+
// Color constructor heads. All compile to OKLCh arrays at runtime — the
|
|
61973
|
+
// canonical color representation in this target. The constructors take
|
|
61974
|
+
// their own colorspace's components and convert internally.
|
|
61975
|
+
// (Mirrors the GPU target's design: color values are vec3 OKLCh.)
|
|
61976
|
+
// -----------------------------------------------------------------------
|
|
61977
|
+
Rgb: (args, compile3) => {
|
|
61978
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
61979
|
+
return `_SYS.rgb(${args.map(compile3).join(", ")})`;
|
|
61980
|
+
},
|
|
61981
|
+
Hsv: (args, compile3) => {
|
|
61982
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
61983
|
+
return `_SYS.hsv(${args.map(compile3).join(", ")})`;
|
|
61984
|
+
},
|
|
61985
|
+
Hsl: (args, compile3) => {
|
|
61986
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
61987
|
+
return `_SYS.hsl(${args.map(compile3).join(", ")})`;
|
|
61988
|
+
},
|
|
61989
|
+
Oklab: (args, compile3) => {
|
|
61990
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
61991
|
+
return `_SYS.oklab(${args.map(compile3).join(", ")})`;
|
|
61992
|
+
},
|
|
61993
|
+
Oklch: (args, compile3) => {
|
|
61994
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
61995
|
+
return `_SYS.oklch(${args.map(compile3).join(", ")})`;
|
|
61996
|
+
},
|
|
61997
|
+
// -----------------------------------------------------------------------
|
|
61998
|
+
// As* converters. Compile-time output convention matches the engine and
|
|
61999
|
+
// the GPU target: each returns components in the named space as a 3- or
|
|
62000
|
+
// 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
|
|
62001
|
+
// layers). `AsOklch` is the identity (canonical form).
|
|
62002
|
+
// -----------------------------------------------------------------------
|
|
62003
|
+
AsRgb: ([c], compile3) => {
|
|
62004
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
62005
|
+
return `_SYS.asRgb(${compile3(c)})`;
|
|
62006
|
+
},
|
|
62007
|
+
AsHsv: ([c], compile3) => {
|
|
62008
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
62009
|
+
return `_SYS.asHsv(${compile3(c)})`;
|
|
62010
|
+
},
|
|
62011
|
+
AsHsl: ([c], compile3) => {
|
|
62012
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
62013
|
+
return `_SYS.asHsl(${compile3(c)})`;
|
|
62014
|
+
},
|
|
62015
|
+
AsOklab: ([c], compile3) => {
|
|
62016
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
62017
|
+
return `_SYS.asOklab(${compile3(c)})`;
|
|
62018
|
+
},
|
|
62019
|
+
AsOklch: ([c], compile3) => {
|
|
62020
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
62021
|
+
return compile3(c);
|
|
62022
|
+
},
|
|
62023
|
+
// Perceptual color difference (ΔE_OK).
|
|
62024
|
+
ColorDelta: ([a, b], compile3) => {
|
|
62025
|
+
if (a === null || b === null)
|
|
62026
|
+
throw new Error("ColorDelta: need two colors");
|
|
62027
|
+
return `_SYS.colorDelta(${compile3(a)}, ${compile3(b)})`;
|
|
62028
|
+
},
|
|
62029
|
+
// Euclidean distance between two tuples (any positive dimension).
|
|
62030
|
+
// The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
|
|
62031
|
+
// (vec-only); this JS handler works on plain arrays of any length.
|
|
62032
|
+
Distance: ([a, b], compile3) => {
|
|
62033
|
+
if (a === null || b === null) throw new Error("Distance: need two points");
|
|
62034
|
+
return `_SYS.distance(${compile3(a)}, ${compile3(b)})`;
|
|
60808
62035
|
}
|
|
60809
62036
|
};
|
|
60810
62037
|
function toRI(c) {
|
|
60811
62038
|
return { re: c.re, im: c.im };
|
|
60812
62039
|
}
|
|
62040
|
+
function normalizeAlpha2(a) {
|
|
62041
|
+
if (a === void 0) return void 0;
|
|
62042
|
+
if (!Number.isFinite(a)) return void 0;
|
|
62043
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
62044
|
+
return a;
|
|
62045
|
+
}
|
|
60813
62046
|
function toRgb255(input) {
|
|
60814
62047
|
if (typeof input === "string") {
|
|
60815
62048
|
const c = parseColor(input);
|
|
60816
|
-
|
|
62049
|
+
const rgb2 = {
|
|
60817
62050
|
r: c >>> 24 & 255,
|
|
60818
62051
|
g: c >>> 16 & 255,
|
|
60819
|
-
b: c >>> 8 & 255
|
|
60820
|
-
alpha: (c & 255) / 255
|
|
62052
|
+
b: c >>> 8 & 255
|
|
60821
62053
|
};
|
|
62054
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62055
|
+
if (alpha !== void 0) rgb2.alpha = alpha;
|
|
62056
|
+
return rgb2;
|
|
62057
|
+
}
|
|
62058
|
+
const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
|
|
62059
|
+
if (input.length >= 4) {
|
|
62060
|
+
const alpha = normalizeAlpha2(input[3]);
|
|
62061
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
60822
62062
|
}
|
|
60823
|
-
const rgb = {
|
|
60824
|
-
r: input[0] * 255,
|
|
60825
|
-
g: input[1] * 255,
|
|
60826
|
-
b: input[2] * 255
|
|
60827
|
-
};
|
|
60828
|
-
if (input.length >= 4) rgb.alpha = input[3];
|
|
60829
62063
|
return rgb;
|
|
60830
62064
|
}
|
|
60831
|
-
function
|
|
60832
|
-
|
|
60833
|
-
|
|
60834
|
-
|
|
60835
|
-
|
|
60836
|
-
|
|
62065
|
+
function toOklch2(input) {
|
|
62066
|
+
if (typeof input === "string") {
|
|
62067
|
+
const c = parseColor(input);
|
|
62068
|
+
const r = c >>> 24 & 255;
|
|
62069
|
+
const g = c >>> 16 & 255;
|
|
62070
|
+
const b = c >>> 8 & 255;
|
|
62071
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62072
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62073
|
+
if (alpha !== void 0) oklch2.alpha = alpha;
|
|
62074
|
+
return oklch2;
|
|
62075
|
+
}
|
|
62076
|
+
return {
|
|
62077
|
+
L: input[0],
|
|
62078
|
+
C: input[1],
|
|
62079
|
+
H: input[2],
|
|
62080
|
+
alpha: input.length >= 4 ? normalizeAlpha2(input[3]) : void 0
|
|
62081
|
+
};
|
|
62082
|
+
}
|
|
62083
|
+
function packedToOklch(c) {
|
|
62084
|
+
const r = c >>> 24 & 255;
|
|
62085
|
+
const g = c >>> 16 & 255;
|
|
62086
|
+
const b = c >>> 8 & 255;
|
|
62087
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62088
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62089
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
60837
62090
|
}
|
|
60838
62091
|
var colorHelpers = {
|
|
60839
62092
|
color(input) {
|
|
60840
|
-
return
|
|
62093
|
+
return packedToOklch(parseColor(input));
|
|
60841
62094
|
},
|
|
60842
62095
|
colorToString(input, format) {
|
|
60843
62096
|
const rgb = toRgb255(input);
|
|
@@ -60848,7 +62101,7 @@ Error in definition of "${name}"`,
|
|
|
60848
62101
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
60849
62102
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
60850
62103
|
let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
60851
|
-
if (rgb.alpha !== void 0
|
|
62104
|
+
if (rgb.alpha !== void 0) {
|
|
60852
62105
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
60853
62106
|
hex += a.toString(16).padStart(2, "0");
|
|
60854
62107
|
}
|
|
@@ -60858,7 +62111,7 @@ Error in definition of "${name}"`,
|
|
|
60858
62111
|
const r = Math.round(rgb.r);
|
|
60859
62112
|
const g = Math.round(rgb.g);
|
|
60860
62113
|
const b = Math.round(rgb.b);
|
|
60861
|
-
if (rgb.alpha !== void 0
|
|
62114
|
+
if (rgb.alpha !== void 0)
|
|
60862
62115
|
return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
|
|
60863
62116
|
return `rgb(${r} ${g} ${b})`;
|
|
60864
62117
|
}
|
|
@@ -60867,7 +62120,7 @@ Error in definition of "${name}"`,
|
|
|
60867
62120
|
const h = Math.round(hsl.h * 10) / 10;
|
|
60868
62121
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
60869
62122
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
60870
|
-
if (rgb.alpha !== void 0
|
|
62123
|
+
if (rgb.alpha !== void 0)
|
|
60871
62124
|
return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
|
|
60872
62125
|
return `hsl(${h} ${s}% ${l}%)`;
|
|
60873
62126
|
}
|
|
@@ -60876,7 +62129,7 @@ Error in definition of "${name}"`,
|
|
|
60876
62129
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
60877
62130
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
60878
62131
|
const H = Math.round(c.H * 10) / 10;
|
|
60879
|
-
if (rgb.alpha !== void 0
|
|
62132
|
+
if (rgb.alpha !== void 0)
|
|
60880
62133
|
return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
|
|
60881
62134
|
return `oklch(${L} ${C} ${H})`;
|
|
60882
62135
|
}
|
|
@@ -60885,29 +62138,29 @@ Error in definition of "${name}"`,
|
|
|
60885
62138
|
}
|
|
60886
62139
|
},
|
|
60887
62140
|
colorMix(input1, input2, ratio = 0.5) {
|
|
60888
|
-
const
|
|
60889
|
-
const
|
|
62141
|
+
const c1 = toOklch2(input1);
|
|
62142
|
+
const c2 = toOklch2(input2);
|
|
60890
62143
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
60891
|
-
const
|
|
60892
|
-
const
|
|
60893
|
-
let
|
|
60894
|
-
if (
|
|
60895
|
-
if (
|
|
60896
|
-
|
|
60897
|
-
|
|
60898
|
-
|
|
60899
|
-
|
|
60900
|
-
|
|
60901
|
-
|
|
60902
|
-
H
|
|
60903
|
-
|
|
60904
|
-
|
|
60905
|
-
const
|
|
60906
|
-
const
|
|
60907
|
-
const a1 =
|
|
60908
|
-
const a2 =
|
|
60909
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
60910
|
-
return
|
|
62144
|
+
const c1Achromatic = c1.C < 1e-6;
|
|
62145
|
+
const c2Achromatic = c2.C < 1e-6;
|
|
62146
|
+
let H;
|
|
62147
|
+
if (c1Achromatic && c2Achromatic) H = c1.H;
|
|
62148
|
+
else if (c1Achromatic) H = c2.H;
|
|
62149
|
+
else if (c2Achromatic) H = c1.H;
|
|
62150
|
+
else {
|
|
62151
|
+
let dh = c2.H - c1.H;
|
|
62152
|
+
if (dh > 180) dh -= 360;
|
|
62153
|
+
if (dh < -180) dh += 360;
|
|
62154
|
+
H = c1.H + dh * ratio;
|
|
62155
|
+
if (H < 0) H += 360;
|
|
62156
|
+
if (H >= 360) H -= 360;
|
|
62157
|
+
}
|
|
62158
|
+
const L = c1.L + (c2.L - c1.L) * ratio;
|
|
62159
|
+
const C = c1.C + (c2.C - c1.C) * ratio;
|
|
62160
|
+
const a1 = c1.alpha ?? 1;
|
|
62161
|
+
const a2 = c2.alpha ?? 1;
|
|
62162
|
+
const alpha = normalizeAlpha2(a1 + (a2 - a1) * ratio);
|
|
62163
|
+
return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
|
|
60911
62164
|
},
|
|
60912
62165
|
colorContrast(bg, fg) {
|
|
60913
62166
|
return apca(toRgb255(bg), toRgb255(fg));
|
|
@@ -60915,11 +62168,11 @@ Error in definition of "${name}"`,
|
|
|
60915
62168
|
contrastingColor(bg, fg1, fg2) {
|
|
60916
62169
|
const bgRgb = toRgb255(bg);
|
|
60917
62170
|
if (fg1 !== void 0 && fg2 !== void 0) {
|
|
60918
|
-
return
|
|
62171
|
+
return packedToOklch(
|
|
60919
62172
|
contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
|
|
60920
62173
|
);
|
|
60921
62174
|
}
|
|
60922
|
-
return
|
|
62175
|
+
return packedToOklch(contrastingColor(bgRgb));
|
|
60923
62176
|
},
|
|
60924
62177
|
colorToColorspace(input, space) {
|
|
60925
62178
|
const rgb = toRgb255(input);
|
|
@@ -60948,7 +62201,7 @@ Error in definition of "${name}"`,
|
|
|
60948
62201
|
default:
|
|
60949
62202
|
throw new Error(`Unknown color space: ${space}`);
|
|
60950
62203
|
}
|
|
60951
|
-
if (alpha !== void 0
|
|
62204
|
+
if (alpha !== void 0) result.push(alpha);
|
|
60952
62205
|
return result;
|
|
60953
62206
|
},
|
|
60954
62207
|
colormap(name, arg) {
|
|
@@ -60960,7 +62213,7 @@ Error in definition of "${name}"`,
|
|
|
60960
62213
|
const palette = allPalettes[name];
|
|
60961
62214
|
if (!palette) throw new Error(`Unknown palette: ${name}`);
|
|
60962
62215
|
const colors = palette.map(
|
|
60963
|
-
(hex) =>
|
|
62216
|
+
(hex) => packedToOklch(parseColor(hex))
|
|
60964
62217
|
);
|
|
60965
62218
|
if (arg === void 0) return colors;
|
|
60966
62219
|
if (Number.isInteger(arg) && arg >= 2) {
|
|
@@ -60984,62 +62237,128 @@ Error in definition of "${name}"`,
|
|
|
60984
62237
|
const frac = pos - i;
|
|
60985
62238
|
if (frac === 0 || i >= colors.length - 1)
|
|
60986
62239
|
return [...colors[Math.min(i, colors.length - 1)]];
|
|
60987
|
-
const
|
|
60988
|
-
|
|
60989
|
-
|
|
60990
|
-
|
|
60991
|
-
|
|
60992
|
-
|
|
60993
|
-
|
|
60994
|
-
|
|
60995
|
-
|
|
60996
|
-
|
|
60997
|
-
|
|
60998
|
-
|
|
60999
|
-
|
|
61000
|
-
|
|
61001
|
-
|
|
61002
|
-
|
|
61003
|
-
|
|
61004
|
-
if (H >= 360) H -= 360;
|
|
61005
|
-
const mixed = oklchToRgb({
|
|
61006
|
-
L: c1.L + (c2.L - c1.L) * frac,
|
|
61007
|
-
C: c1.C + (c2.C - c1.C) * frac,
|
|
61008
|
-
H
|
|
61009
|
-
});
|
|
61010
|
-
return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
|
|
62240
|
+
const [L1, C1, H1] = colors[i];
|
|
62241
|
+
const [L2, C2, H2] = colors[i + 1];
|
|
62242
|
+
const c1Achromatic = C1 < 1e-6;
|
|
62243
|
+
const c2Achromatic = C2 < 1e-6;
|
|
62244
|
+
let H;
|
|
62245
|
+
if (c1Achromatic && c2Achromatic) H = H1;
|
|
62246
|
+
else if (c1Achromatic) H = H2;
|
|
62247
|
+
else if (c2Achromatic) H = H1;
|
|
62248
|
+
else {
|
|
62249
|
+
let dh = H2 - H1;
|
|
62250
|
+
if (dh > 180) dh -= 360;
|
|
62251
|
+
if (dh < -180) dh += 360;
|
|
62252
|
+
H = H1 + dh * frac;
|
|
62253
|
+
if (H < 0) H += 360;
|
|
62254
|
+
if (H >= 360) H -= 360;
|
|
62255
|
+
}
|
|
62256
|
+
return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
|
|
61011
62257
|
},
|
|
61012
62258
|
colorFromColorspace(components, space) {
|
|
61013
62259
|
const c0 = components[0];
|
|
61014
62260
|
const c1 = components[1];
|
|
61015
62261
|
const c2 = components[2];
|
|
61016
62262
|
const alpha = components.length >= 4 ? components[3] : void 0;
|
|
61017
|
-
let
|
|
62263
|
+
let oklch2;
|
|
61018
62264
|
switch (space.toLowerCase()) {
|
|
61019
62265
|
case "rgb":
|
|
61020
|
-
|
|
62266
|
+
oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
|
|
61021
62267
|
break;
|
|
61022
62268
|
case "hsl": {
|
|
61023
|
-
const
|
|
61024
|
-
|
|
62269
|
+
const rgb = hslToRgb(c0, c1, c2);
|
|
62270
|
+
oklch2 = rgbToOklch(rgb);
|
|
61025
62271
|
break;
|
|
61026
62272
|
}
|
|
61027
|
-
case "oklch":
|
|
61028
|
-
|
|
61029
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62273
|
+
case "oklch":
|
|
62274
|
+
oklch2 = { L: c0, C: c1, H: c2 };
|
|
61030
62275
|
break;
|
|
61031
|
-
}
|
|
61032
62276
|
case "oklab":
|
|
61033
|
-
case "lab":
|
|
61034
|
-
|
|
61035
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62277
|
+
case "lab":
|
|
62278
|
+
oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
|
|
61036
62279
|
break;
|
|
61037
|
-
}
|
|
61038
62280
|
default:
|
|
61039
62281
|
throw new Error(`Unknown color space: ${space}`);
|
|
61040
62282
|
}
|
|
61041
|
-
|
|
61042
|
-
|
|
62283
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
62284
|
+
},
|
|
62285
|
+
// -----------------------------------------------------------------------
|
|
62286
|
+
// Color constructors. Each accepts components in its colorspace's natural
|
|
62287
|
+
// units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
|
|
62288
|
+
// -----------------------------------------------------------------------
|
|
62289
|
+
rgb(r, g, b, alpha) {
|
|
62290
|
+
const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
|
|
62291
|
+
const a = normalizeAlpha2(alpha);
|
|
62292
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62293
|
+
},
|
|
62294
|
+
hsv(h, s, v, alpha) {
|
|
62295
|
+
const rgb = hsvToRgb(h, s, v);
|
|
62296
|
+
const c = rgbToOklch(rgb);
|
|
62297
|
+
const a = normalizeAlpha2(alpha);
|
|
62298
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62299
|
+
},
|
|
62300
|
+
hsl(h, s, l, alpha) {
|
|
62301
|
+
const rgb = hslToRgb(h, s, l);
|
|
62302
|
+
const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
|
|
62303
|
+
const a = normalizeAlpha2(alpha);
|
|
62304
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62305
|
+
},
|
|
62306
|
+
oklab(L, a, b, alpha) {
|
|
62307
|
+
const c = oklabToOklch({ L, a, b });
|
|
62308
|
+
const al = normalizeAlpha2(alpha);
|
|
62309
|
+
return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
|
|
62310
|
+
},
|
|
62311
|
+
oklch(L, C, H, alpha) {
|
|
62312
|
+
const a = normalizeAlpha2(alpha);
|
|
62313
|
+
return a !== void 0 ? [L, C, H, a] : [L, C, H];
|
|
62314
|
+
},
|
|
62315
|
+
// -----------------------------------------------------------------------
|
|
62316
|
+
// As* converters. Inputs are anything `toOklch` accepts (string, packed
|
|
62317
|
+
// int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
|
|
62318
|
+
// space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
|
|
62319
|
+
// consistency with the GPU target's shader convention.
|
|
62320
|
+
// -----------------------------------------------------------------------
|
|
62321
|
+
asRgb(input) {
|
|
62322
|
+
const rgb = toRgb255(input);
|
|
62323
|
+
const r = rgb.r / 255;
|
|
62324
|
+
const g = rgb.g / 255;
|
|
62325
|
+
const b = rgb.b / 255;
|
|
62326
|
+
return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
|
|
62327
|
+
},
|
|
62328
|
+
asHsv(input) {
|
|
62329
|
+
const rgb = toRgb255(input);
|
|
62330
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
62331
|
+
return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
|
|
62332
|
+
},
|
|
62333
|
+
asHsl(input) {
|
|
62334
|
+
const rgb = toRgb255(input);
|
|
62335
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
62336
|
+
return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
|
|
62337
|
+
},
|
|
62338
|
+
asOklab(input) {
|
|
62339
|
+
const c = toOklch2(input);
|
|
62340
|
+
const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
|
|
62341
|
+
return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
|
|
62342
|
+
},
|
|
62343
|
+
// asOklch is identity — handled at compile time as a pass-through
|
|
62344
|
+
// Perceptual color difference (ΔE_OK).
|
|
62345
|
+
colorDelta(a, b) {
|
|
62346
|
+
const labA = oklchToOklab(toOklch2(a));
|
|
62347
|
+
const labB = oklchToOklab(toOklch2(b));
|
|
62348
|
+
return oklabDeltaE(labA, labB);
|
|
62349
|
+
},
|
|
62350
|
+
// Euclidean distance between two tuples. Plain numeric — not a color
|
|
62351
|
+
// operation despite living in the same helpers block.
|
|
62352
|
+
distance(a, b) {
|
|
62353
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
62354
|
+
throw new Error("Distance: expected two arrays");
|
|
62355
|
+
if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
|
|
62356
|
+
let sumSq = 0;
|
|
62357
|
+
for (let i = 0; i < a.length; i++) {
|
|
62358
|
+
const d = a[i] - b[i];
|
|
62359
|
+
sumSq += d * d;
|
|
62360
|
+
}
|
|
62361
|
+
return Math.sqrt(sumSq);
|
|
61043
62362
|
}
|
|
61044
62363
|
};
|
|
61045
62364
|
var SYS_HELPERS = {
|
|
@@ -61478,6 +62797,13 @@ Error in definition of "${name}"`,
|
|
|
61478
62797
|
function gpuVec2(target) {
|
|
61479
62798
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
61480
62799
|
}
|
|
62800
|
+
function gpuVec3(target) {
|
|
62801
|
+
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
62802
|
+
}
|
|
62803
|
+
function readStringLiteral(expr2) {
|
|
62804
|
+
if (!isString(expr2)) return null;
|
|
62805
|
+
return expr2.string?.toLowerCase() ?? null;
|
|
62806
|
+
}
|
|
61481
62807
|
function compileIntArg(expr2, compile3, target) {
|
|
61482
62808
|
const c = tryGetConstant(expr2);
|
|
61483
62809
|
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
@@ -61536,7 +62862,7 @@ Error in definition of "${name}"`,
|
|
|
61536
62862
|
`for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
|
|
61537
62863
|
` ${acc} ${op}= ${body};`,
|
|
61538
62864
|
`}`,
|
|
61539
|
-
`return ${acc}
|
|
62865
|
+
`return ${acc};`
|
|
61540
62866
|
];
|
|
61541
62867
|
return lines.join("\n");
|
|
61542
62868
|
}
|
|
@@ -61590,8 +62916,7 @@ Error in definition of "${name}"`,
|
|
|
61590
62916
|
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
61591
62917
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
61592
62918
|
const v2 = gpuVec2(target);
|
|
61593
|
-
if (realFactors.length === 0)
|
|
61594
|
-
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
62919
|
+
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
61595
62920
|
const factors = realFactors.map((f) => compile3(f));
|
|
61596
62921
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
61597
62922
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
@@ -61644,8 +62969,7 @@ Error in definition of "${name}"`,
|
|
|
61644
62969
|
if (isNumber(x) && x.im !== 0) {
|
|
61645
62970
|
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
61646
62971
|
}
|
|
61647
|
-
if (isSymbol2(x, "ImaginaryUnit"))
|
|
61648
|
-
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
62972
|
+
if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
61649
62973
|
return `(-${compile3(x)})`;
|
|
61650
62974
|
},
|
|
61651
62975
|
// Standard math functions with complex dispatch
|
|
@@ -62018,17 +63342,127 @@ Error in definition of "${name}"`,
|
|
|
62018
63342
|
}
|
|
62019
63343
|
const isWGSL = target?.language === "wgsl";
|
|
62020
63344
|
const v3 = isWGSL ? "vec3f" : "vec3";
|
|
62021
|
-
|
|
63345
|
+
const black = `${v3}(0.0)`;
|
|
63346
|
+
const white = `${v3}(1.0, 0.0, 0.0)`;
|
|
63347
|
+
return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
|
|
62022
63348
|
},
|
|
62023
63349
|
ColorToColorspace: ([color, space], compile3) => {
|
|
62024
63350
|
if (color === null || space === null)
|
|
62025
63351
|
throw new Error("ColorToColorspace: need color and space");
|
|
62026
|
-
|
|
63352
|
+
const spaceName = readStringLiteral(space);
|
|
63353
|
+
if (spaceName === null)
|
|
63354
|
+
throw new Error("ColorToColorspace: space must be a string literal");
|
|
63355
|
+
const c = compile3(color);
|
|
63356
|
+
switch (spaceName) {
|
|
63357
|
+
case "oklch":
|
|
63358
|
+
return c;
|
|
63359
|
+
case "oklab":
|
|
63360
|
+
case "lab":
|
|
63361
|
+
return `_gpu_oklch_to_oklab(${c})`;
|
|
63362
|
+
case "rgb":
|
|
63363
|
+
return `_gpu_oklch_to_srgb(${c})`;
|
|
63364
|
+
case "hsl":
|
|
63365
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
|
|
63366
|
+
case "hsv":
|
|
63367
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
|
|
63368
|
+
default:
|
|
63369
|
+
throw new Error(
|
|
63370
|
+
`ColorToColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63371
|
+
);
|
|
63372
|
+
}
|
|
62027
63373
|
},
|
|
62028
63374
|
ColorFromColorspace: ([components, space], compile3) => {
|
|
62029
63375
|
if (components === null || space === null)
|
|
62030
63376
|
throw new Error("ColorFromColorspace: need components and space");
|
|
62031
|
-
|
|
63377
|
+
const spaceName = readStringLiteral(space);
|
|
63378
|
+
if (spaceName === null)
|
|
63379
|
+
throw new Error("ColorFromColorspace: space must be a string literal");
|
|
63380
|
+
const c = compile3(components);
|
|
63381
|
+
switch (spaceName) {
|
|
63382
|
+
case "oklch":
|
|
63383
|
+
return c;
|
|
63384
|
+
case "oklab":
|
|
63385
|
+
case "lab":
|
|
63386
|
+
return `_gpu_oklab_to_oklch(${c})`;
|
|
63387
|
+
case "rgb":
|
|
63388
|
+
return `_gpu_srgb_to_oklch(${c})`;
|
|
63389
|
+
case "hsl":
|
|
63390
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
|
|
63391
|
+
case "hsv":
|
|
63392
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
|
|
63393
|
+
default:
|
|
63394
|
+
throw new Error(
|
|
63395
|
+
`ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63396
|
+
);
|
|
63397
|
+
}
|
|
63398
|
+
},
|
|
63399
|
+
// ---------------------------------------------------------------------------
|
|
63400
|
+
// Color literals. Each typed head compiles to a canonical OKLCh vec3.
|
|
63401
|
+
// Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
|
|
63402
|
+
// alpha as a separate uniform if it's needed at the framebuffer boundary.
|
|
63403
|
+
// ---------------------------------------------------------------------------
|
|
63404
|
+
Color: ([s], _compile2, target) => {
|
|
63405
|
+
if (s === null) throw new Error("Color: no argument");
|
|
63406
|
+
const str = readStringLiteral(s);
|
|
63407
|
+
if (str === null)
|
|
63408
|
+
throw new Error("Color: argument must be a string literal on GPU target");
|
|
63409
|
+
const packed = parseColor(str);
|
|
63410
|
+
if (packed === 0 && str.trim().toLowerCase() !== "transparent")
|
|
63411
|
+
throw new Error(`Color: invalid color string "${str}"`);
|
|
63412
|
+
const r = packed >>> 24 & 255;
|
|
63413
|
+
const g = packed >>> 16 & 255;
|
|
63414
|
+
const b = packed >>> 8 & 255;
|
|
63415
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
63416
|
+
return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
|
|
63417
|
+
},
|
|
63418
|
+
Rgb: (args, compile3, target) => {
|
|
63419
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
63420
|
+
const v3 = gpuVec3(target);
|
|
63421
|
+
return `_gpu_srgb_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63422
|
+
},
|
|
63423
|
+
Hsv: (args, compile3, target) => {
|
|
63424
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
63425
|
+
const v3 = gpuVec3(target);
|
|
63426
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63427
|
+
},
|
|
63428
|
+
Hsl: (args, compile3, target) => {
|
|
63429
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
63430
|
+
const v3 = gpuVec3(target);
|
|
63431
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63432
|
+
},
|
|
63433
|
+
Oklab: (args, compile3, target) => {
|
|
63434
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
63435
|
+
const v3 = gpuVec3(target);
|
|
63436
|
+
return `_gpu_oklab_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63437
|
+
},
|
|
63438
|
+
Oklch: (args, compile3, target) => {
|
|
63439
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
63440
|
+
const v3 = gpuVec3(target);
|
|
63441
|
+
return `${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})`;
|
|
63442
|
+
},
|
|
63443
|
+
// ---------------------------------------------------------------------------
|
|
63444
|
+
// As* operators. AsOklch is identity (canonical). The other As* return
|
|
63445
|
+
// components in the named space, equivalent to ColorToColorspace(c, 'x').
|
|
63446
|
+
// ---------------------------------------------------------------------------
|
|
63447
|
+
AsOklch: ([c], compile3) => {
|
|
63448
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
63449
|
+
return compile3(c);
|
|
63450
|
+
},
|
|
63451
|
+
AsOklab: ([c], compile3) => {
|
|
63452
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
63453
|
+
return `_gpu_oklch_to_oklab(${compile3(c)})`;
|
|
63454
|
+
},
|
|
63455
|
+
AsRgb: ([c], compile3) => {
|
|
63456
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
63457
|
+
return `_gpu_oklch_to_srgb(${compile3(c)})`;
|
|
63458
|
+
},
|
|
63459
|
+
AsHsv: ([c], compile3) => {
|
|
63460
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
63461
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
63462
|
+
},
|
|
63463
|
+
AsHsl: ([c], compile3) => {
|
|
63464
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
63465
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
62032
63466
|
},
|
|
62033
63467
|
// Fractal functions
|
|
62034
63468
|
Mandelbrot: ([c, maxIter], compile3, target) => {
|
|
@@ -62721,28 +64155,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
|
|
|
62721
64155
|
|
|
62722
64156
|
vec3 _gpu_oklab_to_oklch(vec3 lab) {
|
|
62723
64157
|
float C = length(lab.yz);
|
|
62724
|
-
float H = atan(lab.z, lab.y);
|
|
64158
|
+
float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64159
|
+
if (H < 0.0) H += 360.0;
|
|
62725
64160
|
return vec3(lab.x, C, H);
|
|
62726
64161
|
}
|
|
62727
64162
|
|
|
62728
64163
|
vec3 _gpu_oklch_to_oklab(vec3 lch) {
|
|
62729
|
-
|
|
64164
|
+
float h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64165
|
+
return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64166
|
+
}
|
|
64167
|
+
|
|
64168
|
+
vec3 _gpu_srgb_to_oklch(vec3 rgb) {
|
|
64169
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
62730
64170
|
}
|
|
62731
64171
|
|
|
62732
|
-
vec3
|
|
62733
|
-
|
|
62734
|
-
|
|
64172
|
+
vec3 _gpu_oklch_to_srgb(vec3 lch) {
|
|
64173
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64174
|
+
}
|
|
64175
|
+
|
|
64176
|
+
// HSL conversion. Hue in degrees, saturation/lightness in 0-1.
|
|
64177
|
+
vec3 _gpu_hsl_to_rgb(vec3 hsl) {
|
|
64178
|
+
float h = hsl.x;
|
|
64179
|
+
float s = hsl.y;
|
|
64180
|
+
float l = hsl.z;
|
|
64181
|
+
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64182
|
+
float h6 = h / 60.0;
|
|
64183
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64184
|
+
float r = 0.0;
|
|
64185
|
+
float g = 0.0;
|
|
64186
|
+
float b = 0.0;
|
|
64187
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64188
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64189
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64190
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64191
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64192
|
+
else { r = c; g = 0.0; b = x; }
|
|
64193
|
+
float m = l - c / 2.0;
|
|
64194
|
+
return vec3(r + m, g + m, b + m);
|
|
64195
|
+
}
|
|
64196
|
+
|
|
64197
|
+
vec3 _gpu_rgb_to_hsl(vec3 rgb) {
|
|
64198
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64199
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64200
|
+
float l = (maxc + minc) / 2.0;
|
|
64201
|
+
float d = maxc - minc;
|
|
64202
|
+
if (d < 1e-6) return vec3(0.0, 0.0, l);
|
|
64203
|
+
float s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64204
|
+
float h;
|
|
64205
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64206
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64207
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64208
|
+
h *= 60.0;
|
|
64209
|
+
if (h < 0.0) h += 360.0;
|
|
64210
|
+
return vec3(h, s, l);
|
|
64211
|
+
}
|
|
64212
|
+
|
|
64213
|
+
// HSV conversion. Hue in degrees, saturation/value in 0-1.
|
|
64214
|
+
vec3 _gpu_hsv_to_rgb(vec3 hsv) {
|
|
64215
|
+
float h = hsv.x;
|
|
64216
|
+
float s = hsv.y;
|
|
64217
|
+
float v = hsv.z;
|
|
64218
|
+
float c = v * s;
|
|
64219
|
+
float h6 = h / 60.0;
|
|
64220
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64221
|
+
float r = 0.0;
|
|
64222
|
+
float g = 0.0;
|
|
64223
|
+
float b = 0.0;
|
|
64224
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64225
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64226
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64227
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64228
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64229
|
+
else { r = c; g = 0.0; b = x; }
|
|
64230
|
+
float m = v - c;
|
|
64231
|
+
return vec3(r + m, g + m, b + m);
|
|
64232
|
+
}
|
|
64233
|
+
|
|
64234
|
+
vec3 _gpu_rgb_to_hsv(vec3 rgb) {
|
|
64235
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64236
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64237
|
+
float v = maxc;
|
|
64238
|
+
float d = maxc - minc;
|
|
64239
|
+
if (d < 1e-6) return vec3(0.0, 0.0, v);
|
|
64240
|
+
float s = (maxc < 1e-6) ? 0.0 : d / maxc;
|
|
64241
|
+
float h;
|
|
64242
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64243
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64244
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64245
|
+
h *= 60.0;
|
|
64246
|
+
if (h < 0.0) h += 360.0;
|
|
64247
|
+
return vec3(h, s, v);
|
|
64248
|
+
}
|
|
64249
|
+
|
|
64250
|
+
vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
|
|
62735
64251
|
float L = mix(lch1.x, lch2.x, t);
|
|
62736
64252
|
float C = mix(lch1.y, lch2.y, t);
|
|
62737
|
-
|
|
62738
|
-
|
|
62739
|
-
|
|
62740
|
-
if (
|
|
62741
|
-
|
|
62742
|
-
|
|
64253
|
+
bool a1 = lch1.y < 1e-6;
|
|
64254
|
+
bool a2 = lch2.y < 1e-6;
|
|
64255
|
+
float H;
|
|
64256
|
+
if (a1 && a2) {
|
|
64257
|
+
H = lch1.z;
|
|
64258
|
+
} else if (a1) {
|
|
64259
|
+
H = lch2.z;
|
|
64260
|
+
} else if (a2) {
|
|
64261
|
+
H = lch1.z;
|
|
64262
|
+
} else {
|
|
64263
|
+
float dh = lch2.z - lch1.z;
|
|
64264
|
+
if (dh > 180.0) dh -= 360.0;
|
|
64265
|
+
if (dh < -180.0) dh += 360.0;
|
|
64266
|
+
H = lch1.z + dh * t;
|
|
64267
|
+
if (H < 0.0) H += 360.0;
|
|
64268
|
+
if (H >= 360.0) H -= 360.0;
|
|
64269
|
+
}
|
|
64270
|
+
return vec3(L, C, H);
|
|
62743
64271
|
}
|
|
62744
64272
|
|
|
62745
|
-
float _gpu_apca(vec3
|
|
64273
|
+
float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
|
|
64274
|
+
vec3 bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64275
|
+
vec3 fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62746
64276
|
float bgR = _gpu_srgb_to_linear(bg.x);
|
|
62747
64277
|
float bgG = _gpu_srgb_to_linear(bg.y);
|
|
62748
64278
|
float bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -62753,9 +64283,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
|
|
|
62753
64283
|
float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
|
|
62754
64284
|
float bgC = pow(bgY, 0.56);
|
|
62755
64285
|
float fgC = pow(fgY, 0.57);
|
|
62756
|
-
float contrast = (bgC
|
|
62757
|
-
? (bgC - fgC) * 1.14
|
|
62758
|
-
: (bgC - fgC) * 1.14;
|
|
64286
|
+
float contrast = (bgC - fgC) * 1.14;
|
|
62759
64287
|
return contrast * 100.0;
|
|
62760
64288
|
}
|
|
62761
64289
|
`;
|
|
@@ -62799,28 +64327,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
|
|
|
62799
64327
|
|
|
62800
64328
|
fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
|
|
62801
64329
|
let C = length(lab.yz);
|
|
62802
|
-
|
|
64330
|
+
var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64331
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
62803
64332
|
return vec3f(lab.x, C, H);
|
|
62804
64333
|
}
|
|
62805
64334
|
|
|
62806
64335
|
fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
|
|
62807
|
-
|
|
64336
|
+
let h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64337
|
+
return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64338
|
+
}
|
|
64339
|
+
|
|
64340
|
+
fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
|
|
64341
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
64342
|
+
}
|
|
64343
|
+
|
|
64344
|
+
fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
|
|
64345
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64346
|
+
}
|
|
64347
|
+
|
|
64348
|
+
fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
|
|
64349
|
+
let h = hsl.x;
|
|
64350
|
+
let s = hsl.y;
|
|
64351
|
+
let l = hsl.z;
|
|
64352
|
+
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64353
|
+
let h6 = h / 60.0;
|
|
64354
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64355
|
+
var r: f32 = 0.0;
|
|
64356
|
+
var g: f32 = 0.0;
|
|
64357
|
+
var b: f32 = 0.0;
|
|
64358
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64359
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64360
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64361
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64362
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64363
|
+
else { r = c; g = 0.0; b = x; }
|
|
64364
|
+
let m = l - c / 2.0;
|
|
64365
|
+
return vec3f(r + m, g + m, b + m);
|
|
62808
64366
|
}
|
|
62809
64367
|
|
|
62810
|
-
fn
|
|
62811
|
-
let
|
|
62812
|
-
let
|
|
64368
|
+
fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
|
|
64369
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64370
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64371
|
+
let l = (maxc + minc) / 2.0;
|
|
64372
|
+
let d = maxc - minc;
|
|
64373
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
|
|
64374
|
+
let s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64375
|
+
var h: f32;
|
|
64376
|
+
if (maxc == rgb.x) {
|
|
64377
|
+
let v = (rgb.y - rgb.z) / d;
|
|
64378
|
+
h = v - 6.0 * floor(v / 6.0);
|
|
64379
|
+
} else if (maxc == rgb.y) {
|
|
64380
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64381
|
+
} else {
|
|
64382
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64383
|
+
}
|
|
64384
|
+
h = h * 60.0;
|
|
64385
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64386
|
+
return vec3f(h, s, l);
|
|
64387
|
+
}
|
|
64388
|
+
|
|
64389
|
+
fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
|
|
64390
|
+
let h = hsv.x;
|
|
64391
|
+
let s = hsv.y;
|
|
64392
|
+
let v = hsv.z;
|
|
64393
|
+
let c = v * s;
|
|
64394
|
+
let h6 = h / 60.0;
|
|
64395
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64396
|
+
var r: f32 = 0.0;
|
|
64397
|
+
var g: f32 = 0.0;
|
|
64398
|
+
var b: f32 = 0.0;
|
|
64399
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64400
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64401
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64402
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64403
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64404
|
+
else { r = c; g = 0.0; b = x; }
|
|
64405
|
+
let m = v - c;
|
|
64406
|
+
return vec3f(r + m, g + m, b + m);
|
|
64407
|
+
}
|
|
64408
|
+
|
|
64409
|
+
fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
|
|
64410
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64411
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64412
|
+
let v = maxc;
|
|
64413
|
+
let d = maxc - minc;
|
|
64414
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
|
|
64415
|
+
var s: f32 = 0.0;
|
|
64416
|
+
if (maxc >= 1e-6) { s = d / maxc; }
|
|
64417
|
+
var h: f32;
|
|
64418
|
+
if (maxc == rgb.x) {
|
|
64419
|
+
let q = (rgb.y - rgb.z) / d;
|
|
64420
|
+
h = q - 6.0 * floor(q / 6.0);
|
|
64421
|
+
} else if (maxc == rgb.y) {
|
|
64422
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64423
|
+
} else {
|
|
64424
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64425
|
+
}
|
|
64426
|
+
h = h * 60.0;
|
|
64427
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64428
|
+
return vec3f(h, s, v);
|
|
64429
|
+
}
|
|
64430
|
+
|
|
64431
|
+
fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
|
|
62813
64432
|
let L = mix(lch1.x, lch2.x, t);
|
|
62814
64433
|
let C = mix(lch1.y, lch2.y, t);
|
|
62815
|
-
let
|
|
62816
|
-
|
|
62817
|
-
|
|
62818
|
-
if (
|
|
62819
|
-
|
|
62820
|
-
|
|
64434
|
+
let a1 = lch1.y < 1e-6;
|
|
64435
|
+
let a2 = lch2.y < 1e-6;
|
|
64436
|
+
var H: f32;
|
|
64437
|
+
if (a1 && a2) {
|
|
64438
|
+
H = lch1.z;
|
|
64439
|
+
} else if (a1) {
|
|
64440
|
+
H = lch2.z;
|
|
64441
|
+
} else if (a2) {
|
|
64442
|
+
H = lch1.z;
|
|
64443
|
+
} else {
|
|
64444
|
+
var dh = lch2.z - lch1.z;
|
|
64445
|
+
if (dh > 180.0) { dh = dh - 360.0; }
|
|
64446
|
+
if (dh < -180.0) { dh = dh + 360.0; }
|
|
64447
|
+
H = lch1.z + dh * t;
|
|
64448
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
64449
|
+
if (H >= 360.0) { H = H - 360.0; }
|
|
64450
|
+
}
|
|
64451
|
+
return vec3f(L, C, H);
|
|
62821
64452
|
}
|
|
62822
64453
|
|
|
62823
|
-
fn _gpu_apca(
|
|
64454
|
+
fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
64455
|
+
let bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64456
|
+
let fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62824
64457
|
let bgR = _gpu_srgb_to_linear(bg.x);
|
|
62825
64458
|
let bgG = _gpu_srgb_to_linear(bg.y);
|
|
62826
64459
|
let bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -63108,7 +64741,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
63108
64741
|
if (stmts.length === 0) return "";
|
|
63109
64742
|
const last = stmts.length - 1;
|
|
63110
64743
|
stmts[last] = `return ${stmts[last]}`;
|
|
63111
|
-
return stmts.join(";\n");
|
|
64744
|
+
return stmts.join(";\n") + ";";
|
|
63112
64745
|
},
|
|
63113
64746
|
...options
|
|
63114
64747
|
};
|
|
@@ -63207,7 +64840,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
63207
64840
|
if (body.includes("\n")) {
|
|
63208
64841
|
const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
|
|
63209
64842
|
return `${returnType} ${functionName}(${params}) {
|
|
63210
|
-
${indented}
|
|
64843
|
+
${indented}
|
|
63211
64844
|
}`;
|
|
63212
64845
|
}
|
|
63213
64846
|
return `${returnType} ${functionName}(${params}) {
|
|
@@ -63318,7 +64951,7 @@ ${indented};
|
|
|
63318
64951
|
return `fn ${functionName}(${params}) -> ${toWGSLType(
|
|
63319
64952
|
returnType
|
|
63320
64953
|
)} {
|
|
63321
|
-
${indented}
|
|
64954
|
+
${indented}
|
|
63322
64955
|
}`;
|
|
63323
64956
|
}
|
|
63324
64957
|
return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
|
|
@@ -67303,6 +68936,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
67303
68936
|
this.pushScope(void 0, "global");
|
|
67304
68937
|
this._compilationTargets.registerDefaults();
|
|
67305
68938
|
if (options?.latexSyntax) this._latexSyntax = options.latexSyntax;
|
|
68939
|
+
if (options?.latexOptions) this._latexOptions = { ...options.latexOptions };
|
|
67306
68940
|
hidePrivateProperties(this);
|
|
67307
68941
|
}
|
|
67308
68942
|
toJSON() {
|
|
@@ -67717,6 +69351,15 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
67717
69351
|
lookupDefinition(id) {
|
|
67718
69352
|
return lookupDefinition(this, id);
|
|
67719
69353
|
}
|
|
69354
|
+
operatorInfo(head) {
|
|
69355
|
+
const def = this.lookupDefinition(head);
|
|
69356
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
69357
|
+
const op = def.operator;
|
|
69358
|
+
return {
|
|
69359
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
69360
|
+
signature: op.signature
|
|
69361
|
+
};
|
|
69362
|
+
}
|
|
67720
69363
|
/**
|
|
67721
69364
|
* Associate a new definition to a symbol in the current context.
|
|
67722
69365
|
*
|
|
@@ -67963,6 +69606,29 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
67963
69606
|
);
|
|
67964
69607
|
return this._latexSyntax;
|
|
67965
69608
|
}
|
|
69609
|
+
/** @internal Engine-wide LaTeX parse/serialize options (e.g. decimalSeparator).
|
|
69610
|
+
* Merged into every `parse()` and `toLatex()` call between the LatexSyntax
|
|
69611
|
+
* instance defaults and any per-call overrides. */
|
|
69612
|
+
_latexOptions = {};
|
|
69613
|
+
/** Engine-wide LaTeX parse/serialize options.
|
|
69614
|
+
*
|
|
69615
|
+
* These options are merged into every `parse()` and `toLatex()` call.
|
|
69616
|
+
* Precedence (most-specific wins):
|
|
69617
|
+
* 1. LatexSyntax instance defaults (set at its construction)
|
|
69618
|
+
* 2. `ce.latexOptions` (this property)
|
|
69619
|
+
* 3. Per-call options passed to `ce.parse()` / `expr.toLatex()`
|
|
69620
|
+
*
|
|
69621
|
+
* Assigning replaces the whole bag. Use spread to merge:
|
|
69622
|
+
* ```ts
|
|
69623
|
+
* ce.latexOptions = { ...ce.latexOptions, decimalSeparator: '{,}' };
|
|
69624
|
+
* ```
|
|
69625
|
+
*/
|
|
69626
|
+
get latexOptions() {
|
|
69627
|
+
return this._latexOptions;
|
|
69628
|
+
}
|
|
69629
|
+
set latexOptions(options) {
|
|
69630
|
+
this._latexOptions = { ...options };
|
|
69631
|
+
}
|
|
67966
69632
|
parse(latex, options) {
|
|
67967
69633
|
if (latex === null || latex === void 0) return null;
|
|
67968
69634
|
if (typeof latex !== "string")
|
|
@@ -67970,7 +69636,6 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
67970
69636
|
const syntax = this._requireLatexSyntax();
|
|
67971
69637
|
const { form, ...parseOpts } = options ?? {};
|
|
67972
69638
|
const result = syntax.parse(latex, {
|
|
67973
|
-
decimalSeparator: ".",
|
|
67974
69639
|
getSymbolType: (id) => {
|
|
67975
69640
|
const def = this.lookupDefinition(id);
|
|
67976
69641
|
if (!def) return BoxedType.unknown;
|
|
@@ -67982,6 +69647,8 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
67982
69647
|
const def = this.lookupDefinition(id);
|
|
67983
69648
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
67984
69649
|
},
|
|
69650
|
+
tolerance: this.tolerance,
|
|
69651
|
+
...this._latexOptions,
|
|
67985
69652
|
...parseOpts
|
|
67986
69653
|
});
|
|
67987
69654
|
if (result === null) return null;
|
|
@@ -68145,7 +69812,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
68145
69812
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
68146
69813
|
|
|
68147
69814
|
// src/core.ts
|
|
68148
|
-
var version = "0.
|
|
69815
|
+
var version = "0.57.0";
|
|
68149
69816
|
return __toCommonJS(core_exports);
|
|
68150
69817
|
})();
|
|
68151
69818
|
/*! Bundled license information:
|