@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 0.57.0 */
|
|
2
2
|
|
|
3
3
|
// node_modules/complex-esm/dist/src/complex.js
|
|
4
4
|
var cosh = Math.cosh || function(x) {
|
|
@@ -2240,6 +2240,7 @@ var SCALAR_TYPES = [
|
|
|
2240
2240
|
];
|
|
2241
2241
|
var VALUE_TYPES = [
|
|
2242
2242
|
"value",
|
|
2243
|
+
"color",
|
|
2243
2244
|
...COLLECTION_TYPES,
|
|
2244
2245
|
...SCALAR_TYPES
|
|
2245
2246
|
];
|
|
@@ -3939,6 +3940,7 @@ var PRIMITIVE_SUBTYPES = {
|
|
|
3939
3940
|
symbol: [],
|
|
3940
3941
|
boolean: [],
|
|
3941
3942
|
string: [],
|
|
3943
|
+
color: [],
|
|
3942
3944
|
expression: EXPRESSION_TYPES
|
|
3943
3945
|
};
|
|
3944
3946
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
@@ -7822,9 +7824,10 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
7822
7824
|
if (!materialized.isLazyCollection) return materialized.latex;
|
|
7823
7825
|
}
|
|
7824
7826
|
const syntax = this.engine._requireLatexSyntax();
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
);
|
|
7827
|
+
const json = this.toMathJson({ prettify: true, fractionalDigits: "auto" });
|
|
7828
|
+
const latexOpts = this.engine.latexOptions;
|
|
7829
|
+
if (Object.keys(latexOpts).length === 0) return syntax.serialize(json);
|
|
7830
|
+
return syntax.serialize(json, { ...latexOpts });
|
|
7828
7831
|
}
|
|
7829
7832
|
/**
|
|
7830
7833
|
* Return a LaTeX representation of this expression with custom
|
|
@@ -7835,8 +7838,15 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
7835
7838
|
*
|
|
7836
7839
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7837
7840
|
* (via `fractionalDigits: 'auto'`).
|
|
7841
|
+
*
|
|
7842
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
7843
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
7844
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
7845
|
+
* re-serialization if no verbatim is available.
|
|
7838
7846
|
*/
|
|
7839
7847
|
toLatex(options) {
|
|
7848
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
7849
|
+
return this.verbatimLatex;
|
|
7840
7850
|
if (this.isLazyCollection) {
|
|
7841
7851
|
const materialized = this.evaluate({
|
|
7842
7852
|
materialization: options?.materialization ?? true
|
|
@@ -7848,9 +7858,13 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
7848
7858
|
fractionalDigits: "auto"
|
|
7849
7859
|
});
|
|
7850
7860
|
const syntax = this.engine._requireLatexSyntax();
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7861
|
+
const latexOpts = this.engine.latexOptions;
|
|
7862
|
+
const haveEngineOpts = Object.keys(latexOpts).length > 0;
|
|
7863
|
+
const haveCallOpts = options && Object.keys(options).length > 0;
|
|
7864
|
+
if (!haveEngineOpts && !haveCallOpts) return syntax.serialize(json);
|
|
7865
|
+
if (!haveEngineOpts) return syntax.serialize(json, options);
|
|
7866
|
+
if (!haveCallOpts) return syntax.serialize(json, { ...latexOpts });
|
|
7867
|
+
return syntax.serialize(json, { ...latexOpts, ...options });
|
|
7854
7868
|
}
|
|
7855
7869
|
/** Called by `JSON.stringify()` when serializing to json.
|
|
7856
7870
|
*
|
|
@@ -7894,11 +7908,13 @@ var _BoxedExpression = class __BoxedExpression {
|
|
|
7894
7908
|
"number",
|
|
7895
7909
|
"dictionary"
|
|
7896
7910
|
];
|
|
7897
|
-
}
|
|
7898
|
-
if (Array.isArray(options.shorthands))
|
|
7911
|
+
} else if (Array.isArray(options.shorthands)) {
|
|
7899
7912
|
defaultOptions.shorthands = options.shorthands;
|
|
7913
|
+
}
|
|
7900
7914
|
if (typeof options.metadata === "string" && options.metadata === "all" || options.metadata?.includes("all")) {
|
|
7901
7915
|
defaultOptions.metadata = ["latex", "wikidata"];
|
|
7916
|
+
} else if (Array.isArray(options.metadata)) {
|
|
7917
|
+
defaultOptions.metadata = options.metadata;
|
|
7902
7918
|
}
|
|
7903
7919
|
if (options.fractionalDigits === "auto")
|
|
7904
7920
|
defaultOptions.fractionalDigits = -this.engine.precision;
|
|
@@ -9973,6 +9989,64 @@ function parseQuantifier(kind) {
|
|
|
9973
9989
|
}
|
|
9974
9990
|
|
|
9975
9991
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
9992
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
9993
|
+
x: "First",
|
|
9994
|
+
y: "Second",
|
|
9995
|
+
z: "Third",
|
|
9996
|
+
real: "Real",
|
|
9997
|
+
re: "Real",
|
|
9998
|
+
imag: "Imaginary",
|
|
9999
|
+
im: "Imaginary",
|
|
10000
|
+
count: "Length",
|
|
10001
|
+
total: "Sum",
|
|
10002
|
+
max: "Max",
|
|
10003
|
+
min: "Min"
|
|
10004
|
+
};
|
|
10005
|
+
function memberHead(name) {
|
|
10006
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10007
|
+
}
|
|
10008
|
+
function parseComponentAccess(parser, lhs) {
|
|
10009
|
+
parser.skipVisualSpace();
|
|
10010
|
+
if (parser.match("\\operatorname")) {
|
|
10011
|
+
const name = parser.parseStringGroup();
|
|
10012
|
+
if (name === null) return null;
|
|
10013
|
+
const head = memberHead(name.trim());
|
|
10014
|
+
if (head === null) return null;
|
|
10015
|
+
return [head, lhs];
|
|
10016
|
+
}
|
|
10017
|
+
const tok = parser.peek;
|
|
10018
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10019
|
+
const bare = tok.slice(1);
|
|
10020
|
+
const head = memberHead(bare);
|
|
10021
|
+
if (head !== null) {
|
|
10022
|
+
parser.nextToken();
|
|
10023
|
+
return [head, lhs];
|
|
10024
|
+
}
|
|
10025
|
+
return null;
|
|
10026
|
+
}
|
|
10027
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10028
|
+
const head = memberHead(tok);
|
|
10029
|
+
if (head === null) return null;
|
|
10030
|
+
parser.nextToken();
|
|
10031
|
+
return [head, lhs];
|
|
10032
|
+
}
|
|
10033
|
+
return null;
|
|
10034
|
+
}
|
|
10035
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10036
|
+
parser.addBoundary(close);
|
|
10037
|
+
parser.skipVisualSpace();
|
|
10038
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10039
|
+
if (cond === null) {
|
|
10040
|
+
parser.removeBoundary();
|
|
10041
|
+
return null;
|
|
10042
|
+
}
|
|
10043
|
+
parser.skipVisualSpace();
|
|
10044
|
+
if (!parser.matchBoundary()) {
|
|
10045
|
+
parser.removeBoundary();
|
|
10046
|
+
return null;
|
|
10047
|
+
}
|
|
10048
|
+
return ["When", lhs, cond];
|
|
10049
|
+
}
|
|
9976
10050
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
9977
10051
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
9978
10052
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10444,6 +10518,15 @@ var DEFINITIONS_CORE = [
|
|
|
10444
10518
|
}
|
|
10445
10519
|
},
|
|
10446
10520
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10521
|
+
// Component-access postfix: expr.member (C3)
|
|
10522
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10523
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10524
|
+
{
|
|
10525
|
+
kind: "postfix",
|
|
10526
|
+
precedence: 850,
|
|
10527
|
+
latexTrigger: ["."],
|
|
10528
|
+
parse: parseComponentAccess
|
|
10529
|
+
},
|
|
10447
10530
|
{
|
|
10448
10531
|
name: "At",
|
|
10449
10532
|
kind: "postfix",
|
|
@@ -10464,6 +10547,29 @@ var DEFINITIONS_CORE = [
|
|
|
10464
10547
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10465
10548
|
parse: parseAt("\\right", "\\rbrack")
|
|
10466
10549
|
},
|
|
10550
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10551
|
+
{
|
|
10552
|
+
name: "When",
|
|
10553
|
+
kind: "postfix",
|
|
10554
|
+
precedence: 800,
|
|
10555
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10556
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10557
|
+
serialize: (serializer, expr2) => {
|
|
10558
|
+
const e = operand(expr2, 1);
|
|
10559
|
+
const cond = operand(expr2, 2);
|
|
10560
|
+
if (!e || !cond) return "";
|
|
10561
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10562
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10563
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10564
|
+
}
|
|
10565
|
+
},
|
|
10566
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10567
|
+
{
|
|
10568
|
+
kind: "postfix",
|
|
10569
|
+
precedence: 800,
|
|
10570
|
+
latexTrigger: ["\\{"],
|
|
10571
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10572
|
+
},
|
|
10467
10573
|
{
|
|
10468
10574
|
kind: "postfix",
|
|
10469
10575
|
latexTrigger: ["_"],
|
|
@@ -10546,6 +10652,29 @@ var DEFINITIONS_CORE = [
|
|
|
10546
10652
|
return "";
|
|
10547
10653
|
}
|
|
10548
10654
|
},
|
|
10655
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10656
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10657
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10658
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10659
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10660
|
+
{
|
|
10661
|
+
latexTrigger: [".", ".", "."],
|
|
10662
|
+
kind: "infix",
|
|
10663
|
+
precedence: 800,
|
|
10664
|
+
parse: parseRange
|
|
10665
|
+
},
|
|
10666
|
+
{
|
|
10667
|
+
latexTrigger: ["\\ldots"],
|
|
10668
|
+
kind: "infix",
|
|
10669
|
+
precedence: 800,
|
|
10670
|
+
parse: parseRange
|
|
10671
|
+
},
|
|
10672
|
+
{
|
|
10673
|
+
latexTrigger: ["\\dots"],
|
|
10674
|
+
kind: "infix",
|
|
10675
|
+
precedence: 800,
|
|
10676
|
+
parse: parseRange
|
|
10677
|
+
},
|
|
10549
10678
|
{
|
|
10550
10679
|
latexTrigger: [";"],
|
|
10551
10680
|
kind: "infix",
|
|
@@ -10730,13 +10859,24 @@ var DEFINITIONS_CORE = [
|
|
|
10730
10859
|
const args = operands(expr2);
|
|
10731
10860
|
if (!args || args.length < 2) return "";
|
|
10732
10861
|
const body = args[0];
|
|
10733
|
-
const
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10862
|
+
const elements = args.slice(1);
|
|
10863
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
10864
|
+
if (!allElements) {
|
|
10865
|
+
return joinLatex([
|
|
10866
|
+
"\\operatorname{Loop}(",
|
|
10867
|
+
serializer.serialize(body),
|
|
10868
|
+
", ",
|
|
10869
|
+
serializer.serialize(elements[0]),
|
|
10870
|
+
")"
|
|
10871
|
+
]);
|
|
10872
|
+
}
|
|
10873
|
+
if (elements.length === 1) {
|
|
10874
|
+
const elem = elements[0];
|
|
10875
|
+
const index = operand(elem, 1);
|
|
10876
|
+
const coll = operand(elem, 2);
|
|
10877
|
+
if (operator(coll) === "Range") {
|
|
10878
|
+
const lo = operand(coll, 1);
|
|
10879
|
+
const hi = operand(coll, 2);
|
|
10740
10880
|
return joinLatex([
|
|
10741
10881
|
"\\text{for }",
|
|
10742
10882
|
serializer.serialize(index),
|
|
@@ -10748,13 +10888,27 @@ var DEFINITIONS_CORE = [
|
|
|
10748
10888
|
serializer.serialize(body)
|
|
10749
10889
|
]);
|
|
10750
10890
|
}
|
|
10891
|
+
return joinLatex([
|
|
10892
|
+
serializer.serialize(body),
|
|
10893
|
+
" \\operatorname{for} ",
|
|
10894
|
+
serializer.serialize(index),
|
|
10895
|
+
" = ",
|
|
10896
|
+
serializer.serialize(coll)
|
|
10897
|
+
]);
|
|
10751
10898
|
}
|
|
10899
|
+
const bindings = elements.map((elem) => {
|
|
10900
|
+
const name = operand(elem, 1);
|
|
10901
|
+
const coll = operand(elem, 2);
|
|
10902
|
+
return joinLatex([
|
|
10903
|
+
serializer.serialize(name),
|
|
10904
|
+
" = ",
|
|
10905
|
+
serializer.serialize(coll)
|
|
10906
|
+
]);
|
|
10907
|
+
}).join(", ");
|
|
10752
10908
|
return joinLatex([
|
|
10753
|
-
"\\operatorname{Loop}(",
|
|
10754
10909
|
serializer.serialize(body),
|
|
10755
|
-
"
|
|
10756
|
-
|
|
10757
|
-
")"
|
|
10910
|
+
" \\operatorname{for} ",
|
|
10911
|
+
bindings
|
|
10758
10912
|
]);
|
|
10759
10913
|
}
|
|
10760
10914
|
},
|
|
@@ -10787,6 +10941,18 @@ var DEFINITIONS_CORE = [
|
|
|
10787
10941
|
precedence: 245,
|
|
10788
10942
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10789
10943
|
},
|
|
10944
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
10945
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
10946
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
10947
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
10948
|
+
// bindings can be comma-separated below us.
|
|
10949
|
+
{
|
|
10950
|
+
symbolTrigger: "for",
|
|
10951
|
+
kind: "infix",
|
|
10952
|
+
associativity: "none",
|
|
10953
|
+
precedence: 19,
|
|
10954
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
10955
|
+
},
|
|
10790
10956
|
// \operatorname{break}
|
|
10791
10957
|
{
|
|
10792
10958
|
symbolTrigger: "break",
|
|
@@ -10991,7 +11157,10 @@ var DEFINITIONS_CORE = [
|
|
|
10991
11157
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
10992
11158
|
parser.addBoundary([")"]);
|
|
10993
11159
|
const expr2 = parser.parseExpression(until);
|
|
10994
|
-
if (!parser.matchBoundary())
|
|
11160
|
+
if (!parser.matchBoundary()) {
|
|
11161
|
+
parser.removeBoundary();
|
|
11162
|
+
return null;
|
|
11163
|
+
}
|
|
10995
11164
|
if (!parser.match("<}>")) return null;
|
|
10996
11165
|
return ["Derivative", lhs, expr2];
|
|
10997
11166
|
}
|
|
@@ -11432,7 +11601,12 @@ function parseBrackets(parser, body) {
|
|
|
11432
11601
|
if (isEmptySequence(body)) return ["List"];
|
|
11433
11602
|
const h = operator(body);
|
|
11434
11603
|
if (h === "Range" || h === "Linspace") return body;
|
|
11435
|
-
if (h === "Sequence")
|
|
11604
|
+
if (h === "Sequence") {
|
|
11605
|
+
const elems = operands(body);
|
|
11606
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11607
|
+
if (inferred) return inferred;
|
|
11608
|
+
return ["List", ...elems];
|
|
11609
|
+
}
|
|
11436
11610
|
if (h === "Delimiter") {
|
|
11437
11611
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11438
11612
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11445,12 +11619,37 @@ function parseBrackets(parser, body) {
|
|
|
11445
11619
|
}
|
|
11446
11620
|
if (delim === "," || delim === ".,.") {
|
|
11447
11621
|
body = operand(body, 1);
|
|
11448
|
-
if (operator(body) === "Sequence")
|
|
11622
|
+
if (operator(body) === "Sequence") {
|
|
11623
|
+
const elems = operands(body);
|
|
11624
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11625
|
+
if (inferred) return inferred;
|
|
11626
|
+
return ["List", ...elems];
|
|
11627
|
+
}
|
|
11449
11628
|
return ["List", body ?? "Nothing"];
|
|
11450
11629
|
}
|
|
11451
11630
|
}
|
|
11452
11631
|
return ["List", body];
|
|
11453
11632
|
}
|
|
11633
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11634
|
+
if (elems.length < 4) return null;
|
|
11635
|
+
const penultimate = elems[elems.length - 2];
|
|
11636
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11637
|
+
const samples = elems.slice(0, -2);
|
|
11638
|
+
const endExpr = elems[elems.length - 1];
|
|
11639
|
+
if (samples.length < 2) return null;
|
|
11640
|
+
const sampleNums = samples.map(machineValue);
|
|
11641
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11642
|
+
const nums = sampleNums;
|
|
11643
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11644
|
+
const tol = parser.options.tolerance;
|
|
11645
|
+
if (Math.abs(step) < tol)
|
|
11646
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11647
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11648
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11649
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11650
|
+
}
|
|
11651
|
+
return ["Range", nums[0], endExpr, step];
|
|
11652
|
+
}
|
|
11454
11653
|
function serializeList(serializer, expr2) {
|
|
11455
11654
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11456
11655
|
const op = operator(x);
|
|
@@ -11702,6 +11901,35 @@ function parseForExpression(parser, until) {
|
|
|
11702
11901
|
["Element", index, ["Range", lower, upper]]
|
|
11703
11902
|
];
|
|
11704
11903
|
}
|
|
11904
|
+
function parseForComprehension(parser, lhs, until) {
|
|
11905
|
+
const bindingTerminator = {
|
|
11906
|
+
minPrec: 21,
|
|
11907
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
11908
|
+
condition: (p) => {
|
|
11909
|
+
if (until?.condition?.(p)) return true;
|
|
11910
|
+
const saved = p.index;
|
|
11911
|
+
p.skipVisualSpace();
|
|
11912
|
+
const isComma = p.peek === ",";
|
|
11913
|
+
p.index = saved;
|
|
11914
|
+
return isComma;
|
|
11915
|
+
}
|
|
11916
|
+
};
|
|
11917
|
+
const elements = [];
|
|
11918
|
+
do {
|
|
11919
|
+
parser.skipVisualSpace();
|
|
11920
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
11921
|
+
if (binding === null) break;
|
|
11922
|
+
const op = operator(binding);
|
|
11923
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
11924
|
+
const name = operand(binding, 1);
|
|
11925
|
+
const list = operand(binding, 2);
|
|
11926
|
+
if (!name || !list) return null;
|
|
11927
|
+
elements.push(["Element", name, list]);
|
|
11928
|
+
parser.skipVisualSpace();
|
|
11929
|
+
} while (parser.match(","));
|
|
11930
|
+
if (elements.length === 0) return null;
|
|
11931
|
+
return ["Loop", lhs, ...elements];
|
|
11932
|
+
}
|
|
11705
11933
|
function parseWhereExpression(parser, lhs, until) {
|
|
11706
11934
|
const bindingTerminator = {
|
|
11707
11935
|
minPrec: 21,
|
|
@@ -13620,6 +13848,8 @@ var DEFINITIONS_ARITHMETIC = [
|
|
|
13620
13848
|
precedence: DIVISION_PRECEDENCE,
|
|
13621
13849
|
parse: "Mod"
|
|
13622
13850
|
},
|
|
13851
|
+
// Function-style alias: `\operatorname{mod}(a, b)`
|
|
13852
|
+
{ latexTrigger: "\\operatorname{mod}", parse: "Mod" },
|
|
13623
13853
|
{
|
|
13624
13854
|
latexTrigger: "\\pmod",
|
|
13625
13855
|
kind: "prefix",
|
|
@@ -13860,6 +14090,13 @@ var DEFINITIONS_ARITHMETIC = [
|
|
|
13860
14090
|
const rhs = serializer.wrap(operand(expr2, 2), ADDITION_PRECEDENCE + 3);
|
|
13861
14091
|
return joinLatex([lhs, "-", rhs]);
|
|
13862
14092
|
}
|
|
14093
|
+
},
|
|
14094
|
+
// Euclidean distance between two points (tuples of numbers).
|
|
14095
|
+
{
|
|
14096
|
+
name: "Distance",
|
|
14097
|
+
latexTrigger: ["\\operatorname{distance}"],
|
|
14098
|
+
kind: "function",
|
|
14099
|
+
serialize: (serializer, expr2) => "\\operatorname{distance}" + serializer.wrapArguments(expr2)
|
|
13863
14100
|
}
|
|
13864
14101
|
];
|
|
13865
14102
|
function getIndexAssignment(expr2, upper) {
|
|
@@ -15284,7 +15521,9 @@ var DEFINITIONS_STATISTICS = [
|
|
|
15284
15521
|
if (!expr2 || !symbol(expr2)) return null;
|
|
15285
15522
|
return ["Mean", expr2];
|
|
15286
15523
|
}
|
|
15287
|
-
}
|
|
15524
|
+
},
|
|
15525
|
+
// Function-style alias: `\operatorname{var}(...)`
|
|
15526
|
+
{ latexTrigger: "\\operatorname{var}", parse: "Variance" }
|
|
15288
15527
|
];
|
|
15289
15528
|
|
|
15290
15529
|
// src/compute-engine/numerics/unit-data.ts
|
|
@@ -16385,7 +16624,7 @@ var DEFINITIONS_OTHERS = [
|
|
|
16385
16624
|
36: "\\qquad"
|
|
16386
16625
|
}[v] ?? "";
|
|
16387
16626
|
}
|
|
16388
|
-
}
|
|
16627
|
+
},
|
|
16389
16628
|
// if (
|
|
16390
16629
|
// [
|
|
16391
16630
|
// '\\!',
|
|
@@ -16409,6 +16648,121 @@ var DEFINITIONS_OTHERS = [
|
|
|
16409
16648
|
// name: '',
|
|
16410
16649
|
// trigger: '\\check',
|
|
16411
16650
|
// },
|
|
16651
|
+
// ---------------------------------------------------------------------------
|
|
16652
|
+
// Function-style aliases for collection / random operators that some
|
|
16653
|
+
// notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
|
|
16654
|
+
// The capitalized library entries already exist; these are pure parse
|
|
16655
|
+
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16656
|
+
// ---------------------------------------------------------------------------
|
|
16657
|
+
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16658
|
+
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16659
|
+
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16660
|
+
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16661
|
+
// ---------------------------------------------------------------------------
|
|
16662
|
+
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16663
|
+
// can branch on the operator name; CE itself doesn't render them. The
|
|
16664
|
+
// library entries (with no evaluator) live in `library/core.ts`.
|
|
16665
|
+
// ---------------------------------------------------------------------------
|
|
16666
|
+
{
|
|
16667
|
+
name: "Triangle",
|
|
16668
|
+
latexTrigger: ["\\operatorname{triangle}"],
|
|
16669
|
+
kind: "function",
|
|
16670
|
+
serialize: (serializer, expr2) => "\\operatorname{triangle}" + serializer.wrapArguments(expr2)
|
|
16671
|
+
},
|
|
16672
|
+
// Desmos's geometric `vector(p1, p2)` — a directed segment between two
|
|
16673
|
+
// points. Routed to a dedicated head (not the existing column-vector
|
|
16674
|
+
// `Vector`, which has a narrower `(number+) -> vector` signature).
|
|
16675
|
+
{
|
|
16676
|
+
name: "GeometricVector",
|
|
16677
|
+
latexTrigger: ["\\operatorname{vector}"],
|
|
16678
|
+
kind: "function",
|
|
16679
|
+
serialize: (serializer, expr2) => "\\operatorname{vector}" + serializer.wrapArguments(expr2)
|
|
16680
|
+
},
|
|
16681
|
+
{
|
|
16682
|
+
name: "Sphere",
|
|
16683
|
+
latexTrigger: ["\\operatorname{sphere}"],
|
|
16684
|
+
kind: "function",
|
|
16685
|
+
serialize: (serializer, expr2) => "\\operatorname{sphere}" + serializer.wrapArguments(expr2)
|
|
16686
|
+
},
|
|
16687
|
+
{
|
|
16688
|
+
name: "Segment",
|
|
16689
|
+
latexTrigger: ["\\operatorname{segment}"],
|
|
16690
|
+
kind: "function",
|
|
16691
|
+
serialize: (serializer, expr2) => "\\operatorname{segment}" + serializer.wrapArguments(expr2)
|
|
16692
|
+
}
|
|
16693
|
+
];
|
|
16694
|
+
|
|
16695
|
+
// src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
|
|
16696
|
+
var DEFINITIONS_COLORS = [
|
|
16697
|
+
// Color constructors (one per colorspace, preserves space on evaluation)
|
|
16698
|
+
{
|
|
16699
|
+
name: "Rgb",
|
|
16700
|
+
latexTrigger: ["\\operatorname{rgb}"],
|
|
16701
|
+
kind: "function",
|
|
16702
|
+
serialize: (serializer, expr2) => "\\operatorname{rgb}" + serializer.wrapArguments(expr2)
|
|
16703
|
+
},
|
|
16704
|
+
{
|
|
16705
|
+
name: "Hsv",
|
|
16706
|
+
latexTrigger: ["\\operatorname{hsv}"],
|
|
16707
|
+
kind: "function",
|
|
16708
|
+
serialize: (serializer, expr2) => "\\operatorname{hsv}" + serializer.wrapArguments(expr2)
|
|
16709
|
+
},
|
|
16710
|
+
{
|
|
16711
|
+
name: "Hsl",
|
|
16712
|
+
latexTrigger: ["\\operatorname{hsl}"],
|
|
16713
|
+
kind: "function",
|
|
16714
|
+
serialize: (serializer, expr2) => "\\operatorname{hsl}" + serializer.wrapArguments(expr2)
|
|
16715
|
+
},
|
|
16716
|
+
{
|
|
16717
|
+
name: "Oklab",
|
|
16718
|
+
latexTrigger: ["\\operatorname{oklab}"],
|
|
16719
|
+
kind: "function",
|
|
16720
|
+
serialize: (serializer, expr2) => "\\operatorname{oklab}" + serializer.wrapArguments(expr2)
|
|
16721
|
+
},
|
|
16722
|
+
{
|
|
16723
|
+
name: "Oklch",
|
|
16724
|
+
latexTrigger: ["\\operatorname{oklch}"],
|
|
16725
|
+
kind: "function",
|
|
16726
|
+
serialize: (serializer, expr2) => "\\operatorname{oklch}" + serializer.wrapArguments(expr2)
|
|
16727
|
+
},
|
|
16728
|
+
// Conversion functions (color → color in the named space)
|
|
16729
|
+
{
|
|
16730
|
+
name: "AsRgb",
|
|
16731
|
+
latexTrigger: ["\\operatorname{asRgb}"],
|
|
16732
|
+
kind: "function",
|
|
16733
|
+
serialize: (serializer, expr2) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr2)
|
|
16734
|
+
},
|
|
16735
|
+
{
|
|
16736
|
+
name: "AsHsv",
|
|
16737
|
+
latexTrigger: ["\\operatorname{asHsv}"],
|
|
16738
|
+
kind: "function",
|
|
16739
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr2)
|
|
16740
|
+
},
|
|
16741
|
+
{
|
|
16742
|
+
name: "AsHsl",
|
|
16743
|
+
latexTrigger: ["\\operatorname{asHsl}"],
|
|
16744
|
+
kind: "function",
|
|
16745
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr2)
|
|
16746
|
+
},
|
|
16747
|
+
{
|
|
16748
|
+
name: "AsOklab",
|
|
16749
|
+
latexTrigger: ["\\operatorname{asOklab}"],
|
|
16750
|
+
kind: "function",
|
|
16751
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr2)
|
|
16752
|
+
},
|
|
16753
|
+
{
|
|
16754
|
+
name: "AsOklch",
|
|
16755
|
+
latexTrigger: ["\\operatorname{asOklch}"],
|
|
16756
|
+
kind: "function",
|
|
16757
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr2)
|
|
16758
|
+
},
|
|
16759
|
+
// Perceptual difference (returns a scalar in [0, ~1])
|
|
16760
|
+
{
|
|
16761
|
+
name: "ColorDelta",
|
|
16762
|
+
latexTrigger: ["\\operatorname{colorDelta}"],
|
|
16763
|
+
kind: "function",
|
|
16764
|
+
serialize: (serializer, expr2) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr2)
|
|
16765
|
+
}
|
|
16412
16766
|
];
|
|
16413
16767
|
|
|
16414
16768
|
// src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
|
|
@@ -16439,7 +16793,8 @@ var LATEX_DICTIONARY = [
|
|
|
16439
16793
|
...DEFINITIONS_STATISTICS,
|
|
16440
16794
|
...DEFINITIONS_UNITS,
|
|
16441
16795
|
...DEFINITIONS_OTHERS,
|
|
16442
|
-
...DEFINITIONS_PHYSICS
|
|
16796
|
+
...DEFINITIONS_PHYSICS,
|
|
16797
|
+
...DEFINITIONS_COLORS
|
|
16443
16798
|
];
|
|
16444
16799
|
|
|
16445
16800
|
// src/math-json/symbols.ts
|
|
@@ -16604,6 +16959,17 @@ function addEntry(result, entry, onError) {
|
|
|
16604
16959
|
} else if (Array.isArray(openTrigger) && openTrigger.length > 0) {
|
|
16605
16960
|
openTokens.push(openTrigger[0]);
|
|
16606
16961
|
}
|
|
16962
|
+
const closeTrigger = indexedEntry.closeTrigger;
|
|
16963
|
+
const closeTokens = /* @__PURE__ */ new Set();
|
|
16964
|
+
if (typeof closeTrigger === "string") {
|
|
16965
|
+
const variants = DELIMITER_SHORTHAND[closeTrigger];
|
|
16966
|
+
if (variants) for (const v of variants) closeTokens.add(v);
|
|
16967
|
+
else closeTokens.add(closeTrigger);
|
|
16968
|
+
if (closeTrigger === "||") closeTokens.add("|");
|
|
16969
|
+
} else if (Array.isArray(closeTrigger) && closeTrigger.length > 0) {
|
|
16970
|
+
closeTokens.add(closeTrigger[0]);
|
|
16971
|
+
}
|
|
16972
|
+
indexedEntry.closeTokens = closeTokens;
|
|
16607
16973
|
for (const token of openTokens) {
|
|
16608
16974
|
const existing = result.matchfixByOpen.get(token);
|
|
16609
16975
|
if (existing) {
|
|
@@ -16795,11 +17161,7 @@ function makeSerializeHandler(entry, latexTrigger, idTrigger) {
|
|
|
16795
17161
|
if (style === "scaled")
|
|
16796
17162
|
return joinLatex([`\\left${openDelim}`, inner, `\\right${closeDelim}`]);
|
|
16797
17163
|
if (style === "big")
|
|
16798
|
-
return joinLatex([
|
|
16799
|
-
`\\Bigl${openDelim}`,
|
|
16800
|
-
inner,
|
|
16801
|
-
`\\Bigr${closeDelim}`
|
|
16802
|
-
]);
|
|
17164
|
+
return joinLatex([`\\Bigl${openDelim}`, inner, `\\Bigr${closeDelim}`]);
|
|
16803
17165
|
return joinLatex([openDelim, inner, closeDelim]);
|
|
16804
17166
|
};
|
|
16805
17167
|
}
|
|
@@ -18150,7 +18512,7 @@ var _Parser = class __Parser {
|
|
|
18150
18512
|
}
|
|
18151
18513
|
if (this.match("\\hskip") || this.match("\\kern")) {
|
|
18152
18514
|
this.skipSpace();
|
|
18153
|
-
this.match("-")
|
|
18515
|
+
if (!this.match("-")) this.match("+");
|
|
18154
18516
|
while (/^[\d.]$/.test(this.peek)) this.nextToken();
|
|
18155
18517
|
for (const unit of [
|
|
18156
18518
|
"pt",
|
|
@@ -18664,6 +19026,19 @@ var _Parser = class __Parser {
|
|
|
18664
19026
|
}
|
|
18665
19027
|
for (const def of defs) {
|
|
18666
19028
|
this.index = start;
|
|
19029
|
+
if (def.closeTokens.size > 0) {
|
|
19030
|
+
let found = false;
|
|
19031
|
+
const tokens = this._tokens;
|
|
19032
|
+
for (let i = start; i < tokens.length; i++) {
|
|
19033
|
+
if (def.closeTokens.has(tokens[i])) {
|
|
19034
|
+
found = true;
|
|
19035
|
+
break;
|
|
19036
|
+
}
|
|
19037
|
+
}
|
|
19038
|
+
if (!found) continue;
|
|
19039
|
+
}
|
|
19040
|
+
if (typeof def.openTrigger === "string" && def.openTrigger === "." && !OPEN_DELIMITER_PREFIX[currentToken])
|
|
19041
|
+
continue;
|
|
18667
19042
|
const matched = this.matchDelimiter(def.openTrigger, def.closeTrigger);
|
|
18668
19043
|
if (!matched) continue;
|
|
18669
19044
|
const bodyStart = this.index;
|
|
@@ -19326,6 +19701,19 @@ var _Parser = class __Parser {
|
|
|
19326
19701
|
} while (postfix !== null);
|
|
19327
19702
|
}
|
|
19328
19703
|
if (result !== null) result = this.parseSupsub(result);
|
|
19704
|
+
if (result !== null) {
|
|
19705
|
+
let postfix = null;
|
|
19706
|
+
let index = this.index;
|
|
19707
|
+
do {
|
|
19708
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
19709
|
+
result = postfix ?? result;
|
|
19710
|
+
if (this.index === index && postfix !== null) {
|
|
19711
|
+
console.assert(this.index !== index, "No token consumed");
|
|
19712
|
+
break;
|
|
19713
|
+
}
|
|
19714
|
+
index = this.index;
|
|
19715
|
+
} while (postfix !== null);
|
|
19716
|
+
}
|
|
19329
19717
|
if (result === null) {
|
|
19330
19718
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19331
19719
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -19834,6 +20222,28 @@ function toDecimalNumber(wholePart, fractionalPart, exp3) {
|
|
|
19834
20222
|
}
|
|
19835
20223
|
|
|
19836
20224
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20225
|
+
var DOT_NOTATION_MAP = {
|
|
20226
|
+
First: ".x",
|
|
20227
|
+
Second: ".y",
|
|
20228
|
+
Third: ".z",
|
|
20229
|
+
Real: ".\\operatorname{real}",
|
|
20230
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20231
|
+
Length: ".\\operatorname{count}",
|
|
20232
|
+
Sum: ".\\operatorname{total}",
|
|
20233
|
+
Max: ".\\max",
|
|
20234
|
+
Min: ".\\min"
|
|
20235
|
+
};
|
|
20236
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20237
|
+
if (!serializer.options.dotNotation) return null;
|
|
20238
|
+
const ops = operands(expr2);
|
|
20239
|
+
if (!ops || ops.length !== 1) return null;
|
|
20240
|
+
const head = operator(expr2);
|
|
20241
|
+
if (!head) return null;
|
|
20242
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20243
|
+
if (suffix === void 0) return null;
|
|
20244
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20245
|
+
return `${lhs}${suffix}`;
|
|
20246
|
+
}
|
|
19837
20247
|
var ACCENT_MODIFIERS = {
|
|
19838
20248
|
deg: (s) => `${s}\\degree`,
|
|
19839
20249
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -19877,6 +20287,7 @@ var Serializer5 = class {
|
|
|
19877
20287
|
constructor(dictionary, options) {
|
|
19878
20288
|
this.dictionary = dictionary;
|
|
19879
20289
|
this.options = {
|
|
20290
|
+
dotNotation: false,
|
|
19880
20291
|
dmsFormat: false,
|
|
19881
20292
|
angleNormalization: "none",
|
|
19882
20293
|
...options
|
|
@@ -19975,6 +20386,8 @@ var Serializer5 = class {
|
|
|
19975
20386
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
19976
20387
|
}
|
|
19977
20388
|
serializeFunction(expr2, def) {
|
|
20389
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20390
|
+
if (dotResult !== null) return dotResult;
|
|
19978
20391
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
19979
20392
|
const h = operator(expr2);
|
|
19980
20393
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20217,6 +20630,8 @@ function defaultParseOptions(opts) {
|
|
|
20217
20630
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20218
20631
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20219
20632
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20633
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20634
|
+
tolerance: 1e-7,
|
|
20220
20635
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20221
20636
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20222
20637
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20249,6 +20664,7 @@ function defaultSerializeOptions(opts) {
|
|
|
20249
20664
|
invisiblePlus: "",
|
|
20250
20665
|
multiply: "\\times",
|
|
20251
20666
|
missingSymbol: "\\blacksquare",
|
|
20667
|
+
dotNotation: false,
|
|
20252
20668
|
dmsFormat: false,
|
|
20253
20669
|
angleNormalization: "none",
|
|
20254
20670
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -27219,7 +27635,11 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27219
27635
|
//
|
|
27220
27636
|
Range: {
|
|
27221
27637
|
complexity: 8200,
|
|
27222
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27638
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27639
|
+
type: (ops) => {
|
|
27640
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27641
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27642
|
+
},
|
|
27223
27643
|
canonical: (ops, { engine: ce }) => {
|
|
27224
27644
|
if (ops.length === 0) return null;
|
|
27225
27645
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27243,19 +27663,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27243
27663
|
const [lower, upper, step] = range(expr2);
|
|
27244
27664
|
if (step === 0) return 0;
|
|
27245
27665
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27246
|
-
return
|
|
27666
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27247
27667
|
},
|
|
27248
27668
|
contains: (expr2, target) => {
|
|
27249
|
-
if (!target.type.matches("integer")) return false;
|
|
27250
27669
|
const t = target.re;
|
|
27670
|
+
if (!isFinite(t)) return false;
|
|
27251
27671
|
const [lower, upper, step] = range(expr2);
|
|
27252
27672
|
if (step === 0) return false;
|
|
27253
|
-
if (step > 0)
|
|
27254
|
-
|
|
27673
|
+
if (step > 0) {
|
|
27674
|
+
if (t < lower || t > upper) return false;
|
|
27675
|
+
} else {
|
|
27676
|
+
if (t > lower || t < upper) return false;
|
|
27677
|
+
}
|
|
27678
|
+
const k = (t - lower) / step;
|
|
27679
|
+
const tol = expr2.engine.tolerance;
|
|
27680
|
+
const kRounded = Math.round(k);
|
|
27681
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27255
27682
|
},
|
|
27256
27683
|
iterator: (expr2) => {
|
|
27257
27684
|
const [lower, upper, step] = range(expr2);
|
|
27258
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
27685
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27259
27686
|
let index = 1;
|
|
27260
27687
|
return {
|
|
27261
27688
|
next: () => {
|
|
@@ -27273,7 +27700,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27273
27700
|
at: (expr2, index) => {
|
|
27274
27701
|
if (typeof index !== "number") return void 0;
|
|
27275
27702
|
const [lower, upper, step] = range(expr2);
|
|
27276
|
-
if (
|
|
27703
|
+
if (step === 0) return void 0;
|
|
27704
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27705
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27277
27706
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27278
27707
|
},
|
|
27279
27708
|
indexWhere: void 0,
|
|
@@ -27298,7 +27727,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27298
27727
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27299
27728
|
return lower >= upper ? "positive" : "negative";
|
|
27300
27729
|
},
|
|
27301
|
-
elttype: (
|
|
27730
|
+
elttype: (expr2) => {
|
|
27731
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
27732
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
27733
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
27734
|
+
}
|
|
27735
|
+
return "finite_integer";
|
|
27736
|
+
}
|
|
27302
27737
|
}
|
|
27303
27738
|
},
|
|
27304
27739
|
Interval: {
|
|
@@ -27896,15 +28331,45 @@ var COLLECTIONS_LIBRARY = {
|
|
|
27896
28331
|
},
|
|
27897
28332
|
First: {
|
|
27898
28333
|
complexity: 8200,
|
|
27899
|
-
signature: "(
|
|
28334
|
+
signature: "(any) -> any",
|
|
27900
28335
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27901
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28336
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28337
|
+
if (!xs.isCollection)
|
|
28338
|
+
return ce.error([
|
|
28339
|
+
"incompatible-type",
|
|
28340
|
+
`'collection'`,
|
|
28341
|
+
xs.type.toString()
|
|
28342
|
+
]);
|
|
28343
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28344
|
+
}
|
|
27902
28345
|
},
|
|
27903
28346
|
Second: {
|
|
27904
28347
|
complexity: 8200,
|
|
27905
|
-
signature: "(
|
|
28348
|
+
signature: "(any) -> any",
|
|
28349
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28350
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28351
|
+
if (!xs.isCollection)
|
|
28352
|
+
return ce.error([
|
|
28353
|
+
"incompatible-type",
|
|
28354
|
+
`'collection'`,
|
|
28355
|
+
xs.type.toString()
|
|
28356
|
+
]);
|
|
28357
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28358
|
+
}
|
|
28359
|
+
},
|
|
28360
|
+
Third: {
|
|
28361
|
+
complexity: 8200,
|
|
28362
|
+
signature: "(any) -> any",
|
|
27906
28363
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27907
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28364
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28365
|
+
if (!xs.isCollection)
|
|
28366
|
+
return ce.error([
|
|
28367
|
+
"incompatible-type",
|
|
28368
|
+
`'collection'`,
|
|
28369
|
+
xs.type.toString()
|
|
28370
|
+
]);
|
|
28371
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28372
|
+
}
|
|
27908
28373
|
},
|
|
27909
28374
|
Last: {
|
|
27910
28375
|
complexity: 8200,
|
|
@@ -28883,17 +29348,14 @@ function range(expr2) {
|
|
|
28883
29348
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
28884
29349
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
28885
29350
|
let op1 = expr2.op1.re;
|
|
28886
|
-
if (!isFinite(op1)) op1 = 1;
|
|
28887
|
-
else op1 = Math.round(op1);
|
|
29351
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
28888
29352
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
28889
29353
|
let op2 = expr2.op2.re;
|
|
28890
29354
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
28891
|
-
|
|
28892
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29355
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
28893
29356
|
let op3 = expr2.op3.re;
|
|
28894
|
-
if (!isFinite(op3)) op3 = 1;
|
|
28895
|
-
|
|
28896
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29357
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29358
|
+
return [op1, op2, op3];
|
|
28897
29359
|
}
|
|
28898
29360
|
function rangeLast(r) {
|
|
28899
29361
|
const [lower, upper, step] = r;
|
|
@@ -32226,6 +32688,29 @@ var ARITHMETIC_LIBRARY = [
|
|
|
32226
32688
|
signature: "(value*) -> number | list",
|
|
32227
32689
|
evaluate: (xs, { engine }) => evaluateMinMax(engine, xs, "Infimum")
|
|
32228
32690
|
},
|
|
32691
|
+
Distance: {
|
|
32692
|
+
description: "Euclidean distance between two points (tuples of numbers).",
|
|
32693
|
+
complexity: 6e3,
|
|
32694
|
+
signature: "(tuple, tuple) -> number",
|
|
32695
|
+
evaluate: ([a, b], { engine: ce }) => {
|
|
32696
|
+
if (!isFunction2(a) || !isFunction2(b))
|
|
32697
|
+
return ce.error("incompatible-type");
|
|
32698
|
+
if (a.operator !== "Tuple" || b.operator !== "Tuple")
|
|
32699
|
+
return ce.error("incompatible-type");
|
|
32700
|
+
if (a.ops.length !== b.ops.length || a.ops.length === 0)
|
|
32701
|
+
return ce.error("incompatible-type");
|
|
32702
|
+
let sumSq = 0;
|
|
32703
|
+
for (let i = 0; i < a.ops.length; i++) {
|
|
32704
|
+
const ai = a.ops[i].re;
|
|
32705
|
+
const bi = b.ops[i].re;
|
|
32706
|
+
if (!Number.isFinite(ai) || !Number.isFinite(bi))
|
|
32707
|
+
return ce.error("expected-value");
|
|
32708
|
+
const d = ai - bi;
|
|
32709
|
+
sumSq += d * d;
|
|
32710
|
+
}
|
|
32711
|
+
return ce.number(Math.sqrt(sumSq));
|
|
32712
|
+
}
|
|
32713
|
+
},
|
|
32229
32714
|
Product: {
|
|
32230
32715
|
description: "`Product(f, a, b)` computes the product of `f` from `a` to `b`",
|
|
32231
32716
|
wikidata: "Q901718",
|
|
@@ -32758,16 +33243,11 @@ function boxRule(ce, rule, options) {
|
|
|
32758
33243
|
);
|
|
32759
33244
|
let condFn;
|
|
32760
33245
|
if (typeof condition === "string") {
|
|
32761
|
-
const
|
|
32762
|
-
|
|
32763
|
-
const
|
|
32764
|
-
|
|
32765
|
-
|
|
32766
|
-
condFn = (x, _ce) => {
|
|
32767
|
-
const evaluated = condPattern.subs(x).evaluate();
|
|
32768
|
-
return isSymbol2(evaluated, "True");
|
|
32769
|
-
};
|
|
32770
|
-
}
|
|
33246
|
+
const condPattern = ce.parse(condition) ?? ce.expr("Nothing");
|
|
33247
|
+
condFn = (x, _ce) => {
|
|
33248
|
+
const evaluated = condPattern.subs(x).evaluate();
|
|
33249
|
+
return isSymbol2(evaluated, "True");
|
|
33250
|
+
};
|
|
32771
33251
|
} else {
|
|
32772
33252
|
if (condition !== void 0 && typeof condition !== "function")
|
|
32773
33253
|
throw new Error(
|
|
@@ -32869,6 +33349,15 @@ ${e.message}
|
|
|
32869
33349
|
function applyRule(rule, expr2, substitution, options) {
|
|
32870
33350
|
if (!rule) return null;
|
|
32871
33351
|
let canonical2 = options?.canonical ?? (expr2.isCanonical || expr2.isStructural);
|
|
33352
|
+
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
33353
|
+
const because = id ?? "";
|
|
33354
|
+
const ce = expr2.engine;
|
|
33355
|
+
if (canonical2 && match2) {
|
|
33356
|
+
const awc = getWildcards(match2);
|
|
33357
|
+
const canonicalMatch = match2.canonical;
|
|
33358
|
+
const bwc = getWildcards(canonicalMatch);
|
|
33359
|
+
if (!awc.every((x) => bwc.includes(x))) return null;
|
|
33360
|
+
}
|
|
32872
33361
|
let operandsMatched = false;
|
|
32873
33362
|
if (isFunction2(expr2) && options?.recursive) {
|
|
32874
33363
|
const newOps = expr2.ops.map((op) => {
|
|
@@ -32880,20 +33369,11 @@ function applyRule(rule, expr2, substitution, options) {
|
|
|
32880
33369
|
if (operandsMatched) {
|
|
32881
33370
|
if (!canonical2 && options?.canonical === void 0 && newOps.every((x) => x.isCanonical))
|
|
32882
33371
|
canonical2 = true;
|
|
32883
|
-
expr2 =
|
|
33372
|
+
expr2 = ce.function(expr2.operator, newOps, {
|
|
32884
33373
|
form: canonical2 ? "canonical" : "raw"
|
|
32885
33374
|
});
|
|
32886
33375
|
}
|
|
32887
33376
|
}
|
|
32888
|
-
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
32889
|
-
const because = id ?? "";
|
|
32890
|
-
if (canonical2 && match2) {
|
|
32891
|
-
const awc = getWildcards(match2);
|
|
32892
|
-
const canonicalMatch = match2.canonical;
|
|
32893
|
-
const bwc = getWildcards(canonicalMatch);
|
|
32894
|
-
if (!awc.every((x) => bwc.includes(x)))
|
|
32895
|
-
return operandsMatched ? { value: expr2, because } : null;
|
|
32896
|
-
}
|
|
32897
33377
|
const useVariations = rule.useVariations ?? options?.useVariations ?? false;
|
|
32898
33378
|
const matchPermutations = options?.matchPermutations ?? true;
|
|
32899
33379
|
onBeforeMatch?.(rule, expr2);
|
|
@@ -32912,7 +33392,7 @@ function applyRule(rule, expr2, substitution, options) {
|
|
|
32912
33392
|
...sub2
|
|
32913
33393
|
};
|
|
32914
33394
|
try {
|
|
32915
|
-
if (!condition(conditionSub,
|
|
33395
|
+
if (!condition(conditionSub, ce))
|
|
32916
33396
|
return operandsMatched ? { value: expr2, because } : null;
|
|
32917
33397
|
} catch (e) {
|
|
32918
33398
|
console.error(
|
|
@@ -32927,7 +33407,8 @@ function applyRule(rule, expr2, substitution, options) {
|
|
|
32927
33407
|
if (!canonical2 && options?.canonical === void 0 && replace2 instanceof _BoxedExpression && replace2.isCanonical)
|
|
32928
33408
|
canonical2 = true;
|
|
32929
33409
|
const result = typeof replace2 === "function" ? replace2(expr2, sub2) : replace2.subs(sub2, { canonical: canonical2 });
|
|
32930
|
-
if (!result)
|
|
33410
|
+
if (!result)
|
|
33411
|
+
return operandsMatched ? { value: canonical2 ? expr2.canonical : expr2, because } : null;
|
|
32931
33412
|
onMatch?.(rule, expr2, result);
|
|
32932
33413
|
if (isRuleStep(result))
|
|
32933
33414
|
return canonical2 ? { ...result, value: result.value.canonical } : result;
|
|
@@ -38501,6 +38982,40 @@ function rgbToHsl(r, g, b) {
|
|
|
38501
38982
|
else h = ((r - g) / d + 4) / 6;
|
|
38502
38983
|
return { h: h * 360, s, l };
|
|
38503
38984
|
}
|
|
38985
|
+
function hsvToRgb(h, s, v) {
|
|
38986
|
+
h = (h % 360 + 360) % 360;
|
|
38987
|
+
s = Math.max(0, Math.min(1, s));
|
|
38988
|
+
v = Math.max(0, Math.min(1, v));
|
|
38989
|
+
const c = v * s;
|
|
38990
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
38991
|
+
const m = v - c;
|
|
38992
|
+
let r = 0, g = 0, b = 0;
|
|
38993
|
+
if (h < 60) [r, g, b] = [c, x, 0];
|
|
38994
|
+
else if (h < 120) [r, g, b] = [x, c, 0];
|
|
38995
|
+
else if (h < 180) [r, g, b] = [0, c, x];
|
|
38996
|
+
else if (h < 240) [r, g, b] = [0, x, c];
|
|
38997
|
+
else if (h < 300) [r, g, b] = [x, 0, c];
|
|
38998
|
+
else [r, g, b] = [c, 0, x];
|
|
38999
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
39000
|
+
}
|
|
39001
|
+
function rgbToHsv(r, g, b) {
|
|
39002
|
+
r /= 255;
|
|
39003
|
+
g /= 255;
|
|
39004
|
+
b /= 255;
|
|
39005
|
+
const max2 = Math.max(r, g, b);
|
|
39006
|
+
const min2 = Math.min(r, g, b);
|
|
39007
|
+
const d = max2 - min2;
|
|
39008
|
+
let h = 0;
|
|
39009
|
+
if (d > 0) {
|
|
39010
|
+
if (max2 === r) h = (g - b) / d % 6;
|
|
39011
|
+
else if (max2 === g) h = (b - r) / d + 2;
|
|
39012
|
+
else h = (r - g) / d + 4;
|
|
39013
|
+
h *= 60;
|
|
39014
|
+
if (h < 0) h += 360;
|
|
39015
|
+
}
|
|
39016
|
+
const s = max2 === 0 ? 0 : d / max2;
|
|
39017
|
+
return { h, s, v: max2 };
|
|
39018
|
+
}
|
|
38504
39019
|
function parseHexColor(s) {
|
|
38505
39020
|
const hex = s.startsWith("#") ? s.substring(1) : s;
|
|
38506
39021
|
let r, g, b;
|
|
@@ -38525,6 +39040,12 @@ function parseHexColor(s) {
|
|
|
38525
39040
|
if (alpha !== void 0) result.alpha = alpha;
|
|
38526
39041
|
return result;
|
|
38527
39042
|
}
|
|
39043
|
+
function asOklch(color) {
|
|
39044
|
+
if (typeof color === "string") return rgbToOklch(parseHexColor(color));
|
|
39045
|
+
if ("C" in color) return color;
|
|
39046
|
+
if ("a" in color && "b" in color) return oklabToOklch(color);
|
|
39047
|
+
return rgbToOklch(color);
|
|
39048
|
+
}
|
|
38528
39049
|
function asRgb(color) {
|
|
38529
39050
|
if (typeof color === "number") {
|
|
38530
39051
|
return {
|
|
@@ -38956,6 +39477,13 @@ var NAMED_COLORS = {
|
|
|
38956
39477
|
};
|
|
38957
39478
|
function parseColor(s, darkMode) {
|
|
38958
39479
|
const str = s.trim().toLowerCase();
|
|
39480
|
+
const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
|
|
39481
|
+
if (opacityMatch) {
|
|
39482
|
+
const base = parseColor(opacityMatch[1].trim(), darkMode);
|
|
39483
|
+
const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
|
|
39484
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
39485
|
+
return base & 4294967040 | alpha;
|
|
39486
|
+
}
|
|
38959
39487
|
if (str.startsWith("#")) {
|
|
38960
39488
|
const hex = str.substring(1);
|
|
38961
39489
|
let r, g, b, a = 255;
|
|
@@ -39088,14 +39616,6 @@ function parseColor(s, darkMode) {
|
|
|
39088
39616
|
console.warn(`parseColor: unrecognized color "${s}"`);
|
|
39089
39617
|
return 0;
|
|
39090
39618
|
}
|
|
39091
|
-
function parseColorToRgb01(s, darkMode) {
|
|
39092
|
-
const color = parseColor(s, darkMode);
|
|
39093
|
-
return [
|
|
39094
|
-
(color >>> 24 & 255) / 255,
|
|
39095
|
-
(color >>> 16 & 255) / 255,
|
|
39096
|
-
(color >>> 8 & 255) / 255
|
|
39097
|
-
];
|
|
39098
|
-
}
|
|
39099
39619
|
function apca(bgColor, fgColor) {
|
|
39100
39620
|
const bgRgb = asRgb(bgColor);
|
|
39101
39621
|
const fgRgb = asRgb(fgColor);
|
|
@@ -39154,6 +39674,12 @@ function contrastingColor(arg) {
|
|
|
39154
39674
|
const contrast2 = Math.abs(apca(fg2, bg));
|
|
39155
39675
|
return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
|
|
39156
39676
|
}
|
|
39677
|
+
function oklabDeltaE(a, b) {
|
|
39678
|
+
const dL = a.L - b.L;
|
|
39679
|
+
const da = a.a - b.a;
|
|
39680
|
+
const db = a.b - b.b;
|
|
39681
|
+
return Math.sqrt(dL * dL + da * da + db * db);
|
|
39682
|
+
}
|
|
39157
39683
|
function lerpOklch(c1, c2, f) {
|
|
39158
39684
|
const L = c1.L + (c2.L - c1.L) * f;
|
|
39159
39685
|
const C = c1.C + (c2.C - c1.C) * f;
|
|
@@ -41915,14 +42441,30 @@ var SEQUENTIAL_PALETTES = {
|
|
|
41915
42441
|
};
|
|
41916
42442
|
|
|
41917
42443
|
// src/compute-engine/library/colors.ts
|
|
41918
|
-
function
|
|
41919
|
-
|
|
41920
|
-
|
|
41921
|
-
|
|
41922
|
-
|
|
41923
|
-
|
|
41924
|
-
|
|
41925
|
-
|
|
42444
|
+
function normalizeAlpha(a) {
|
|
42445
|
+
if (a === void 0) return void 0;
|
|
42446
|
+
if (!Number.isFinite(a)) return void 0;
|
|
42447
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
42448
|
+
return a;
|
|
42449
|
+
}
|
|
42450
|
+
function normalizeColorHead(ce, expr2) {
|
|
42451
|
+
if (!isFunction2(expr2) || !expr2.ops || expr2.ops.length < 4) return expr2;
|
|
42452
|
+
const alphaExpr = expr2.ops[3];
|
|
42453
|
+
if (!isNumber(alphaExpr)) return expr2;
|
|
42454
|
+
if (normalizeAlpha(alphaExpr.re) === void 0) {
|
|
42455
|
+
return ce.function(expr2.operator, [expr2.ops[0], expr2.ops[1], expr2.ops[2]]);
|
|
42456
|
+
}
|
|
42457
|
+
return expr2;
|
|
42458
|
+
}
|
|
42459
|
+
function colorNumberToOklch(ce, color) {
|
|
42460
|
+
const r = color >>> 24 & 255;
|
|
42461
|
+
const g = color >>> 16 & 255;
|
|
42462
|
+
const b = color >>> 8 & 255;
|
|
42463
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42464
|
+
const c = rgbToOklch({ r, g, b });
|
|
42465
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42466
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42467
|
+
return ce.function("Oklch", args);
|
|
41926
42468
|
}
|
|
41927
42469
|
var ALL_PALETTES = {
|
|
41928
42470
|
...SEQUENTIAL_PALETTES,
|
|
@@ -41933,45 +42475,139 @@ function samplePalette(ce, palette, t) {
|
|
|
41933
42475
|
t = Math.max(0, Math.min(1, t));
|
|
41934
42476
|
const n = palette.length;
|
|
41935
42477
|
if (n === 0) return ce.error("expected-value");
|
|
41936
|
-
if (n === 1) return
|
|
42478
|
+
if (n === 1) return colorNumberToOklch(ce, parseColor(palette[0]));
|
|
41937
42479
|
const pos = t * (n - 1);
|
|
41938
42480
|
const i = Math.floor(pos);
|
|
41939
42481
|
const frac = pos - i;
|
|
41940
|
-
if (i >= n - 1) return
|
|
41941
|
-
if (frac < 1e-9) return
|
|
41942
|
-
|
|
41943
|
-
|
|
41944
|
-
|
|
41945
|
-
|
|
41946
|
-
|
|
42482
|
+
if (i >= n - 1) return colorNumberToOklch(ce, parseColor(palette[n - 1]));
|
|
42483
|
+
if (frac < 1e-9) return colorNumberToOklch(ce, parseColor(palette[i]));
|
|
42484
|
+
return oklchToExpr(
|
|
42485
|
+
ce,
|
|
42486
|
+
asOklch(interpolateOklch(palette[i], palette[i + 1], frac))
|
|
42487
|
+
);
|
|
42488
|
+
}
|
|
42489
|
+
var COLOR_OPERATORS = /* @__PURE__ */ new Set(["Rgb", "Hsv", "Hsl", "Oklab", "Oklch"]);
|
|
42490
|
+
function readColorExpr(arg) {
|
|
42491
|
+
if (!isFunction2(arg)) return null;
|
|
42492
|
+
if (!COLOR_OPERATORS.has(arg.operator)) return null;
|
|
42493
|
+
if (!arg.ops || arg.ops.length < 3) return null;
|
|
42494
|
+
const c0 = arg.ops[0].re;
|
|
42495
|
+
const c1 = arg.ops[1].re;
|
|
42496
|
+
const c2 = arg.ops[2].re;
|
|
42497
|
+
if (!Number.isFinite(c0) || !Number.isFinite(c1) || !Number.isFinite(c2))
|
|
42498
|
+
return null;
|
|
42499
|
+
const alpha = arg.ops.length >= 4 ? normalizeAlpha(arg.ops[3].re) : void 0;
|
|
42500
|
+
return { space: arg.operator, c0, c1, c2, alpha };
|
|
42501
|
+
}
|
|
42502
|
+
function colorExprToRgb(arg) {
|
|
42503
|
+
const c = readColorExpr(arg);
|
|
42504
|
+
if (!c) return null;
|
|
42505
|
+
const withAlpha = (rgb) => c.alpha !== void 0 ? { ...rgb, alpha: c.alpha } : rgb;
|
|
42506
|
+
switch (c.space) {
|
|
42507
|
+
case "Rgb":
|
|
42508
|
+
return withAlpha({ r: c.c0 * 255, g: c.c1 * 255, b: c.c2 * 255 });
|
|
42509
|
+
case "Hsv":
|
|
42510
|
+
return withAlpha(hsvToRgb(c.c0, c.c1, c.c2));
|
|
42511
|
+
case "Hsl":
|
|
42512
|
+
return withAlpha(hslToRgb(c.c0, c.c1, c.c2));
|
|
42513
|
+
case "Oklab":
|
|
42514
|
+
return withAlpha(oklabToRgb({ L: c.c0, a: c.c1, b: c.c2 }));
|
|
42515
|
+
case "Oklch":
|
|
42516
|
+
return withAlpha(oklchToRgb({ L: c.c0, C: c.c1, H: c.c2 }));
|
|
42517
|
+
}
|
|
42518
|
+
return null;
|
|
42519
|
+
}
|
|
42520
|
+
function colorExprToOklch(arg) {
|
|
42521
|
+
const c = readColorExpr(arg);
|
|
42522
|
+
if (!c) return null;
|
|
42523
|
+
switch (c.space) {
|
|
42524
|
+
case "Oklch":
|
|
42525
|
+
return asOklch({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
42526
|
+
case "Oklab":
|
|
42527
|
+
return asOklch({ L: c.c0, a: c.c1, b: c.c2, alpha: c.alpha });
|
|
42528
|
+
case "Rgb":
|
|
42529
|
+
return asOklch({
|
|
42530
|
+
r: c.c0 * 255,
|
|
42531
|
+
g: c.c1 * 255,
|
|
42532
|
+
b: c.c2 * 255,
|
|
42533
|
+
alpha: c.alpha
|
|
42534
|
+
});
|
|
42535
|
+
case "Hsv": {
|
|
42536
|
+
const rgb = hsvToRgb(c.c0, c.c1, c.c2);
|
|
42537
|
+
return asOklch({ ...rgb, alpha: c.alpha });
|
|
42538
|
+
}
|
|
42539
|
+
case "Hsl": {
|
|
42540
|
+
const rgb = hslToRgb(c.c0, c.c1, c.c2);
|
|
42541
|
+
return asOklch({ r: rgb.r, g: rgb.g, b: rgb.b, alpha: c.alpha });
|
|
42542
|
+
}
|
|
42543
|
+
}
|
|
42544
|
+
return null;
|
|
42545
|
+
}
|
|
42546
|
+
function toOklch(ce, arg) {
|
|
42547
|
+
const direct = colorExprToOklch(arg);
|
|
42548
|
+
if (direct) return direct;
|
|
42549
|
+
const rgb = extractRgb(ce, arg);
|
|
42550
|
+
return rgb ? asOklch(rgb) : null;
|
|
42551
|
+
}
|
|
42552
|
+
function lerpOklchColor(a, b, t) {
|
|
42553
|
+
const L = a.L + (b.L - a.L) * t;
|
|
42554
|
+
const C = a.C + (b.C - a.C) * t;
|
|
42555
|
+
const aAchromatic = a.C < 1e-6;
|
|
42556
|
+
const bAchromatic = b.C < 1e-6;
|
|
42557
|
+
let H;
|
|
42558
|
+
if (aAchromatic && bAchromatic) H = a.H;
|
|
42559
|
+
else if (aAchromatic) H = b.H;
|
|
42560
|
+
else if (bAchromatic) H = a.H;
|
|
42561
|
+
else {
|
|
42562
|
+
let dH = b.H - a.H;
|
|
42563
|
+
if (dH > 180) dH -= 360;
|
|
42564
|
+
if (dH < -180) dH += 360;
|
|
42565
|
+
H = a.H + dH * t;
|
|
42566
|
+
if (H < 0) H += 360;
|
|
42567
|
+
if (H >= 360) H -= 360;
|
|
42568
|
+
}
|
|
42569
|
+
const alphaA = a.alpha ?? 1;
|
|
42570
|
+
const alphaB = b.alpha ?? 1;
|
|
42571
|
+
return { L, C, H, alpha: normalizeAlpha(alphaA + (alphaB - alphaA) * t) };
|
|
42572
|
+
}
|
|
42573
|
+
function oklchToExpr(ce, c) {
|
|
42574
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42575
|
+
if (c.alpha !== void 0) args.push(ce.number(c.alpha));
|
|
42576
|
+
return ce.function("Oklch", args);
|
|
41947
42577
|
}
|
|
41948
42578
|
function extractRgb(ce, arg) {
|
|
41949
42579
|
if (isString(arg)) {
|
|
41950
42580
|
const s = arg.string;
|
|
41951
42581
|
if (!s) return void 0;
|
|
41952
42582
|
const color = parseColor(s);
|
|
41953
|
-
|
|
42583
|
+
const rgb = {
|
|
41954
42584
|
r: color >>> 24 & 255,
|
|
41955
42585
|
g: color >>> 16 & 255,
|
|
41956
|
-
b: color >>> 8 & 255
|
|
41957
|
-
alpha: (color & 255) / 255
|
|
42586
|
+
b: color >>> 8 & 255
|
|
41958
42587
|
};
|
|
42588
|
+
const alpha = normalizeAlpha((color & 255) / 255);
|
|
42589
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42590
|
+
return rgb;
|
|
41959
42591
|
}
|
|
42592
|
+
const fromTyped = colorExprToRgb(arg);
|
|
42593
|
+
if (fromTyped) return fromTyped;
|
|
41960
42594
|
if (arg.operator === "Tuple" && arg.ops && arg.ops.length >= 3) {
|
|
41961
42595
|
const rgb = {
|
|
41962
42596
|
r: arg.ops[0].re * 255,
|
|
41963
42597
|
g: arg.ops[1].re * 255,
|
|
41964
42598
|
b: arg.ops[2].re * 255
|
|
41965
42599
|
};
|
|
41966
|
-
if (arg.ops.length >= 4)
|
|
42600
|
+
if (arg.ops.length >= 4) {
|
|
42601
|
+
const alpha = normalizeAlpha(arg.ops[3].re);
|
|
42602
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42603
|
+
}
|
|
41967
42604
|
return rgb;
|
|
41968
42605
|
}
|
|
41969
42606
|
return void 0;
|
|
41970
42607
|
}
|
|
41971
42608
|
function componentsTuple(ce, components, alpha) {
|
|
41972
42609
|
const args = components.map((v) => ce.number(v));
|
|
41973
|
-
if (alpha !== void 0
|
|
41974
|
-
args.push(ce.number(alpha));
|
|
42610
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
41975
42611
|
return ce.tuple(...args);
|
|
41976
42612
|
}
|
|
41977
42613
|
function rgbToHex(rgb) {
|
|
@@ -41979,7 +42615,7 @@ function rgbToHex(rgb) {
|
|
|
41979
42615
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
41980
42616
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
41981
42617
|
const hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
41982
|
-
if (rgb.alpha !== void 0
|
|
42618
|
+
if (rgb.alpha !== void 0) {
|
|
41983
42619
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
41984
42620
|
return hex + a.toString(16).padStart(2, "0");
|
|
41985
42621
|
}
|
|
@@ -41987,22 +42623,29 @@ function rgbToHex(rgb) {
|
|
|
41987
42623
|
}
|
|
41988
42624
|
var COLORS_LIBRARY = {
|
|
41989
42625
|
Color: {
|
|
41990
|
-
description: "
|
|
42626
|
+
description: "Parse a CSS-style color string to an Oklch color",
|
|
41991
42627
|
complexity: 8e3,
|
|
41992
|
-
signature: "(string) ->
|
|
42628
|
+
signature: "(string) -> color",
|
|
41993
42629
|
evaluate: (ops, { engine: ce }) => {
|
|
41994
42630
|
const input = isString(ops[0]) ? ops[0].string : void 0;
|
|
41995
42631
|
if (!input) return ce.error("incompatible-type");
|
|
41996
42632
|
const color = parseColor(input);
|
|
41997
42633
|
if (color === 0 && input.trim().toLowerCase() !== "transparent")
|
|
41998
42634
|
return ce.error("incompatible-type");
|
|
41999
|
-
|
|
42635
|
+
const r = color >>> 24 & 255;
|
|
42636
|
+
const g = color >>> 16 & 255;
|
|
42637
|
+
const b = color >>> 8 & 255;
|
|
42638
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42639
|
+
const c = rgbToOklch({ r, g, b });
|
|
42640
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42641
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42642
|
+
return ce.function("Oklch", args);
|
|
42000
42643
|
}
|
|
42001
42644
|
},
|
|
42002
42645
|
ColorToString: {
|
|
42003
42646
|
description: "Convert a color to a string in the specified format",
|
|
42004
42647
|
complexity: 8e3,
|
|
42005
|
-
signature: "(
|
|
42648
|
+
signature: "(color | string | tuple, string?) -> string",
|
|
42006
42649
|
evaluate: (ops, { engine: ce }) => {
|
|
42007
42650
|
const rgb = extractRgb(ce, ops[0]);
|
|
42008
42651
|
if (!rgb) return ce.error("incompatible-type");
|
|
@@ -42014,7 +42657,7 @@ var COLORS_LIBRARY = {
|
|
|
42014
42657
|
const r = Math.round(rgb.r);
|
|
42015
42658
|
const g = Math.round(rgb.g);
|
|
42016
42659
|
const b = Math.round(rgb.b);
|
|
42017
|
-
if (rgb.alpha !== void 0
|
|
42660
|
+
if (rgb.alpha !== void 0)
|
|
42018
42661
|
return ce.string(`rgb(${r} ${g} ${b} / ${rgb.alpha})`);
|
|
42019
42662
|
return ce.string(`rgb(${r} ${g} ${b})`);
|
|
42020
42663
|
}
|
|
@@ -42023,17 +42666,17 @@ var COLORS_LIBRARY = {
|
|
|
42023
42666
|
const h = Math.round(hsl.h * 10) / 10;
|
|
42024
42667
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
42025
42668
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
42026
|
-
if (rgb.alpha !== void 0
|
|
42669
|
+
if (rgb.alpha !== void 0)
|
|
42027
42670
|
return ce.string(`hsl(${h} ${s}% ${l}% / ${rgb.alpha})`);
|
|
42028
42671
|
return ce.string(`hsl(${h} ${s}% ${l}%)`);
|
|
42029
42672
|
}
|
|
42030
42673
|
case "oklch": {
|
|
42031
|
-
const c =
|
|
42674
|
+
const c = colorExprToOklch(ops[0]) ?? asOklch(rgb);
|
|
42032
42675
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
42033
42676
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
42034
42677
|
const H = Math.round(c.H * 10) / 10;
|
|
42035
|
-
if (
|
|
42036
|
-
return ce.string(`oklch(${L} ${C} ${H} / ${
|
|
42678
|
+
if (c.alpha !== void 0)
|
|
42679
|
+
return ce.string(`oklch(${L} ${C} ${H} / ${c.alpha})`);
|
|
42037
42680
|
return ce.string(`oklch(${L} ${C} ${H})`);
|
|
42038
42681
|
}
|
|
42039
42682
|
default:
|
|
@@ -42044,60 +42687,44 @@ var COLORS_LIBRARY = {
|
|
|
42044
42687
|
ColorMix: {
|
|
42045
42688
|
description: "Mix two colors in OKLCh space",
|
|
42046
42689
|
complexity: 8e3,
|
|
42047
|
-
signature: "(
|
|
42690
|
+
signature: "(color | string | tuple, color | string | tuple, number?) -> color",
|
|
42048
42691
|
evaluate: (ops, { engine: ce }) => {
|
|
42049
|
-
const rgb1 = extractRgb(ce, ops[0]);
|
|
42050
|
-
const rgb2 = extractRgb(ce, ops[1]);
|
|
42051
|
-
if (!rgb1 || !rgb2) return ce.error("incompatible-type");
|
|
42052
42692
|
let ratio = 0.5;
|
|
42053
42693
|
if (ops.length >= 3 && ops[2] !== void 0) {
|
|
42054
42694
|
ratio = ops[2].re;
|
|
42055
42695
|
if (!Number.isFinite(ratio)) return ce.error("expected-value");
|
|
42056
42696
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
42057
42697
|
}
|
|
42058
|
-
const
|
|
42059
|
-
const
|
|
42060
|
-
|
|
42061
|
-
|
|
42062
|
-
const g = mixed.g / 255;
|
|
42063
|
-
const b = mixed.b / 255;
|
|
42064
|
-
const a1 = rgb1.alpha ?? 1;
|
|
42065
|
-
const a2 = rgb2.alpha ?? 1;
|
|
42066
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
42067
|
-
if (Math.abs(alpha - 1) > 1e-4)
|
|
42068
|
-
return ce.tuple(
|
|
42069
|
-
ce.number(r),
|
|
42070
|
-
ce.number(g),
|
|
42071
|
-
ce.number(b),
|
|
42072
|
-
ce.number(alpha)
|
|
42073
|
-
);
|
|
42074
|
-
return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
|
|
42698
|
+
const oklch1 = toOklch(ce, ops[0]);
|
|
42699
|
+
const oklch2 = toOklch(ce, ops[1]);
|
|
42700
|
+
if (!oklch1 || !oklch2) return ce.error("incompatible-type");
|
|
42701
|
+
return oklchToExpr(ce, lerpOklchColor(oklch1, oklch2, ratio));
|
|
42075
42702
|
}
|
|
42076
42703
|
},
|
|
42077
42704
|
Colormap: {
|
|
42078
42705
|
description: "Sample colors from a named palette",
|
|
42079
42706
|
complexity: 8e3,
|
|
42080
|
-
signature: "(string, number?) ->
|
|
42707
|
+
signature: "(string, number?) -> color | list<color>",
|
|
42081
42708
|
evaluate: (ops, { engine: ce }) => {
|
|
42082
42709
|
const name = isString(ops[0]) ? ops[0].string : void 0;
|
|
42083
42710
|
if (!name) return ce.error("incompatible-type");
|
|
42084
42711
|
const palette = ALL_PALETTES[name];
|
|
42085
42712
|
if (!palette) return ce.error("expected-value", name);
|
|
42086
42713
|
if (ops.length < 2 || ops[1] === void 0) {
|
|
42087
|
-
const
|
|
42088
|
-
(hex) =>
|
|
42714
|
+
const colors = palette.map(
|
|
42715
|
+
(hex) => colorNumberToOklch(ce, parseColor(hex))
|
|
42089
42716
|
);
|
|
42090
|
-
return ce.function("List",
|
|
42717
|
+
return ce.function("List", colors);
|
|
42091
42718
|
}
|
|
42092
42719
|
const val = ops[1].re;
|
|
42093
42720
|
if (!Number.isFinite(val)) return ce.error("expected-value");
|
|
42094
42721
|
if (Number.isInteger(val) && val >= 2) {
|
|
42095
42722
|
const n = val;
|
|
42096
|
-
const
|
|
42723
|
+
const colors = [];
|
|
42097
42724
|
for (let i = 0; i < n; i++) {
|
|
42098
|
-
|
|
42725
|
+
colors.push(samplePalette(ce, palette, i / (n - 1)));
|
|
42099
42726
|
}
|
|
42100
|
-
return ce.function("List",
|
|
42727
|
+
return ce.function("List", colors);
|
|
42101
42728
|
}
|
|
42102
42729
|
return samplePalette(ce, palette, val);
|
|
42103
42730
|
}
|
|
@@ -42105,12 +42732,25 @@ var COLORS_LIBRARY = {
|
|
|
42105
42732
|
ColorToColorspace: {
|
|
42106
42733
|
description: "Convert a color to components in a target color space",
|
|
42107
42734
|
complexity: 8e3,
|
|
42108
|
-
signature: "(
|
|
42735
|
+
signature: "(color | string | tuple, string) -> tuple",
|
|
42109
42736
|
evaluate: (ops, { engine: ce }) => {
|
|
42110
|
-
const rgb = extractRgb(ce, ops[0]);
|
|
42111
|
-
if (!rgb) return ce.error("incompatible-type");
|
|
42112
42737
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42113
42738
|
if (!space) return ce.error("incompatible-type");
|
|
42739
|
+
if (space === "oklch" || space === "oklab" || space === "lab") {
|
|
42740
|
+
const oklch2 = colorExprToOklch(ops[0]);
|
|
42741
|
+
if (oklch2) {
|
|
42742
|
+
if (space === "oklch")
|
|
42743
|
+
return componentsTuple(
|
|
42744
|
+
ce,
|
|
42745
|
+
[oklch2.L, oklch2.C, oklch2.H],
|
|
42746
|
+
oklch2.alpha
|
|
42747
|
+
);
|
|
42748
|
+
const lab = oklchToOklab(oklch2);
|
|
42749
|
+
return componentsTuple(ce, [lab.L, lab.a, lab.b], lab.alpha);
|
|
42750
|
+
}
|
|
42751
|
+
}
|
|
42752
|
+
const rgb = extractRgb(ce, ops[0]);
|
|
42753
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42114
42754
|
const alpha = rgb.alpha;
|
|
42115
42755
|
switch (space) {
|
|
42116
42756
|
case "rgb":
|
|
@@ -42140,17 +42780,27 @@ var COLORS_LIBRARY = {
|
|
|
42140
42780
|
ColorFromColorspace: {
|
|
42141
42781
|
description: "Convert color space components to a canonical sRGB tuple",
|
|
42142
42782
|
complexity: 8e3,
|
|
42143
|
-
signature: "(tuple, string) -> tuple",
|
|
42783
|
+
signature: "(color | tuple, string) -> tuple",
|
|
42144
42784
|
evaluate: (ops, { engine: ce }) => {
|
|
42145
|
-
const tuple = ops[0];
|
|
42146
|
-
if (!isFunction2(tuple) || tuple.operator !== "Tuple" || tuple.ops.length < 3)
|
|
42147
|
-
return ce.error("incompatible-type");
|
|
42148
|
-
const c0 = tuple.ops[0].re;
|
|
42149
|
-
const c1 = tuple.ops[1].re;
|
|
42150
|
-
const c2 = tuple.ops[2].re;
|
|
42151
|
-
const alpha = tuple.ops.length >= 4 ? tuple.ops[3].re : void 0;
|
|
42152
42785
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42153
42786
|
if (!space) return ce.error("incompatible-type");
|
|
42787
|
+
let c0, c1, c2;
|
|
42788
|
+
let alpha;
|
|
42789
|
+
const arg = ops[0];
|
|
42790
|
+
const typed = readColorExpr(arg);
|
|
42791
|
+
if (typed) {
|
|
42792
|
+
c0 = typed.c0;
|
|
42793
|
+
c1 = typed.c1;
|
|
42794
|
+
c2 = typed.c2;
|
|
42795
|
+
alpha = typed.alpha;
|
|
42796
|
+
} else if (isFunction2(arg) && arg.operator === "Tuple" && arg.ops.length >= 3) {
|
|
42797
|
+
c0 = arg.ops[0].re;
|
|
42798
|
+
c1 = arg.ops[1].re;
|
|
42799
|
+
c2 = arg.ops[2].re;
|
|
42800
|
+
alpha = arg.ops.length >= 4 ? arg.ops[3].re : void 0;
|
|
42801
|
+
} else {
|
|
42802
|
+
return ce.error("incompatible-type");
|
|
42803
|
+
}
|
|
42154
42804
|
let rgb;
|
|
42155
42805
|
switch (space) {
|
|
42156
42806
|
case "rgb":
|
|
@@ -42186,7 +42836,7 @@ var COLORS_LIBRARY = {
|
|
|
42186
42836
|
ColorContrast: {
|
|
42187
42837
|
description: "APCA contrast ratio between two colors",
|
|
42188
42838
|
complexity: 8e3,
|
|
42189
|
-
signature: "(
|
|
42839
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
42190
42840
|
evaluate: (ops, { engine: ce }) => {
|
|
42191
42841
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42192
42842
|
const fgRgb = extractRgb(ce, ops[1]);
|
|
@@ -42197,19 +42847,186 @@ var COLORS_LIBRARY = {
|
|
|
42197
42847
|
ContrastingColor: {
|
|
42198
42848
|
description: "Choose the foreground color with better APCA contrast against a background",
|
|
42199
42849
|
complexity: 8e3,
|
|
42200
|
-
signature: "(
|
|
42850
|
+
signature: "(color | string | tuple, (color | string | tuple)?, (color | string | tuple)?) -> color",
|
|
42201
42851
|
evaluate: (ops, { engine: ce }) => {
|
|
42202
42852
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42203
42853
|
if (!bgRgb) return ce.error("incompatible-type");
|
|
42854
|
+
let packed;
|
|
42204
42855
|
if (ops.length >= 3 && ops[1] !== void 0 && ops[2] !== void 0) {
|
|
42205
42856
|
const fg1 = extractRgb(ce, ops[1]);
|
|
42206
42857
|
const fg2 = extractRgb(ce, ops[2]);
|
|
42207
42858
|
if (!fg1 || !fg2) return ce.error("incompatible-type");
|
|
42208
|
-
|
|
42209
|
-
|
|
42859
|
+
packed = contrastingColor({ bg: bgRgb, fg1, fg2 });
|
|
42860
|
+
} else {
|
|
42861
|
+
packed = contrastingColor(bgRgb);
|
|
42862
|
+
}
|
|
42863
|
+
const r = (packed >>> 24 & 255) / 255;
|
|
42864
|
+
const g = (packed >>> 16 & 255) / 255;
|
|
42865
|
+
const b = (packed >>> 8 & 255) / 255;
|
|
42866
|
+
const alpha = normalizeAlpha((packed & 255) / 255);
|
|
42867
|
+
const args = [ce.number(r), ce.number(g), ce.number(b)];
|
|
42868
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
42869
|
+
return ce.function("Rgb", args);
|
|
42870
|
+
}
|
|
42871
|
+
},
|
|
42872
|
+
// ---------------------------------------------------------------------------
|
|
42873
|
+
// Color constructors. Each preserves its colorspace on evaluation; the
|
|
42874
|
+
// operator name is the discriminator. Components are interpreted per
|
|
42875
|
+
// colorspace conventions (Rgb channels 0-1, Hsv/Hsl hue in degrees with
|
|
42876
|
+
// sat/value 0-1, Oklab/Oklch L 0-1 with standard a/b/C/H ranges). The
|
|
42877
|
+
// optional 4th argument is alpha in [0, 1]. No clamping at evaluation time.
|
|
42878
|
+
// ---------------------------------------------------------------------------
|
|
42879
|
+
Rgb: {
|
|
42880
|
+
description: "sRGB color (channels 0-1, optional alpha 0-1)",
|
|
42881
|
+
complexity: 8e3,
|
|
42882
|
+
signature: "(number, number, number, number?) -> color"
|
|
42883
|
+
},
|
|
42884
|
+
Hsv: {
|
|
42885
|
+
description: "HSV color (hue degrees, saturation/value 0-1, optional alpha)",
|
|
42886
|
+
complexity: 8e3,
|
|
42887
|
+
signature: "(number, number, number, number?) -> color"
|
|
42888
|
+
},
|
|
42889
|
+
Hsl: {
|
|
42890
|
+
description: "HSL color (hue degrees, saturation/lightness 0-1, optional alpha)",
|
|
42891
|
+
complexity: 8e3,
|
|
42892
|
+
signature: "(number, number, number, number?) -> color"
|
|
42893
|
+
},
|
|
42894
|
+
Oklab: {
|
|
42895
|
+
description: "OKLab color (L 0-1, a/b ~ -0.4..0.4, optional alpha)",
|
|
42896
|
+
complexity: 8e3,
|
|
42897
|
+
signature: "(number, number, number, number?) -> color"
|
|
42898
|
+
},
|
|
42899
|
+
Oklch: {
|
|
42900
|
+
description: "OKLCh color (L 0-1, C 0-~0.4, hue degrees, optional alpha)",
|
|
42901
|
+
complexity: 8e3,
|
|
42902
|
+
signature: "(number, number, number, number?) -> color"
|
|
42903
|
+
},
|
|
42904
|
+
// ---------------------------------------------------------------------------
|
|
42905
|
+
// Color-space conversions. Each accepts any of the five color heads and
|
|
42906
|
+
// returns the same color in the named space. If the input is already in
|
|
42907
|
+
// the target space, returns the input unchanged.
|
|
42908
|
+
// ---------------------------------------------------------------------------
|
|
42909
|
+
AsRgb: {
|
|
42910
|
+
description: "Convert any color to sRGB (channels 0-1)",
|
|
42911
|
+
complexity: 8e3,
|
|
42912
|
+
signature: "(color) -> color",
|
|
42913
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42914
|
+
const arg = ops[0];
|
|
42915
|
+
if (isFunction2(arg) && arg.operator === "Rgb")
|
|
42916
|
+
return normalizeColorHead(ce, arg);
|
|
42917
|
+
const rgb = colorExprToRgb(arg);
|
|
42918
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42919
|
+
const args = [
|
|
42920
|
+
ce.number(rgb.r / 255),
|
|
42921
|
+
ce.number(rgb.g / 255),
|
|
42922
|
+
ce.number(rgb.b / 255)
|
|
42923
|
+
];
|
|
42924
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42925
|
+
return ce.function("Rgb", args);
|
|
42926
|
+
}
|
|
42927
|
+
},
|
|
42928
|
+
AsHsv: {
|
|
42929
|
+
description: "Convert any color to HSV (hue degrees, s/v 0-1)",
|
|
42930
|
+
complexity: 8e3,
|
|
42931
|
+
signature: "(color) -> color",
|
|
42932
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42933
|
+
const arg = ops[0];
|
|
42934
|
+
if (isFunction2(arg) && arg.operator === "Hsv")
|
|
42935
|
+
return normalizeColorHead(ce, arg);
|
|
42936
|
+
const rgb = colorExprToRgb(arg);
|
|
42937
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42938
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
42939
|
+
const args = [ce.number(hsv.h), ce.number(hsv.s), ce.number(hsv.v)];
|
|
42940
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42941
|
+
return ce.function("Hsv", args);
|
|
42942
|
+
}
|
|
42943
|
+
},
|
|
42944
|
+
AsHsl: {
|
|
42945
|
+
description: "Convert any color to HSL (hue degrees, s/l 0-1)",
|
|
42946
|
+
complexity: 8e3,
|
|
42947
|
+
signature: "(color) -> color",
|
|
42948
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42949
|
+
const arg = ops[0];
|
|
42950
|
+
if (isFunction2(arg) && arg.operator === "Hsl")
|
|
42951
|
+
return normalizeColorHead(ce, arg);
|
|
42952
|
+
const rgb = colorExprToRgb(arg);
|
|
42953
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42954
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
42955
|
+
const args = [ce.number(hsl.h), ce.number(hsl.s), ce.number(hsl.l)];
|
|
42956
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42957
|
+
return ce.function("Hsl", args);
|
|
42958
|
+
}
|
|
42959
|
+
},
|
|
42960
|
+
AsOklab: {
|
|
42961
|
+
description: "Convert any color to OKLab",
|
|
42962
|
+
complexity: 8e3,
|
|
42963
|
+
signature: "(color) -> color",
|
|
42964
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42965
|
+
const arg = ops[0];
|
|
42966
|
+
if (isFunction2(arg) && arg.operator === "Oklab")
|
|
42967
|
+
return normalizeColorHead(ce, arg);
|
|
42968
|
+
if (isFunction2(arg) && arg.operator === "Oklch") {
|
|
42969
|
+
const c = readColorExpr(arg);
|
|
42970
|
+
if (!c) return ce.error("incompatible-type");
|
|
42971
|
+
const lab2 = oklchToOklab({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
42972
|
+
const args2 = [ce.number(lab2.L), ce.number(lab2.a), ce.number(lab2.b)];
|
|
42973
|
+
if (lab2.alpha !== void 0) args2.push(ce.number(lab2.alpha));
|
|
42974
|
+
return ce.function("Oklab", args2);
|
|
42975
|
+
}
|
|
42976
|
+
const rgb = colorExprToRgb(arg);
|
|
42977
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42978
|
+
const lab = rgbToOklab(rgb);
|
|
42979
|
+
const args = [ce.number(lab.L), ce.number(lab.a), ce.number(lab.b)];
|
|
42980
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
42981
|
+
return ce.function("Oklab", args);
|
|
42982
|
+
}
|
|
42983
|
+
},
|
|
42984
|
+
AsOklch: {
|
|
42985
|
+
description: "Convert any color to OKLCh",
|
|
42986
|
+
complexity: 8e3,
|
|
42987
|
+
signature: "(color) -> color",
|
|
42988
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42989
|
+
const arg = ops[0];
|
|
42990
|
+
if (isFunction2(arg) && arg.operator === "Oklch")
|
|
42991
|
+
return normalizeColorHead(ce, arg);
|
|
42992
|
+
if (isFunction2(arg) && arg.operator === "Oklab") {
|
|
42993
|
+
const c2 = readColorExpr(arg);
|
|
42994
|
+
if (!c2) return ce.error("incompatible-type");
|
|
42995
|
+
const oklch2 = oklabToOklch({
|
|
42996
|
+
L: c2.c0,
|
|
42997
|
+
a: c2.c1,
|
|
42998
|
+
b: c2.c2,
|
|
42999
|
+
alpha: c2.alpha
|
|
43000
|
+
});
|
|
43001
|
+
const args2 = [
|
|
43002
|
+
ce.number(oklch2.L),
|
|
43003
|
+
ce.number(oklch2.C),
|
|
43004
|
+
ce.number(oklch2.H)
|
|
43005
|
+
];
|
|
43006
|
+
if (oklch2.alpha !== void 0) args2.push(ce.number(oklch2.alpha));
|
|
43007
|
+
return ce.function("Oklch", args2);
|
|
42210
43008
|
}
|
|
42211
|
-
const
|
|
42212
|
-
return
|
|
43009
|
+
const rgb = colorExprToRgb(arg);
|
|
43010
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43011
|
+
const c = rgbToOklch(rgb);
|
|
43012
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
43013
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43014
|
+
return ce.function("Oklch", args);
|
|
43015
|
+
}
|
|
43016
|
+
},
|
|
43017
|
+
// ---------------------------------------------------------------------------
|
|
43018
|
+
// Perceptual difference. Returns ΔE_OK (Euclidean distance in OKLab),
|
|
43019
|
+
// an approximately perceptually uniform scalar.
|
|
43020
|
+
// ---------------------------------------------------------------------------
|
|
43021
|
+
ColorDelta: {
|
|
43022
|
+
description: "Perceptual color difference (\u0394E_OK) between two colors",
|
|
43023
|
+
complexity: 8e3,
|
|
43024
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
43025
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43026
|
+
const a = toOklch(ce, ops[0]);
|
|
43027
|
+
const b = toOklch(ce, ops[1]);
|
|
43028
|
+
if (!a || !b) return ce.error("incompatible-type");
|
|
43029
|
+
return ce.number(oklabDeltaE(oklchToOklab(a), oklchToOklab(b)));
|
|
42213
43030
|
}
|
|
42214
43031
|
}
|
|
42215
43032
|
};
|
|
@@ -42268,12 +43085,42 @@ var CONTROL_STRUCTURES_LIBRARY = [
|
|
|
42268
43085
|
}
|
|
42269
43086
|
},
|
|
42270
43087
|
Loop: {
|
|
42271
|
-
description: "Evaluate a body expression over
|
|
43088
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
43089
|
+
lazy: true,
|
|
43090
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43091
|
+
type: ([body]) => {
|
|
43092
|
+
if (!body) return "nothing";
|
|
43093
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43094
|
+
},
|
|
43095
|
+
canonical: canonicalLoop,
|
|
43096
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43097
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43098
|
+
},
|
|
43099
|
+
When: {
|
|
43100
|
+
description: "Conditional value: returns expr when cond holds, undefined otherwise.",
|
|
42272
43101
|
lazy: true,
|
|
42273
|
-
signature: "(
|
|
42274
|
-
type: ([
|
|
42275
|
-
|
|
42276
|
-
|
|
43102
|
+
signature: "(expression, boolean) -> any",
|
|
43103
|
+
type: ([expr2]) => expr2.type,
|
|
43104
|
+
canonical: (args, { engine: ce }) => {
|
|
43105
|
+
if (args.length !== 2) return null;
|
|
43106
|
+
const [expr2, cond] = args;
|
|
43107
|
+
if (isFunction2(expr2, "When")) {
|
|
43108
|
+
const inner = expr2.op1.canonical;
|
|
43109
|
+
const innerCond = expr2.op2.canonical;
|
|
43110
|
+
return ce._fn("When", [
|
|
43111
|
+
inner,
|
|
43112
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43113
|
+
]);
|
|
43114
|
+
}
|
|
43115
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43116
|
+
},
|
|
43117
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43118
|
+
const c = cond.evaluate();
|
|
43119
|
+
const cs = sym(c);
|
|
43120
|
+
if (cs === "True") return expr2.evaluate();
|
|
43121
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43122
|
+
return ce._fn("When", [expr2, c]);
|
|
43123
|
+
}
|
|
42277
43124
|
},
|
|
42278
43125
|
Which: {
|
|
42279
43126
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42333,9 +43180,141 @@ function canonicalBlock(ops, options) {
|
|
|
42333
43180
|
);
|
|
42334
43181
|
return result;
|
|
42335
43182
|
}
|
|
42336
|
-
function
|
|
43183
|
+
function canonicalLoop(ops, options) {
|
|
43184
|
+
const { engine: ce, scope } = options;
|
|
43185
|
+
if (ops.length === 0) return null;
|
|
43186
|
+
if (ops.length === 1) {
|
|
43187
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43188
|
+
}
|
|
43189
|
+
const body = ops[0];
|
|
43190
|
+
const iterators = ops.slice(1);
|
|
43191
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43192
|
+
if (!allElement) {
|
|
43193
|
+
return ce._fn(
|
|
43194
|
+
"Loop",
|
|
43195
|
+
ops.map((op) => op.canonical)
|
|
43196
|
+
);
|
|
43197
|
+
}
|
|
43198
|
+
const loopScope = scope ?? {
|
|
43199
|
+
parent: ce.context.lexicalScope,
|
|
43200
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43201
|
+
};
|
|
43202
|
+
loopScope.noAutoDeclare = true;
|
|
43203
|
+
ce.pushScope(loopScope);
|
|
43204
|
+
let canonicalIterators;
|
|
43205
|
+
let canonicalBody;
|
|
43206
|
+
try {
|
|
43207
|
+
canonicalIterators = iterators.map((it) => {
|
|
43208
|
+
if (!isFunction2(it, "Element")) {
|
|
43209
|
+
return ce._fn("Element", [
|
|
43210
|
+
ce.error("missing").canonical,
|
|
43211
|
+
ce.error("missing").canonical
|
|
43212
|
+
]);
|
|
43213
|
+
}
|
|
43214
|
+
const indexExpr = it.ops[0];
|
|
43215
|
+
const collExpr = it.ops[1];
|
|
43216
|
+
if (!indexExpr || !collExpr) {
|
|
43217
|
+
return ce._fn("Element", [
|
|
43218
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43219
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43220
|
+
]);
|
|
43221
|
+
}
|
|
43222
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43223
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43224
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43225
|
+
}
|
|
43226
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43227
|
+
});
|
|
43228
|
+
canonicalBody = body.canonical;
|
|
43229
|
+
} finally {
|
|
43230
|
+
ce.popScope();
|
|
43231
|
+
loopScope.noAutoDeclare = false;
|
|
43232
|
+
}
|
|
43233
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43234
|
+
scope: loopScope
|
|
43235
|
+
});
|
|
43236
|
+
}
|
|
43237
|
+
function* runLoop(body, elements, ce) {
|
|
42337
43238
|
body ??= ce.Nothing;
|
|
42338
43239
|
if (sym(body) === "Nothing") return body;
|
|
43240
|
+
if (elements.length === 0) {
|
|
43241
|
+
const result = body.evaluate();
|
|
43242
|
+
yield result;
|
|
43243
|
+
return result;
|
|
43244
|
+
}
|
|
43245
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43246
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43247
|
+
}
|
|
43248
|
+
const results = [];
|
|
43249
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43250
|
+
const freshScope = {
|
|
43251
|
+
parent: ce.context.lexicalScope,
|
|
43252
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43253
|
+
};
|
|
43254
|
+
ce._pushEvalContext(freshScope);
|
|
43255
|
+
try {
|
|
43256
|
+
for (const elem of elements) {
|
|
43257
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43258
|
+
const idx = elem.ops[0];
|
|
43259
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43260
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43261
|
+
ce.declare(idx.symbol, "unknown");
|
|
43262
|
+
}
|
|
43263
|
+
}
|
|
43264
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43265
|
+
} finally {
|
|
43266
|
+
ce._popEvalContext();
|
|
43267
|
+
}
|
|
43268
|
+
if (state.stopped && state.value !== void 0) {
|
|
43269
|
+
if (!state.broke) return state.value;
|
|
43270
|
+
return state.value;
|
|
43271
|
+
}
|
|
43272
|
+
return ce.function("List", results);
|
|
43273
|
+
}
|
|
43274
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43275
|
+
if (state.stopped) return;
|
|
43276
|
+
if (index === elements.length) {
|
|
43277
|
+
const result = body.evaluate();
|
|
43278
|
+
state.count += 1;
|
|
43279
|
+
if (state.count > ce.iterationLimit)
|
|
43280
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43281
|
+
if (isFunction2(result, "Break")) {
|
|
43282
|
+
state.stopped = true;
|
|
43283
|
+
state.broke = true;
|
|
43284
|
+
state.value = result.op1;
|
|
43285
|
+
return;
|
|
43286
|
+
}
|
|
43287
|
+
if (result.operator === "Return") {
|
|
43288
|
+
state.stopped = true;
|
|
43289
|
+
state.value = result;
|
|
43290
|
+
return;
|
|
43291
|
+
}
|
|
43292
|
+
results.push(result);
|
|
43293
|
+
yield result;
|
|
43294
|
+
return;
|
|
43295
|
+
}
|
|
43296
|
+
const elem = elements[index];
|
|
43297
|
+
if (!isFunction2(elem, "Element")) {
|
|
43298
|
+
return;
|
|
43299
|
+
}
|
|
43300
|
+
const indexExpr = elem.ops[0];
|
|
43301
|
+
const collExpr = elem.ops[1];
|
|
43302
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43303
|
+
return;
|
|
43304
|
+
}
|
|
43305
|
+
const name = indexExpr.symbol;
|
|
43306
|
+
const collection = collExpr.evaluate();
|
|
43307
|
+
if (!collection?.isCollection) {
|
|
43308
|
+
return;
|
|
43309
|
+
}
|
|
43310
|
+
const skipAssign = name === "Nothing";
|
|
43311
|
+
for (const value of collection.each()) {
|
|
43312
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43313
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43314
|
+
if (state.stopped) return;
|
|
43315
|
+
}
|
|
43316
|
+
}
|
|
43317
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42339
43318
|
if (collection?.isCollection) {
|
|
42340
43319
|
let result = void 0;
|
|
42341
43320
|
const fn = applicable(body);
|
|
@@ -44689,6 +45668,34 @@ var CORE_LIBRARY = [
|
|
|
44689
45668
|
signature: "() -> expression",
|
|
44690
45669
|
evaluate: (_ops, { engine }) => engine.expr(randomExpression())
|
|
44691
45670
|
}
|
|
45671
|
+
},
|
|
45672
|
+
// ---------------------------------------------------------------------------
|
|
45673
|
+
// Opaque typed heads — registered so the names are in the standard set
|
|
45674
|
+
// (consumers can branch on the operator name); CE itself does not evaluate
|
|
45675
|
+
// them. Geometric primitives `Triangle`/`Sphere`/`Segment` and the action
|
|
45676
|
+
// arrow `To` (`a \to b`).
|
|
45677
|
+
// ---------------------------------------------------------------------------
|
|
45678
|
+
{
|
|
45679
|
+
Triangle: {
|
|
45680
|
+
description: "Triangle primitive \u2014 opaque typed head.",
|
|
45681
|
+
signature: "(any+) -> expression"
|
|
45682
|
+
},
|
|
45683
|
+
GeometricVector: {
|
|
45684
|
+
description: "Geometric vector (directed segment between two points) \u2014 opaque typed head. Distinct from the column-vector `Vector` operator.",
|
|
45685
|
+
signature: "(any, any) -> expression"
|
|
45686
|
+
},
|
|
45687
|
+
Sphere: {
|
|
45688
|
+
description: "Sphere primitive \u2014 opaque typed head.",
|
|
45689
|
+
signature: "(any+) -> expression"
|
|
45690
|
+
},
|
|
45691
|
+
Segment: {
|
|
45692
|
+
description: "Segment primitive \u2014 opaque typed head.",
|
|
45693
|
+
signature: "(any+) -> expression"
|
|
45694
|
+
},
|
|
45695
|
+
To: {
|
|
45696
|
+
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45697
|
+
signature: "(any, any) -> nothing"
|
|
45698
|
+
}
|
|
44692
45699
|
}
|
|
44693
45700
|
];
|
|
44694
45701
|
|
|
@@ -51825,6 +52832,7 @@ function orderConvexHull(points) {
|
|
|
51825
52832
|
|
|
51826
52833
|
// src/compute-engine/boxed-expression/cache.ts
|
|
51827
52834
|
function cachedValue(v, generation, fn) {
|
|
52835
|
+
if (v.generation === generation && v.value !== null) return v.value;
|
|
51828
52836
|
v.generation = generation;
|
|
51829
52837
|
v.value = fn();
|
|
51830
52838
|
return v.value;
|
|
@@ -53602,6 +54610,12 @@ function _setProduct(fn) {
|
|
|
53602
54610
|
function _escapeJsonString(s) {
|
|
53603
54611
|
return s;
|
|
53604
54612
|
}
|
|
54613
|
+
function _serializeLatexMetadata(ce, expr2) {
|
|
54614
|
+
const syntax = ce.latexSyntax;
|
|
54615
|
+
const opts = ce.latexOptions;
|
|
54616
|
+
if (Object.keys(opts).length === 0) return syntax.serialize(expr2);
|
|
54617
|
+
return syntax.serialize(expr2, { ...opts });
|
|
54618
|
+
}
|
|
53605
54619
|
function serializeSubtract(ce, a, b, options, metadata) {
|
|
53606
54620
|
if (isNumber(a) && a.isNegative) {
|
|
53607
54621
|
const v = a.numericValue;
|
|
@@ -53906,7 +54920,7 @@ function serializeJsonFunction(ce, name, args, options, metadata) {
|
|
|
53906
54920
|
];
|
|
53907
54921
|
const md = { ...metadata ?? {} };
|
|
53908
54922
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
53909
|
-
md.latex = _escapeJsonString(md.latex ?? ce
|
|
54923
|
+
md.latex = _escapeJsonString(md.latex ?? _serializeLatexMetadata(ce, fn));
|
|
53910
54924
|
} else md.latex = "";
|
|
53911
54925
|
if (!options.metadata.includes("wikidata")) md.wikidata = "";
|
|
53912
54926
|
if (!md.latex && !md.wikidata && options.shorthands.includes("function"))
|
|
@@ -53931,7 +54945,7 @@ function serializeJsonSymbol(ce, sym2, options, metadata) {
|
|
|
53931
54945
|
}
|
|
53932
54946
|
metadata = { ...metadata };
|
|
53933
54947
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
53934
|
-
metadata.latex = metadata.latex ?? ce
|
|
54948
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, sym2);
|
|
53935
54949
|
if (metadata.latex !== void 0)
|
|
53936
54950
|
metadata.latex = _escapeJsonString(metadata.latex);
|
|
53937
54951
|
} else metadata.latex = void 0;
|
|
@@ -54093,7 +55107,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
|
|
|
54093
55107
|
}
|
|
54094
55108
|
}
|
|
54095
55109
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54096
|
-
metadata.latex = metadata.latex ?? ce
|
|
55110
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, result2 ?? { num });
|
|
54097
55111
|
if (result2) {
|
|
54098
55112
|
if (metadata.latex !== void 0)
|
|
54099
55113
|
return { sym: result2, latex: metadata.latex };
|
|
@@ -54109,7 +55123,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
|
|
|
54109
55123
|
if (value.isNaN()) {
|
|
54110
55124
|
num = "NaN";
|
|
54111
55125
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54112
|
-
metadata.latex = metadata.latex ?? ce
|
|
55126
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54113
55127
|
return metadata.latex !== void 0 ? { num, latex: metadata.latex } : { num };
|
|
54114
55128
|
}
|
|
54115
55129
|
return serializeJsonFunction(
|
|
@@ -54143,7 +55157,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
|
|
|
54143
55157
|
value = Number(value);
|
|
54144
55158
|
} else {
|
|
54145
55159
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54146
|
-
metadata.latex = metadata.latex ?? ce
|
|
55160
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, {
|
|
54147
55161
|
num: value.toString()
|
|
54148
55162
|
});
|
|
54149
55163
|
if (metadata.latex !== void 0)
|
|
@@ -54157,7 +55171,7 @@ function serializeJsonNumber(ce, value, options, metadata) {
|
|
|
54157
55171
|
result = value > 0 ? "PositiveInfinity" : "NegativeInfinity";
|
|
54158
55172
|
else num = serializeRepeatingDecimals(value.toString(), options);
|
|
54159
55173
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54160
|
-
metadata.latex = metadata.latex ?? ce
|
|
55174
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54161
55175
|
if (result) {
|
|
54162
55176
|
if (metadata.latex !== void 0)
|
|
54163
55177
|
return { sym: result, latex: metadata.latex };
|
|
@@ -54383,6 +55397,23 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
54383
55397
|
};
|
|
54384
55398
|
return compilePair(0);
|
|
54385
55399
|
}
|
|
55400
|
+
if (h === "When") {
|
|
55401
|
+
if (args.length !== 2)
|
|
55402
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55403
|
+
const fn2 = target.functions?.(h);
|
|
55404
|
+
if (fn2) {
|
|
55405
|
+
if (typeof fn2 === "function") {
|
|
55406
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55407
|
+
}
|
|
55408
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55409
|
+
}
|
|
55410
|
+
if (isSymbol2(args[1], "True"))
|
|
55411
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55412
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55413
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55414
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55415
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55416
|
+
}
|
|
54386
55417
|
if (h === "Block") {
|
|
54387
55418
|
return _BaseCompiler.compileBlock(args, target);
|
|
54388
55419
|
}
|
|
@@ -54457,17 +55488,91 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
54457
55488
|
)}${target.ws("\n")}})()`;
|
|
54458
55489
|
}
|
|
54459
55490
|
/**
|
|
54460
|
-
* Compile a Loop expression
|
|
54461
|
-
*
|
|
55491
|
+
* Compile a Loop expression.
|
|
55492
|
+
*
|
|
55493
|
+
* Two forms are supported:
|
|
55494
|
+
*
|
|
55495
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
55496
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
55497
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
55498
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
55499
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
55500
|
+
* references to the loop index inside the body are re-wrapped via
|
|
55501
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
55502
|
+
*
|
|
55503
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
55504
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
55505
|
+
* When two or more `Element` clauses are present — or when the single
|
|
55506
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
55507
|
+
* comprehension that collects results into an array. Each clause
|
|
55508
|
+
* produces a `for (const name of collection)` loop, nested
|
|
55509
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
55510
|
+
*
|
|
55511
|
+
* Example output (JS):
|
|
55512
|
+
* ```js
|
|
55513
|
+
* (() => { const result = [];
|
|
55514
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
55515
|
+
* return result; })()
|
|
55516
|
+
* ```
|
|
54462
55517
|
*
|
|
54463
|
-
*
|
|
54464
|
-
*
|
|
54465
|
-
*
|
|
55518
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
55519
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
55520
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
55521
|
+
* array or by unrolling when bounds are known at compile time.
|
|
54466
55522
|
*/
|
|
54467
55523
|
static compileForLoop(args, target) {
|
|
54468
55524
|
if (!args[0]) throw new Error("Loop: no body");
|
|
54469
55525
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
54470
|
-
const
|
|
55526
|
+
const body = args[0];
|
|
55527
|
+
const elements = args.slice(1);
|
|
55528
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
55529
|
+
if (useComprehension) {
|
|
55530
|
+
const lang = target.language ?? "";
|
|
55531
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
55532
|
+
throw new Error(
|
|
55533
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
55534
|
+
);
|
|
55535
|
+
}
|
|
55536
|
+
const narrowedElements = [];
|
|
55537
|
+
for (let i = 0; i < elements.length; i++) {
|
|
55538
|
+
const elem = elements[i];
|
|
55539
|
+
if (!isFunction2(elem, "Element"))
|
|
55540
|
+
throw new Error(
|
|
55541
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
55542
|
+
);
|
|
55543
|
+
if (!isSymbol2(elem.ops[0]))
|
|
55544
|
+
throw new Error(
|
|
55545
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
55546
|
+
);
|
|
55547
|
+
narrowedElements.push(elem);
|
|
55548
|
+
}
|
|
55549
|
+
const loopVarSet = new Set(
|
|
55550
|
+
narrowedElements.map(
|
|
55551
|
+
(e) => e.ops[0].symbol
|
|
55552
|
+
)
|
|
55553
|
+
);
|
|
55554
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
55555
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
55556
|
+
...target,
|
|
55557
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
55558
|
+
} : target;
|
|
55559
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
55560
|
+
let inner = `result.push(${bodyCode});`;
|
|
55561
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
55562
|
+
const elem = narrowedElements[i];
|
|
55563
|
+
const name = elem.ops[0].symbol;
|
|
55564
|
+
const collExpr = elem.ops[1];
|
|
55565
|
+
let collection;
|
|
55566
|
+
if (isFunction2(collExpr, "Range")) {
|
|
55567
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
55568
|
+
} else {
|
|
55569
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
55570
|
+
}
|
|
55571
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
55572
|
+
}
|
|
55573
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
55574
|
+
}
|
|
55575
|
+
const indexing = elements[0];
|
|
54471
55576
|
if (!isFunction2(indexing, "Element"))
|
|
54472
55577
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
54473
55578
|
const indexExpr = indexing.ops[0];
|
|
@@ -54485,13 +55590,72 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
54485
55590
|
...target,
|
|
54486
55591
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
54487
55592
|
};
|
|
54488
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
55593
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
54489
55594
|
return `(() => {${target.ws(
|
|
54490
55595
|
"\n"
|
|
54491
55596
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
54492
55597
|
"\n"
|
|
54493
55598
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
54494
55599
|
}
|
|
55600
|
+
/**
|
|
55601
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
55602
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
55603
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
55604
|
+
*
|
|
55605
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
55606
|
+
* are not statically numeric we accept the Range (the historical
|
|
55607
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
55608
|
+
* left as a known limitation; callers can force the iterable path by
|
|
55609
|
+
* supplying an explicit step.
|
|
55610
|
+
*/
|
|
55611
|
+
static isLegacyCompatibleRange(coll) {
|
|
55612
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
55613
|
+
if (coll.ops.length >= 3) {
|
|
55614
|
+
const stepExpr = coll.ops[2];
|
|
55615
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
55616
|
+
}
|
|
55617
|
+
const lo = coll.ops[0];
|
|
55618
|
+
const hi = coll.ops[1];
|
|
55619
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
55620
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
55621
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
55622
|
+
return true;
|
|
55623
|
+
}
|
|
55624
|
+
/**
|
|
55625
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
55626
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
55627
|
+
* `library/collections.ts` Range:
|
|
55628
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
55629
|
+
* element = lo + step * k (0-indexed)
|
|
55630
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
55631
|
+
*
|
|
55632
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
55633
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
55634
|
+
*/
|
|
55635
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
55636
|
+
const loExpr = rangeExpr.ops[0];
|
|
55637
|
+
const hiExpr = rangeExpr.ops[1];
|
|
55638
|
+
const stepExpr = rangeExpr.ops[2];
|
|
55639
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
55640
|
+
const lo2 = loExpr.re;
|
|
55641
|
+
const hi2 = hiExpr.re;
|
|
55642
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
55643
|
+
if (step2 === 0) return "[]";
|
|
55644
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
55645
|
+
if (step2 === 1) {
|
|
55646
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
55647
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
55648
|
+
}
|
|
55649
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
55650
|
+
}
|
|
55651
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
55652
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
55653
|
+
if (stepExpr === void 0) {
|
|
55654
|
+
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})`;
|
|
55655
|
+
}
|
|
55656
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
55657
|
+
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})`;
|
|
55658
|
+
}
|
|
54495
55659
|
/**
|
|
54496
55660
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
54497
55661
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -54922,8 +56086,7 @@ function compile(expr2, options) {
|
|
|
54922
56086
|
ce.pushScope();
|
|
54923
56087
|
try {
|
|
54924
56088
|
if (vars && typeof vars === "object") {
|
|
54925
|
-
for (const [k, v] of Object.entries(vars))
|
|
54926
|
-
ce.assign(k, v);
|
|
56089
|
+
for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
|
|
54927
56090
|
}
|
|
54928
56091
|
return expr2.evaluate().re;
|
|
54929
56092
|
} finally {
|
|
@@ -60153,8 +61316,7 @@ function tryGetComplexParts(expr2, compile3) {
|
|
|
60153
61316
|
return { re: null, im: formatFloat(iScale) };
|
|
60154
61317
|
}
|
|
60155
61318
|
const compiledFactors = remaining.map((r) => compile3(r));
|
|
60156
|
-
if (iScale !== 1)
|
|
60157
|
-
compiledFactors.unshift(formatFloat(iScale));
|
|
61319
|
+
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
60158
61320
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
60159
61321
|
return { re: null, im: imCode };
|
|
60160
61322
|
}
|
|
@@ -60758,39 +61920,130 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
60758
61920
|
if (args.length >= 2)
|
|
60759
61921
|
return `_SYS.colormap(${compile3(args[0])}, ${compile3(args[1])})`;
|
|
60760
61922
|
return `_SYS.colormap(${compile3(args[0])})`;
|
|
61923
|
+
},
|
|
61924
|
+
// -----------------------------------------------------------------------
|
|
61925
|
+
// Color constructor heads. All compile to OKLCh arrays at runtime — the
|
|
61926
|
+
// canonical color representation in this target. The constructors take
|
|
61927
|
+
// their own colorspace's components and convert internally.
|
|
61928
|
+
// (Mirrors the GPU target's design: color values are vec3 OKLCh.)
|
|
61929
|
+
// -----------------------------------------------------------------------
|
|
61930
|
+
Rgb: (args, compile3) => {
|
|
61931
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
61932
|
+
return `_SYS.rgb(${args.map(compile3).join(", ")})`;
|
|
61933
|
+
},
|
|
61934
|
+
Hsv: (args, compile3) => {
|
|
61935
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
61936
|
+
return `_SYS.hsv(${args.map(compile3).join(", ")})`;
|
|
61937
|
+
},
|
|
61938
|
+
Hsl: (args, compile3) => {
|
|
61939
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
61940
|
+
return `_SYS.hsl(${args.map(compile3).join(", ")})`;
|
|
61941
|
+
},
|
|
61942
|
+
Oklab: (args, compile3) => {
|
|
61943
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
61944
|
+
return `_SYS.oklab(${args.map(compile3).join(", ")})`;
|
|
61945
|
+
},
|
|
61946
|
+
Oklch: (args, compile3) => {
|
|
61947
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
61948
|
+
return `_SYS.oklch(${args.map(compile3).join(", ")})`;
|
|
61949
|
+
},
|
|
61950
|
+
// -----------------------------------------------------------------------
|
|
61951
|
+
// As* converters. Compile-time output convention matches the engine and
|
|
61952
|
+
// the GPU target: each returns components in the named space as a 3- or
|
|
61953
|
+
// 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
|
|
61954
|
+
// layers). `AsOklch` is the identity (canonical form).
|
|
61955
|
+
// -----------------------------------------------------------------------
|
|
61956
|
+
AsRgb: ([c], compile3) => {
|
|
61957
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
61958
|
+
return `_SYS.asRgb(${compile3(c)})`;
|
|
61959
|
+
},
|
|
61960
|
+
AsHsv: ([c], compile3) => {
|
|
61961
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
61962
|
+
return `_SYS.asHsv(${compile3(c)})`;
|
|
61963
|
+
},
|
|
61964
|
+
AsHsl: ([c], compile3) => {
|
|
61965
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
61966
|
+
return `_SYS.asHsl(${compile3(c)})`;
|
|
61967
|
+
},
|
|
61968
|
+
AsOklab: ([c], compile3) => {
|
|
61969
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
61970
|
+
return `_SYS.asOklab(${compile3(c)})`;
|
|
61971
|
+
},
|
|
61972
|
+
AsOklch: ([c], compile3) => {
|
|
61973
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
61974
|
+
return compile3(c);
|
|
61975
|
+
},
|
|
61976
|
+
// Perceptual color difference (ΔE_OK).
|
|
61977
|
+
ColorDelta: ([a, b], compile3) => {
|
|
61978
|
+
if (a === null || b === null)
|
|
61979
|
+
throw new Error("ColorDelta: need two colors");
|
|
61980
|
+
return `_SYS.colorDelta(${compile3(a)}, ${compile3(b)})`;
|
|
61981
|
+
},
|
|
61982
|
+
// Euclidean distance between two tuples (any positive dimension).
|
|
61983
|
+
// The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
|
|
61984
|
+
// (vec-only); this JS handler works on plain arrays of any length.
|
|
61985
|
+
Distance: ([a, b], compile3) => {
|
|
61986
|
+
if (a === null || b === null) throw new Error("Distance: need two points");
|
|
61987
|
+
return `_SYS.distance(${compile3(a)}, ${compile3(b)})`;
|
|
60761
61988
|
}
|
|
60762
61989
|
};
|
|
60763
61990
|
function toRI(c) {
|
|
60764
61991
|
return { re: c.re, im: c.im };
|
|
60765
61992
|
}
|
|
61993
|
+
function normalizeAlpha2(a) {
|
|
61994
|
+
if (a === void 0) return void 0;
|
|
61995
|
+
if (!Number.isFinite(a)) return void 0;
|
|
61996
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
61997
|
+
return a;
|
|
61998
|
+
}
|
|
60766
61999
|
function toRgb255(input) {
|
|
60767
62000
|
if (typeof input === "string") {
|
|
60768
62001
|
const c = parseColor(input);
|
|
60769
|
-
|
|
62002
|
+
const rgb2 = {
|
|
60770
62003
|
r: c >>> 24 & 255,
|
|
60771
62004
|
g: c >>> 16 & 255,
|
|
60772
|
-
b: c >>> 8 & 255
|
|
60773
|
-
alpha: (c & 255) / 255
|
|
62005
|
+
b: c >>> 8 & 255
|
|
60774
62006
|
};
|
|
62007
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62008
|
+
if (alpha !== void 0) rgb2.alpha = alpha;
|
|
62009
|
+
return rgb2;
|
|
62010
|
+
}
|
|
62011
|
+
const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
|
|
62012
|
+
if (input.length >= 4) {
|
|
62013
|
+
const alpha = normalizeAlpha2(input[3]);
|
|
62014
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
60775
62015
|
}
|
|
60776
|
-
const rgb = {
|
|
60777
|
-
r: input[0] * 255,
|
|
60778
|
-
g: input[1] * 255,
|
|
60779
|
-
b: input[2] * 255
|
|
60780
|
-
};
|
|
60781
|
-
if (input.length >= 4) rgb.alpha = input[3];
|
|
60782
62016
|
return rgb;
|
|
60783
62017
|
}
|
|
60784
|
-
function
|
|
60785
|
-
|
|
60786
|
-
|
|
60787
|
-
|
|
60788
|
-
|
|
60789
|
-
|
|
62018
|
+
function toOklch2(input) {
|
|
62019
|
+
if (typeof input === "string") {
|
|
62020
|
+
const c = parseColor(input);
|
|
62021
|
+
const r = c >>> 24 & 255;
|
|
62022
|
+
const g = c >>> 16 & 255;
|
|
62023
|
+
const b = c >>> 8 & 255;
|
|
62024
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62025
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62026
|
+
if (alpha !== void 0) oklch2.alpha = alpha;
|
|
62027
|
+
return oklch2;
|
|
62028
|
+
}
|
|
62029
|
+
return {
|
|
62030
|
+
L: input[0],
|
|
62031
|
+
C: input[1],
|
|
62032
|
+
H: input[2],
|
|
62033
|
+
alpha: input.length >= 4 ? normalizeAlpha2(input[3]) : void 0
|
|
62034
|
+
};
|
|
62035
|
+
}
|
|
62036
|
+
function packedToOklch(c) {
|
|
62037
|
+
const r = c >>> 24 & 255;
|
|
62038
|
+
const g = c >>> 16 & 255;
|
|
62039
|
+
const b = c >>> 8 & 255;
|
|
62040
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62041
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62042
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
60790
62043
|
}
|
|
60791
62044
|
var colorHelpers = {
|
|
60792
62045
|
color(input) {
|
|
60793
|
-
return
|
|
62046
|
+
return packedToOklch(parseColor(input));
|
|
60794
62047
|
},
|
|
60795
62048
|
colorToString(input, format) {
|
|
60796
62049
|
const rgb = toRgb255(input);
|
|
@@ -60801,7 +62054,7 @@ var colorHelpers = {
|
|
|
60801
62054
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
60802
62055
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
60803
62056
|
let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
60804
|
-
if (rgb.alpha !== void 0
|
|
62057
|
+
if (rgb.alpha !== void 0) {
|
|
60805
62058
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
60806
62059
|
hex += a.toString(16).padStart(2, "0");
|
|
60807
62060
|
}
|
|
@@ -60811,7 +62064,7 @@ var colorHelpers = {
|
|
|
60811
62064
|
const r = Math.round(rgb.r);
|
|
60812
62065
|
const g = Math.round(rgb.g);
|
|
60813
62066
|
const b = Math.round(rgb.b);
|
|
60814
|
-
if (rgb.alpha !== void 0
|
|
62067
|
+
if (rgb.alpha !== void 0)
|
|
60815
62068
|
return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
|
|
60816
62069
|
return `rgb(${r} ${g} ${b})`;
|
|
60817
62070
|
}
|
|
@@ -60820,7 +62073,7 @@ var colorHelpers = {
|
|
|
60820
62073
|
const h = Math.round(hsl.h * 10) / 10;
|
|
60821
62074
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
60822
62075
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
60823
|
-
if (rgb.alpha !== void 0
|
|
62076
|
+
if (rgb.alpha !== void 0)
|
|
60824
62077
|
return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
|
|
60825
62078
|
return `hsl(${h} ${s}% ${l}%)`;
|
|
60826
62079
|
}
|
|
@@ -60829,7 +62082,7 @@ var colorHelpers = {
|
|
|
60829
62082
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
60830
62083
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
60831
62084
|
const H = Math.round(c.H * 10) / 10;
|
|
60832
|
-
if (rgb.alpha !== void 0
|
|
62085
|
+
if (rgb.alpha !== void 0)
|
|
60833
62086
|
return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
|
|
60834
62087
|
return `oklch(${L} ${C} ${H})`;
|
|
60835
62088
|
}
|
|
@@ -60838,29 +62091,29 @@ var colorHelpers = {
|
|
|
60838
62091
|
}
|
|
60839
62092
|
},
|
|
60840
62093
|
colorMix(input1, input2, ratio = 0.5) {
|
|
60841
|
-
const
|
|
60842
|
-
const
|
|
62094
|
+
const c1 = toOklch2(input1);
|
|
62095
|
+
const c2 = toOklch2(input2);
|
|
60843
62096
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
60844
|
-
const
|
|
60845
|
-
const
|
|
60846
|
-
let
|
|
60847
|
-
if (
|
|
60848
|
-
if (
|
|
60849
|
-
|
|
60850
|
-
|
|
60851
|
-
|
|
60852
|
-
|
|
60853
|
-
|
|
60854
|
-
|
|
60855
|
-
H
|
|
60856
|
-
|
|
60857
|
-
|
|
60858
|
-
const
|
|
60859
|
-
const
|
|
60860
|
-
const a1 =
|
|
60861
|
-
const a2 =
|
|
60862
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
60863
|
-
return
|
|
62097
|
+
const c1Achromatic = c1.C < 1e-6;
|
|
62098
|
+
const c2Achromatic = c2.C < 1e-6;
|
|
62099
|
+
let H;
|
|
62100
|
+
if (c1Achromatic && c2Achromatic) H = c1.H;
|
|
62101
|
+
else if (c1Achromatic) H = c2.H;
|
|
62102
|
+
else if (c2Achromatic) H = c1.H;
|
|
62103
|
+
else {
|
|
62104
|
+
let dh = c2.H - c1.H;
|
|
62105
|
+
if (dh > 180) dh -= 360;
|
|
62106
|
+
if (dh < -180) dh += 360;
|
|
62107
|
+
H = c1.H + dh * ratio;
|
|
62108
|
+
if (H < 0) H += 360;
|
|
62109
|
+
if (H >= 360) H -= 360;
|
|
62110
|
+
}
|
|
62111
|
+
const L = c1.L + (c2.L - c1.L) * ratio;
|
|
62112
|
+
const C = c1.C + (c2.C - c1.C) * ratio;
|
|
62113
|
+
const a1 = c1.alpha ?? 1;
|
|
62114
|
+
const a2 = c2.alpha ?? 1;
|
|
62115
|
+
const alpha = normalizeAlpha2(a1 + (a2 - a1) * ratio);
|
|
62116
|
+
return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
|
|
60864
62117
|
},
|
|
60865
62118
|
colorContrast(bg, fg) {
|
|
60866
62119
|
return apca(toRgb255(bg), toRgb255(fg));
|
|
@@ -60868,11 +62121,11 @@ var colorHelpers = {
|
|
|
60868
62121
|
contrastingColor(bg, fg1, fg2) {
|
|
60869
62122
|
const bgRgb = toRgb255(bg);
|
|
60870
62123
|
if (fg1 !== void 0 && fg2 !== void 0) {
|
|
60871
|
-
return
|
|
62124
|
+
return packedToOklch(
|
|
60872
62125
|
contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
|
|
60873
62126
|
);
|
|
60874
62127
|
}
|
|
60875
|
-
return
|
|
62128
|
+
return packedToOklch(contrastingColor(bgRgb));
|
|
60876
62129
|
},
|
|
60877
62130
|
colorToColorspace(input, space) {
|
|
60878
62131
|
const rgb = toRgb255(input);
|
|
@@ -60901,7 +62154,7 @@ var colorHelpers = {
|
|
|
60901
62154
|
default:
|
|
60902
62155
|
throw new Error(`Unknown color space: ${space}`);
|
|
60903
62156
|
}
|
|
60904
|
-
if (alpha !== void 0
|
|
62157
|
+
if (alpha !== void 0) result.push(alpha);
|
|
60905
62158
|
return result;
|
|
60906
62159
|
},
|
|
60907
62160
|
colormap(name, arg) {
|
|
@@ -60913,7 +62166,7 @@ var colorHelpers = {
|
|
|
60913
62166
|
const palette = allPalettes[name];
|
|
60914
62167
|
if (!palette) throw new Error(`Unknown palette: ${name}`);
|
|
60915
62168
|
const colors = palette.map(
|
|
60916
|
-
(hex) =>
|
|
62169
|
+
(hex) => packedToOklch(parseColor(hex))
|
|
60917
62170
|
);
|
|
60918
62171
|
if (arg === void 0) return colors;
|
|
60919
62172
|
if (Number.isInteger(arg) && arg >= 2) {
|
|
@@ -60937,62 +62190,128 @@ var colorHelpers = {
|
|
|
60937
62190
|
const frac = pos - i;
|
|
60938
62191
|
if (frac === 0 || i >= colors.length - 1)
|
|
60939
62192
|
return [...colors[Math.min(i, colors.length - 1)]];
|
|
60940
|
-
const
|
|
60941
|
-
|
|
60942
|
-
|
|
60943
|
-
|
|
60944
|
-
|
|
60945
|
-
|
|
60946
|
-
|
|
60947
|
-
|
|
60948
|
-
|
|
60949
|
-
|
|
60950
|
-
|
|
60951
|
-
|
|
60952
|
-
|
|
60953
|
-
|
|
60954
|
-
|
|
60955
|
-
|
|
60956
|
-
|
|
60957
|
-
if (H >= 360) H -= 360;
|
|
60958
|
-
const mixed = oklchToRgb({
|
|
60959
|
-
L: c1.L + (c2.L - c1.L) * frac,
|
|
60960
|
-
C: c1.C + (c2.C - c1.C) * frac,
|
|
60961
|
-
H
|
|
60962
|
-
});
|
|
60963
|
-
return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
|
|
62193
|
+
const [L1, C1, H1] = colors[i];
|
|
62194
|
+
const [L2, C2, H2] = colors[i + 1];
|
|
62195
|
+
const c1Achromatic = C1 < 1e-6;
|
|
62196
|
+
const c2Achromatic = C2 < 1e-6;
|
|
62197
|
+
let H;
|
|
62198
|
+
if (c1Achromatic && c2Achromatic) H = H1;
|
|
62199
|
+
else if (c1Achromatic) H = H2;
|
|
62200
|
+
else if (c2Achromatic) H = H1;
|
|
62201
|
+
else {
|
|
62202
|
+
let dh = H2 - H1;
|
|
62203
|
+
if (dh > 180) dh -= 360;
|
|
62204
|
+
if (dh < -180) dh += 360;
|
|
62205
|
+
H = H1 + dh * frac;
|
|
62206
|
+
if (H < 0) H += 360;
|
|
62207
|
+
if (H >= 360) H -= 360;
|
|
62208
|
+
}
|
|
62209
|
+
return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
|
|
60964
62210
|
},
|
|
60965
62211
|
colorFromColorspace(components, space) {
|
|
60966
62212
|
const c0 = components[0];
|
|
60967
62213
|
const c1 = components[1];
|
|
60968
62214
|
const c2 = components[2];
|
|
60969
62215
|
const alpha = components.length >= 4 ? components[3] : void 0;
|
|
60970
|
-
let
|
|
62216
|
+
let oklch2;
|
|
60971
62217
|
switch (space.toLowerCase()) {
|
|
60972
62218
|
case "rgb":
|
|
60973
|
-
|
|
62219
|
+
oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
|
|
60974
62220
|
break;
|
|
60975
62221
|
case "hsl": {
|
|
60976
|
-
const
|
|
60977
|
-
|
|
62222
|
+
const rgb = hslToRgb(c0, c1, c2);
|
|
62223
|
+
oklch2 = rgbToOklch(rgb);
|
|
60978
62224
|
break;
|
|
60979
62225
|
}
|
|
60980
|
-
case "oklch":
|
|
60981
|
-
|
|
60982
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62226
|
+
case "oklch":
|
|
62227
|
+
oklch2 = { L: c0, C: c1, H: c2 };
|
|
60983
62228
|
break;
|
|
60984
|
-
}
|
|
60985
62229
|
case "oklab":
|
|
60986
|
-
case "lab":
|
|
60987
|
-
|
|
60988
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62230
|
+
case "lab":
|
|
62231
|
+
oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
|
|
60989
62232
|
break;
|
|
60990
|
-
}
|
|
60991
62233
|
default:
|
|
60992
62234
|
throw new Error(`Unknown color space: ${space}`);
|
|
60993
62235
|
}
|
|
60994
|
-
|
|
60995
|
-
|
|
62236
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
62237
|
+
},
|
|
62238
|
+
// -----------------------------------------------------------------------
|
|
62239
|
+
// Color constructors. Each accepts components in its colorspace's natural
|
|
62240
|
+
// units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
|
|
62241
|
+
// -----------------------------------------------------------------------
|
|
62242
|
+
rgb(r, g, b, alpha) {
|
|
62243
|
+
const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
|
|
62244
|
+
const a = normalizeAlpha2(alpha);
|
|
62245
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62246
|
+
},
|
|
62247
|
+
hsv(h, s, v, alpha) {
|
|
62248
|
+
const rgb = hsvToRgb(h, s, v);
|
|
62249
|
+
const c = rgbToOklch(rgb);
|
|
62250
|
+
const a = normalizeAlpha2(alpha);
|
|
62251
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62252
|
+
},
|
|
62253
|
+
hsl(h, s, l, alpha) {
|
|
62254
|
+
const rgb = hslToRgb(h, s, l);
|
|
62255
|
+
const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
|
|
62256
|
+
const a = normalizeAlpha2(alpha);
|
|
62257
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62258
|
+
},
|
|
62259
|
+
oklab(L, a, b, alpha) {
|
|
62260
|
+
const c = oklabToOklch({ L, a, b });
|
|
62261
|
+
const al = normalizeAlpha2(alpha);
|
|
62262
|
+
return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
|
|
62263
|
+
},
|
|
62264
|
+
oklch(L, C, H, alpha) {
|
|
62265
|
+
const a = normalizeAlpha2(alpha);
|
|
62266
|
+
return a !== void 0 ? [L, C, H, a] : [L, C, H];
|
|
62267
|
+
},
|
|
62268
|
+
// -----------------------------------------------------------------------
|
|
62269
|
+
// As* converters. Inputs are anything `toOklch` accepts (string, packed
|
|
62270
|
+
// int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
|
|
62271
|
+
// space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
|
|
62272
|
+
// consistency with the GPU target's shader convention.
|
|
62273
|
+
// -----------------------------------------------------------------------
|
|
62274
|
+
asRgb(input) {
|
|
62275
|
+
const rgb = toRgb255(input);
|
|
62276
|
+
const r = rgb.r / 255;
|
|
62277
|
+
const g = rgb.g / 255;
|
|
62278
|
+
const b = rgb.b / 255;
|
|
62279
|
+
return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
|
|
62280
|
+
},
|
|
62281
|
+
asHsv(input) {
|
|
62282
|
+
const rgb = toRgb255(input);
|
|
62283
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
62284
|
+
return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
|
|
62285
|
+
},
|
|
62286
|
+
asHsl(input) {
|
|
62287
|
+
const rgb = toRgb255(input);
|
|
62288
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
62289
|
+
return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
|
|
62290
|
+
},
|
|
62291
|
+
asOklab(input) {
|
|
62292
|
+
const c = toOklch2(input);
|
|
62293
|
+
const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
|
|
62294
|
+
return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
|
|
62295
|
+
},
|
|
62296
|
+
// asOklch is identity — handled at compile time as a pass-through
|
|
62297
|
+
// Perceptual color difference (ΔE_OK).
|
|
62298
|
+
colorDelta(a, b) {
|
|
62299
|
+
const labA = oklchToOklab(toOklch2(a));
|
|
62300
|
+
const labB = oklchToOklab(toOklch2(b));
|
|
62301
|
+
return oklabDeltaE(labA, labB);
|
|
62302
|
+
},
|
|
62303
|
+
// Euclidean distance between two tuples. Plain numeric — not a color
|
|
62304
|
+
// operation despite living in the same helpers block.
|
|
62305
|
+
distance(a, b) {
|
|
62306
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
62307
|
+
throw new Error("Distance: expected two arrays");
|
|
62308
|
+
if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
|
|
62309
|
+
let sumSq = 0;
|
|
62310
|
+
for (let i = 0; i < a.length; i++) {
|
|
62311
|
+
const d = a[i] - b[i];
|
|
62312
|
+
sumSq += d * d;
|
|
62313
|
+
}
|
|
62314
|
+
return Math.sqrt(sumSq);
|
|
60996
62315
|
}
|
|
60997
62316
|
};
|
|
60998
62317
|
var SYS_HELPERS = {
|
|
@@ -61431,6 +62750,13 @@ var GPU_OPERATORS = {
|
|
|
61431
62750
|
function gpuVec2(target) {
|
|
61432
62751
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
61433
62752
|
}
|
|
62753
|
+
function gpuVec3(target) {
|
|
62754
|
+
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
62755
|
+
}
|
|
62756
|
+
function readStringLiteral(expr2) {
|
|
62757
|
+
if (!isString(expr2)) return null;
|
|
62758
|
+
return expr2.string?.toLowerCase() ?? null;
|
|
62759
|
+
}
|
|
61434
62760
|
function compileIntArg(expr2, compile3, target) {
|
|
61435
62761
|
const c = tryGetConstant(expr2);
|
|
61436
62762
|
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
@@ -61489,7 +62815,7 @@ function compileGPUSumProduct(kind, args, _compile2, target) {
|
|
|
61489
62815
|
`for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
|
|
61490
62816
|
` ${acc} ${op}= ${body};`,
|
|
61491
62817
|
`}`,
|
|
61492
|
-
`return ${acc}
|
|
62818
|
+
`return ${acc};`
|
|
61493
62819
|
];
|
|
61494
62820
|
return lines.join("\n");
|
|
61495
62821
|
}
|
|
@@ -61543,8 +62869,7 @@ var GPU_FUNCTIONS = {
|
|
|
61543
62869
|
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
61544
62870
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
61545
62871
|
const v2 = gpuVec2(target);
|
|
61546
|
-
if (realFactors.length === 0)
|
|
61547
|
-
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
62872
|
+
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
61548
62873
|
const factors = realFactors.map((f) => compile3(f));
|
|
61549
62874
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
61550
62875
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
@@ -61597,8 +62922,7 @@ var GPU_FUNCTIONS = {
|
|
|
61597
62922
|
if (isNumber(x) && x.im !== 0) {
|
|
61598
62923
|
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
61599
62924
|
}
|
|
61600
|
-
if (isSymbol2(x, "ImaginaryUnit"))
|
|
61601
|
-
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
62925
|
+
if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
61602
62926
|
return `(-${compile3(x)})`;
|
|
61603
62927
|
},
|
|
61604
62928
|
// Standard math functions with complex dispatch
|
|
@@ -61971,17 +63295,127 @@ var GPU_FUNCTIONS = {
|
|
|
61971
63295
|
}
|
|
61972
63296
|
const isWGSL = target?.language === "wgsl";
|
|
61973
63297
|
const v3 = isWGSL ? "vec3f" : "vec3";
|
|
61974
|
-
|
|
63298
|
+
const black = `${v3}(0.0)`;
|
|
63299
|
+
const white = `${v3}(1.0, 0.0, 0.0)`;
|
|
63300
|
+
return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
|
|
61975
63301
|
},
|
|
61976
63302
|
ColorToColorspace: ([color, space], compile3) => {
|
|
61977
63303
|
if (color === null || space === null)
|
|
61978
63304
|
throw new Error("ColorToColorspace: need color and space");
|
|
61979
|
-
|
|
63305
|
+
const spaceName = readStringLiteral(space);
|
|
63306
|
+
if (spaceName === null)
|
|
63307
|
+
throw new Error("ColorToColorspace: space must be a string literal");
|
|
63308
|
+
const c = compile3(color);
|
|
63309
|
+
switch (spaceName) {
|
|
63310
|
+
case "oklch":
|
|
63311
|
+
return c;
|
|
63312
|
+
case "oklab":
|
|
63313
|
+
case "lab":
|
|
63314
|
+
return `_gpu_oklch_to_oklab(${c})`;
|
|
63315
|
+
case "rgb":
|
|
63316
|
+
return `_gpu_oklch_to_srgb(${c})`;
|
|
63317
|
+
case "hsl":
|
|
63318
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
|
|
63319
|
+
case "hsv":
|
|
63320
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
|
|
63321
|
+
default:
|
|
63322
|
+
throw new Error(
|
|
63323
|
+
`ColorToColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63324
|
+
);
|
|
63325
|
+
}
|
|
61980
63326
|
},
|
|
61981
63327
|
ColorFromColorspace: ([components, space], compile3) => {
|
|
61982
63328
|
if (components === null || space === null)
|
|
61983
63329
|
throw new Error("ColorFromColorspace: need components and space");
|
|
61984
|
-
|
|
63330
|
+
const spaceName = readStringLiteral(space);
|
|
63331
|
+
if (spaceName === null)
|
|
63332
|
+
throw new Error("ColorFromColorspace: space must be a string literal");
|
|
63333
|
+
const c = compile3(components);
|
|
63334
|
+
switch (spaceName) {
|
|
63335
|
+
case "oklch":
|
|
63336
|
+
return c;
|
|
63337
|
+
case "oklab":
|
|
63338
|
+
case "lab":
|
|
63339
|
+
return `_gpu_oklab_to_oklch(${c})`;
|
|
63340
|
+
case "rgb":
|
|
63341
|
+
return `_gpu_srgb_to_oklch(${c})`;
|
|
63342
|
+
case "hsl":
|
|
63343
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
|
|
63344
|
+
case "hsv":
|
|
63345
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
|
|
63346
|
+
default:
|
|
63347
|
+
throw new Error(
|
|
63348
|
+
`ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63349
|
+
);
|
|
63350
|
+
}
|
|
63351
|
+
},
|
|
63352
|
+
// ---------------------------------------------------------------------------
|
|
63353
|
+
// Color literals. Each typed head compiles to a canonical OKLCh vec3.
|
|
63354
|
+
// Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
|
|
63355
|
+
// alpha as a separate uniform if it's needed at the framebuffer boundary.
|
|
63356
|
+
// ---------------------------------------------------------------------------
|
|
63357
|
+
Color: ([s], _compile2, target) => {
|
|
63358
|
+
if (s === null) throw new Error("Color: no argument");
|
|
63359
|
+
const str = readStringLiteral(s);
|
|
63360
|
+
if (str === null)
|
|
63361
|
+
throw new Error("Color: argument must be a string literal on GPU target");
|
|
63362
|
+
const packed = parseColor(str);
|
|
63363
|
+
if (packed === 0 && str.trim().toLowerCase() !== "transparent")
|
|
63364
|
+
throw new Error(`Color: invalid color string "${str}"`);
|
|
63365
|
+
const r = packed >>> 24 & 255;
|
|
63366
|
+
const g = packed >>> 16 & 255;
|
|
63367
|
+
const b = packed >>> 8 & 255;
|
|
63368
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
63369
|
+
return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
|
|
63370
|
+
},
|
|
63371
|
+
Rgb: (args, compile3, target) => {
|
|
63372
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
63373
|
+
const v3 = gpuVec3(target);
|
|
63374
|
+
return `_gpu_srgb_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63375
|
+
},
|
|
63376
|
+
Hsv: (args, compile3, target) => {
|
|
63377
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
63378
|
+
const v3 = gpuVec3(target);
|
|
63379
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63380
|
+
},
|
|
63381
|
+
Hsl: (args, compile3, target) => {
|
|
63382
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
63383
|
+
const v3 = gpuVec3(target);
|
|
63384
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63385
|
+
},
|
|
63386
|
+
Oklab: (args, compile3, target) => {
|
|
63387
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
63388
|
+
const v3 = gpuVec3(target);
|
|
63389
|
+
return `_gpu_oklab_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63390
|
+
},
|
|
63391
|
+
Oklch: (args, compile3, target) => {
|
|
63392
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
63393
|
+
const v3 = gpuVec3(target);
|
|
63394
|
+
return `${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})`;
|
|
63395
|
+
},
|
|
63396
|
+
// ---------------------------------------------------------------------------
|
|
63397
|
+
// As* operators. AsOklch is identity (canonical). The other As* return
|
|
63398
|
+
// components in the named space, equivalent to ColorToColorspace(c, 'x').
|
|
63399
|
+
// ---------------------------------------------------------------------------
|
|
63400
|
+
AsOklch: ([c], compile3) => {
|
|
63401
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
63402
|
+
return compile3(c);
|
|
63403
|
+
},
|
|
63404
|
+
AsOklab: ([c], compile3) => {
|
|
63405
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
63406
|
+
return `_gpu_oklch_to_oklab(${compile3(c)})`;
|
|
63407
|
+
},
|
|
63408
|
+
AsRgb: ([c], compile3) => {
|
|
63409
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
63410
|
+
return `_gpu_oklch_to_srgb(${compile3(c)})`;
|
|
63411
|
+
},
|
|
63412
|
+
AsHsv: ([c], compile3) => {
|
|
63413
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
63414
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
63415
|
+
},
|
|
63416
|
+
AsHsl: ([c], compile3) => {
|
|
63417
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
63418
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
61985
63419
|
},
|
|
61986
63420
|
// Fractal functions
|
|
61987
63421
|
Mandelbrot: ([c, maxIter], compile3, target) => {
|
|
@@ -62674,28 +64108,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
|
|
|
62674
64108
|
|
|
62675
64109
|
vec3 _gpu_oklab_to_oklch(vec3 lab) {
|
|
62676
64110
|
float C = length(lab.yz);
|
|
62677
|
-
float H = atan(lab.z, lab.y);
|
|
64111
|
+
float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64112
|
+
if (H < 0.0) H += 360.0;
|
|
62678
64113
|
return vec3(lab.x, C, H);
|
|
62679
64114
|
}
|
|
62680
64115
|
|
|
62681
64116
|
vec3 _gpu_oklch_to_oklab(vec3 lch) {
|
|
62682
|
-
|
|
64117
|
+
float h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64118
|
+
return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64119
|
+
}
|
|
64120
|
+
|
|
64121
|
+
vec3 _gpu_srgb_to_oklch(vec3 rgb) {
|
|
64122
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
64123
|
+
}
|
|
64124
|
+
|
|
64125
|
+
vec3 _gpu_oklch_to_srgb(vec3 lch) {
|
|
64126
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64127
|
+
}
|
|
64128
|
+
|
|
64129
|
+
// HSL conversion. Hue in degrees, saturation/lightness in 0-1.
|
|
64130
|
+
vec3 _gpu_hsl_to_rgb(vec3 hsl) {
|
|
64131
|
+
float h = hsl.x;
|
|
64132
|
+
float s = hsl.y;
|
|
64133
|
+
float l = hsl.z;
|
|
64134
|
+
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64135
|
+
float h6 = h / 60.0;
|
|
64136
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64137
|
+
float r = 0.0;
|
|
64138
|
+
float g = 0.0;
|
|
64139
|
+
float b = 0.0;
|
|
64140
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64141
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64142
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64143
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64144
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64145
|
+
else { r = c; g = 0.0; b = x; }
|
|
64146
|
+
float m = l - c / 2.0;
|
|
64147
|
+
return vec3(r + m, g + m, b + m);
|
|
64148
|
+
}
|
|
64149
|
+
|
|
64150
|
+
vec3 _gpu_rgb_to_hsl(vec3 rgb) {
|
|
64151
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64152
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64153
|
+
float l = (maxc + minc) / 2.0;
|
|
64154
|
+
float d = maxc - minc;
|
|
64155
|
+
if (d < 1e-6) return vec3(0.0, 0.0, l);
|
|
64156
|
+
float s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64157
|
+
float h;
|
|
64158
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64159
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64160
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64161
|
+
h *= 60.0;
|
|
64162
|
+
if (h < 0.0) h += 360.0;
|
|
64163
|
+
return vec3(h, s, l);
|
|
64164
|
+
}
|
|
64165
|
+
|
|
64166
|
+
// HSV conversion. Hue in degrees, saturation/value in 0-1.
|
|
64167
|
+
vec3 _gpu_hsv_to_rgb(vec3 hsv) {
|
|
64168
|
+
float h = hsv.x;
|
|
64169
|
+
float s = hsv.y;
|
|
64170
|
+
float v = hsv.z;
|
|
64171
|
+
float c = v * s;
|
|
64172
|
+
float h6 = h / 60.0;
|
|
64173
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64174
|
+
float r = 0.0;
|
|
64175
|
+
float g = 0.0;
|
|
64176
|
+
float b = 0.0;
|
|
64177
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64178
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64179
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64180
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64181
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64182
|
+
else { r = c; g = 0.0; b = x; }
|
|
64183
|
+
float m = v - c;
|
|
64184
|
+
return vec3(r + m, g + m, b + m);
|
|
62683
64185
|
}
|
|
62684
64186
|
|
|
62685
|
-
vec3
|
|
62686
|
-
|
|
62687
|
-
|
|
64187
|
+
vec3 _gpu_rgb_to_hsv(vec3 rgb) {
|
|
64188
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64189
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64190
|
+
float v = maxc;
|
|
64191
|
+
float d = maxc - minc;
|
|
64192
|
+
if (d < 1e-6) return vec3(0.0, 0.0, v);
|
|
64193
|
+
float s = (maxc < 1e-6) ? 0.0 : d / maxc;
|
|
64194
|
+
float h;
|
|
64195
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64196
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64197
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64198
|
+
h *= 60.0;
|
|
64199
|
+
if (h < 0.0) h += 360.0;
|
|
64200
|
+
return vec3(h, s, v);
|
|
64201
|
+
}
|
|
64202
|
+
|
|
64203
|
+
vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
|
|
62688
64204
|
float L = mix(lch1.x, lch2.x, t);
|
|
62689
64205
|
float C = mix(lch1.y, lch2.y, t);
|
|
62690
|
-
|
|
62691
|
-
|
|
62692
|
-
|
|
62693
|
-
if (
|
|
62694
|
-
|
|
62695
|
-
|
|
64206
|
+
bool a1 = lch1.y < 1e-6;
|
|
64207
|
+
bool a2 = lch2.y < 1e-6;
|
|
64208
|
+
float H;
|
|
64209
|
+
if (a1 && a2) {
|
|
64210
|
+
H = lch1.z;
|
|
64211
|
+
} else if (a1) {
|
|
64212
|
+
H = lch2.z;
|
|
64213
|
+
} else if (a2) {
|
|
64214
|
+
H = lch1.z;
|
|
64215
|
+
} else {
|
|
64216
|
+
float dh = lch2.z - lch1.z;
|
|
64217
|
+
if (dh > 180.0) dh -= 360.0;
|
|
64218
|
+
if (dh < -180.0) dh += 360.0;
|
|
64219
|
+
H = lch1.z + dh * t;
|
|
64220
|
+
if (H < 0.0) H += 360.0;
|
|
64221
|
+
if (H >= 360.0) H -= 360.0;
|
|
64222
|
+
}
|
|
64223
|
+
return vec3(L, C, H);
|
|
62696
64224
|
}
|
|
62697
64225
|
|
|
62698
|
-
float _gpu_apca(vec3
|
|
64226
|
+
float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
|
|
64227
|
+
vec3 bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64228
|
+
vec3 fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62699
64229
|
float bgR = _gpu_srgb_to_linear(bg.x);
|
|
62700
64230
|
float bgG = _gpu_srgb_to_linear(bg.y);
|
|
62701
64231
|
float bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -62706,9 +64236,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
|
|
|
62706
64236
|
float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
|
|
62707
64237
|
float bgC = pow(bgY, 0.56);
|
|
62708
64238
|
float fgC = pow(fgY, 0.57);
|
|
62709
|
-
float contrast = (bgC
|
|
62710
|
-
? (bgC - fgC) * 1.14
|
|
62711
|
-
: (bgC - fgC) * 1.14;
|
|
64239
|
+
float contrast = (bgC - fgC) * 1.14;
|
|
62712
64240
|
return contrast * 100.0;
|
|
62713
64241
|
}
|
|
62714
64242
|
`;
|
|
@@ -62752,28 +64280,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
|
|
|
62752
64280
|
|
|
62753
64281
|
fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
|
|
62754
64282
|
let C = length(lab.yz);
|
|
62755
|
-
|
|
64283
|
+
var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64284
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
62756
64285
|
return vec3f(lab.x, C, H);
|
|
62757
64286
|
}
|
|
62758
64287
|
|
|
62759
64288
|
fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
|
|
62760
|
-
|
|
64289
|
+
let h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64290
|
+
return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64291
|
+
}
|
|
64292
|
+
|
|
64293
|
+
fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
|
|
64294
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
64295
|
+
}
|
|
64296
|
+
|
|
64297
|
+
fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
|
|
64298
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64299
|
+
}
|
|
64300
|
+
|
|
64301
|
+
fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
|
|
64302
|
+
let h = hsl.x;
|
|
64303
|
+
let s = hsl.y;
|
|
64304
|
+
let l = hsl.z;
|
|
64305
|
+
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64306
|
+
let h6 = h / 60.0;
|
|
64307
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64308
|
+
var r: f32 = 0.0;
|
|
64309
|
+
var g: f32 = 0.0;
|
|
64310
|
+
var b: f32 = 0.0;
|
|
64311
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64312
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64313
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64314
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64315
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64316
|
+
else { r = c; g = 0.0; b = x; }
|
|
64317
|
+
let m = l - c / 2.0;
|
|
64318
|
+
return vec3f(r + m, g + m, b + m);
|
|
64319
|
+
}
|
|
64320
|
+
|
|
64321
|
+
fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
|
|
64322
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64323
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64324
|
+
let l = (maxc + minc) / 2.0;
|
|
64325
|
+
let d = maxc - minc;
|
|
64326
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
|
|
64327
|
+
let s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64328
|
+
var h: f32;
|
|
64329
|
+
if (maxc == rgb.x) {
|
|
64330
|
+
let v = (rgb.y - rgb.z) / d;
|
|
64331
|
+
h = v - 6.0 * floor(v / 6.0);
|
|
64332
|
+
} else if (maxc == rgb.y) {
|
|
64333
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64334
|
+
} else {
|
|
64335
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64336
|
+
}
|
|
64337
|
+
h = h * 60.0;
|
|
64338
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64339
|
+
return vec3f(h, s, l);
|
|
64340
|
+
}
|
|
64341
|
+
|
|
64342
|
+
fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
|
|
64343
|
+
let h = hsv.x;
|
|
64344
|
+
let s = hsv.y;
|
|
64345
|
+
let v = hsv.z;
|
|
64346
|
+
let c = v * s;
|
|
64347
|
+
let h6 = h / 60.0;
|
|
64348
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64349
|
+
var r: f32 = 0.0;
|
|
64350
|
+
var g: f32 = 0.0;
|
|
64351
|
+
var b: f32 = 0.0;
|
|
64352
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64353
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64354
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64355
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64356
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64357
|
+
else { r = c; g = 0.0; b = x; }
|
|
64358
|
+
let m = v - c;
|
|
64359
|
+
return vec3f(r + m, g + m, b + m);
|
|
62761
64360
|
}
|
|
62762
64361
|
|
|
62763
|
-
fn
|
|
62764
|
-
let
|
|
62765
|
-
let
|
|
64362
|
+
fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
|
|
64363
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64364
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64365
|
+
let v = maxc;
|
|
64366
|
+
let d = maxc - minc;
|
|
64367
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
|
|
64368
|
+
var s: f32 = 0.0;
|
|
64369
|
+
if (maxc >= 1e-6) { s = d / maxc; }
|
|
64370
|
+
var h: f32;
|
|
64371
|
+
if (maxc == rgb.x) {
|
|
64372
|
+
let q = (rgb.y - rgb.z) / d;
|
|
64373
|
+
h = q - 6.0 * floor(q / 6.0);
|
|
64374
|
+
} else if (maxc == rgb.y) {
|
|
64375
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64376
|
+
} else {
|
|
64377
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64378
|
+
}
|
|
64379
|
+
h = h * 60.0;
|
|
64380
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64381
|
+
return vec3f(h, s, v);
|
|
64382
|
+
}
|
|
64383
|
+
|
|
64384
|
+
fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
|
|
62766
64385
|
let L = mix(lch1.x, lch2.x, t);
|
|
62767
64386
|
let C = mix(lch1.y, lch2.y, t);
|
|
62768
|
-
let
|
|
62769
|
-
|
|
62770
|
-
|
|
62771
|
-
if (
|
|
62772
|
-
|
|
62773
|
-
|
|
64387
|
+
let a1 = lch1.y < 1e-6;
|
|
64388
|
+
let a2 = lch2.y < 1e-6;
|
|
64389
|
+
var H: f32;
|
|
64390
|
+
if (a1 && a2) {
|
|
64391
|
+
H = lch1.z;
|
|
64392
|
+
} else if (a1) {
|
|
64393
|
+
H = lch2.z;
|
|
64394
|
+
} else if (a2) {
|
|
64395
|
+
H = lch1.z;
|
|
64396
|
+
} else {
|
|
64397
|
+
var dh = lch2.z - lch1.z;
|
|
64398
|
+
if (dh > 180.0) { dh = dh - 360.0; }
|
|
64399
|
+
if (dh < -180.0) { dh = dh + 360.0; }
|
|
64400
|
+
H = lch1.z + dh * t;
|
|
64401
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
64402
|
+
if (H >= 360.0) { H = H - 360.0; }
|
|
64403
|
+
}
|
|
64404
|
+
return vec3f(L, C, H);
|
|
62774
64405
|
}
|
|
62775
64406
|
|
|
62776
|
-
fn _gpu_apca(
|
|
64407
|
+
fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
64408
|
+
let bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64409
|
+
let fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62777
64410
|
let bgR = _gpu_srgb_to_linear(bg.x);
|
|
62778
64411
|
let bgG = _gpu_srgb_to_linear(bg.y);
|
|
62779
64412
|
let bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -63061,7 +64694,7 @@ var GPUShaderTarget = class {
|
|
|
63061
64694
|
if (stmts.length === 0) return "";
|
|
63062
64695
|
const last = stmts.length - 1;
|
|
63063
64696
|
stmts[last] = `return ${stmts[last]}`;
|
|
63064
|
-
return stmts.join(";\n");
|
|
64697
|
+
return stmts.join(";\n") + ";";
|
|
63065
64698
|
},
|
|
63066
64699
|
...options
|
|
63067
64700
|
};
|
|
@@ -63160,7 +64793,7 @@ var GLSLTarget = class extends GPUShaderTarget {
|
|
|
63160
64793
|
if (body.includes("\n")) {
|
|
63161
64794
|
const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
|
|
63162
64795
|
return `${returnType} ${functionName}(${params}) {
|
|
63163
|
-
${indented}
|
|
64796
|
+
${indented}
|
|
63164
64797
|
}`;
|
|
63165
64798
|
}
|
|
63166
64799
|
return `${returnType} ${functionName}(${params}) {
|
|
@@ -63271,7 +64904,7 @@ var WGSLTarget = class extends GPUShaderTarget {
|
|
|
63271
64904
|
return `fn ${functionName}(${params}) -> ${toWGSLType(
|
|
63272
64905
|
returnType
|
|
63273
64906
|
)} {
|
|
63274
|
-
${indented}
|
|
64907
|
+
${indented}
|
|
63275
64908
|
}`;
|
|
63276
64909
|
}
|
|
63277
64910
|
return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
|
|
@@ -67678,6 +69311,7 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
67678
69311
|
this.pushScope(void 0, "global");
|
|
67679
69312
|
this._compilationTargets.registerDefaults();
|
|
67680
69313
|
if (options?.latexSyntax) this._latexSyntax = options.latexSyntax;
|
|
69314
|
+
if (options?.latexOptions) this._latexOptions = { ...options.latexOptions };
|
|
67681
69315
|
hidePrivateProperties(this);
|
|
67682
69316
|
}
|
|
67683
69317
|
toJSON() {
|
|
@@ -68092,6 +69726,15 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68092
69726
|
lookupDefinition(id) {
|
|
68093
69727
|
return lookupDefinition(this, id);
|
|
68094
69728
|
}
|
|
69729
|
+
operatorInfo(head) {
|
|
69730
|
+
const def = this.lookupDefinition(head);
|
|
69731
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
69732
|
+
const op = def.operator;
|
|
69733
|
+
return {
|
|
69734
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
69735
|
+
signature: op.signature
|
|
69736
|
+
};
|
|
69737
|
+
}
|
|
68095
69738
|
/**
|
|
68096
69739
|
* Associate a new definition to a symbol in the current context.
|
|
68097
69740
|
*
|
|
@@ -68338,6 +69981,29 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68338
69981
|
);
|
|
68339
69982
|
return this._latexSyntax;
|
|
68340
69983
|
}
|
|
69984
|
+
/** @internal Engine-wide LaTeX parse/serialize options (e.g. decimalSeparator).
|
|
69985
|
+
* Merged into every `parse()` and `toLatex()` call between the LatexSyntax
|
|
69986
|
+
* instance defaults and any per-call overrides. */
|
|
69987
|
+
_latexOptions = {};
|
|
69988
|
+
/** Engine-wide LaTeX parse/serialize options.
|
|
69989
|
+
*
|
|
69990
|
+
* These options are merged into every `parse()` and `toLatex()` call.
|
|
69991
|
+
* Precedence (most-specific wins):
|
|
69992
|
+
* 1. LatexSyntax instance defaults (set at its construction)
|
|
69993
|
+
* 2. `ce.latexOptions` (this property)
|
|
69994
|
+
* 3. Per-call options passed to `ce.parse()` / `expr.toLatex()`
|
|
69995
|
+
*
|
|
69996
|
+
* Assigning replaces the whole bag. Use spread to merge:
|
|
69997
|
+
* ```ts
|
|
69998
|
+
* ce.latexOptions = { ...ce.latexOptions, decimalSeparator: '{,}' };
|
|
69999
|
+
* ```
|
|
70000
|
+
*/
|
|
70001
|
+
get latexOptions() {
|
|
70002
|
+
return this._latexOptions;
|
|
70003
|
+
}
|
|
70004
|
+
set latexOptions(options) {
|
|
70005
|
+
this._latexOptions = { ...options };
|
|
70006
|
+
}
|
|
68341
70007
|
parse(latex, options) {
|
|
68342
70008
|
if (latex === null || latex === void 0) return null;
|
|
68343
70009
|
if (typeof latex !== "string")
|
|
@@ -68345,7 +70011,6 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68345
70011
|
const syntax = this._requireLatexSyntax();
|
|
68346
70012
|
const { form, ...parseOpts } = options ?? {};
|
|
68347
70013
|
const result = syntax.parse(latex, {
|
|
68348
|
-
decimalSeparator: ".",
|
|
68349
70014
|
getSymbolType: (id) => {
|
|
68350
70015
|
const def = this.lookupDefinition(id);
|
|
68351
70016
|
if (!def) return BoxedType.unknown;
|
|
@@ -68357,6 +70022,8 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68357
70022
|
const def = this.lookupDefinition(id);
|
|
68358
70023
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
68359
70024
|
},
|
|
70025
|
+
tolerance: this.tolerance,
|
|
70026
|
+
...this._latexOptions,
|
|
68360
70027
|
...parseOpts
|
|
68361
70028
|
});
|
|
68362
70029
|
if (result === null) return null;
|
|
@@ -68520,14 +70187,14 @@ var ComputeEngine = class _ComputeEngine {
|
|
|
68520
70187
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
68521
70188
|
|
|
68522
70189
|
// src/compute-engine.ts
|
|
68523
|
-
var version = "0.
|
|
70190
|
+
var version = "0.57.0";
|
|
68524
70191
|
ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
|
|
68525
70192
|
_setDefaultEngineFactory(
|
|
68526
70193
|
() => new ComputeEngine({ latexSyntax: new LatexSyntax() })
|
|
68527
70194
|
);
|
|
68528
70195
|
globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
|
|
68529
70196
|
ComputeEngine: ComputeEngine.prototype.constructor,
|
|
68530
|
-
version: "0.
|
|
70197
|
+
version: "0.57.0"
|
|
68531
70198
|
};
|
|
68532
70199
|
export {
|
|
68533
70200
|
DEFINITIONS_ALGEBRA as ALGEBRA_DICTIONARY,
|