@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
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngine = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var ComputeEngine = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -2316,6 +2316,7 @@ var ComputeEngine = (() => {
|
|
|
2316
2316
|
];
|
|
2317
2317
|
var VALUE_TYPES = [
|
|
2318
2318
|
"value",
|
|
2319
|
+
"color",
|
|
2319
2320
|
...COLLECTION_TYPES,
|
|
2320
2321
|
...SCALAR_TYPES
|
|
2321
2322
|
];
|
|
@@ -4015,6 +4016,7 @@ var ComputeEngine = (() => {
|
|
|
4015
4016
|
symbol: [],
|
|
4016
4017
|
boolean: [],
|
|
4017
4018
|
string: [],
|
|
4019
|
+
color: [],
|
|
4018
4020
|
expression: EXPRESSION_TYPES
|
|
4019
4021
|
};
|
|
4020
4022
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
@@ -7898,9 +7900,10 @@ var ComputeEngine = (() => {
|
|
|
7898
7900
|
if (!materialized.isLazyCollection) return materialized.latex;
|
|
7899
7901
|
}
|
|
7900
7902
|
const syntax = this.engine._requireLatexSyntax();
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
);
|
|
7903
|
+
const json = this.toMathJson({ prettify: true, fractionalDigits: "auto" });
|
|
7904
|
+
const latexOpts = this.engine.latexOptions;
|
|
7905
|
+
if (Object.keys(latexOpts).length === 0) return syntax.serialize(json);
|
|
7906
|
+
return syntax.serialize(json, { ...latexOpts });
|
|
7904
7907
|
}
|
|
7905
7908
|
/**
|
|
7906
7909
|
* Return a LaTeX representation of this expression with custom
|
|
@@ -7911,8 +7914,15 @@ var ComputeEngine = (() => {
|
|
|
7911
7914
|
*
|
|
7912
7915
|
* Numeric values are rounded to `ce.precision` significant digits
|
|
7913
7916
|
* (via `fractionalDigits: 'auto'`).
|
|
7917
|
+
*
|
|
7918
|
+
* If `options.verbatim` is `true` and `verbatimLatex` is set on this
|
|
7919
|
+
* expression (i.e. it was parsed with `preserveLatex: true`), return
|
|
7920
|
+
* the verbatim source instead of re-serializing. Falls through to
|
|
7921
|
+
* re-serialization if no verbatim is available.
|
|
7914
7922
|
*/
|
|
7915
7923
|
toLatex(options) {
|
|
7924
|
+
if (options?.verbatim === true && this.verbatimLatex !== void 0)
|
|
7925
|
+
return this.verbatimLatex;
|
|
7916
7926
|
if (this.isLazyCollection) {
|
|
7917
7927
|
const materialized = this.evaluate({
|
|
7918
7928
|
materialization: options?.materialization ?? true
|
|
@@ -7924,9 +7934,13 @@ var ComputeEngine = (() => {
|
|
|
7924
7934
|
fractionalDigits: "auto"
|
|
7925
7935
|
});
|
|
7926
7936
|
const syntax = this.engine._requireLatexSyntax();
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7937
|
+
const latexOpts = this.engine.latexOptions;
|
|
7938
|
+
const haveEngineOpts = Object.keys(latexOpts).length > 0;
|
|
7939
|
+
const haveCallOpts = options && Object.keys(options).length > 0;
|
|
7940
|
+
if (!haveEngineOpts && !haveCallOpts) return syntax.serialize(json);
|
|
7941
|
+
if (!haveEngineOpts) return syntax.serialize(json, options);
|
|
7942
|
+
if (!haveCallOpts) return syntax.serialize(json, { ...latexOpts });
|
|
7943
|
+
return syntax.serialize(json, { ...latexOpts, ...options });
|
|
7930
7944
|
}
|
|
7931
7945
|
/** Called by `JSON.stringify()` when serializing to json.
|
|
7932
7946
|
*
|
|
@@ -7970,11 +7984,13 @@ var ComputeEngine = (() => {
|
|
|
7970
7984
|
"number",
|
|
7971
7985
|
"dictionary"
|
|
7972
7986
|
];
|
|
7973
|
-
}
|
|
7974
|
-
if (Array.isArray(options.shorthands))
|
|
7987
|
+
} else if (Array.isArray(options.shorthands)) {
|
|
7975
7988
|
defaultOptions.shorthands = options.shorthands;
|
|
7989
|
+
}
|
|
7976
7990
|
if (typeof options.metadata === "string" && options.metadata === "all" || options.metadata?.includes("all")) {
|
|
7977
7991
|
defaultOptions.metadata = ["latex", "wikidata"];
|
|
7992
|
+
} else if (Array.isArray(options.metadata)) {
|
|
7993
|
+
defaultOptions.metadata = options.metadata;
|
|
7978
7994
|
}
|
|
7979
7995
|
if (options.fractionalDigits === "auto")
|
|
7980
7996
|
defaultOptions.fractionalDigits = -this.engine.precision;
|
|
@@ -10049,6 +10065,64 @@ var ComputeEngine = (() => {
|
|
|
10049
10065
|
}
|
|
10050
10066
|
|
|
10051
10067
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
10068
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
10069
|
+
x: "First",
|
|
10070
|
+
y: "Second",
|
|
10071
|
+
z: "Third",
|
|
10072
|
+
real: "Real",
|
|
10073
|
+
re: "Real",
|
|
10074
|
+
imag: "Imaginary",
|
|
10075
|
+
im: "Imaginary",
|
|
10076
|
+
count: "Length",
|
|
10077
|
+
total: "Sum",
|
|
10078
|
+
max: "Max",
|
|
10079
|
+
min: "Min"
|
|
10080
|
+
};
|
|
10081
|
+
function memberHead(name) {
|
|
10082
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
10083
|
+
}
|
|
10084
|
+
function parseComponentAccess(parser, lhs) {
|
|
10085
|
+
parser.skipVisualSpace();
|
|
10086
|
+
if (parser.match("\\operatorname")) {
|
|
10087
|
+
const name = parser.parseStringGroup();
|
|
10088
|
+
if (name === null) return null;
|
|
10089
|
+
const head = memberHead(name.trim());
|
|
10090
|
+
if (head === null) return null;
|
|
10091
|
+
return [head, lhs];
|
|
10092
|
+
}
|
|
10093
|
+
const tok = parser.peek;
|
|
10094
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
10095
|
+
const bare = tok.slice(1);
|
|
10096
|
+
const head = memberHead(bare);
|
|
10097
|
+
if (head !== null) {
|
|
10098
|
+
parser.nextToken();
|
|
10099
|
+
return [head, lhs];
|
|
10100
|
+
}
|
|
10101
|
+
return null;
|
|
10102
|
+
}
|
|
10103
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
10104
|
+
const head = memberHead(tok);
|
|
10105
|
+
if (head === null) return null;
|
|
10106
|
+
parser.nextToken();
|
|
10107
|
+
return [head, lhs];
|
|
10108
|
+
}
|
|
10109
|
+
return null;
|
|
10110
|
+
}
|
|
10111
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
10112
|
+
parser.addBoundary(close);
|
|
10113
|
+
parser.skipVisualSpace();
|
|
10114
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
10115
|
+
if (cond === null) {
|
|
10116
|
+
parser.removeBoundary();
|
|
10117
|
+
return null;
|
|
10118
|
+
}
|
|
10119
|
+
parser.skipVisualSpace();
|
|
10120
|
+
if (!parser.matchBoundary()) {
|
|
10121
|
+
parser.removeBoundary();
|
|
10122
|
+
return null;
|
|
10123
|
+
}
|
|
10124
|
+
return ["When", lhs, cond];
|
|
10125
|
+
}
|
|
10052
10126
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
10053
10127
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
10054
10128
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -10520,6 +10594,15 @@ var ComputeEngine = (() => {
|
|
|
10520
10594
|
}
|
|
10521
10595
|
},
|
|
10522
10596
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
10597
|
+
// Component-access postfix: expr.member (C3)
|
|
10598
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
10599
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
10600
|
+
{
|
|
10601
|
+
kind: "postfix",
|
|
10602
|
+
precedence: 850,
|
|
10603
|
+
latexTrigger: ["."],
|
|
10604
|
+
parse: parseComponentAccess
|
|
10605
|
+
},
|
|
10523
10606
|
{
|
|
10524
10607
|
name: "At",
|
|
10525
10608
|
kind: "postfix",
|
|
@@ -10540,6 +10623,29 @@ var ComputeEngine = (() => {
|
|
|
10540
10623
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
10541
10624
|
parse: parseAt("\\right", "\\rbrack")
|
|
10542
10625
|
},
|
|
10626
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
10627
|
+
{
|
|
10628
|
+
name: "When",
|
|
10629
|
+
kind: "postfix",
|
|
10630
|
+
precedence: 800,
|
|
10631
|
+
latexTrigger: ["\\left", "\\{"],
|
|
10632
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
10633
|
+
serialize: (serializer, expr2) => {
|
|
10634
|
+
const e = operand(expr2, 1);
|
|
10635
|
+
const cond = operand(expr2, 2);
|
|
10636
|
+
if (!e || !cond) return "";
|
|
10637
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
10638
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
10639
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
10640
|
+
}
|
|
10641
|
+
},
|
|
10642
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
10643
|
+
{
|
|
10644
|
+
kind: "postfix",
|
|
10645
|
+
precedence: 800,
|
|
10646
|
+
latexTrigger: ["\\{"],
|
|
10647
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
10648
|
+
},
|
|
10543
10649
|
{
|
|
10544
10650
|
kind: "postfix",
|
|
10545
10651
|
latexTrigger: ["_"],
|
|
@@ -10622,6 +10728,29 @@ var ComputeEngine = (() => {
|
|
|
10622
10728
|
return "";
|
|
10623
10729
|
}
|
|
10624
10730
|
},
|
|
10731
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
10732
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
10733
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
10734
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
10735
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
10736
|
+
{
|
|
10737
|
+
latexTrigger: [".", ".", "."],
|
|
10738
|
+
kind: "infix",
|
|
10739
|
+
precedence: 800,
|
|
10740
|
+
parse: parseRange
|
|
10741
|
+
},
|
|
10742
|
+
{
|
|
10743
|
+
latexTrigger: ["\\ldots"],
|
|
10744
|
+
kind: "infix",
|
|
10745
|
+
precedence: 800,
|
|
10746
|
+
parse: parseRange
|
|
10747
|
+
},
|
|
10748
|
+
{
|
|
10749
|
+
latexTrigger: ["\\dots"],
|
|
10750
|
+
kind: "infix",
|
|
10751
|
+
precedence: 800,
|
|
10752
|
+
parse: parseRange
|
|
10753
|
+
},
|
|
10625
10754
|
{
|
|
10626
10755
|
latexTrigger: [";"],
|
|
10627
10756
|
kind: "infix",
|
|
@@ -10806,13 +10935,24 @@ var ComputeEngine = (() => {
|
|
|
10806
10935
|
const args = operands(expr2);
|
|
10807
10936
|
if (!args || args.length < 2) return "";
|
|
10808
10937
|
const body = args[0];
|
|
10809
|
-
const
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10938
|
+
const elements = args.slice(1);
|
|
10939
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
10940
|
+
if (!allElements) {
|
|
10941
|
+
return joinLatex([
|
|
10942
|
+
"\\operatorname{Loop}(",
|
|
10943
|
+
serializer.serialize(body),
|
|
10944
|
+
", ",
|
|
10945
|
+
serializer.serialize(elements[0]),
|
|
10946
|
+
")"
|
|
10947
|
+
]);
|
|
10948
|
+
}
|
|
10949
|
+
if (elements.length === 1) {
|
|
10950
|
+
const elem = elements[0];
|
|
10951
|
+
const index = operand(elem, 1);
|
|
10952
|
+
const coll = operand(elem, 2);
|
|
10953
|
+
if (operator(coll) === "Range") {
|
|
10954
|
+
const lo = operand(coll, 1);
|
|
10955
|
+
const hi = operand(coll, 2);
|
|
10816
10956
|
return joinLatex([
|
|
10817
10957
|
"\\text{for }",
|
|
10818
10958
|
serializer.serialize(index),
|
|
@@ -10824,13 +10964,27 @@ var ComputeEngine = (() => {
|
|
|
10824
10964
|
serializer.serialize(body)
|
|
10825
10965
|
]);
|
|
10826
10966
|
}
|
|
10967
|
+
return joinLatex([
|
|
10968
|
+
serializer.serialize(body),
|
|
10969
|
+
" \\operatorname{for} ",
|
|
10970
|
+
serializer.serialize(index),
|
|
10971
|
+
" = ",
|
|
10972
|
+
serializer.serialize(coll)
|
|
10973
|
+
]);
|
|
10827
10974
|
}
|
|
10975
|
+
const bindings = elements.map((elem) => {
|
|
10976
|
+
const name = operand(elem, 1);
|
|
10977
|
+
const coll = operand(elem, 2);
|
|
10978
|
+
return joinLatex([
|
|
10979
|
+
serializer.serialize(name),
|
|
10980
|
+
" = ",
|
|
10981
|
+
serializer.serialize(coll)
|
|
10982
|
+
]);
|
|
10983
|
+
}).join(", ");
|
|
10828
10984
|
return joinLatex([
|
|
10829
|
-
"\\operatorname{Loop}(",
|
|
10830
10985
|
serializer.serialize(body),
|
|
10831
|
-
"
|
|
10832
|
-
|
|
10833
|
-
")"
|
|
10986
|
+
" \\operatorname{for} ",
|
|
10987
|
+
bindings
|
|
10834
10988
|
]);
|
|
10835
10989
|
}
|
|
10836
10990
|
},
|
|
@@ -10863,6 +11017,18 @@ var ComputeEngine = (() => {
|
|
|
10863
11017
|
precedence: 245,
|
|
10864
11018
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
10865
11019
|
},
|
|
11020
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
11021
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
11022
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
11023
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
11024
|
+
// bindings can be comma-separated below us.
|
|
11025
|
+
{
|
|
11026
|
+
symbolTrigger: "for",
|
|
11027
|
+
kind: "infix",
|
|
11028
|
+
associativity: "none",
|
|
11029
|
+
precedence: 19,
|
|
11030
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
11031
|
+
},
|
|
10866
11032
|
// \operatorname{break}
|
|
10867
11033
|
{
|
|
10868
11034
|
symbolTrigger: "break",
|
|
@@ -11067,7 +11233,10 @@ var ComputeEngine = (() => {
|
|
|
11067
11233
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
11068
11234
|
parser.addBoundary([")"]);
|
|
11069
11235
|
const expr2 = parser.parseExpression(until);
|
|
11070
|
-
if (!parser.matchBoundary())
|
|
11236
|
+
if (!parser.matchBoundary()) {
|
|
11237
|
+
parser.removeBoundary();
|
|
11238
|
+
return null;
|
|
11239
|
+
}
|
|
11071
11240
|
if (!parser.match("<}>")) return null;
|
|
11072
11241
|
return ["Derivative", lhs, expr2];
|
|
11073
11242
|
}
|
|
@@ -11508,7 +11677,12 @@ var ComputeEngine = (() => {
|
|
|
11508
11677
|
if (isEmptySequence(body)) return ["List"];
|
|
11509
11678
|
const h = operator(body);
|
|
11510
11679
|
if (h === "Range" || h === "Linspace") return body;
|
|
11511
|
-
if (h === "Sequence")
|
|
11680
|
+
if (h === "Sequence") {
|
|
11681
|
+
const elems = operands(body);
|
|
11682
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11683
|
+
if (inferred) return inferred;
|
|
11684
|
+
return ["List", ...elems];
|
|
11685
|
+
}
|
|
11512
11686
|
if (h === "Delimiter") {
|
|
11513
11687
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
11514
11688
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -11521,12 +11695,37 @@ var ComputeEngine = (() => {
|
|
|
11521
11695
|
}
|
|
11522
11696
|
if (delim === "," || delim === ".,.") {
|
|
11523
11697
|
body = operand(body, 1);
|
|
11524
|
-
if (operator(body) === "Sequence")
|
|
11698
|
+
if (operator(body) === "Sequence") {
|
|
11699
|
+
const elems = operands(body);
|
|
11700
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
11701
|
+
if (inferred) return inferred;
|
|
11702
|
+
return ["List", ...elems];
|
|
11703
|
+
}
|
|
11525
11704
|
return ["List", body ?? "Nothing"];
|
|
11526
11705
|
}
|
|
11527
11706
|
}
|
|
11528
11707
|
return ["List", body];
|
|
11529
11708
|
}
|
|
11709
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
11710
|
+
if (elems.length < 4) return null;
|
|
11711
|
+
const penultimate = elems[elems.length - 2];
|
|
11712
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
11713
|
+
const samples = elems.slice(0, -2);
|
|
11714
|
+
const endExpr = elems[elems.length - 1];
|
|
11715
|
+
if (samples.length < 2) return null;
|
|
11716
|
+
const sampleNums = samples.map(machineValue);
|
|
11717
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
11718
|
+
const nums = sampleNums;
|
|
11719
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
11720
|
+
const tol = parser.options.tolerance;
|
|
11721
|
+
if (Math.abs(step) < tol)
|
|
11722
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
11723
|
+
for (let i = 1; i < nums.length; i++) {
|
|
11724
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
11725
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
11726
|
+
}
|
|
11727
|
+
return ["Range", nums[0], endExpr, step];
|
|
11728
|
+
}
|
|
11530
11729
|
function serializeList(serializer, expr2) {
|
|
11531
11730
|
if (nops(expr2) > 1 && operands(expr2).every((x) => {
|
|
11532
11731
|
const op = operator(x);
|
|
@@ -11778,6 +11977,35 @@ var ComputeEngine = (() => {
|
|
|
11778
11977
|
["Element", index, ["Range", lower, upper]]
|
|
11779
11978
|
];
|
|
11780
11979
|
}
|
|
11980
|
+
function parseForComprehension(parser, lhs, until) {
|
|
11981
|
+
const bindingTerminator = {
|
|
11982
|
+
minPrec: 21,
|
|
11983
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
11984
|
+
condition: (p) => {
|
|
11985
|
+
if (until?.condition?.(p)) return true;
|
|
11986
|
+
const saved = p.index;
|
|
11987
|
+
p.skipVisualSpace();
|
|
11988
|
+
const isComma = p.peek === ",";
|
|
11989
|
+
p.index = saved;
|
|
11990
|
+
return isComma;
|
|
11991
|
+
}
|
|
11992
|
+
};
|
|
11993
|
+
const elements = [];
|
|
11994
|
+
do {
|
|
11995
|
+
parser.skipVisualSpace();
|
|
11996
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
11997
|
+
if (binding === null) break;
|
|
11998
|
+
const op = operator(binding);
|
|
11999
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
12000
|
+
const name = operand(binding, 1);
|
|
12001
|
+
const list = operand(binding, 2);
|
|
12002
|
+
if (!name || !list) return null;
|
|
12003
|
+
elements.push(["Element", name, list]);
|
|
12004
|
+
parser.skipVisualSpace();
|
|
12005
|
+
} while (parser.match(","));
|
|
12006
|
+
if (elements.length === 0) return null;
|
|
12007
|
+
return ["Loop", lhs, ...elements];
|
|
12008
|
+
}
|
|
11781
12009
|
function parseWhereExpression(parser, lhs, until) {
|
|
11782
12010
|
const bindingTerminator = {
|
|
11783
12011
|
minPrec: 21,
|
|
@@ -13696,6 +13924,8 @@ var ComputeEngine = (() => {
|
|
|
13696
13924
|
precedence: DIVISION_PRECEDENCE,
|
|
13697
13925
|
parse: "Mod"
|
|
13698
13926
|
},
|
|
13927
|
+
// Function-style alias: `\operatorname{mod}(a, b)`
|
|
13928
|
+
{ latexTrigger: "\\operatorname{mod}", parse: "Mod" },
|
|
13699
13929
|
{
|
|
13700
13930
|
latexTrigger: "\\pmod",
|
|
13701
13931
|
kind: "prefix",
|
|
@@ -13936,6 +14166,13 @@ var ComputeEngine = (() => {
|
|
|
13936
14166
|
const rhs = serializer.wrap(operand(expr2, 2), ADDITION_PRECEDENCE + 3);
|
|
13937
14167
|
return joinLatex([lhs, "-", rhs]);
|
|
13938
14168
|
}
|
|
14169
|
+
},
|
|
14170
|
+
// Euclidean distance between two points (tuples of numbers).
|
|
14171
|
+
{
|
|
14172
|
+
name: "Distance",
|
|
14173
|
+
latexTrigger: ["\\operatorname{distance}"],
|
|
14174
|
+
kind: "function",
|
|
14175
|
+
serialize: (serializer, expr2) => "\\operatorname{distance}" + serializer.wrapArguments(expr2)
|
|
13939
14176
|
}
|
|
13940
14177
|
];
|
|
13941
14178
|
function getIndexAssignment(expr2, upper) {
|
|
@@ -15360,7 +15597,9 @@ var ComputeEngine = (() => {
|
|
|
15360
15597
|
if (!expr2 || !symbol(expr2)) return null;
|
|
15361
15598
|
return ["Mean", expr2];
|
|
15362
15599
|
}
|
|
15363
|
-
}
|
|
15600
|
+
},
|
|
15601
|
+
// Function-style alias: `\operatorname{var}(...)`
|
|
15602
|
+
{ latexTrigger: "\\operatorname{var}", parse: "Variance" }
|
|
15364
15603
|
];
|
|
15365
15604
|
|
|
15366
15605
|
// src/compute-engine/numerics/unit-data.ts
|
|
@@ -16461,7 +16700,7 @@ var ComputeEngine = (() => {
|
|
|
16461
16700
|
36: "\\qquad"
|
|
16462
16701
|
}[v] ?? "";
|
|
16463
16702
|
}
|
|
16464
|
-
}
|
|
16703
|
+
},
|
|
16465
16704
|
// if (
|
|
16466
16705
|
// [
|
|
16467
16706
|
// '\\!',
|
|
@@ -16485,6 +16724,121 @@ var ComputeEngine = (() => {
|
|
|
16485
16724
|
// name: '',
|
|
16486
16725
|
// trigger: '\\check',
|
|
16487
16726
|
// },
|
|
16727
|
+
// ---------------------------------------------------------------------------
|
|
16728
|
+
// Function-style aliases for collection / random operators that some
|
|
16729
|
+
// notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
|
|
16730
|
+
// The capitalized library entries already exist; these are pure parse
|
|
16731
|
+
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
16732
|
+
// ---------------------------------------------------------------------------
|
|
16733
|
+
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
16734
|
+
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
16735
|
+
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
16736
|
+
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
16737
|
+
// ---------------------------------------------------------------------------
|
|
16738
|
+
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
16739
|
+
// can branch on the operator name; CE itself doesn't render them. The
|
|
16740
|
+
// library entries (with no evaluator) live in `library/core.ts`.
|
|
16741
|
+
// ---------------------------------------------------------------------------
|
|
16742
|
+
{
|
|
16743
|
+
name: "Triangle",
|
|
16744
|
+
latexTrigger: ["\\operatorname{triangle}"],
|
|
16745
|
+
kind: "function",
|
|
16746
|
+
serialize: (serializer, expr2) => "\\operatorname{triangle}" + serializer.wrapArguments(expr2)
|
|
16747
|
+
},
|
|
16748
|
+
// Desmos's geometric `vector(p1, p2)` — a directed segment between two
|
|
16749
|
+
// points. Routed to a dedicated head (not the existing column-vector
|
|
16750
|
+
// `Vector`, which has a narrower `(number+) -> vector` signature).
|
|
16751
|
+
{
|
|
16752
|
+
name: "GeometricVector",
|
|
16753
|
+
latexTrigger: ["\\operatorname{vector}"],
|
|
16754
|
+
kind: "function",
|
|
16755
|
+
serialize: (serializer, expr2) => "\\operatorname{vector}" + serializer.wrapArguments(expr2)
|
|
16756
|
+
},
|
|
16757
|
+
{
|
|
16758
|
+
name: "Sphere",
|
|
16759
|
+
latexTrigger: ["\\operatorname{sphere}"],
|
|
16760
|
+
kind: "function",
|
|
16761
|
+
serialize: (serializer, expr2) => "\\operatorname{sphere}" + serializer.wrapArguments(expr2)
|
|
16762
|
+
},
|
|
16763
|
+
{
|
|
16764
|
+
name: "Segment",
|
|
16765
|
+
latexTrigger: ["\\operatorname{segment}"],
|
|
16766
|
+
kind: "function",
|
|
16767
|
+
serialize: (serializer, expr2) => "\\operatorname{segment}" + serializer.wrapArguments(expr2)
|
|
16768
|
+
}
|
|
16769
|
+
];
|
|
16770
|
+
|
|
16771
|
+
// src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
|
|
16772
|
+
var DEFINITIONS_COLORS = [
|
|
16773
|
+
// Color constructors (one per colorspace, preserves space on evaluation)
|
|
16774
|
+
{
|
|
16775
|
+
name: "Rgb",
|
|
16776
|
+
latexTrigger: ["\\operatorname{rgb}"],
|
|
16777
|
+
kind: "function",
|
|
16778
|
+
serialize: (serializer, expr2) => "\\operatorname{rgb}" + serializer.wrapArguments(expr2)
|
|
16779
|
+
},
|
|
16780
|
+
{
|
|
16781
|
+
name: "Hsv",
|
|
16782
|
+
latexTrigger: ["\\operatorname{hsv}"],
|
|
16783
|
+
kind: "function",
|
|
16784
|
+
serialize: (serializer, expr2) => "\\operatorname{hsv}" + serializer.wrapArguments(expr2)
|
|
16785
|
+
},
|
|
16786
|
+
{
|
|
16787
|
+
name: "Hsl",
|
|
16788
|
+
latexTrigger: ["\\operatorname{hsl}"],
|
|
16789
|
+
kind: "function",
|
|
16790
|
+
serialize: (serializer, expr2) => "\\operatorname{hsl}" + serializer.wrapArguments(expr2)
|
|
16791
|
+
},
|
|
16792
|
+
{
|
|
16793
|
+
name: "Oklab",
|
|
16794
|
+
latexTrigger: ["\\operatorname{oklab}"],
|
|
16795
|
+
kind: "function",
|
|
16796
|
+
serialize: (serializer, expr2) => "\\operatorname{oklab}" + serializer.wrapArguments(expr2)
|
|
16797
|
+
},
|
|
16798
|
+
{
|
|
16799
|
+
name: "Oklch",
|
|
16800
|
+
latexTrigger: ["\\operatorname{oklch}"],
|
|
16801
|
+
kind: "function",
|
|
16802
|
+
serialize: (serializer, expr2) => "\\operatorname{oklch}" + serializer.wrapArguments(expr2)
|
|
16803
|
+
},
|
|
16804
|
+
// Conversion functions (color → color in the named space)
|
|
16805
|
+
{
|
|
16806
|
+
name: "AsRgb",
|
|
16807
|
+
latexTrigger: ["\\operatorname{asRgb}"],
|
|
16808
|
+
kind: "function",
|
|
16809
|
+
serialize: (serializer, expr2) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr2)
|
|
16810
|
+
},
|
|
16811
|
+
{
|
|
16812
|
+
name: "AsHsv",
|
|
16813
|
+
latexTrigger: ["\\operatorname{asHsv}"],
|
|
16814
|
+
kind: "function",
|
|
16815
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr2)
|
|
16816
|
+
},
|
|
16817
|
+
{
|
|
16818
|
+
name: "AsHsl",
|
|
16819
|
+
latexTrigger: ["\\operatorname{asHsl}"],
|
|
16820
|
+
kind: "function",
|
|
16821
|
+
serialize: (serializer, expr2) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr2)
|
|
16822
|
+
},
|
|
16823
|
+
{
|
|
16824
|
+
name: "AsOklab",
|
|
16825
|
+
latexTrigger: ["\\operatorname{asOklab}"],
|
|
16826
|
+
kind: "function",
|
|
16827
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr2)
|
|
16828
|
+
},
|
|
16829
|
+
{
|
|
16830
|
+
name: "AsOklch",
|
|
16831
|
+
latexTrigger: ["\\operatorname{asOklch}"],
|
|
16832
|
+
kind: "function",
|
|
16833
|
+
serialize: (serializer, expr2) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr2)
|
|
16834
|
+
},
|
|
16835
|
+
// Perceptual difference (returns a scalar in [0, ~1])
|
|
16836
|
+
{
|
|
16837
|
+
name: "ColorDelta",
|
|
16838
|
+
latexTrigger: ["\\operatorname{colorDelta}"],
|
|
16839
|
+
kind: "function",
|
|
16840
|
+
serialize: (serializer, expr2) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr2)
|
|
16841
|
+
}
|
|
16488
16842
|
];
|
|
16489
16843
|
|
|
16490
16844
|
// src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
|
|
@@ -16515,7 +16869,8 @@ var ComputeEngine = (() => {
|
|
|
16515
16869
|
...DEFINITIONS_STATISTICS,
|
|
16516
16870
|
...DEFINITIONS_UNITS,
|
|
16517
16871
|
...DEFINITIONS_OTHERS,
|
|
16518
|
-
...DEFINITIONS_PHYSICS
|
|
16872
|
+
...DEFINITIONS_PHYSICS,
|
|
16873
|
+
...DEFINITIONS_COLORS
|
|
16519
16874
|
];
|
|
16520
16875
|
|
|
16521
16876
|
// src/math-json/symbols.ts
|
|
@@ -16680,6 +17035,17 @@ var ComputeEngine = (() => {
|
|
|
16680
17035
|
} else if (Array.isArray(openTrigger) && openTrigger.length > 0) {
|
|
16681
17036
|
openTokens.push(openTrigger[0]);
|
|
16682
17037
|
}
|
|
17038
|
+
const closeTrigger = indexedEntry.closeTrigger;
|
|
17039
|
+
const closeTokens = /* @__PURE__ */ new Set();
|
|
17040
|
+
if (typeof closeTrigger === "string") {
|
|
17041
|
+
const variants = DELIMITER_SHORTHAND[closeTrigger];
|
|
17042
|
+
if (variants) for (const v of variants) closeTokens.add(v);
|
|
17043
|
+
else closeTokens.add(closeTrigger);
|
|
17044
|
+
if (closeTrigger === "||") closeTokens.add("|");
|
|
17045
|
+
} else if (Array.isArray(closeTrigger) && closeTrigger.length > 0) {
|
|
17046
|
+
closeTokens.add(closeTrigger[0]);
|
|
17047
|
+
}
|
|
17048
|
+
indexedEntry.closeTokens = closeTokens;
|
|
16683
17049
|
for (const token of openTokens) {
|
|
16684
17050
|
const existing = result.matchfixByOpen.get(token);
|
|
16685
17051
|
if (existing) {
|
|
@@ -16871,11 +17237,7 @@ var ComputeEngine = (() => {
|
|
|
16871
17237
|
if (style === "scaled")
|
|
16872
17238
|
return joinLatex([`\\left${openDelim}`, inner, `\\right${closeDelim}`]);
|
|
16873
17239
|
if (style === "big")
|
|
16874
|
-
return joinLatex([
|
|
16875
|
-
`\\Bigl${openDelim}`,
|
|
16876
|
-
inner,
|
|
16877
|
-
`\\Bigr${closeDelim}`
|
|
16878
|
-
]);
|
|
17240
|
+
return joinLatex([`\\Bigl${openDelim}`, inner, `\\Bigr${closeDelim}`]);
|
|
16879
17241
|
return joinLatex([openDelim, inner, closeDelim]);
|
|
16880
17242
|
};
|
|
16881
17243
|
}
|
|
@@ -18226,7 +18588,7 @@ var ComputeEngine = (() => {
|
|
|
18226
18588
|
}
|
|
18227
18589
|
if (this.match("\\hskip") || this.match("\\kern")) {
|
|
18228
18590
|
this.skipSpace();
|
|
18229
|
-
this.match("-")
|
|
18591
|
+
if (!this.match("-")) this.match("+");
|
|
18230
18592
|
while (/^[\d.]$/.test(this.peek)) this.nextToken();
|
|
18231
18593
|
for (const unit of [
|
|
18232
18594
|
"pt",
|
|
@@ -18740,6 +19102,19 @@ var ComputeEngine = (() => {
|
|
|
18740
19102
|
}
|
|
18741
19103
|
for (const def of defs) {
|
|
18742
19104
|
this.index = start;
|
|
19105
|
+
if (def.closeTokens.size > 0) {
|
|
19106
|
+
let found = false;
|
|
19107
|
+
const tokens = this._tokens;
|
|
19108
|
+
for (let i = start; i < tokens.length; i++) {
|
|
19109
|
+
if (def.closeTokens.has(tokens[i])) {
|
|
19110
|
+
found = true;
|
|
19111
|
+
break;
|
|
19112
|
+
}
|
|
19113
|
+
}
|
|
19114
|
+
if (!found) continue;
|
|
19115
|
+
}
|
|
19116
|
+
if (typeof def.openTrigger === "string" && def.openTrigger === "." && !OPEN_DELIMITER_PREFIX[currentToken])
|
|
19117
|
+
continue;
|
|
18743
19118
|
const matched = this.matchDelimiter(def.openTrigger, def.closeTrigger);
|
|
18744
19119
|
if (!matched) continue;
|
|
18745
19120
|
const bodyStart = this.index;
|
|
@@ -19402,6 +19777,19 @@ var ComputeEngine = (() => {
|
|
|
19402
19777
|
} while (postfix !== null);
|
|
19403
19778
|
}
|
|
19404
19779
|
if (result !== null) result = this.parseSupsub(result);
|
|
19780
|
+
if (result !== null) {
|
|
19781
|
+
let postfix = null;
|
|
19782
|
+
let index = this.index;
|
|
19783
|
+
do {
|
|
19784
|
+
postfix = this.parsePostfixOperator(result, until);
|
|
19785
|
+
result = postfix ?? result;
|
|
19786
|
+
if (this.index === index && postfix !== null) {
|
|
19787
|
+
console.assert(this.index !== index, "No token consumed");
|
|
19788
|
+
break;
|
|
19789
|
+
}
|
|
19790
|
+
index = this.index;
|
|
19791
|
+
} while (postfix !== null);
|
|
19792
|
+
}
|
|
19405
19793
|
if (result === null) {
|
|
19406
19794
|
result = this.options.parseUnexpectedToken?.(null, this) ?? null;
|
|
19407
19795
|
if (result === null && this.peek.startsWith("\\")) {
|
|
@@ -19910,6 +20298,28 @@ var ComputeEngine = (() => {
|
|
|
19910
20298
|
}
|
|
19911
20299
|
|
|
19912
20300
|
// src/compute-engine/latex-syntax/serializer.ts
|
|
20301
|
+
var DOT_NOTATION_MAP = {
|
|
20302
|
+
First: ".x",
|
|
20303
|
+
Second: ".y",
|
|
20304
|
+
Third: ".z",
|
|
20305
|
+
Real: ".\\operatorname{real}",
|
|
20306
|
+
Imaginary: ".\\operatorname{imag}",
|
|
20307
|
+
Length: ".\\operatorname{count}",
|
|
20308
|
+
Sum: ".\\operatorname{total}",
|
|
20309
|
+
Max: ".\\max",
|
|
20310
|
+
Min: ".\\min"
|
|
20311
|
+
};
|
|
20312
|
+
function trySerializeDotNotation(serializer, expr2) {
|
|
20313
|
+
if (!serializer.options.dotNotation) return null;
|
|
20314
|
+
const ops = operands(expr2);
|
|
20315
|
+
if (!ops || ops.length !== 1) return null;
|
|
20316
|
+
const head = operator(expr2);
|
|
20317
|
+
if (!head) return null;
|
|
20318
|
+
const suffix = DOT_NOTATION_MAP[head];
|
|
20319
|
+
if (suffix === void 0) return null;
|
|
20320
|
+
const lhs = serializer.wrap(ops[0], 810);
|
|
20321
|
+
return `${lhs}${suffix}`;
|
|
20322
|
+
}
|
|
19913
20323
|
var ACCENT_MODIFIERS = {
|
|
19914
20324
|
deg: (s) => `${s}\\degree`,
|
|
19915
20325
|
prime: (s) => `${s}^{\\prime}`,
|
|
@@ -19953,6 +20363,7 @@ var ComputeEngine = (() => {
|
|
|
19953
20363
|
constructor(dictionary, options) {
|
|
19954
20364
|
this.dictionary = dictionary;
|
|
19955
20365
|
this.options = {
|
|
20366
|
+
dotNotation: false,
|
|
19956
20367
|
dmsFormat: false,
|
|
19957
20368
|
angleNormalization: "none",
|
|
19958
20369
|
...options
|
|
@@ -20051,6 +20462,8 @@ var ComputeEngine = (() => {
|
|
|
20051
20462
|
return def?.serialize?.(this, expr2) ?? serializeSymbol2(symbol(expr2)) ?? "";
|
|
20052
20463
|
}
|
|
20053
20464
|
serializeFunction(expr2, def) {
|
|
20465
|
+
const dotResult = trySerializeDotNotation(this, expr2);
|
|
20466
|
+
if (dotResult !== null) return dotResult;
|
|
20054
20467
|
if (def?.serialize) return def.serialize(this, expr2);
|
|
20055
20468
|
const h = operator(expr2);
|
|
20056
20469
|
return serializeSymbol2(h, "auto") + this.wrapArguments(expr2);
|
|
@@ -20293,6 +20706,8 @@ var ComputeEngine = (() => {
|
|
|
20293
20706
|
preserveLatex: opts.preserveLatex ?? false,
|
|
20294
20707
|
quantifierScope: opts.quantifierScope ?? "tight",
|
|
20295
20708
|
timeDerivativeVariable: opts.timeDerivativeVariable ?? "t",
|
|
20709
|
+
// Standalone mode has no engine; use the same default as ComputeEngine
|
|
20710
|
+
tolerance: 1e-7,
|
|
20296
20711
|
// Callbacks -- standalone mode has no engine, so these are stubs
|
|
20297
20712
|
getSymbolType: (_id) => BoxedType.unknown,
|
|
20298
20713
|
hasSubscriptEvaluate: (_id) => false,
|
|
@@ -20325,6 +20740,7 @@ var ComputeEngine = (() => {
|
|
|
20325
20740
|
invisiblePlus: "",
|
|
20326
20741
|
multiply: "\\times",
|
|
20327
20742
|
missingSymbol: "\\blacksquare",
|
|
20743
|
+
dotNotation: false,
|
|
20328
20744
|
dmsFormat: false,
|
|
20329
20745
|
angleNormalization: "none",
|
|
20330
20746
|
// Style callbacks -- use same defaults as the engine
|
|
@@ -27295,7 +27711,11 @@ ${lines.join("\n")}`;
|
|
|
27295
27711
|
//
|
|
27296
27712
|
Range: {
|
|
27297
27713
|
complexity: 8200,
|
|
27298
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
27714
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
27715
|
+
type: (ops) => {
|
|
27716
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
27717
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
27718
|
+
},
|
|
27299
27719
|
canonical: (ops, { engine: ce }) => {
|
|
27300
27720
|
if (ops.length === 0) return null;
|
|
27301
27721
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -27319,19 +27739,26 @@ ${lines.join("\n")}`;
|
|
|
27319
27739
|
const [lower, upper, step] = range(expr2);
|
|
27320
27740
|
if (step === 0) return 0;
|
|
27321
27741
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
27322
|
-
return
|
|
27742
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27323
27743
|
},
|
|
27324
27744
|
contains: (expr2, target) => {
|
|
27325
|
-
if (!target.type.matches("integer")) return false;
|
|
27326
27745
|
const t = target.re;
|
|
27746
|
+
if (!isFinite(t)) return false;
|
|
27327
27747
|
const [lower, upper, step] = range(expr2);
|
|
27328
27748
|
if (step === 0) return false;
|
|
27329
|
-
if (step > 0)
|
|
27330
|
-
|
|
27749
|
+
if (step > 0) {
|
|
27750
|
+
if (t < lower || t > upper) return false;
|
|
27751
|
+
} else {
|
|
27752
|
+
if (t > lower || t < upper) return false;
|
|
27753
|
+
}
|
|
27754
|
+
const k = (t - lower) / step;
|
|
27755
|
+
const tol = expr2.engine.tolerance;
|
|
27756
|
+
const kRounded = Math.round(k);
|
|
27757
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
27331
27758
|
},
|
|
27332
27759
|
iterator: (expr2) => {
|
|
27333
27760
|
const [lower, upper, step] = range(expr2);
|
|
27334
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
27761
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27335
27762
|
let index = 1;
|
|
27336
27763
|
return {
|
|
27337
27764
|
next: () => {
|
|
@@ -27349,7 +27776,9 @@ ${lines.join("\n")}`;
|
|
|
27349
27776
|
at: (expr2, index) => {
|
|
27350
27777
|
if (typeof index !== "number") return void 0;
|
|
27351
27778
|
const [lower, upper, step] = range(expr2);
|
|
27352
|
-
if (
|
|
27779
|
+
if (step === 0) return void 0;
|
|
27780
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
27781
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
27353
27782
|
return expr2.engine.number(lower + step * (index - 1));
|
|
27354
27783
|
},
|
|
27355
27784
|
indexWhere: void 0,
|
|
@@ -27374,7 +27803,13 @@ ${lines.join("\n")}`;
|
|
|
27374
27803
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
27375
27804
|
return lower >= upper ? "positive" : "negative";
|
|
27376
27805
|
},
|
|
27377
|
-
elttype: (
|
|
27806
|
+
elttype: (expr2) => {
|
|
27807
|
+
if (!isFunction2(expr2)) return "finite_integer";
|
|
27808
|
+
for (let i = 1; i <= expr2.nops; i++) {
|
|
27809
|
+
if (!expr2[`op${i}`].isInteger) return "finite_real";
|
|
27810
|
+
}
|
|
27811
|
+
return "finite_integer";
|
|
27812
|
+
}
|
|
27378
27813
|
}
|
|
27379
27814
|
},
|
|
27380
27815
|
Interval: {
|
|
@@ -27972,15 +28407,45 @@ ${lines.join("\n")}`;
|
|
|
27972
28407
|
},
|
|
27973
28408
|
First: {
|
|
27974
28409
|
complexity: 8200,
|
|
27975
|
-
signature: "(
|
|
28410
|
+
signature: "(any) -> any",
|
|
27976
28411
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27977
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28412
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28413
|
+
if (!xs.isCollection)
|
|
28414
|
+
return ce.error([
|
|
28415
|
+
"incompatible-type",
|
|
28416
|
+
`'collection'`,
|
|
28417
|
+
xs.type.toString()
|
|
28418
|
+
]);
|
|
28419
|
+
return xs.at(1) ?? ce.Nothing;
|
|
28420
|
+
}
|
|
27978
28421
|
},
|
|
27979
28422
|
Second: {
|
|
27980
28423
|
complexity: 8200,
|
|
27981
|
-
signature: "(
|
|
28424
|
+
signature: "(any) -> any",
|
|
27982
28425
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
27983
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
28426
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28427
|
+
if (!xs.isCollection)
|
|
28428
|
+
return ce.error([
|
|
28429
|
+
"incompatible-type",
|
|
28430
|
+
`'collection'`,
|
|
28431
|
+
xs.type.toString()
|
|
28432
|
+
]);
|
|
28433
|
+
return xs.at(2) ?? ce.Nothing;
|
|
28434
|
+
}
|
|
28435
|
+
},
|
|
28436
|
+
Third: {
|
|
28437
|
+
complexity: 8200,
|
|
28438
|
+
signature: "(any) -> any",
|
|
28439
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
28440
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
28441
|
+
if (!xs.isCollection)
|
|
28442
|
+
return ce.error([
|
|
28443
|
+
"incompatible-type",
|
|
28444
|
+
`'collection'`,
|
|
28445
|
+
xs.type.toString()
|
|
28446
|
+
]);
|
|
28447
|
+
return xs.at(3) ?? ce.Nothing;
|
|
28448
|
+
}
|
|
27984
28449
|
},
|
|
27985
28450
|
Last: {
|
|
27986
28451
|
complexity: 8200,
|
|
@@ -28959,17 +29424,14 @@ ${lines.join("\n")}`;
|
|
|
28959
29424
|
if (!isFunction2(expr2)) return [1, 0, 0];
|
|
28960
29425
|
if (expr2.nops === 0) return [1, 0, 0];
|
|
28961
29426
|
let op1 = expr2.op1.re;
|
|
28962
|
-
if (!isFinite(op1)) op1 = 1;
|
|
28963
|
-
else op1 = Math.round(op1);
|
|
29427
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
28964
29428
|
if (expr2.nops === 1) return [1, op1, 1];
|
|
28965
29429
|
let op2 = expr2.op2.re;
|
|
28966
29430
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
28967
|
-
|
|
28968
|
-
if (expr2.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
29431
|
+
if (expr2.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
28969
29432
|
let op3 = expr2.op3.re;
|
|
28970
|
-
if (!isFinite(op3)) op3 = 1;
|
|
28971
|
-
|
|
28972
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
29433
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
29434
|
+
return [op1, op2, op3];
|
|
28973
29435
|
}
|
|
28974
29436
|
function rangeLast(r) {
|
|
28975
29437
|
const [lower, upper, step] = r;
|
|
@@ -32302,6 +32764,29 @@ ${lines.join("\n")}`;
|
|
|
32302
32764
|
signature: "(value*) -> number | list",
|
|
32303
32765
|
evaluate: (xs, { engine }) => evaluateMinMax(engine, xs, "Infimum")
|
|
32304
32766
|
},
|
|
32767
|
+
Distance: {
|
|
32768
|
+
description: "Euclidean distance between two points (tuples of numbers).",
|
|
32769
|
+
complexity: 6e3,
|
|
32770
|
+
signature: "(tuple, tuple) -> number",
|
|
32771
|
+
evaluate: ([a, b], { engine: ce }) => {
|
|
32772
|
+
if (!isFunction2(a) || !isFunction2(b))
|
|
32773
|
+
return ce.error("incompatible-type");
|
|
32774
|
+
if (a.operator !== "Tuple" || b.operator !== "Tuple")
|
|
32775
|
+
return ce.error("incompatible-type");
|
|
32776
|
+
if (a.ops.length !== b.ops.length || a.ops.length === 0)
|
|
32777
|
+
return ce.error("incompatible-type");
|
|
32778
|
+
let sumSq = 0;
|
|
32779
|
+
for (let i = 0; i < a.ops.length; i++) {
|
|
32780
|
+
const ai = a.ops[i].re;
|
|
32781
|
+
const bi = b.ops[i].re;
|
|
32782
|
+
if (!Number.isFinite(ai) || !Number.isFinite(bi))
|
|
32783
|
+
return ce.error("expected-value");
|
|
32784
|
+
const d = ai - bi;
|
|
32785
|
+
sumSq += d * d;
|
|
32786
|
+
}
|
|
32787
|
+
return ce.number(Math.sqrt(sumSq));
|
|
32788
|
+
}
|
|
32789
|
+
},
|
|
32305
32790
|
Product: {
|
|
32306
32791
|
description: "`Product(f, a, b)` computes the product of `f` from `a` to `b`",
|
|
32307
32792
|
wikidata: "Q901718",
|
|
@@ -32834,16 +33319,11 @@ ${lines.join("\n")}`;
|
|
|
32834
33319
|
);
|
|
32835
33320
|
let condFn;
|
|
32836
33321
|
if (typeof condition === "string") {
|
|
32837
|
-
const
|
|
32838
|
-
|
|
32839
|
-
const
|
|
32840
|
-
|
|
32841
|
-
|
|
32842
|
-
condFn = (x, _ce) => {
|
|
32843
|
-
const evaluated = condPattern.subs(x).evaluate();
|
|
32844
|
-
return isSymbol2(evaluated, "True");
|
|
32845
|
-
};
|
|
32846
|
-
}
|
|
33322
|
+
const condPattern = ce.parse(condition) ?? ce.expr("Nothing");
|
|
33323
|
+
condFn = (x, _ce) => {
|
|
33324
|
+
const evaluated = condPattern.subs(x).evaluate();
|
|
33325
|
+
return isSymbol2(evaluated, "True");
|
|
33326
|
+
};
|
|
32847
33327
|
} else {
|
|
32848
33328
|
if (condition !== void 0 && typeof condition !== "function")
|
|
32849
33329
|
throw new Error(
|
|
@@ -32945,6 +33425,15 @@ ${e.message}
|
|
|
32945
33425
|
function applyRule(rule, expr2, substitution, options) {
|
|
32946
33426
|
if (!rule) return null;
|
|
32947
33427
|
let canonical2 = options?.canonical ?? (expr2.isCanonical || expr2.isStructural);
|
|
33428
|
+
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
33429
|
+
const because = id ?? "";
|
|
33430
|
+
const ce = expr2.engine;
|
|
33431
|
+
if (canonical2 && match2) {
|
|
33432
|
+
const awc = getWildcards(match2);
|
|
33433
|
+
const canonicalMatch = match2.canonical;
|
|
33434
|
+
const bwc = getWildcards(canonicalMatch);
|
|
33435
|
+
if (!awc.every((x) => bwc.includes(x))) return null;
|
|
33436
|
+
}
|
|
32948
33437
|
let operandsMatched = false;
|
|
32949
33438
|
if (isFunction2(expr2) && options?.recursive) {
|
|
32950
33439
|
const newOps = expr2.ops.map((op) => {
|
|
@@ -32956,20 +33445,11 @@ ${e.message}
|
|
|
32956
33445
|
if (operandsMatched) {
|
|
32957
33446
|
if (!canonical2 && options?.canonical === void 0 && newOps.every((x) => x.isCanonical))
|
|
32958
33447
|
canonical2 = true;
|
|
32959
|
-
expr2 =
|
|
33448
|
+
expr2 = ce.function(expr2.operator, newOps, {
|
|
32960
33449
|
form: canonical2 ? "canonical" : "raw"
|
|
32961
33450
|
});
|
|
32962
33451
|
}
|
|
32963
33452
|
}
|
|
32964
|
-
let { match: match2, replace: replace2, condition, id, onMatch, onBeforeMatch } = rule;
|
|
32965
|
-
const because = id ?? "";
|
|
32966
|
-
if (canonical2 && match2) {
|
|
32967
|
-
const awc = getWildcards(match2);
|
|
32968
|
-
const canonicalMatch = match2.canonical;
|
|
32969
|
-
const bwc = getWildcards(canonicalMatch);
|
|
32970
|
-
if (!awc.every((x) => bwc.includes(x)))
|
|
32971
|
-
return operandsMatched ? { value: expr2, because } : null;
|
|
32972
|
-
}
|
|
32973
33453
|
const useVariations = rule.useVariations ?? options?.useVariations ?? false;
|
|
32974
33454
|
const matchPermutations = options?.matchPermutations ?? true;
|
|
32975
33455
|
onBeforeMatch?.(rule, expr2);
|
|
@@ -32988,7 +33468,7 @@ ${e.message}
|
|
|
32988
33468
|
...sub2
|
|
32989
33469
|
};
|
|
32990
33470
|
try {
|
|
32991
|
-
if (!condition(conditionSub,
|
|
33471
|
+
if (!condition(conditionSub, ce))
|
|
32992
33472
|
return operandsMatched ? { value: expr2, because } : null;
|
|
32993
33473
|
} catch (e) {
|
|
32994
33474
|
console.error(
|
|
@@ -33003,7 +33483,8 @@ ${e.message}
|
|
|
33003
33483
|
if (!canonical2 && options?.canonical === void 0 && replace2 instanceof _BoxedExpression && replace2.isCanonical)
|
|
33004
33484
|
canonical2 = true;
|
|
33005
33485
|
const result = typeof replace2 === "function" ? replace2(expr2, sub2) : replace2.subs(sub2, { canonical: canonical2 });
|
|
33006
|
-
if (!result)
|
|
33486
|
+
if (!result)
|
|
33487
|
+
return operandsMatched ? { value: canonical2 ? expr2.canonical : expr2, because } : null;
|
|
33007
33488
|
onMatch?.(rule, expr2, result);
|
|
33008
33489
|
if (isRuleStep(result))
|
|
33009
33490
|
return canonical2 ? { ...result, value: result.value.canonical } : result;
|
|
@@ -38577,6 +39058,40 @@ ${e.message}
|
|
|
38577
39058
|
else h = ((r - g) / d + 4) / 6;
|
|
38578
39059
|
return { h: h * 360, s, l };
|
|
38579
39060
|
}
|
|
39061
|
+
function hsvToRgb(h, s, v) {
|
|
39062
|
+
h = (h % 360 + 360) % 360;
|
|
39063
|
+
s = Math.max(0, Math.min(1, s));
|
|
39064
|
+
v = Math.max(0, Math.min(1, v));
|
|
39065
|
+
const c = v * s;
|
|
39066
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
39067
|
+
const m = v - c;
|
|
39068
|
+
let r = 0, g = 0, b = 0;
|
|
39069
|
+
if (h < 60) [r, g, b] = [c, x, 0];
|
|
39070
|
+
else if (h < 120) [r, g, b] = [x, c, 0];
|
|
39071
|
+
else if (h < 180) [r, g, b] = [0, c, x];
|
|
39072
|
+
else if (h < 240) [r, g, b] = [0, x, c];
|
|
39073
|
+
else if (h < 300) [r, g, b] = [x, 0, c];
|
|
39074
|
+
else [r, g, b] = [c, 0, x];
|
|
39075
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
39076
|
+
}
|
|
39077
|
+
function rgbToHsv(r, g, b) {
|
|
39078
|
+
r /= 255;
|
|
39079
|
+
g /= 255;
|
|
39080
|
+
b /= 255;
|
|
39081
|
+
const max2 = Math.max(r, g, b);
|
|
39082
|
+
const min2 = Math.min(r, g, b);
|
|
39083
|
+
const d = max2 - min2;
|
|
39084
|
+
let h = 0;
|
|
39085
|
+
if (d > 0) {
|
|
39086
|
+
if (max2 === r) h = (g - b) / d % 6;
|
|
39087
|
+
else if (max2 === g) h = (b - r) / d + 2;
|
|
39088
|
+
else h = (r - g) / d + 4;
|
|
39089
|
+
h *= 60;
|
|
39090
|
+
if (h < 0) h += 360;
|
|
39091
|
+
}
|
|
39092
|
+
const s = max2 === 0 ? 0 : d / max2;
|
|
39093
|
+
return { h, s, v: max2 };
|
|
39094
|
+
}
|
|
38580
39095
|
function parseHexColor(s) {
|
|
38581
39096
|
const hex = s.startsWith("#") ? s.substring(1) : s;
|
|
38582
39097
|
let r, g, b;
|
|
@@ -38601,6 +39116,12 @@ ${e.message}
|
|
|
38601
39116
|
if (alpha !== void 0) result.alpha = alpha;
|
|
38602
39117
|
return result;
|
|
38603
39118
|
}
|
|
39119
|
+
function asOklch(color) {
|
|
39120
|
+
if (typeof color === "string") return rgbToOklch(parseHexColor(color));
|
|
39121
|
+
if ("C" in color) return color;
|
|
39122
|
+
if ("a" in color && "b" in color) return oklabToOklch(color);
|
|
39123
|
+
return rgbToOklch(color);
|
|
39124
|
+
}
|
|
38604
39125
|
function asRgb(color) {
|
|
38605
39126
|
if (typeof color === "number") {
|
|
38606
39127
|
return {
|
|
@@ -39032,6 +39553,13 @@ ${e.message}
|
|
|
39032
39553
|
};
|
|
39033
39554
|
function parseColor(s, darkMode) {
|
|
39034
39555
|
const str = s.trim().toLowerCase();
|
|
39556
|
+
const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
|
|
39557
|
+
if (opacityMatch) {
|
|
39558
|
+
const base = parseColor(opacityMatch[1].trim(), darkMode);
|
|
39559
|
+
const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
|
|
39560
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
39561
|
+
return base & 4294967040 | alpha;
|
|
39562
|
+
}
|
|
39035
39563
|
if (str.startsWith("#")) {
|
|
39036
39564
|
const hex = str.substring(1);
|
|
39037
39565
|
let r, g, b, a = 255;
|
|
@@ -39164,14 +39692,6 @@ ${e.message}
|
|
|
39164
39692
|
console.warn(`parseColor: unrecognized color "${s}"`);
|
|
39165
39693
|
return 0;
|
|
39166
39694
|
}
|
|
39167
|
-
function parseColorToRgb01(s, darkMode) {
|
|
39168
|
-
const color = parseColor(s, darkMode);
|
|
39169
|
-
return [
|
|
39170
|
-
(color >>> 24 & 255) / 255,
|
|
39171
|
-
(color >>> 16 & 255) / 255,
|
|
39172
|
-
(color >>> 8 & 255) / 255
|
|
39173
|
-
];
|
|
39174
|
-
}
|
|
39175
39695
|
function apca(bgColor, fgColor) {
|
|
39176
39696
|
const bgRgb = asRgb(bgColor);
|
|
39177
39697
|
const fgRgb = asRgb(fgColor);
|
|
@@ -39230,6 +39750,12 @@ ${e.message}
|
|
|
39230
39750
|
const contrast2 = Math.abs(apca(fg2, bg));
|
|
39231
39751
|
return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
|
|
39232
39752
|
}
|
|
39753
|
+
function oklabDeltaE(a, b) {
|
|
39754
|
+
const dL = a.L - b.L;
|
|
39755
|
+
const da = a.a - b.a;
|
|
39756
|
+
const db = a.b - b.b;
|
|
39757
|
+
return Math.sqrt(dL * dL + da * da + db * db);
|
|
39758
|
+
}
|
|
39233
39759
|
function lerpOklch(c1, c2, f) {
|
|
39234
39760
|
const L = c1.L + (c2.L - c1.L) * f;
|
|
39235
39761
|
const C = c1.C + (c2.C - c1.C) * f;
|
|
@@ -41991,14 +42517,30 @@ ${e.message}
|
|
|
41991
42517
|
};
|
|
41992
42518
|
|
|
41993
42519
|
// src/compute-engine/library/colors.ts
|
|
41994
|
-
function
|
|
41995
|
-
|
|
41996
|
-
|
|
41997
|
-
|
|
41998
|
-
|
|
41999
|
-
|
|
42000
|
-
|
|
42001
|
-
|
|
42520
|
+
function normalizeAlpha(a) {
|
|
42521
|
+
if (a === void 0) return void 0;
|
|
42522
|
+
if (!Number.isFinite(a)) return void 0;
|
|
42523
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
42524
|
+
return a;
|
|
42525
|
+
}
|
|
42526
|
+
function normalizeColorHead(ce, expr2) {
|
|
42527
|
+
if (!isFunction2(expr2) || !expr2.ops || expr2.ops.length < 4) return expr2;
|
|
42528
|
+
const alphaExpr = expr2.ops[3];
|
|
42529
|
+
if (!isNumber(alphaExpr)) return expr2;
|
|
42530
|
+
if (normalizeAlpha(alphaExpr.re) === void 0) {
|
|
42531
|
+
return ce.function(expr2.operator, [expr2.ops[0], expr2.ops[1], expr2.ops[2]]);
|
|
42532
|
+
}
|
|
42533
|
+
return expr2;
|
|
42534
|
+
}
|
|
42535
|
+
function colorNumberToOklch(ce, color) {
|
|
42536
|
+
const r = color >>> 24 & 255;
|
|
42537
|
+
const g = color >>> 16 & 255;
|
|
42538
|
+
const b = color >>> 8 & 255;
|
|
42539
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42540
|
+
const c = rgbToOklch({ r, g, b });
|
|
42541
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42542
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42543
|
+
return ce.function("Oklch", args);
|
|
42002
42544
|
}
|
|
42003
42545
|
var ALL_PALETTES = {
|
|
42004
42546
|
...SEQUENTIAL_PALETTES,
|
|
@@ -42009,45 +42551,139 @@ ${e.message}
|
|
|
42009
42551
|
t = Math.max(0, Math.min(1, t));
|
|
42010
42552
|
const n = palette.length;
|
|
42011
42553
|
if (n === 0) return ce.error("expected-value");
|
|
42012
|
-
if (n === 1) return
|
|
42554
|
+
if (n === 1) return colorNumberToOklch(ce, parseColor(palette[0]));
|
|
42013
42555
|
const pos = t * (n - 1);
|
|
42014
42556
|
const i = Math.floor(pos);
|
|
42015
42557
|
const frac = pos - i;
|
|
42016
|
-
if (i >= n - 1) return
|
|
42017
|
-
if (frac < 1e-9) return
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42558
|
+
if (i >= n - 1) return colorNumberToOklch(ce, parseColor(palette[n - 1]));
|
|
42559
|
+
if (frac < 1e-9) return colorNumberToOklch(ce, parseColor(palette[i]));
|
|
42560
|
+
return oklchToExpr(
|
|
42561
|
+
ce,
|
|
42562
|
+
asOklch(interpolateOklch(palette[i], palette[i + 1], frac))
|
|
42563
|
+
);
|
|
42564
|
+
}
|
|
42565
|
+
var COLOR_OPERATORS = /* @__PURE__ */ new Set(["Rgb", "Hsv", "Hsl", "Oklab", "Oklch"]);
|
|
42566
|
+
function readColorExpr(arg) {
|
|
42567
|
+
if (!isFunction2(arg)) return null;
|
|
42568
|
+
if (!COLOR_OPERATORS.has(arg.operator)) return null;
|
|
42569
|
+
if (!arg.ops || arg.ops.length < 3) return null;
|
|
42570
|
+
const c0 = arg.ops[0].re;
|
|
42571
|
+
const c1 = arg.ops[1].re;
|
|
42572
|
+
const c2 = arg.ops[2].re;
|
|
42573
|
+
if (!Number.isFinite(c0) || !Number.isFinite(c1) || !Number.isFinite(c2))
|
|
42574
|
+
return null;
|
|
42575
|
+
const alpha = arg.ops.length >= 4 ? normalizeAlpha(arg.ops[3].re) : void 0;
|
|
42576
|
+
return { space: arg.operator, c0, c1, c2, alpha };
|
|
42577
|
+
}
|
|
42578
|
+
function colorExprToRgb(arg) {
|
|
42579
|
+
const c = readColorExpr(arg);
|
|
42580
|
+
if (!c) return null;
|
|
42581
|
+
const withAlpha = (rgb) => c.alpha !== void 0 ? { ...rgb, alpha: c.alpha } : rgb;
|
|
42582
|
+
switch (c.space) {
|
|
42583
|
+
case "Rgb":
|
|
42584
|
+
return withAlpha({ r: c.c0 * 255, g: c.c1 * 255, b: c.c2 * 255 });
|
|
42585
|
+
case "Hsv":
|
|
42586
|
+
return withAlpha(hsvToRgb(c.c0, c.c1, c.c2));
|
|
42587
|
+
case "Hsl":
|
|
42588
|
+
return withAlpha(hslToRgb(c.c0, c.c1, c.c2));
|
|
42589
|
+
case "Oklab":
|
|
42590
|
+
return withAlpha(oklabToRgb({ L: c.c0, a: c.c1, b: c.c2 }));
|
|
42591
|
+
case "Oklch":
|
|
42592
|
+
return withAlpha(oklchToRgb({ L: c.c0, C: c.c1, H: c.c2 }));
|
|
42593
|
+
}
|
|
42594
|
+
return null;
|
|
42595
|
+
}
|
|
42596
|
+
function colorExprToOklch(arg) {
|
|
42597
|
+
const c = readColorExpr(arg);
|
|
42598
|
+
if (!c) return null;
|
|
42599
|
+
switch (c.space) {
|
|
42600
|
+
case "Oklch":
|
|
42601
|
+
return asOklch({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
42602
|
+
case "Oklab":
|
|
42603
|
+
return asOklch({ L: c.c0, a: c.c1, b: c.c2, alpha: c.alpha });
|
|
42604
|
+
case "Rgb":
|
|
42605
|
+
return asOklch({
|
|
42606
|
+
r: c.c0 * 255,
|
|
42607
|
+
g: c.c1 * 255,
|
|
42608
|
+
b: c.c2 * 255,
|
|
42609
|
+
alpha: c.alpha
|
|
42610
|
+
});
|
|
42611
|
+
case "Hsv": {
|
|
42612
|
+
const rgb = hsvToRgb(c.c0, c.c1, c.c2);
|
|
42613
|
+
return asOklch({ ...rgb, alpha: c.alpha });
|
|
42614
|
+
}
|
|
42615
|
+
case "Hsl": {
|
|
42616
|
+
const rgb = hslToRgb(c.c0, c.c1, c.c2);
|
|
42617
|
+
return asOklch({ r: rgb.r, g: rgb.g, b: rgb.b, alpha: c.alpha });
|
|
42618
|
+
}
|
|
42619
|
+
}
|
|
42620
|
+
return null;
|
|
42621
|
+
}
|
|
42622
|
+
function toOklch(ce, arg) {
|
|
42623
|
+
const direct = colorExprToOklch(arg);
|
|
42624
|
+
if (direct) return direct;
|
|
42625
|
+
const rgb = extractRgb(ce, arg);
|
|
42626
|
+
return rgb ? asOklch(rgb) : null;
|
|
42627
|
+
}
|
|
42628
|
+
function lerpOklchColor(a, b, t) {
|
|
42629
|
+
const L = a.L + (b.L - a.L) * t;
|
|
42630
|
+
const C = a.C + (b.C - a.C) * t;
|
|
42631
|
+
const aAchromatic = a.C < 1e-6;
|
|
42632
|
+
const bAchromatic = b.C < 1e-6;
|
|
42633
|
+
let H;
|
|
42634
|
+
if (aAchromatic && bAchromatic) H = a.H;
|
|
42635
|
+
else if (aAchromatic) H = b.H;
|
|
42636
|
+
else if (bAchromatic) H = a.H;
|
|
42637
|
+
else {
|
|
42638
|
+
let dH = b.H - a.H;
|
|
42639
|
+
if (dH > 180) dH -= 360;
|
|
42640
|
+
if (dH < -180) dH += 360;
|
|
42641
|
+
H = a.H + dH * t;
|
|
42642
|
+
if (H < 0) H += 360;
|
|
42643
|
+
if (H >= 360) H -= 360;
|
|
42644
|
+
}
|
|
42645
|
+
const alphaA = a.alpha ?? 1;
|
|
42646
|
+
const alphaB = b.alpha ?? 1;
|
|
42647
|
+
return { L, C, H, alpha: normalizeAlpha(alphaA + (alphaB - alphaA) * t) };
|
|
42648
|
+
}
|
|
42649
|
+
function oklchToExpr(ce, c) {
|
|
42650
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42651
|
+
if (c.alpha !== void 0) args.push(ce.number(c.alpha));
|
|
42652
|
+
return ce.function("Oklch", args);
|
|
42023
42653
|
}
|
|
42024
42654
|
function extractRgb(ce, arg) {
|
|
42025
42655
|
if (isString(arg)) {
|
|
42026
42656
|
const s = arg.string;
|
|
42027
42657
|
if (!s) return void 0;
|
|
42028
42658
|
const color = parseColor(s);
|
|
42029
|
-
|
|
42659
|
+
const rgb = {
|
|
42030
42660
|
r: color >>> 24 & 255,
|
|
42031
42661
|
g: color >>> 16 & 255,
|
|
42032
|
-
b: color >>> 8 & 255
|
|
42033
|
-
alpha: (color & 255) / 255
|
|
42662
|
+
b: color >>> 8 & 255
|
|
42034
42663
|
};
|
|
42664
|
+
const alpha = normalizeAlpha((color & 255) / 255);
|
|
42665
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42666
|
+
return rgb;
|
|
42035
42667
|
}
|
|
42668
|
+
const fromTyped = colorExprToRgb(arg);
|
|
42669
|
+
if (fromTyped) return fromTyped;
|
|
42036
42670
|
if (arg.operator === "Tuple" && arg.ops && arg.ops.length >= 3) {
|
|
42037
42671
|
const rgb = {
|
|
42038
42672
|
r: arg.ops[0].re * 255,
|
|
42039
42673
|
g: arg.ops[1].re * 255,
|
|
42040
42674
|
b: arg.ops[2].re * 255
|
|
42041
42675
|
};
|
|
42042
|
-
if (arg.ops.length >= 4)
|
|
42676
|
+
if (arg.ops.length >= 4) {
|
|
42677
|
+
const alpha = normalizeAlpha(arg.ops[3].re);
|
|
42678
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
42679
|
+
}
|
|
42043
42680
|
return rgb;
|
|
42044
42681
|
}
|
|
42045
42682
|
return void 0;
|
|
42046
42683
|
}
|
|
42047
42684
|
function componentsTuple(ce, components, alpha) {
|
|
42048
42685
|
const args = components.map((v) => ce.number(v));
|
|
42049
|
-
if (alpha !== void 0
|
|
42050
|
-
args.push(ce.number(alpha));
|
|
42686
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
42051
42687
|
return ce.tuple(...args);
|
|
42052
42688
|
}
|
|
42053
42689
|
function rgbToHex(rgb) {
|
|
@@ -42055,7 +42691,7 @@ ${e.message}
|
|
|
42055
42691
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
42056
42692
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
42057
42693
|
const hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
42058
|
-
if (rgb.alpha !== void 0
|
|
42694
|
+
if (rgb.alpha !== void 0) {
|
|
42059
42695
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
42060
42696
|
return hex + a.toString(16).padStart(2, "0");
|
|
42061
42697
|
}
|
|
@@ -42063,22 +42699,29 @@ ${e.message}
|
|
|
42063
42699
|
}
|
|
42064
42700
|
var COLORS_LIBRARY = {
|
|
42065
42701
|
Color: {
|
|
42066
|
-
description: "
|
|
42702
|
+
description: "Parse a CSS-style color string to an Oklch color",
|
|
42067
42703
|
complexity: 8e3,
|
|
42068
|
-
signature: "(string) ->
|
|
42704
|
+
signature: "(string) -> color",
|
|
42069
42705
|
evaluate: (ops, { engine: ce }) => {
|
|
42070
42706
|
const input = isString(ops[0]) ? ops[0].string : void 0;
|
|
42071
42707
|
if (!input) return ce.error("incompatible-type");
|
|
42072
42708
|
const color = parseColor(input);
|
|
42073
42709
|
if (color === 0 && input.trim().toLowerCase() !== "transparent")
|
|
42074
42710
|
return ce.error("incompatible-type");
|
|
42075
|
-
|
|
42711
|
+
const r = color >>> 24 & 255;
|
|
42712
|
+
const g = color >>> 16 & 255;
|
|
42713
|
+
const b = color >>> 8 & 255;
|
|
42714
|
+
const a = normalizeAlpha((color & 255) / 255);
|
|
42715
|
+
const c = rgbToOklch({ r, g, b });
|
|
42716
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
42717
|
+
if (a !== void 0) args.push(ce.number(a));
|
|
42718
|
+
return ce.function("Oklch", args);
|
|
42076
42719
|
}
|
|
42077
42720
|
},
|
|
42078
42721
|
ColorToString: {
|
|
42079
42722
|
description: "Convert a color to a string in the specified format",
|
|
42080
42723
|
complexity: 8e3,
|
|
42081
|
-
signature: "(
|
|
42724
|
+
signature: "(color | string | tuple, string?) -> string",
|
|
42082
42725
|
evaluate: (ops, { engine: ce }) => {
|
|
42083
42726
|
const rgb = extractRgb(ce, ops[0]);
|
|
42084
42727
|
if (!rgb) return ce.error("incompatible-type");
|
|
@@ -42090,7 +42733,7 @@ ${e.message}
|
|
|
42090
42733
|
const r = Math.round(rgb.r);
|
|
42091
42734
|
const g = Math.round(rgb.g);
|
|
42092
42735
|
const b = Math.round(rgb.b);
|
|
42093
|
-
if (rgb.alpha !== void 0
|
|
42736
|
+
if (rgb.alpha !== void 0)
|
|
42094
42737
|
return ce.string(`rgb(${r} ${g} ${b} / ${rgb.alpha})`);
|
|
42095
42738
|
return ce.string(`rgb(${r} ${g} ${b})`);
|
|
42096
42739
|
}
|
|
@@ -42099,17 +42742,17 @@ ${e.message}
|
|
|
42099
42742
|
const h = Math.round(hsl.h * 10) / 10;
|
|
42100
42743
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
42101
42744
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
42102
|
-
if (rgb.alpha !== void 0
|
|
42745
|
+
if (rgb.alpha !== void 0)
|
|
42103
42746
|
return ce.string(`hsl(${h} ${s}% ${l}% / ${rgb.alpha})`);
|
|
42104
42747
|
return ce.string(`hsl(${h} ${s}% ${l}%)`);
|
|
42105
42748
|
}
|
|
42106
42749
|
case "oklch": {
|
|
42107
|
-
const c =
|
|
42750
|
+
const c = colorExprToOklch(ops[0]) ?? asOklch(rgb);
|
|
42108
42751
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
42109
42752
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
42110
42753
|
const H = Math.round(c.H * 10) / 10;
|
|
42111
|
-
if (
|
|
42112
|
-
return ce.string(`oklch(${L} ${C} ${H} / ${
|
|
42754
|
+
if (c.alpha !== void 0)
|
|
42755
|
+
return ce.string(`oklch(${L} ${C} ${H} / ${c.alpha})`);
|
|
42113
42756
|
return ce.string(`oklch(${L} ${C} ${H})`);
|
|
42114
42757
|
}
|
|
42115
42758
|
default:
|
|
@@ -42120,60 +42763,44 @@ ${e.message}
|
|
|
42120
42763
|
ColorMix: {
|
|
42121
42764
|
description: "Mix two colors in OKLCh space",
|
|
42122
42765
|
complexity: 8e3,
|
|
42123
|
-
signature: "(
|
|
42766
|
+
signature: "(color | string | tuple, color | string | tuple, number?) -> color",
|
|
42124
42767
|
evaluate: (ops, { engine: ce }) => {
|
|
42125
|
-
const rgb1 = extractRgb(ce, ops[0]);
|
|
42126
|
-
const rgb2 = extractRgb(ce, ops[1]);
|
|
42127
|
-
if (!rgb1 || !rgb2) return ce.error("incompatible-type");
|
|
42128
42768
|
let ratio = 0.5;
|
|
42129
42769
|
if (ops.length >= 3 && ops[2] !== void 0) {
|
|
42130
42770
|
ratio = ops[2].re;
|
|
42131
42771
|
if (!Number.isFinite(ratio)) return ce.error("expected-value");
|
|
42132
42772
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
42133
42773
|
}
|
|
42134
|
-
const
|
|
42135
|
-
const
|
|
42136
|
-
|
|
42137
|
-
|
|
42138
|
-
const g = mixed.g / 255;
|
|
42139
|
-
const b = mixed.b / 255;
|
|
42140
|
-
const a1 = rgb1.alpha ?? 1;
|
|
42141
|
-
const a2 = rgb2.alpha ?? 1;
|
|
42142
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
42143
|
-
if (Math.abs(alpha - 1) > 1e-4)
|
|
42144
|
-
return ce.tuple(
|
|
42145
|
-
ce.number(r),
|
|
42146
|
-
ce.number(g),
|
|
42147
|
-
ce.number(b),
|
|
42148
|
-
ce.number(alpha)
|
|
42149
|
-
);
|
|
42150
|
-
return ce.tuple(ce.number(r), ce.number(g), ce.number(b));
|
|
42774
|
+
const oklch1 = toOklch(ce, ops[0]);
|
|
42775
|
+
const oklch2 = toOklch(ce, ops[1]);
|
|
42776
|
+
if (!oklch1 || !oklch2) return ce.error("incompatible-type");
|
|
42777
|
+
return oklchToExpr(ce, lerpOklchColor(oklch1, oklch2, ratio));
|
|
42151
42778
|
}
|
|
42152
42779
|
},
|
|
42153
42780
|
Colormap: {
|
|
42154
42781
|
description: "Sample colors from a named palette",
|
|
42155
42782
|
complexity: 8e3,
|
|
42156
|
-
signature: "(string, number?) ->
|
|
42783
|
+
signature: "(string, number?) -> color | list<color>",
|
|
42157
42784
|
evaluate: (ops, { engine: ce }) => {
|
|
42158
42785
|
const name = isString(ops[0]) ? ops[0].string : void 0;
|
|
42159
42786
|
if (!name) return ce.error("incompatible-type");
|
|
42160
42787
|
const palette = ALL_PALETTES[name];
|
|
42161
42788
|
if (!palette) return ce.error("expected-value", name);
|
|
42162
42789
|
if (ops.length < 2 || ops[1] === void 0) {
|
|
42163
|
-
const
|
|
42164
|
-
(hex) =>
|
|
42790
|
+
const colors = palette.map(
|
|
42791
|
+
(hex) => colorNumberToOklch(ce, parseColor(hex))
|
|
42165
42792
|
);
|
|
42166
|
-
return ce.function("List",
|
|
42793
|
+
return ce.function("List", colors);
|
|
42167
42794
|
}
|
|
42168
42795
|
const val = ops[1].re;
|
|
42169
42796
|
if (!Number.isFinite(val)) return ce.error("expected-value");
|
|
42170
42797
|
if (Number.isInteger(val) && val >= 2) {
|
|
42171
42798
|
const n = val;
|
|
42172
|
-
const
|
|
42799
|
+
const colors = [];
|
|
42173
42800
|
for (let i = 0; i < n; i++) {
|
|
42174
|
-
|
|
42801
|
+
colors.push(samplePalette(ce, palette, i / (n - 1)));
|
|
42175
42802
|
}
|
|
42176
|
-
return ce.function("List",
|
|
42803
|
+
return ce.function("List", colors);
|
|
42177
42804
|
}
|
|
42178
42805
|
return samplePalette(ce, palette, val);
|
|
42179
42806
|
}
|
|
@@ -42181,12 +42808,25 @@ ${e.message}
|
|
|
42181
42808
|
ColorToColorspace: {
|
|
42182
42809
|
description: "Convert a color to components in a target color space",
|
|
42183
42810
|
complexity: 8e3,
|
|
42184
|
-
signature: "(
|
|
42811
|
+
signature: "(color | string | tuple, string) -> tuple",
|
|
42185
42812
|
evaluate: (ops, { engine: ce }) => {
|
|
42186
|
-
const rgb = extractRgb(ce, ops[0]);
|
|
42187
|
-
if (!rgb) return ce.error("incompatible-type");
|
|
42188
42813
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42189
42814
|
if (!space) return ce.error("incompatible-type");
|
|
42815
|
+
if (space === "oklch" || space === "oklab" || space === "lab") {
|
|
42816
|
+
const oklch2 = colorExprToOklch(ops[0]);
|
|
42817
|
+
if (oklch2) {
|
|
42818
|
+
if (space === "oklch")
|
|
42819
|
+
return componentsTuple(
|
|
42820
|
+
ce,
|
|
42821
|
+
[oklch2.L, oklch2.C, oklch2.H],
|
|
42822
|
+
oklch2.alpha
|
|
42823
|
+
);
|
|
42824
|
+
const lab = oklchToOklab(oklch2);
|
|
42825
|
+
return componentsTuple(ce, [lab.L, lab.a, lab.b], lab.alpha);
|
|
42826
|
+
}
|
|
42827
|
+
}
|
|
42828
|
+
const rgb = extractRgb(ce, ops[0]);
|
|
42829
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42190
42830
|
const alpha = rgb.alpha;
|
|
42191
42831
|
switch (space) {
|
|
42192
42832
|
case "rgb":
|
|
@@ -42216,17 +42856,27 @@ ${e.message}
|
|
|
42216
42856
|
ColorFromColorspace: {
|
|
42217
42857
|
description: "Convert color space components to a canonical sRGB tuple",
|
|
42218
42858
|
complexity: 8e3,
|
|
42219
|
-
signature: "(tuple, string) -> tuple",
|
|
42859
|
+
signature: "(color | tuple, string) -> tuple",
|
|
42220
42860
|
evaluate: (ops, { engine: ce }) => {
|
|
42221
|
-
const tuple = ops[0];
|
|
42222
|
-
if (!isFunction2(tuple) || tuple.operator !== "Tuple" || tuple.ops.length < 3)
|
|
42223
|
-
return ce.error("incompatible-type");
|
|
42224
|
-
const c0 = tuple.ops[0].re;
|
|
42225
|
-
const c1 = tuple.ops[1].re;
|
|
42226
|
-
const c2 = tuple.ops[2].re;
|
|
42227
|
-
const alpha = tuple.ops.length >= 4 ? tuple.ops[3].re : void 0;
|
|
42228
42861
|
const space = isString(ops[1]) ? ops[1].string?.toLowerCase() : void 0;
|
|
42229
42862
|
if (!space) return ce.error("incompatible-type");
|
|
42863
|
+
let c0, c1, c2;
|
|
42864
|
+
let alpha;
|
|
42865
|
+
const arg = ops[0];
|
|
42866
|
+
const typed = readColorExpr(arg);
|
|
42867
|
+
if (typed) {
|
|
42868
|
+
c0 = typed.c0;
|
|
42869
|
+
c1 = typed.c1;
|
|
42870
|
+
c2 = typed.c2;
|
|
42871
|
+
alpha = typed.alpha;
|
|
42872
|
+
} else if (isFunction2(arg) && arg.operator === "Tuple" && arg.ops.length >= 3) {
|
|
42873
|
+
c0 = arg.ops[0].re;
|
|
42874
|
+
c1 = arg.ops[1].re;
|
|
42875
|
+
c2 = arg.ops[2].re;
|
|
42876
|
+
alpha = arg.ops.length >= 4 ? arg.ops[3].re : void 0;
|
|
42877
|
+
} else {
|
|
42878
|
+
return ce.error("incompatible-type");
|
|
42879
|
+
}
|
|
42230
42880
|
let rgb;
|
|
42231
42881
|
switch (space) {
|
|
42232
42882
|
case "rgb":
|
|
@@ -42262,7 +42912,7 @@ ${e.message}
|
|
|
42262
42912
|
ColorContrast: {
|
|
42263
42913
|
description: "APCA contrast ratio between two colors",
|
|
42264
42914
|
complexity: 8e3,
|
|
42265
|
-
signature: "(
|
|
42915
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
42266
42916
|
evaluate: (ops, { engine: ce }) => {
|
|
42267
42917
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42268
42918
|
const fgRgb = extractRgb(ce, ops[1]);
|
|
@@ -42273,19 +42923,186 @@ ${e.message}
|
|
|
42273
42923
|
ContrastingColor: {
|
|
42274
42924
|
description: "Choose the foreground color with better APCA contrast against a background",
|
|
42275
42925
|
complexity: 8e3,
|
|
42276
|
-
signature: "(
|
|
42926
|
+
signature: "(color | string | tuple, (color | string | tuple)?, (color | string | tuple)?) -> color",
|
|
42277
42927
|
evaluate: (ops, { engine: ce }) => {
|
|
42278
42928
|
const bgRgb = extractRgb(ce, ops[0]);
|
|
42279
42929
|
if (!bgRgb) return ce.error("incompatible-type");
|
|
42930
|
+
let packed;
|
|
42280
42931
|
if (ops.length >= 3 && ops[1] !== void 0 && ops[2] !== void 0) {
|
|
42281
42932
|
const fg1 = extractRgb(ce, ops[1]);
|
|
42282
42933
|
const fg2 = extractRgb(ce, ops[2]);
|
|
42283
42934
|
if (!fg1 || !fg2) return ce.error("incompatible-type");
|
|
42284
|
-
|
|
42285
|
-
|
|
42935
|
+
packed = contrastingColor({ bg: bgRgb, fg1, fg2 });
|
|
42936
|
+
} else {
|
|
42937
|
+
packed = contrastingColor(bgRgb);
|
|
42938
|
+
}
|
|
42939
|
+
const r = (packed >>> 24 & 255) / 255;
|
|
42940
|
+
const g = (packed >>> 16 & 255) / 255;
|
|
42941
|
+
const b = (packed >>> 8 & 255) / 255;
|
|
42942
|
+
const alpha = normalizeAlpha((packed & 255) / 255);
|
|
42943
|
+
const args = [ce.number(r), ce.number(g), ce.number(b)];
|
|
42944
|
+
if (alpha !== void 0) args.push(ce.number(alpha));
|
|
42945
|
+
return ce.function("Rgb", args);
|
|
42946
|
+
}
|
|
42947
|
+
},
|
|
42948
|
+
// ---------------------------------------------------------------------------
|
|
42949
|
+
// Color constructors. Each preserves its colorspace on evaluation; the
|
|
42950
|
+
// operator name is the discriminator. Components are interpreted per
|
|
42951
|
+
// colorspace conventions (Rgb channels 0-1, Hsv/Hsl hue in degrees with
|
|
42952
|
+
// sat/value 0-1, Oklab/Oklch L 0-1 with standard a/b/C/H ranges). The
|
|
42953
|
+
// optional 4th argument is alpha in [0, 1]. No clamping at evaluation time.
|
|
42954
|
+
// ---------------------------------------------------------------------------
|
|
42955
|
+
Rgb: {
|
|
42956
|
+
description: "sRGB color (channels 0-1, optional alpha 0-1)",
|
|
42957
|
+
complexity: 8e3,
|
|
42958
|
+
signature: "(number, number, number, number?) -> color"
|
|
42959
|
+
},
|
|
42960
|
+
Hsv: {
|
|
42961
|
+
description: "HSV color (hue degrees, saturation/value 0-1, optional alpha)",
|
|
42962
|
+
complexity: 8e3,
|
|
42963
|
+
signature: "(number, number, number, number?) -> color"
|
|
42964
|
+
},
|
|
42965
|
+
Hsl: {
|
|
42966
|
+
description: "HSL color (hue degrees, saturation/lightness 0-1, optional alpha)",
|
|
42967
|
+
complexity: 8e3,
|
|
42968
|
+
signature: "(number, number, number, number?) -> color"
|
|
42969
|
+
},
|
|
42970
|
+
Oklab: {
|
|
42971
|
+
description: "OKLab color (L 0-1, a/b ~ -0.4..0.4, optional alpha)",
|
|
42972
|
+
complexity: 8e3,
|
|
42973
|
+
signature: "(number, number, number, number?) -> color"
|
|
42974
|
+
},
|
|
42975
|
+
Oklch: {
|
|
42976
|
+
description: "OKLCh color (L 0-1, C 0-~0.4, hue degrees, optional alpha)",
|
|
42977
|
+
complexity: 8e3,
|
|
42978
|
+
signature: "(number, number, number, number?) -> color"
|
|
42979
|
+
},
|
|
42980
|
+
// ---------------------------------------------------------------------------
|
|
42981
|
+
// Color-space conversions. Each accepts any of the five color heads and
|
|
42982
|
+
// returns the same color in the named space. If the input is already in
|
|
42983
|
+
// the target space, returns the input unchanged.
|
|
42984
|
+
// ---------------------------------------------------------------------------
|
|
42985
|
+
AsRgb: {
|
|
42986
|
+
description: "Convert any color to sRGB (channels 0-1)",
|
|
42987
|
+
complexity: 8e3,
|
|
42988
|
+
signature: "(color) -> color",
|
|
42989
|
+
evaluate: (ops, { engine: ce }) => {
|
|
42990
|
+
const arg = ops[0];
|
|
42991
|
+
if (isFunction2(arg) && arg.operator === "Rgb")
|
|
42992
|
+
return normalizeColorHead(ce, arg);
|
|
42993
|
+
const rgb = colorExprToRgb(arg);
|
|
42994
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
42995
|
+
const args = [
|
|
42996
|
+
ce.number(rgb.r / 255),
|
|
42997
|
+
ce.number(rgb.g / 255),
|
|
42998
|
+
ce.number(rgb.b / 255)
|
|
42999
|
+
];
|
|
43000
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43001
|
+
return ce.function("Rgb", args);
|
|
43002
|
+
}
|
|
43003
|
+
},
|
|
43004
|
+
AsHsv: {
|
|
43005
|
+
description: "Convert any color to HSV (hue degrees, s/v 0-1)",
|
|
43006
|
+
complexity: 8e3,
|
|
43007
|
+
signature: "(color) -> color",
|
|
43008
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43009
|
+
const arg = ops[0];
|
|
43010
|
+
if (isFunction2(arg) && arg.operator === "Hsv")
|
|
43011
|
+
return normalizeColorHead(ce, arg);
|
|
43012
|
+
const rgb = colorExprToRgb(arg);
|
|
43013
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43014
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
43015
|
+
const args = [ce.number(hsv.h), ce.number(hsv.s), ce.number(hsv.v)];
|
|
43016
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43017
|
+
return ce.function("Hsv", args);
|
|
43018
|
+
}
|
|
43019
|
+
},
|
|
43020
|
+
AsHsl: {
|
|
43021
|
+
description: "Convert any color to HSL (hue degrees, s/l 0-1)",
|
|
43022
|
+
complexity: 8e3,
|
|
43023
|
+
signature: "(color) -> color",
|
|
43024
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43025
|
+
const arg = ops[0];
|
|
43026
|
+
if (isFunction2(arg) && arg.operator === "Hsl")
|
|
43027
|
+
return normalizeColorHead(ce, arg);
|
|
43028
|
+
const rgb = colorExprToRgb(arg);
|
|
43029
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43030
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
43031
|
+
const args = [ce.number(hsl.h), ce.number(hsl.s), ce.number(hsl.l)];
|
|
43032
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43033
|
+
return ce.function("Hsl", args);
|
|
43034
|
+
}
|
|
43035
|
+
},
|
|
43036
|
+
AsOklab: {
|
|
43037
|
+
description: "Convert any color to OKLab",
|
|
43038
|
+
complexity: 8e3,
|
|
43039
|
+
signature: "(color) -> color",
|
|
43040
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43041
|
+
const arg = ops[0];
|
|
43042
|
+
if (isFunction2(arg) && arg.operator === "Oklab")
|
|
43043
|
+
return normalizeColorHead(ce, arg);
|
|
43044
|
+
if (isFunction2(arg) && arg.operator === "Oklch") {
|
|
43045
|
+
const c = readColorExpr(arg);
|
|
43046
|
+
if (!c) return ce.error("incompatible-type");
|
|
43047
|
+
const lab2 = oklchToOklab({ L: c.c0, C: c.c1, H: c.c2, alpha: c.alpha });
|
|
43048
|
+
const args2 = [ce.number(lab2.L), ce.number(lab2.a), ce.number(lab2.b)];
|
|
43049
|
+
if (lab2.alpha !== void 0) args2.push(ce.number(lab2.alpha));
|
|
43050
|
+
return ce.function("Oklab", args2);
|
|
43051
|
+
}
|
|
43052
|
+
const rgb = colorExprToRgb(arg);
|
|
43053
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43054
|
+
const lab = rgbToOklab(rgb);
|
|
43055
|
+
const args = [ce.number(lab.L), ce.number(lab.a), ce.number(lab.b)];
|
|
43056
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43057
|
+
return ce.function("Oklab", args);
|
|
43058
|
+
}
|
|
43059
|
+
},
|
|
43060
|
+
AsOklch: {
|
|
43061
|
+
description: "Convert any color to OKLCh",
|
|
43062
|
+
complexity: 8e3,
|
|
43063
|
+
signature: "(color) -> color",
|
|
43064
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43065
|
+
const arg = ops[0];
|
|
43066
|
+
if (isFunction2(arg) && arg.operator === "Oklch")
|
|
43067
|
+
return normalizeColorHead(ce, arg);
|
|
43068
|
+
if (isFunction2(arg) && arg.operator === "Oklab") {
|
|
43069
|
+
const c2 = readColorExpr(arg);
|
|
43070
|
+
if (!c2) return ce.error("incompatible-type");
|
|
43071
|
+
const oklch2 = oklabToOklch({
|
|
43072
|
+
L: c2.c0,
|
|
43073
|
+
a: c2.c1,
|
|
43074
|
+
b: c2.c2,
|
|
43075
|
+
alpha: c2.alpha
|
|
43076
|
+
});
|
|
43077
|
+
const args2 = [
|
|
43078
|
+
ce.number(oklch2.L),
|
|
43079
|
+
ce.number(oklch2.C),
|
|
43080
|
+
ce.number(oklch2.H)
|
|
43081
|
+
];
|
|
43082
|
+
if (oklch2.alpha !== void 0) args2.push(ce.number(oklch2.alpha));
|
|
43083
|
+
return ce.function("Oklch", args2);
|
|
42286
43084
|
}
|
|
42287
|
-
const
|
|
42288
|
-
return
|
|
43085
|
+
const rgb = colorExprToRgb(arg);
|
|
43086
|
+
if (!rgb) return ce.error("incompatible-type");
|
|
43087
|
+
const c = rgbToOklch(rgb);
|
|
43088
|
+
const args = [ce.number(c.L), ce.number(c.C), ce.number(c.H)];
|
|
43089
|
+
if (rgb.alpha !== void 0) args.push(ce.number(rgb.alpha));
|
|
43090
|
+
return ce.function("Oklch", args);
|
|
43091
|
+
}
|
|
43092
|
+
},
|
|
43093
|
+
// ---------------------------------------------------------------------------
|
|
43094
|
+
// Perceptual difference. Returns ΔE_OK (Euclidean distance in OKLab),
|
|
43095
|
+
// an approximately perceptually uniform scalar.
|
|
43096
|
+
// ---------------------------------------------------------------------------
|
|
43097
|
+
ColorDelta: {
|
|
43098
|
+
description: "Perceptual color difference (\u0394E_OK) between two colors",
|
|
43099
|
+
complexity: 8e3,
|
|
43100
|
+
signature: "(color | string | tuple, color | string | tuple) -> number",
|
|
43101
|
+
evaluate: (ops, { engine: ce }) => {
|
|
43102
|
+
const a = toOklch(ce, ops[0]);
|
|
43103
|
+
const b = toOklch(ce, ops[1]);
|
|
43104
|
+
if (!a || !b) return ce.error("incompatible-type");
|
|
43105
|
+
return ce.number(oklabDeltaE(oklchToOklab(a), oklchToOklab(b)));
|
|
42289
43106
|
}
|
|
42290
43107
|
}
|
|
42291
43108
|
};
|
|
@@ -42344,12 +43161,42 @@ ${e.message}
|
|
|
42344
43161
|
}
|
|
42345
43162
|
},
|
|
42346
43163
|
Loop: {
|
|
42347
|
-
description: "Evaluate a body expression over
|
|
43164
|
+
description: "Evaluate a body expression in nested iteration over Element clauses. Later clauses see earlier bindings; independent clauses produce a Cartesian product.",
|
|
42348
43165
|
lazy: true,
|
|
42349
|
-
signature: "(body:expression,
|
|
42350
|
-
type: ([body]) =>
|
|
42351
|
-
|
|
42352
|
-
|
|
43166
|
+
signature: "(body:expression, iterators:expression*) -> any",
|
|
43167
|
+
type: ([body]) => {
|
|
43168
|
+
if (!body) return "nothing";
|
|
43169
|
+
return parseType(`indexed_collection<${String(body.type)}>`);
|
|
43170
|
+
},
|
|
43171
|
+
canonical: canonicalLoop,
|
|
43172
|
+
evaluate: (ops, { engine: ce }) => run(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining),
|
|
43173
|
+
evaluateAsync: async (ops, { engine: ce, signal }) => runAsync(runLoop(ops[0], ops.slice(1), ce), ce._timeRemaining, signal)
|
|
43174
|
+
},
|
|
43175
|
+
When: {
|
|
43176
|
+
description: "Conditional value: returns expr when cond holds, undefined otherwise.",
|
|
43177
|
+
lazy: true,
|
|
43178
|
+
signature: "(expression, boolean) -> any",
|
|
43179
|
+
type: ([expr2]) => expr2.type,
|
|
43180
|
+
canonical: (args, { engine: ce }) => {
|
|
43181
|
+
if (args.length !== 2) return null;
|
|
43182
|
+
const [expr2, cond] = args;
|
|
43183
|
+
if (isFunction2(expr2, "When")) {
|
|
43184
|
+
const inner = expr2.op1.canonical;
|
|
43185
|
+
const innerCond = expr2.op2.canonical;
|
|
43186
|
+
return ce._fn("When", [
|
|
43187
|
+
inner,
|
|
43188
|
+
ce._fn("And", [innerCond, cond.canonical])
|
|
43189
|
+
]);
|
|
43190
|
+
}
|
|
43191
|
+
return ce._fn("When", [expr2.canonical, cond.canonical]);
|
|
43192
|
+
},
|
|
43193
|
+
evaluate: ([expr2, cond], { engine: ce }) => {
|
|
43194
|
+
const c = cond.evaluate();
|
|
43195
|
+
const cs = sym(c);
|
|
43196
|
+
if (cs === "True") return expr2.evaluate();
|
|
43197
|
+
if (cs === "False") return ce.symbol("Undefined");
|
|
43198
|
+
return ce._fn("When", [expr2, c]);
|
|
43199
|
+
}
|
|
42353
43200
|
},
|
|
42354
43201
|
Which: {
|
|
42355
43202
|
description: "Return the value for the first condition that is true.",
|
|
@@ -42409,9 +43256,141 @@ ${e.message}
|
|
|
42409
43256
|
);
|
|
42410
43257
|
return result;
|
|
42411
43258
|
}
|
|
42412
|
-
function
|
|
43259
|
+
function canonicalLoop(ops, options) {
|
|
43260
|
+
const { engine: ce, scope } = options;
|
|
43261
|
+
if (ops.length === 0) return null;
|
|
43262
|
+
if (ops.length === 1) {
|
|
43263
|
+
return ce._fn("Loop", [ops[0].canonical]);
|
|
43264
|
+
}
|
|
43265
|
+
const body = ops[0];
|
|
43266
|
+
const iterators = ops.slice(1);
|
|
43267
|
+
const allElement = iterators.every((it) => it.operator === "Element");
|
|
43268
|
+
if (!allElement) {
|
|
43269
|
+
return ce._fn(
|
|
43270
|
+
"Loop",
|
|
43271
|
+
ops.map((op) => op.canonical)
|
|
43272
|
+
);
|
|
43273
|
+
}
|
|
43274
|
+
const loopScope = scope ?? {
|
|
43275
|
+
parent: ce.context.lexicalScope,
|
|
43276
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43277
|
+
};
|
|
43278
|
+
loopScope.noAutoDeclare = true;
|
|
43279
|
+
ce.pushScope(loopScope);
|
|
43280
|
+
let canonicalIterators;
|
|
43281
|
+
let canonicalBody;
|
|
43282
|
+
try {
|
|
43283
|
+
canonicalIterators = iterators.map((it) => {
|
|
43284
|
+
if (!isFunction2(it, "Element")) {
|
|
43285
|
+
return ce._fn("Element", [
|
|
43286
|
+
ce.error("missing").canonical,
|
|
43287
|
+
ce.error("missing").canonical
|
|
43288
|
+
]);
|
|
43289
|
+
}
|
|
43290
|
+
const indexExpr = it.ops[0];
|
|
43291
|
+
const collExpr = it.ops[1];
|
|
43292
|
+
if (!indexExpr || !collExpr) {
|
|
43293
|
+
return ce._fn("Element", [
|
|
43294
|
+
(indexExpr ?? ce.error("missing")).canonical,
|
|
43295
|
+
(collExpr ?? ce.error("missing")).canonical
|
|
43296
|
+
]);
|
|
43297
|
+
}
|
|
43298
|
+
if (isSymbol2(indexExpr) && indexExpr.symbol !== "Nothing") {
|
|
43299
|
+
if (!ce.context.lexicalScope.bindings.has(indexExpr.symbol))
|
|
43300
|
+
ce.declare(indexExpr.symbol, "unknown");
|
|
43301
|
+
}
|
|
43302
|
+
return ce._fn("Element", [indexExpr.canonical, collExpr.canonical]);
|
|
43303
|
+
});
|
|
43304
|
+
canonicalBody = body.canonical;
|
|
43305
|
+
} finally {
|
|
43306
|
+
ce.popScope();
|
|
43307
|
+
loopScope.noAutoDeclare = false;
|
|
43308
|
+
}
|
|
43309
|
+
return ce._fn("Loop", [canonicalBody, ...canonicalIterators], {
|
|
43310
|
+
scope: loopScope
|
|
43311
|
+
});
|
|
43312
|
+
}
|
|
43313
|
+
function* runLoop(body, elements, ce) {
|
|
42413
43314
|
body ??= ce.Nothing;
|
|
42414
43315
|
if (sym(body) === "Nothing") return body;
|
|
43316
|
+
if (elements.length === 0) {
|
|
43317
|
+
const result = body.evaluate();
|
|
43318
|
+
yield result;
|
|
43319
|
+
return result;
|
|
43320
|
+
}
|
|
43321
|
+
if (elements.length === 1 && elements[0].operator !== "Element") {
|
|
43322
|
+
return yield* runLoopLegacy(body, elements[0], ce);
|
|
43323
|
+
}
|
|
43324
|
+
const results = [];
|
|
43325
|
+
const state = { stopped: false, broke: false, count: 0 };
|
|
43326
|
+
const freshScope = {
|
|
43327
|
+
parent: ce.context.lexicalScope,
|
|
43328
|
+
bindings: /* @__PURE__ */ new Map()
|
|
43329
|
+
};
|
|
43330
|
+
ce._pushEvalContext(freshScope);
|
|
43331
|
+
try {
|
|
43332
|
+
for (const elem of elements) {
|
|
43333
|
+
if (!isFunction2(elem, "Element")) continue;
|
|
43334
|
+
const idx = elem.ops[0];
|
|
43335
|
+
if (idx && isSymbol2(idx) && idx.symbol !== "Nothing") {
|
|
43336
|
+
if (!freshScope.bindings.has(idx.symbol))
|
|
43337
|
+
ce.declare(idx.symbol, "unknown");
|
|
43338
|
+
}
|
|
43339
|
+
}
|
|
43340
|
+
yield* runLoopNested(body, elements, 0, ce, results, state);
|
|
43341
|
+
} finally {
|
|
43342
|
+
ce._popEvalContext();
|
|
43343
|
+
}
|
|
43344
|
+
if (state.stopped && state.value !== void 0) {
|
|
43345
|
+
if (!state.broke) return state.value;
|
|
43346
|
+
return state.value;
|
|
43347
|
+
}
|
|
43348
|
+
return ce.function("List", results);
|
|
43349
|
+
}
|
|
43350
|
+
function* runLoopNested(body, elements, index, ce, results, state) {
|
|
43351
|
+
if (state.stopped) return;
|
|
43352
|
+
if (index === elements.length) {
|
|
43353
|
+
const result = body.evaluate();
|
|
43354
|
+
state.count += 1;
|
|
43355
|
+
if (state.count > ce.iterationLimit)
|
|
43356
|
+
throw new CancellationError({ cause: "iteration-limit-exceeded" });
|
|
43357
|
+
if (isFunction2(result, "Break")) {
|
|
43358
|
+
state.stopped = true;
|
|
43359
|
+
state.broke = true;
|
|
43360
|
+
state.value = result.op1;
|
|
43361
|
+
return;
|
|
43362
|
+
}
|
|
43363
|
+
if (result.operator === "Return") {
|
|
43364
|
+
state.stopped = true;
|
|
43365
|
+
state.value = result;
|
|
43366
|
+
return;
|
|
43367
|
+
}
|
|
43368
|
+
results.push(result);
|
|
43369
|
+
yield result;
|
|
43370
|
+
return;
|
|
43371
|
+
}
|
|
43372
|
+
const elem = elements[index];
|
|
43373
|
+
if (!isFunction2(elem, "Element")) {
|
|
43374
|
+
return;
|
|
43375
|
+
}
|
|
43376
|
+
const indexExpr = elem.ops[0];
|
|
43377
|
+
const collExpr = elem.ops[1];
|
|
43378
|
+
if (!indexExpr || !isSymbol2(indexExpr) || !collExpr) {
|
|
43379
|
+
return;
|
|
43380
|
+
}
|
|
43381
|
+
const name = indexExpr.symbol;
|
|
43382
|
+
const collection = collExpr.evaluate();
|
|
43383
|
+
if (!collection?.isCollection) {
|
|
43384
|
+
return;
|
|
43385
|
+
}
|
|
43386
|
+
const skipAssign = name === "Nothing";
|
|
43387
|
+
for (const value of collection.each()) {
|
|
43388
|
+
if (!skipAssign) ce.assign(name, value);
|
|
43389
|
+
yield* runLoopNested(body, elements, index + 1, ce, results, state);
|
|
43390
|
+
if (state.stopped) return;
|
|
43391
|
+
}
|
|
43392
|
+
}
|
|
43393
|
+
function* runLoopLegacy(body, collection, ce) {
|
|
42415
43394
|
if (collection?.isCollection) {
|
|
42416
43395
|
let result = void 0;
|
|
42417
43396
|
const fn = applicable(body);
|
|
@@ -44765,6 +45744,34 @@ ${e.message}
|
|
|
44765
45744
|
signature: "() -> expression",
|
|
44766
45745
|
evaluate: (_ops, { engine }) => engine.expr(randomExpression())
|
|
44767
45746
|
}
|
|
45747
|
+
},
|
|
45748
|
+
// ---------------------------------------------------------------------------
|
|
45749
|
+
// Opaque typed heads — registered so the names are in the standard set
|
|
45750
|
+
// (consumers can branch on the operator name); CE itself does not evaluate
|
|
45751
|
+
// them. Geometric primitives `Triangle`/`Sphere`/`Segment` and the action
|
|
45752
|
+
// arrow `To` (`a \to b`).
|
|
45753
|
+
// ---------------------------------------------------------------------------
|
|
45754
|
+
{
|
|
45755
|
+
Triangle: {
|
|
45756
|
+
description: "Triangle primitive \u2014 opaque typed head.",
|
|
45757
|
+
signature: "(any+) -> expression"
|
|
45758
|
+
},
|
|
45759
|
+
GeometricVector: {
|
|
45760
|
+
description: "Geometric vector (directed segment between two points) \u2014 opaque typed head. Distinct from the column-vector `Vector` operator.",
|
|
45761
|
+
signature: "(any, any) -> expression"
|
|
45762
|
+
},
|
|
45763
|
+
Sphere: {
|
|
45764
|
+
description: "Sphere primitive \u2014 opaque typed head.",
|
|
45765
|
+
signature: "(any+) -> expression"
|
|
45766
|
+
},
|
|
45767
|
+
Segment: {
|
|
45768
|
+
description: "Segment primitive \u2014 opaque typed head.",
|
|
45769
|
+
signature: "(any+) -> expression"
|
|
45770
|
+
},
|
|
45771
|
+
To: {
|
|
45772
|
+
description: "Action arrow / mapping (`a \\to b`) \u2014 opaque typed head.",
|
|
45773
|
+
signature: "(any, any) -> nothing"
|
|
45774
|
+
}
|
|
44768
45775
|
}
|
|
44769
45776
|
];
|
|
44770
45777
|
|
|
@@ -51901,6 +52908,7 @@ Error in definition of "${name}"`,
|
|
|
51901
52908
|
|
|
51902
52909
|
// src/compute-engine/boxed-expression/cache.ts
|
|
51903
52910
|
function cachedValue(v, generation, fn) {
|
|
52911
|
+
if (v.generation === generation && v.value !== null) return v.value;
|
|
51904
52912
|
v.generation = generation;
|
|
51905
52913
|
v.value = fn();
|
|
51906
52914
|
return v.value;
|
|
@@ -53678,6 +54686,12 @@ Error in definition of "${name}"`,
|
|
|
53678
54686
|
function _escapeJsonString(s) {
|
|
53679
54687
|
return s;
|
|
53680
54688
|
}
|
|
54689
|
+
function _serializeLatexMetadata(ce, expr2) {
|
|
54690
|
+
const syntax = ce.latexSyntax;
|
|
54691
|
+
const opts = ce.latexOptions;
|
|
54692
|
+
if (Object.keys(opts).length === 0) return syntax.serialize(expr2);
|
|
54693
|
+
return syntax.serialize(expr2, { ...opts });
|
|
54694
|
+
}
|
|
53681
54695
|
function serializeSubtract(ce, a, b, options, metadata) {
|
|
53682
54696
|
if (isNumber(a) && a.isNegative) {
|
|
53683
54697
|
const v = a.numericValue;
|
|
@@ -53982,7 +54996,7 @@ Error in definition of "${name}"`,
|
|
|
53982
54996
|
];
|
|
53983
54997
|
const md = { ...metadata ?? {} };
|
|
53984
54998
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
53985
|
-
md.latex = _escapeJsonString(md.latex ?? ce
|
|
54999
|
+
md.latex = _escapeJsonString(md.latex ?? _serializeLatexMetadata(ce, fn));
|
|
53986
55000
|
} else md.latex = "";
|
|
53987
55001
|
if (!options.metadata.includes("wikidata")) md.wikidata = "";
|
|
53988
55002
|
if (!md.latex && !md.wikidata && options.shorthands.includes("function"))
|
|
@@ -54007,7 +55021,7 @@ Error in definition of "${name}"`,
|
|
|
54007
55021
|
}
|
|
54008
55022
|
metadata = { ...metadata };
|
|
54009
55023
|
if (options.metadata.includes("latex") && ce.latexSyntax) {
|
|
54010
|
-
metadata.latex = metadata.latex ?? ce
|
|
55024
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, sym2);
|
|
54011
55025
|
if (metadata.latex !== void 0)
|
|
54012
55026
|
metadata.latex = _escapeJsonString(metadata.latex);
|
|
54013
55027
|
} else metadata.latex = void 0;
|
|
@@ -54169,7 +55183,7 @@ Error in definition of "${name}"`,
|
|
|
54169
55183
|
}
|
|
54170
55184
|
}
|
|
54171
55185
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54172
|
-
metadata.latex = metadata.latex ?? ce
|
|
55186
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, result2 ?? { num });
|
|
54173
55187
|
if (result2) {
|
|
54174
55188
|
if (metadata.latex !== void 0)
|
|
54175
55189
|
return { sym: result2, latex: metadata.latex };
|
|
@@ -54185,7 +55199,7 @@ Error in definition of "${name}"`,
|
|
|
54185
55199
|
if (value.isNaN()) {
|
|
54186
55200
|
num = "NaN";
|
|
54187
55201
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54188
|
-
metadata.latex = metadata.latex ?? ce
|
|
55202
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54189
55203
|
return metadata.latex !== void 0 ? { num, latex: metadata.latex } : { num };
|
|
54190
55204
|
}
|
|
54191
55205
|
return serializeJsonFunction(
|
|
@@ -54219,7 +55233,7 @@ Error in definition of "${name}"`,
|
|
|
54219
55233
|
value = Number(value);
|
|
54220
55234
|
} else {
|
|
54221
55235
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54222
|
-
metadata.latex = metadata.latex ?? ce
|
|
55236
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, {
|
|
54223
55237
|
num: value.toString()
|
|
54224
55238
|
});
|
|
54225
55239
|
if (metadata.latex !== void 0)
|
|
@@ -54233,7 +55247,7 @@ Error in definition of "${name}"`,
|
|
|
54233
55247
|
result = value > 0 ? "PositiveInfinity" : "NegativeInfinity";
|
|
54234
55248
|
else num = serializeRepeatingDecimals(value.toString(), options);
|
|
54235
55249
|
if (options.metadata.includes("latex") && ce.latexSyntax)
|
|
54236
|
-
metadata.latex = metadata.latex ?? ce
|
|
55250
|
+
metadata.latex = metadata.latex ?? _serializeLatexMetadata(ce, { num });
|
|
54237
55251
|
if (result) {
|
|
54238
55252
|
if (metadata.latex !== void 0)
|
|
54239
55253
|
return { sym: result, latex: metadata.latex };
|
|
@@ -54459,6 +55473,23 @@ Error in definition of "${name}"`,
|
|
|
54459
55473
|
};
|
|
54460
55474
|
return compilePair(0);
|
|
54461
55475
|
}
|
|
55476
|
+
if (h === "When") {
|
|
55477
|
+
if (args.length !== 2)
|
|
55478
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
55479
|
+
const fn2 = target.functions?.(h);
|
|
55480
|
+
if (fn2) {
|
|
55481
|
+
if (typeof fn2 === "function") {
|
|
55482
|
+
return fn2(args, (expr2) => _BaseCompiler.compile(expr2, target), target);
|
|
55483
|
+
}
|
|
55484
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
55485
|
+
}
|
|
55486
|
+
if (isSymbol2(args[1], "True"))
|
|
55487
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
55488
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
55489
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
55490
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
55491
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
55492
|
+
}
|
|
54462
55493
|
if (h === "Block") {
|
|
54463
55494
|
return _BaseCompiler.compileBlock(args, target);
|
|
54464
55495
|
}
|
|
@@ -54533,17 +55564,91 @@ Error in definition of "${name}"`,
|
|
|
54533
55564
|
)}${target.ws("\n")}})()`;
|
|
54534
55565
|
}
|
|
54535
55566
|
/**
|
|
54536
|
-
* Compile a Loop expression
|
|
54537
|
-
*
|
|
55567
|
+
* Compile a Loop expression.
|
|
55568
|
+
*
|
|
55569
|
+
* Two forms are supported:
|
|
55570
|
+
*
|
|
55571
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
55572
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
55573
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
55574
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
55575
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
55576
|
+
* references to the loop index inside the body are re-wrapped via
|
|
55577
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
54538
55578
|
*
|
|
54539
|
-
*
|
|
54540
|
-
*
|
|
54541
|
-
*
|
|
55579
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
55580
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
55581
|
+
* When two or more `Element` clauses are present — or when the single
|
|
55582
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
55583
|
+
* comprehension that collects results into an array. Each clause
|
|
55584
|
+
* produces a `for (const name of collection)` loop, nested
|
|
55585
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
55586
|
+
*
|
|
55587
|
+
* Example output (JS):
|
|
55588
|
+
* ```js
|
|
55589
|
+
* (() => { const result = [];
|
|
55590
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
55591
|
+
* return result; })()
|
|
55592
|
+
* ```
|
|
55593
|
+
*
|
|
55594
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
55595
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
55596
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
55597
|
+
* array or by unrolling when bounds are known at compile time.
|
|
54542
55598
|
*/
|
|
54543
55599
|
static compileForLoop(args, target) {
|
|
54544
55600
|
if (!args[0]) throw new Error("Loop: no body");
|
|
54545
55601
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
54546
|
-
const
|
|
55602
|
+
const body = args[0];
|
|
55603
|
+
const elements = args.slice(1);
|
|
55604
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
55605
|
+
if (useComprehension) {
|
|
55606
|
+
const lang = target.language ?? "";
|
|
55607
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
55608
|
+
throw new Error(
|
|
55609
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
55610
|
+
);
|
|
55611
|
+
}
|
|
55612
|
+
const narrowedElements = [];
|
|
55613
|
+
for (let i = 0; i < elements.length; i++) {
|
|
55614
|
+
const elem = elements[i];
|
|
55615
|
+
if (!isFunction2(elem, "Element"))
|
|
55616
|
+
throw new Error(
|
|
55617
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
55618
|
+
);
|
|
55619
|
+
if (!isSymbol2(elem.ops[0]))
|
|
55620
|
+
throw new Error(
|
|
55621
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
55622
|
+
);
|
|
55623
|
+
narrowedElements.push(elem);
|
|
55624
|
+
}
|
|
55625
|
+
const loopVarSet = new Set(
|
|
55626
|
+
narrowedElements.map(
|
|
55627
|
+
(e) => e.ops[0].symbol
|
|
55628
|
+
)
|
|
55629
|
+
);
|
|
55630
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
55631
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
55632
|
+
...target,
|
|
55633
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
55634
|
+
} : target;
|
|
55635
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
55636
|
+
let inner = `result.push(${bodyCode});`;
|
|
55637
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
55638
|
+
const elem = narrowedElements[i];
|
|
55639
|
+
const name = elem.ops[0].symbol;
|
|
55640
|
+
const collExpr = elem.ops[1];
|
|
55641
|
+
let collection;
|
|
55642
|
+
if (isFunction2(collExpr, "Range")) {
|
|
55643
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
55644
|
+
} else {
|
|
55645
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
55646
|
+
}
|
|
55647
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
55648
|
+
}
|
|
55649
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
55650
|
+
}
|
|
55651
|
+
const indexing = elements[0];
|
|
54547
55652
|
if (!isFunction2(indexing, "Element"))
|
|
54548
55653
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
54549
55654
|
const indexExpr = indexing.ops[0];
|
|
@@ -54561,13 +55666,72 @@ Error in definition of "${name}"`,
|
|
|
54561
55666
|
...target,
|
|
54562
55667
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
54563
55668
|
};
|
|
54564
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
55669
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
54565
55670
|
return `(() => {${target.ws(
|
|
54566
55671
|
"\n"
|
|
54567
55672
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
54568
55673
|
"\n"
|
|
54569
55674
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
54570
55675
|
}
|
|
55676
|
+
/**
|
|
55677
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
55678
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
55679
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
55680
|
+
*
|
|
55681
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
55682
|
+
* are not statically numeric we accept the Range (the historical
|
|
55683
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
55684
|
+
* left as a known limitation; callers can force the iterable path by
|
|
55685
|
+
* supplying an explicit step.
|
|
55686
|
+
*/
|
|
55687
|
+
static isLegacyCompatibleRange(coll) {
|
|
55688
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
55689
|
+
if (coll.ops.length >= 3) {
|
|
55690
|
+
const stepExpr = coll.ops[2];
|
|
55691
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
55692
|
+
}
|
|
55693
|
+
const lo = coll.ops[0];
|
|
55694
|
+
const hi = coll.ops[1];
|
|
55695
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
55696
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
55697
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
55698
|
+
return true;
|
|
55699
|
+
}
|
|
55700
|
+
/**
|
|
55701
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
55702
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
55703
|
+
* `library/collections.ts` Range:
|
|
55704
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
55705
|
+
* element = lo + step * k (0-indexed)
|
|
55706
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
55707
|
+
*
|
|
55708
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
55709
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
55710
|
+
*/
|
|
55711
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
55712
|
+
const loExpr = rangeExpr.ops[0];
|
|
55713
|
+
const hiExpr = rangeExpr.ops[1];
|
|
55714
|
+
const stepExpr = rangeExpr.ops[2];
|
|
55715
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
55716
|
+
const lo2 = loExpr.re;
|
|
55717
|
+
const hi2 = hiExpr.re;
|
|
55718
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
55719
|
+
if (step2 === 0) return "[]";
|
|
55720
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
55721
|
+
if (step2 === 1) {
|
|
55722
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
55723
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
55724
|
+
}
|
|
55725
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
55726
|
+
}
|
|
55727
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
55728
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
55729
|
+
if (stepExpr === void 0) {
|
|
55730
|
+
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})`;
|
|
55731
|
+
}
|
|
55732
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
55733
|
+
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})`;
|
|
55734
|
+
}
|
|
54571
55735
|
/**
|
|
54572
55736
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
54573
55737
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -54998,8 +56162,7 @@ Error in definition of "${name}"`,
|
|
|
54998
56162
|
ce.pushScope();
|
|
54999
56163
|
try {
|
|
55000
56164
|
if (vars && typeof vars === "object") {
|
|
55001
|
-
for (const [k, v] of Object.entries(vars))
|
|
55002
|
-
ce.assign(k, v);
|
|
56165
|
+
for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
|
|
55003
56166
|
}
|
|
55004
56167
|
return expr2.evaluate().re;
|
|
55005
56168
|
} finally {
|
|
@@ -60229,8 +61392,7 @@ Error in definition of "${name}"`,
|
|
|
60229
61392
|
return { re: null, im: formatFloat(iScale) };
|
|
60230
61393
|
}
|
|
60231
61394
|
const compiledFactors = remaining.map((r) => compile3(r));
|
|
60232
|
-
if (iScale !== 1)
|
|
60233
|
-
compiledFactors.unshift(formatFloat(iScale));
|
|
61395
|
+
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
60234
61396
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
60235
61397
|
return { re: null, im: imCode };
|
|
60236
61398
|
}
|
|
@@ -60834,39 +61996,130 @@ Error in definition of "${name}"`,
|
|
|
60834
61996
|
if (args.length >= 2)
|
|
60835
61997
|
return `_SYS.colormap(${compile3(args[0])}, ${compile3(args[1])})`;
|
|
60836
61998
|
return `_SYS.colormap(${compile3(args[0])})`;
|
|
61999
|
+
},
|
|
62000
|
+
// -----------------------------------------------------------------------
|
|
62001
|
+
// Color constructor heads. All compile to OKLCh arrays at runtime — the
|
|
62002
|
+
// canonical color representation in this target. The constructors take
|
|
62003
|
+
// their own colorspace's components and convert internally.
|
|
62004
|
+
// (Mirrors the GPU target's design: color values are vec3 OKLCh.)
|
|
62005
|
+
// -----------------------------------------------------------------------
|
|
62006
|
+
Rgb: (args, compile3) => {
|
|
62007
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
62008
|
+
return `_SYS.rgb(${args.map(compile3).join(", ")})`;
|
|
62009
|
+
},
|
|
62010
|
+
Hsv: (args, compile3) => {
|
|
62011
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
62012
|
+
return `_SYS.hsv(${args.map(compile3).join(", ")})`;
|
|
62013
|
+
},
|
|
62014
|
+
Hsl: (args, compile3) => {
|
|
62015
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
62016
|
+
return `_SYS.hsl(${args.map(compile3).join(", ")})`;
|
|
62017
|
+
},
|
|
62018
|
+
Oklab: (args, compile3) => {
|
|
62019
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
62020
|
+
return `_SYS.oklab(${args.map(compile3).join(", ")})`;
|
|
62021
|
+
},
|
|
62022
|
+
Oklch: (args, compile3) => {
|
|
62023
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
62024
|
+
return `_SYS.oklch(${args.map(compile3).join(", ")})`;
|
|
62025
|
+
},
|
|
62026
|
+
// -----------------------------------------------------------------------
|
|
62027
|
+
// As* converters. Compile-time output convention matches the engine and
|
|
62028
|
+
// the GPU target: each returns components in the named space as a 3- or
|
|
62029
|
+
// 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
|
|
62030
|
+
// layers). `AsOklch` is the identity (canonical form).
|
|
62031
|
+
// -----------------------------------------------------------------------
|
|
62032
|
+
AsRgb: ([c], compile3) => {
|
|
62033
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
62034
|
+
return `_SYS.asRgb(${compile3(c)})`;
|
|
62035
|
+
},
|
|
62036
|
+
AsHsv: ([c], compile3) => {
|
|
62037
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
62038
|
+
return `_SYS.asHsv(${compile3(c)})`;
|
|
62039
|
+
},
|
|
62040
|
+
AsHsl: ([c], compile3) => {
|
|
62041
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
62042
|
+
return `_SYS.asHsl(${compile3(c)})`;
|
|
62043
|
+
},
|
|
62044
|
+
AsOklab: ([c], compile3) => {
|
|
62045
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
62046
|
+
return `_SYS.asOklab(${compile3(c)})`;
|
|
62047
|
+
},
|
|
62048
|
+
AsOklch: ([c], compile3) => {
|
|
62049
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
62050
|
+
return compile3(c);
|
|
62051
|
+
},
|
|
62052
|
+
// Perceptual color difference (ΔE_OK).
|
|
62053
|
+
ColorDelta: ([a, b], compile3) => {
|
|
62054
|
+
if (a === null || b === null)
|
|
62055
|
+
throw new Error("ColorDelta: need two colors");
|
|
62056
|
+
return `_SYS.colorDelta(${compile3(a)}, ${compile3(b)})`;
|
|
62057
|
+
},
|
|
62058
|
+
// Euclidean distance between two tuples (any positive dimension).
|
|
62059
|
+
// The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
|
|
62060
|
+
// (vec-only); this JS handler works on plain arrays of any length.
|
|
62061
|
+
Distance: ([a, b], compile3) => {
|
|
62062
|
+
if (a === null || b === null) throw new Error("Distance: need two points");
|
|
62063
|
+
return `_SYS.distance(${compile3(a)}, ${compile3(b)})`;
|
|
60837
62064
|
}
|
|
60838
62065
|
};
|
|
60839
62066
|
function toRI(c) {
|
|
60840
62067
|
return { re: c.re, im: c.im };
|
|
60841
62068
|
}
|
|
62069
|
+
function normalizeAlpha2(a) {
|
|
62070
|
+
if (a === void 0) return void 0;
|
|
62071
|
+
if (!Number.isFinite(a)) return void 0;
|
|
62072
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
62073
|
+
return a;
|
|
62074
|
+
}
|
|
60842
62075
|
function toRgb255(input) {
|
|
60843
62076
|
if (typeof input === "string") {
|
|
60844
62077
|
const c = parseColor(input);
|
|
60845
|
-
|
|
62078
|
+
const rgb2 = {
|
|
60846
62079
|
r: c >>> 24 & 255,
|
|
60847
62080
|
g: c >>> 16 & 255,
|
|
60848
|
-
b: c >>> 8 & 255
|
|
60849
|
-
alpha: (c & 255) / 255
|
|
62081
|
+
b: c >>> 8 & 255
|
|
60850
62082
|
};
|
|
62083
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62084
|
+
if (alpha !== void 0) rgb2.alpha = alpha;
|
|
62085
|
+
return rgb2;
|
|
62086
|
+
}
|
|
62087
|
+
const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
|
|
62088
|
+
if (input.length >= 4) {
|
|
62089
|
+
const alpha = normalizeAlpha2(input[3]);
|
|
62090
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
60851
62091
|
}
|
|
60852
|
-
const rgb = {
|
|
60853
|
-
r: input[0] * 255,
|
|
60854
|
-
g: input[1] * 255,
|
|
60855
|
-
b: input[2] * 255
|
|
60856
|
-
};
|
|
60857
|
-
if (input.length >= 4) rgb.alpha = input[3];
|
|
60858
62092
|
return rgb;
|
|
60859
62093
|
}
|
|
60860
|
-
function
|
|
60861
|
-
|
|
60862
|
-
|
|
60863
|
-
|
|
60864
|
-
|
|
60865
|
-
|
|
62094
|
+
function toOklch2(input) {
|
|
62095
|
+
if (typeof input === "string") {
|
|
62096
|
+
const c = parseColor(input);
|
|
62097
|
+
const r = c >>> 24 & 255;
|
|
62098
|
+
const g = c >>> 16 & 255;
|
|
62099
|
+
const b = c >>> 8 & 255;
|
|
62100
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62101
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62102
|
+
if (alpha !== void 0) oklch2.alpha = alpha;
|
|
62103
|
+
return oklch2;
|
|
62104
|
+
}
|
|
62105
|
+
return {
|
|
62106
|
+
L: input[0],
|
|
62107
|
+
C: input[1],
|
|
62108
|
+
H: input[2],
|
|
62109
|
+
alpha: input.length >= 4 ? normalizeAlpha2(input[3]) : void 0
|
|
62110
|
+
};
|
|
62111
|
+
}
|
|
62112
|
+
function packedToOklch(c) {
|
|
62113
|
+
const r = c >>> 24 & 255;
|
|
62114
|
+
const g = c >>> 16 & 255;
|
|
62115
|
+
const b = c >>> 8 & 255;
|
|
62116
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
62117
|
+
const alpha = normalizeAlpha2((c & 255) / 255);
|
|
62118
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
60866
62119
|
}
|
|
60867
62120
|
var colorHelpers = {
|
|
60868
62121
|
color(input) {
|
|
60869
|
-
return
|
|
62122
|
+
return packedToOklch(parseColor(input));
|
|
60870
62123
|
},
|
|
60871
62124
|
colorToString(input, format) {
|
|
60872
62125
|
const rgb = toRgb255(input);
|
|
@@ -60877,7 +62130,7 @@ Error in definition of "${name}"`,
|
|
|
60877
62130
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
60878
62131
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
60879
62132
|
let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
60880
|
-
if (rgb.alpha !== void 0
|
|
62133
|
+
if (rgb.alpha !== void 0) {
|
|
60881
62134
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
60882
62135
|
hex += a.toString(16).padStart(2, "0");
|
|
60883
62136
|
}
|
|
@@ -60887,7 +62140,7 @@ Error in definition of "${name}"`,
|
|
|
60887
62140
|
const r = Math.round(rgb.r);
|
|
60888
62141
|
const g = Math.round(rgb.g);
|
|
60889
62142
|
const b = Math.round(rgb.b);
|
|
60890
|
-
if (rgb.alpha !== void 0
|
|
62143
|
+
if (rgb.alpha !== void 0)
|
|
60891
62144
|
return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
|
|
60892
62145
|
return `rgb(${r} ${g} ${b})`;
|
|
60893
62146
|
}
|
|
@@ -60896,7 +62149,7 @@ Error in definition of "${name}"`,
|
|
|
60896
62149
|
const h = Math.round(hsl.h * 10) / 10;
|
|
60897
62150
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
60898
62151
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
60899
|
-
if (rgb.alpha !== void 0
|
|
62152
|
+
if (rgb.alpha !== void 0)
|
|
60900
62153
|
return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
|
|
60901
62154
|
return `hsl(${h} ${s}% ${l}%)`;
|
|
60902
62155
|
}
|
|
@@ -60905,7 +62158,7 @@ Error in definition of "${name}"`,
|
|
|
60905
62158
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
60906
62159
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
60907
62160
|
const H = Math.round(c.H * 10) / 10;
|
|
60908
|
-
if (rgb.alpha !== void 0
|
|
62161
|
+
if (rgb.alpha !== void 0)
|
|
60909
62162
|
return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
|
|
60910
62163
|
return `oklch(${L} ${C} ${H})`;
|
|
60911
62164
|
}
|
|
@@ -60914,29 +62167,29 @@ Error in definition of "${name}"`,
|
|
|
60914
62167
|
}
|
|
60915
62168
|
},
|
|
60916
62169
|
colorMix(input1, input2, ratio = 0.5) {
|
|
60917
|
-
const
|
|
60918
|
-
const
|
|
62170
|
+
const c1 = toOklch2(input1);
|
|
62171
|
+
const c2 = toOklch2(input2);
|
|
60919
62172
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
60920
|
-
const
|
|
60921
|
-
const
|
|
60922
|
-
let
|
|
60923
|
-
if (
|
|
60924
|
-
if (
|
|
60925
|
-
|
|
60926
|
-
|
|
60927
|
-
|
|
60928
|
-
|
|
60929
|
-
|
|
60930
|
-
|
|
60931
|
-
H
|
|
60932
|
-
|
|
60933
|
-
|
|
60934
|
-
const
|
|
60935
|
-
const
|
|
60936
|
-
const a1 =
|
|
60937
|
-
const a2 =
|
|
60938
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
60939
|
-
return
|
|
62173
|
+
const c1Achromatic = c1.C < 1e-6;
|
|
62174
|
+
const c2Achromatic = c2.C < 1e-6;
|
|
62175
|
+
let H;
|
|
62176
|
+
if (c1Achromatic && c2Achromatic) H = c1.H;
|
|
62177
|
+
else if (c1Achromatic) H = c2.H;
|
|
62178
|
+
else if (c2Achromatic) H = c1.H;
|
|
62179
|
+
else {
|
|
62180
|
+
let dh = c2.H - c1.H;
|
|
62181
|
+
if (dh > 180) dh -= 360;
|
|
62182
|
+
if (dh < -180) dh += 360;
|
|
62183
|
+
H = c1.H + dh * ratio;
|
|
62184
|
+
if (H < 0) H += 360;
|
|
62185
|
+
if (H >= 360) H -= 360;
|
|
62186
|
+
}
|
|
62187
|
+
const L = c1.L + (c2.L - c1.L) * ratio;
|
|
62188
|
+
const C = c1.C + (c2.C - c1.C) * ratio;
|
|
62189
|
+
const a1 = c1.alpha ?? 1;
|
|
62190
|
+
const a2 = c2.alpha ?? 1;
|
|
62191
|
+
const alpha = normalizeAlpha2(a1 + (a2 - a1) * ratio);
|
|
62192
|
+
return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
|
|
60940
62193
|
},
|
|
60941
62194
|
colorContrast(bg, fg) {
|
|
60942
62195
|
return apca(toRgb255(bg), toRgb255(fg));
|
|
@@ -60944,11 +62197,11 @@ Error in definition of "${name}"`,
|
|
|
60944
62197
|
contrastingColor(bg, fg1, fg2) {
|
|
60945
62198
|
const bgRgb = toRgb255(bg);
|
|
60946
62199
|
if (fg1 !== void 0 && fg2 !== void 0) {
|
|
60947
|
-
return
|
|
62200
|
+
return packedToOklch(
|
|
60948
62201
|
contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
|
|
60949
62202
|
);
|
|
60950
62203
|
}
|
|
60951
|
-
return
|
|
62204
|
+
return packedToOklch(contrastingColor(bgRgb));
|
|
60952
62205
|
},
|
|
60953
62206
|
colorToColorspace(input, space) {
|
|
60954
62207
|
const rgb = toRgb255(input);
|
|
@@ -60977,7 +62230,7 @@ Error in definition of "${name}"`,
|
|
|
60977
62230
|
default:
|
|
60978
62231
|
throw new Error(`Unknown color space: ${space}`);
|
|
60979
62232
|
}
|
|
60980
|
-
if (alpha !== void 0
|
|
62233
|
+
if (alpha !== void 0) result.push(alpha);
|
|
60981
62234
|
return result;
|
|
60982
62235
|
},
|
|
60983
62236
|
colormap(name, arg) {
|
|
@@ -60989,7 +62242,7 @@ Error in definition of "${name}"`,
|
|
|
60989
62242
|
const palette = allPalettes[name];
|
|
60990
62243
|
if (!palette) throw new Error(`Unknown palette: ${name}`);
|
|
60991
62244
|
const colors = palette.map(
|
|
60992
|
-
(hex) =>
|
|
62245
|
+
(hex) => packedToOklch(parseColor(hex))
|
|
60993
62246
|
);
|
|
60994
62247
|
if (arg === void 0) return colors;
|
|
60995
62248
|
if (Number.isInteger(arg) && arg >= 2) {
|
|
@@ -61013,62 +62266,128 @@ Error in definition of "${name}"`,
|
|
|
61013
62266
|
const frac = pos - i;
|
|
61014
62267
|
if (frac === 0 || i >= colors.length - 1)
|
|
61015
62268
|
return [...colors[Math.min(i, colors.length - 1)]];
|
|
61016
|
-
const
|
|
61017
|
-
|
|
61018
|
-
|
|
61019
|
-
|
|
61020
|
-
|
|
61021
|
-
|
|
61022
|
-
|
|
61023
|
-
|
|
61024
|
-
|
|
61025
|
-
|
|
61026
|
-
|
|
61027
|
-
|
|
61028
|
-
|
|
61029
|
-
|
|
61030
|
-
|
|
61031
|
-
|
|
61032
|
-
|
|
61033
|
-
if (H >= 360) H -= 360;
|
|
61034
|
-
const mixed = oklchToRgb({
|
|
61035
|
-
L: c1.L + (c2.L - c1.L) * frac,
|
|
61036
|
-
C: c1.C + (c2.C - c1.C) * frac,
|
|
61037
|
-
H
|
|
61038
|
-
});
|
|
61039
|
-
return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
|
|
62269
|
+
const [L1, C1, H1] = colors[i];
|
|
62270
|
+
const [L2, C2, H2] = colors[i + 1];
|
|
62271
|
+
const c1Achromatic = C1 < 1e-6;
|
|
62272
|
+
const c2Achromatic = C2 < 1e-6;
|
|
62273
|
+
let H;
|
|
62274
|
+
if (c1Achromatic && c2Achromatic) H = H1;
|
|
62275
|
+
else if (c1Achromatic) H = H2;
|
|
62276
|
+
else if (c2Achromatic) H = H1;
|
|
62277
|
+
else {
|
|
62278
|
+
let dh = H2 - H1;
|
|
62279
|
+
if (dh > 180) dh -= 360;
|
|
62280
|
+
if (dh < -180) dh += 360;
|
|
62281
|
+
H = H1 + dh * frac;
|
|
62282
|
+
if (H < 0) H += 360;
|
|
62283
|
+
if (H >= 360) H -= 360;
|
|
62284
|
+
}
|
|
62285
|
+
return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
|
|
61040
62286
|
},
|
|
61041
62287
|
colorFromColorspace(components, space) {
|
|
61042
62288
|
const c0 = components[0];
|
|
61043
62289
|
const c1 = components[1];
|
|
61044
62290
|
const c2 = components[2];
|
|
61045
62291
|
const alpha = components.length >= 4 ? components[3] : void 0;
|
|
61046
|
-
let
|
|
62292
|
+
let oklch2;
|
|
61047
62293
|
switch (space.toLowerCase()) {
|
|
61048
62294
|
case "rgb":
|
|
61049
|
-
|
|
62295
|
+
oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
|
|
61050
62296
|
break;
|
|
61051
62297
|
case "hsl": {
|
|
61052
|
-
const
|
|
61053
|
-
|
|
62298
|
+
const rgb = hslToRgb(c0, c1, c2);
|
|
62299
|
+
oklch2 = rgbToOklch(rgb);
|
|
61054
62300
|
break;
|
|
61055
62301
|
}
|
|
61056
|
-
case "oklch":
|
|
61057
|
-
|
|
61058
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62302
|
+
case "oklch":
|
|
62303
|
+
oklch2 = { L: c0, C: c1, H: c2 };
|
|
61059
62304
|
break;
|
|
61060
|
-
}
|
|
61061
62305
|
case "oklab":
|
|
61062
|
-
case "lab":
|
|
61063
|
-
|
|
61064
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
62306
|
+
case "lab":
|
|
62307
|
+
oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
|
|
61065
62308
|
break;
|
|
61066
|
-
}
|
|
61067
62309
|
default:
|
|
61068
62310
|
throw new Error(`Unknown color space: ${space}`);
|
|
61069
62311
|
}
|
|
61070
|
-
|
|
61071
|
-
|
|
62312
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
62313
|
+
},
|
|
62314
|
+
// -----------------------------------------------------------------------
|
|
62315
|
+
// Color constructors. Each accepts components in its colorspace's natural
|
|
62316
|
+
// units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
|
|
62317
|
+
// -----------------------------------------------------------------------
|
|
62318
|
+
rgb(r, g, b, alpha) {
|
|
62319
|
+
const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
|
|
62320
|
+
const a = normalizeAlpha2(alpha);
|
|
62321
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62322
|
+
},
|
|
62323
|
+
hsv(h, s, v, alpha) {
|
|
62324
|
+
const rgb = hsvToRgb(h, s, v);
|
|
62325
|
+
const c = rgbToOklch(rgb);
|
|
62326
|
+
const a = normalizeAlpha2(alpha);
|
|
62327
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62328
|
+
},
|
|
62329
|
+
hsl(h, s, l, alpha) {
|
|
62330
|
+
const rgb = hslToRgb(h, s, l);
|
|
62331
|
+
const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
|
|
62332
|
+
const a = normalizeAlpha2(alpha);
|
|
62333
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
62334
|
+
},
|
|
62335
|
+
oklab(L, a, b, alpha) {
|
|
62336
|
+
const c = oklabToOklch({ L, a, b });
|
|
62337
|
+
const al = normalizeAlpha2(alpha);
|
|
62338
|
+
return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
|
|
62339
|
+
},
|
|
62340
|
+
oklch(L, C, H, alpha) {
|
|
62341
|
+
const a = normalizeAlpha2(alpha);
|
|
62342
|
+
return a !== void 0 ? [L, C, H, a] : [L, C, H];
|
|
62343
|
+
},
|
|
62344
|
+
// -----------------------------------------------------------------------
|
|
62345
|
+
// As* converters. Inputs are anything `toOklch` accepts (string, packed
|
|
62346
|
+
// int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
|
|
62347
|
+
// space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
|
|
62348
|
+
// consistency with the GPU target's shader convention.
|
|
62349
|
+
// -----------------------------------------------------------------------
|
|
62350
|
+
asRgb(input) {
|
|
62351
|
+
const rgb = toRgb255(input);
|
|
62352
|
+
const r = rgb.r / 255;
|
|
62353
|
+
const g = rgb.g / 255;
|
|
62354
|
+
const b = rgb.b / 255;
|
|
62355
|
+
return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
|
|
62356
|
+
},
|
|
62357
|
+
asHsv(input) {
|
|
62358
|
+
const rgb = toRgb255(input);
|
|
62359
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
62360
|
+
return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
|
|
62361
|
+
},
|
|
62362
|
+
asHsl(input) {
|
|
62363
|
+
const rgb = toRgb255(input);
|
|
62364
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
62365
|
+
return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
|
|
62366
|
+
},
|
|
62367
|
+
asOklab(input) {
|
|
62368
|
+
const c = toOklch2(input);
|
|
62369
|
+
const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
|
|
62370
|
+
return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
|
|
62371
|
+
},
|
|
62372
|
+
// asOklch is identity — handled at compile time as a pass-through
|
|
62373
|
+
// Perceptual color difference (ΔE_OK).
|
|
62374
|
+
colorDelta(a, b) {
|
|
62375
|
+
const labA = oklchToOklab(toOklch2(a));
|
|
62376
|
+
const labB = oklchToOklab(toOklch2(b));
|
|
62377
|
+
return oklabDeltaE(labA, labB);
|
|
62378
|
+
},
|
|
62379
|
+
// Euclidean distance between two tuples. Plain numeric — not a color
|
|
62380
|
+
// operation despite living in the same helpers block.
|
|
62381
|
+
distance(a, b) {
|
|
62382
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
62383
|
+
throw new Error("Distance: expected two arrays");
|
|
62384
|
+
if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
|
|
62385
|
+
let sumSq = 0;
|
|
62386
|
+
for (let i = 0; i < a.length; i++) {
|
|
62387
|
+
const d = a[i] - b[i];
|
|
62388
|
+
sumSq += d * d;
|
|
62389
|
+
}
|
|
62390
|
+
return Math.sqrt(sumSq);
|
|
61072
62391
|
}
|
|
61073
62392
|
};
|
|
61074
62393
|
var SYS_HELPERS = {
|
|
@@ -61507,6 +62826,13 @@ Error in definition of "${name}"`,
|
|
|
61507
62826
|
function gpuVec2(target) {
|
|
61508
62827
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
61509
62828
|
}
|
|
62829
|
+
function gpuVec3(target) {
|
|
62830
|
+
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
62831
|
+
}
|
|
62832
|
+
function readStringLiteral(expr2) {
|
|
62833
|
+
if (!isString(expr2)) return null;
|
|
62834
|
+
return expr2.string?.toLowerCase() ?? null;
|
|
62835
|
+
}
|
|
61510
62836
|
function compileIntArg(expr2, compile3, target) {
|
|
61511
62837
|
const c = tryGetConstant(expr2);
|
|
61512
62838
|
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
@@ -61565,7 +62891,7 @@ Error in definition of "${name}"`,
|
|
|
61565
62891
|
`for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
|
|
61566
62892
|
` ${acc} ${op}= ${body};`,
|
|
61567
62893
|
`}`,
|
|
61568
|
-
`return ${acc}
|
|
62894
|
+
`return ${acc};`
|
|
61569
62895
|
];
|
|
61570
62896
|
return lines.join("\n");
|
|
61571
62897
|
}
|
|
@@ -61619,8 +62945,7 @@ Error in definition of "${name}"`,
|
|
|
61619
62945
|
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
61620
62946
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
61621
62947
|
const v2 = gpuVec2(target);
|
|
61622
|
-
if (realFactors.length === 0)
|
|
61623
|
-
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
62948
|
+
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
61624
62949
|
const factors = realFactors.map((f) => compile3(f));
|
|
61625
62950
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
61626
62951
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
@@ -61673,8 +62998,7 @@ Error in definition of "${name}"`,
|
|
|
61673
62998
|
if (isNumber(x) && x.im !== 0) {
|
|
61674
62999
|
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
61675
63000
|
}
|
|
61676
|
-
if (isSymbol2(x, "ImaginaryUnit"))
|
|
61677
|
-
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
63001
|
+
if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
61678
63002
|
return `(-${compile3(x)})`;
|
|
61679
63003
|
},
|
|
61680
63004
|
// Standard math functions with complex dispatch
|
|
@@ -62047,17 +63371,127 @@ Error in definition of "${name}"`,
|
|
|
62047
63371
|
}
|
|
62048
63372
|
const isWGSL = target?.language === "wgsl";
|
|
62049
63373
|
const v3 = isWGSL ? "vec3f" : "vec3";
|
|
62050
|
-
|
|
63374
|
+
const black = `${v3}(0.0)`;
|
|
63375
|
+
const white = `${v3}(1.0, 0.0, 0.0)`;
|
|
63376
|
+
return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
|
|
62051
63377
|
},
|
|
62052
63378
|
ColorToColorspace: ([color, space], compile3) => {
|
|
62053
63379
|
if (color === null || space === null)
|
|
62054
63380
|
throw new Error("ColorToColorspace: need color and space");
|
|
62055
|
-
|
|
63381
|
+
const spaceName = readStringLiteral(space);
|
|
63382
|
+
if (spaceName === null)
|
|
63383
|
+
throw new Error("ColorToColorspace: space must be a string literal");
|
|
63384
|
+
const c = compile3(color);
|
|
63385
|
+
switch (spaceName) {
|
|
63386
|
+
case "oklch":
|
|
63387
|
+
return c;
|
|
63388
|
+
case "oklab":
|
|
63389
|
+
case "lab":
|
|
63390
|
+
return `_gpu_oklch_to_oklab(${c})`;
|
|
63391
|
+
case "rgb":
|
|
63392
|
+
return `_gpu_oklch_to_srgb(${c})`;
|
|
63393
|
+
case "hsl":
|
|
63394
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
|
|
63395
|
+
case "hsv":
|
|
63396
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
|
|
63397
|
+
default:
|
|
63398
|
+
throw new Error(
|
|
63399
|
+
`ColorToColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63400
|
+
);
|
|
63401
|
+
}
|
|
62056
63402
|
},
|
|
62057
63403
|
ColorFromColorspace: ([components, space], compile3) => {
|
|
62058
63404
|
if (components === null || space === null)
|
|
62059
63405
|
throw new Error("ColorFromColorspace: need components and space");
|
|
62060
|
-
|
|
63406
|
+
const spaceName = readStringLiteral(space);
|
|
63407
|
+
if (spaceName === null)
|
|
63408
|
+
throw new Error("ColorFromColorspace: space must be a string literal");
|
|
63409
|
+
const c = compile3(components);
|
|
63410
|
+
switch (spaceName) {
|
|
63411
|
+
case "oklch":
|
|
63412
|
+
return c;
|
|
63413
|
+
case "oklab":
|
|
63414
|
+
case "lab":
|
|
63415
|
+
return `_gpu_oklab_to_oklch(${c})`;
|
|
63416
|
+
case "rgb":
|
|
63417
|
+
return `_gpu_srgb_to_oklch(${c})`;
|
|
63418
|
+
case "hsl":
|
|
63419
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
|
|
63420
|
+
case "hsv":
|
|
63421
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
|
|
63422
|
+
default:
|
|
63423
|
+
throw new Error(
|
|
63424
|
+
`ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
|
|
63425
|
+
);
|
|
63426
|
+
}
|
|
63427
|
+
},
|
|
63428
|
+
// ---------------------------------------------------------------------------
|
|
63429
|
+
// Color literals. Each typed head compiles to a canonical OKLCh vec3.
|
|
63430
|
+
// Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
|
|
63431
|
+
// alpha as a separate uniform if it's needed at the framebuffer boundary.
|
|
63432
|
+
// ---------------------------------------------------------------------------
|
|
63433
|
+
Color: ([s], _compile2, target) => {
|
|
63434
|
+
if (s === null) throw new Error("Color: no argument");
|
|
63435
|
+
const str = readStringLiteral(s);
|
|
63436
|
+
if (str === null)
|
|
63437
|
+
throw new Error("Color: argument must be a string literal on GPU target");
|
|
63438
|
+
const packed = parseColor(str);
|
|
63439
|
+
if (packed === 0 && str.trim().toLowerCase() !== "transparent")
|
|
63440
|
+
throw new Error(`Color: invalid color string "${str}"`);
|
|
63441
|
+
const r = packed >>> 24 & 255;
|
|
63442
|
+
const g = packed >>> 16 & 255;
|
|
63443
|
+
const b = packed >>> 8 & 255;
|
|
63444
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
63445
|
+
return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
|
|
63446
|
+
},
|
|
63447
|
+
Rgb: (args, compile3, target) => {
|
|
63448
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
63449
|
+
const v3 = gpuVec3(target);
|
|
63450
|
+
return `_gpu_srgb_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63451
|
+
},
|
|
63452
|
+
Hsv: (args, compile3, target) => {
|
|
63453
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
63454
|
+
const v3 = gpuVec3(target);
|
|
63455
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63456
|
+
},
|
|
63457
|
+
Hsl: (args, compile3, target) => {
|
|
63458
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
63459
|
+
const v3 = gpuVec3(target);
|
|
63460
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})))`;
|
|
63461
|
+
},
|
|
63462
|
+
Oklab: (args, compile3, target) => {
|
|
63463
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
63464
|
+
const v3 = gpuVec3(target);
|
|
63465
|
+
return `_gpu_oklab_to_oklch(${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])}))`;
|
|
63466
|
+
},
|
|
63467
|
+
Oklch: (args, compile3, target) => {
|
|
63468
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
63469
|
+
const v3 = gpuVec3(target);
|
|
63470
|
+
return `${v3}(${compile3(args[0])}, ${compile3(args[1])}, ${compile3(args[2])})`;
|
|
63471
|
+
},
|
|
63472
|
+
// ---------------------------------------------------------------------------
|
|
63473
|
+
// As* operators. AsOklch is identity (canonical). The other As* return
|
|
63474
|
+
// components in the named space, equivalent to ColorToColorspace(c, 'x').
|
|
63475
|
+
// ---------------------------------------------------------------------------
|
|
63476
|
+
AsOklch: ([c], compile3) => {
|
|
63477
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
63478
|
+
return compile3(c);
|
|
63479
|
+
},
|
|
63480
|
+
AsOklab: ([c], compile3) => {
|
|
63481
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
63482
|
+
return `_gpu_oklch_to_oklab(${compile3(c)})`;
|
|
63483
|
+
},
|
|
63484
|
+
AsRgb: ([c], compile3) => {
|
|
63485
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
63486
|
+
return `_gpu_oklch_to_srgb(${compile3(c)})`;
|
|
63487
|
+
},
|
|
63488
|
+
AsHsv: ([c], compile3) => {
|
|
63489
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
63490
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
63491
|
+
},
|
|
63492
|
+
AsHsl: ([c], compile3) => {
|
|
63493
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
63494
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile3(c)}))`;
|
|
62061
63495
|
},
|
|
62062
63496
|
// Fractal functions
|
|
62063
63497
|
Mandelbrot: ([c, maxIter], compile3, target) => {
|
|
@@ -62750,28 +64184,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
|
|
|
62750
64184
|
|
|
62751
64185
|
vec3 _gpu_oklab_to_oklch(vec3 lab) {
|
|
62752
64186
|
float C = length(lab.yz);
|
|
62753
|
-
float H = atan(lab.z, lab.y);
|
|
64187
|
+
float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64188
|
+
if (H < 0.0) H += 360.0;
|
|
62754
64189
|
return vec3(lab.x, C, H);
|
|
62755
64190
|
}
|
|
62756
64191
|
|
|
62757
64192
|
vec3 _gpu_oklch_to_oklab(vec3 lch) {
|
|
62758
|
-
|
|
64193
|
+
float h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64194
|
+
return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64195
|
+
}
|
|
64196
|
+
|
|
64197
|
+
vec3 _gpu_srgb_to_oklch(vec3 rgb) {
|
|
64198
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
62759
64199
|
}
|
|
62760
64200
|
|
|
62761
|
-
vec3
|
|
62762
|
-
|
|
62763
|
-
|
|
64201
|
+
vec3 _gpu_oklch_to_srgb(vec3 lch) {
|
|
64202
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64203
|
+
}
|
|
64204
|
+
|
|
64205
|
+
// HSL conversion. Hue in degrees, saturation/lightness in 0-1.
|
|
64206
|
+
vec3 _gpu_hsl_to_rgb(vec3 hsl) {
|
|
64207
|
+
float h = hsl.x;
|
|
64208
|
+
float s = hsl.y;
|
|
64209
|
+
float l = hsl.z;
|
|
64210
|
+
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64211
|
+
float h6 = h / 60.0;
|
|
64212
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64213
|
+
float r = 0.0;
|
|
64214
|
+
float g = 0.0;
|
|
64215
|
+
float b = 0.0;
|
|
64216
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64217
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64218
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64219
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64220
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64221
|
+
else { r = c; g = 0.0; b = x; }
|
|
64222
|
+
float m = l - c / 2.0;
|
|
64223
|
+
return vec3(r + m, g + m, b + m);
|
|
64224
|
+
}
|
|
64225
|
+
|
|
64226
|
+
vec3 _gpu_rgb_to_hsl(vec3 rgb) {
|
|
64227
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64228
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64229
|
+
float l = (maxc + minc) / 2.0;
|
|
64230
|
+
float d = maxc - minc;
|
|
64231
|
+
if (d < 1e-6) return vec3(0.0, 0.0, l);
|
|
64232
|
+
float s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64233
|
+
float h;
|
|
64234
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64235
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64236
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64237
|
+
h *= 60.0;
|
|
64238
|
+
if (h < 0.0) h += 360.0;
|
|
64239
|
+
return vec3(h, s, l);
|
|
64240
|
+
}
|
|
64241
|
+
|
|
64242
|
+
// HSV conversion. Hue in degrees, saturation/value in 0-1.
|
|
64243
|
+
vec3 _gpu_hsv_to_rgb(vec3 hsv) {
|
|
64244
|
+
float h = hsv.x;
|
|
64245
|
+
float s = hsv.y;
|
|
64246
|
+
float v = hsv.z;
|
|
64247
|
+
float c = v * s;
|
|
64248
|
+
float h6 = h / 60.0;
|
|
64249
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
64250
|
+
float r = 0.0;
|
|
64251
|
+
float g = 0.0;
|
|
64252
|
+
float b = 0.0;
|
|
64253
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64254
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64255
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64256
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64257
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64258
|
+
else { r = c; g = 0.0; b = x; }
|
|
64259
|
+
float m = v - c;
|
|
64260
|
+
return vec3(r + m, g + m, b + m);
|
|
64261
|
+
}
|
|
64262
|
+
|
|
64263
|
+
vec3 _gpu_rgb_to_hsv(vec3 rgb) {
|
|
64264
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64265
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64266
|
+
float v = maxc;
|
|
64267
|
+
float d = maxc - minc;
|
|
64268
|
+
if (d < 1e-6) return vec3(0.0, 0.0, v);
|
|
64269
|
+
float s = (maxc < 1e-6) ? 0.0 : d / maxc;
|
|
64270
|
+
float h;
|
|
64271
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
64272
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
64273
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
64274
|
+
h *= 60.0;
|
|
64275
|
+
if (h < 0.0) h += 360.0;
|
|
64276
|
+
return vec3(h, s, v);
|
|
64277
|
+
}
|
|
64278
|
+
|
|
64279
|
+
vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
|
|
62764
64280
|
float L = mix(lch1.x, lch2.x, t);
|
|
62765
64281
|
float C = mix(lch1.y, lch2.y, t);
|
|
62766
|
-
|
|
62767
|
-
|
|
62768
|
-
|
|
62769
|
-
if (
|
|
62770
|
-
|
|
62771
|
-
|
|
64282
|
+
bool a1 = lch1.y < 1e-6;
|
|
64283
|
+
bool a2 = lch2.y < 1e-6;
|
|
64284
|
+
float H;
|
|
64285
|
+
if (a1 && a2) {
|
|
64286
|
+
H = lch1.z;
|
|
64287
|
+
} else if (a1) {
|
|
64288
|
+
H = lch2.z;
|
|
64289
|
+
} else if (a2) {
|
|
64290
|
+
H = lch1.z;
|
|
64291
|
+
} else {
|
|
64292
|
+
float dh = lch2.z - lch1.z;
|
|
64293
|
+
if (dh > 180.0) dh -= 360.0;
|
|
64294
|
+
if (dh < -180.0) dh += 360.0;
|
|
64295
|
+
H = lch1.z + dh * t;
|
|
64296
|
+
if (H < 0.0) H += 360.0;
|
|
64297
|
+
if (H >= 360.0) H -= 360.0;
|
|
64298
|
+
}
|
|
64299
|
+
return vec3(L, C, H);
|
|
62772
64300
|
}
|
|
62773
64301
|
|
|
62774
|
-
float _gpu_apca(vec3
|
|
64302
|
+
float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
|
|
64303
|
+
vec3 bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64304
|
+
vec3 fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62775
64305
|
float bgR = _gpu_srgb_to_linear(bg.x);
|
|
62776
64306
|
float bgG = _gpu_srgb_to_linear(bg.y);
|
|
62777
64307
|
float bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -62782,9 +64312,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
|
|
|
62782
64312
|
float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
|
|
62783
64313
|
float bgC = pow(bgY, 0.56);
|
|
62784
64314
|
float fgC = pow(fgY, 0.57);
|
|
62785
|
-
float contrast = (bgC
|
|
62786
|
-
? (bgC - fgC) * 1.14
|
|
62787
|
-
: (bgC - fgC) * 1.14;
|
|
64315
|
+
float contrast = (bgC - fgC) * 1.14;
|
|
62788
64316
|
return contrast * 100.0;
|
|
62789
64317
|
}
|
|
62790
64318
|
`;
|
|
@@ -62828,28 +64356,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
|
|
|
62828
64356
|
|
|
62829
64357
|
fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
|
|
62830
64358
|
let C = length(lab.yz);
|
|
62831
|
-
|
|
64359
|
+
var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
64360
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
62832
64361
|
return vec3f(lab.x, C, H);
|
|
62833
64362
|
}
|
|
62834
64363
|
|
|
62835
64364
|
fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
|
|
62836
|
-
|
|
64365
|
+
let h_rad = lch.z * (3.14159265359 / 180.0);
|
|
64366
|
+
return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
64367
|
+
}
|
|
64368
|
+
|
|
64369
|
+
fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
|
|
64370
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
64371
|
+
}
|
|
64372
|
+
|
|
64373
|
+
fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
|
|
64374
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
64375
|
+
}
|
|
64376
|
+
|
|
64377
|
+
fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
|
|
64378
|
+
let h = hsl.x;
|
|
64379
|
+
let s = hsl.y;
|
|
64380
|
+
let l = hsl.z;
|
|
64381
|
+
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
64382
|
+
let h6 = h / 60.0;
|
|
64383
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64384
|
+
var r: f32 = 0.0;
|
|
64385
|
+
var g: f32 = 0.0;
|
|
64386
|
+
var b: f32 = 0.0;
|
|
64387
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64388
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64389
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64390
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64391
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64392
|
+
else { r = c; g = 0.0; b = x; }
|
|
64393
|
+
let m = l - c / 2.0;
|
|
64394
|
+
return vec3f(r + m, g + m, b + m);
|
|
62837
64395
|
}
|
|
62838
64396
|
|
|
62839
|
-
fn
|
|
62840
|
-
let
|
|
62841
|
-
let
|
|
64397
|
+
fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
|
|
64398
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64399
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64400
|
+
let l = (maxc + minc) / 2.0;
|
|
64401
|
+
let d = maxc - minc;
|
|
64402
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
|
|
64403
|
+
let s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
64404
|
+
var h: f32;
|
|
64405
|
+
if (maxc == rgb.x) {
|
|
64406
|
+
let v = (rgb.y - rgb.z) / d;
|
|
64407
|
+
h = v - 6.0 * floor(v / 6.0);
|
|
64408
|
+
} else if (maxc == rgb.y) {
|
|
64409
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64410
|
+
} else {
|
|
64411
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64412
|
+
}
|
|
64413
|
+
h = h * 60.0;
|
|
64414
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64415
|
+
return vec3f(h, s, l);
|
|
64416
|
+
}
|
|
64417
|
+
|
|
64418
|
+
fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
|
|
64419
|
+
let h = hsv.x;
|
|
64420
|
+
let s = hsv.y;
|
|
64421
|
+
let v = hsv.z;
|
|
64422
|
+
let c = v * s;
|
|
64423
|
+
let h6 = h / 60.0;
|
|
64424
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
64425
|
+
var r: f32 = 0.0;
|
|
64426
|
+
var g: f32 = 0.0;
|
|
64427
|
+
var b: f32 = 0.0;
|
|
64428
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
64429
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
64430
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
64431
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
64432
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
64433
|
+
else { r = c; g = 0.0; b = x; }
|
|
64434
|
+
let m = v - c;
|
|
64435
|
+
return vec3f(r + m, g + m, b + m);
|
|
64436
|
+
}
|
|
64437
|
+
|
|
64438
|
+
fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
|
|
64439
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
64440
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
64441
|
+
let v = maxc;
|
|
64442
|
+
let d = maxc - minc;
|
|
64443
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
|
|
64444
|
+
var s: f32 = 0.0;
|
|
64445
|
+
if (maxc >= 1e-6) { s = d / maxc; }
|
|
64446
|
+
var h: f32;
|
|
64447
|
+
if (maxc == rgb.x) {
|
|
64448
|
+
let q = (rgb.y - rgb.z) / d;
|
|
64449
|
+
h = q - 6.0 * floor(q / 6.0);
|
|
64450
|
+
} else if (maxc == rgb.y) {
|
|
64451
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
64452
|
+
} else {
|
|
64453
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
64454
|
+
}
|
|
64455
|
+
h = h * 60.0;
|
|
64456
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
64457
|
+
return vec3f(h, s, v);
|
|
64458
|
+
}
|
|
64459
|
+
|
|
64460
|
+
fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
|
|
62842
64461
|
let L = mix(lch1.x, lch2.x, t);
|
|
62843
64462
|
let C = mix(lch1.y, lch2.y, t);
|
|
62844
|
-
let
|
|
62845
|
-
|
|
62846
|
-
|
|
62847
|
-
if (
|
|
62848
|
-
|
|
62849
|
-
|
|
64463
|
+
let a1 = lch1.y < 1e-6;
|
|
64464
|
+
let a2 = lch2.y < 1e-6;
|
|
64465
|
+
var H: f32;
|
|
64466
|
+
if (a1 && a2) {
|
|
64467
|
+
H = lch1.z;
|
|
64468
|
+
} else if (a1) {
|
|
64469
|
+
H = lch2.z;
|
|
64470
|
+
} else if (a2) {
|
|
64471
|
+
H = lch1.z;
|
|
64472
|
+
} else {
|
|
64473
|
+
var dh = lch2.z - lch1.z;
|
|
64474
|
+
if (dh > 180.0) { dh = dh - 360.0; }
|
|
64475
|
+
if (dh < -180.0) { dh = dh + 360.0; }
|
|
64476
|
+
H = lch1.z + dh * t;
|
|
64477
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
64478
|
+
if (H >= 360.0) { H = H - 360.0; }
|
|
64479
|
+
}
|
|
64480
|
+
return vec3f(L, C, H);
|
|
62850
64481
|
}
|
|
62851
64482
|
|
|
62852
|
-
fn _gpu_apca(
|
|
64483
|
+
fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
64484
|
+
let bg = _gpu_oklch_to_srgb(lch_bg);
|
|
64485
|
+
let fg = _gpu_oklch_to_srgb(lch_fg);
|
|
62853
64486
|
let bgR = _gpu_srgb_to_linear(bg.x);
|
|
62854
64487
|
let bgG = _gpu_srgb_to_linear(bg.y);
|
|
62855
64488
|
let bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -63137,7 +64770,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
63137
64770
|
if (stmts.length === 0) return "";
|
|
63138
64771
|
const last = stmts.length - 1;
|
|
63139
64772
|
stmts[last] = `return ${stmts[last]}`;
|
|
63140
|
-
return stmts.join(";\n");
|
|
64773
|
+
return stmts.join(";\n") + ";";
|
|
63141
64774
|
},
|
|
63142
64775
|
...options
|
|
63143
64776
|
};
|
|
@@ -63236,7 +64869,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
63236
64869
|
if (body.includes("\n")) {
|
|
63237
64870
|
const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
|
|
63238
64871
|
return `${returnType} ${functionName}(${params}) {
|
|
63239
|
-
${indented}
|
|
64872
|
+
${indented}
|
|
63240
64873
|
}`;
|
|
63241
64874
|
}
|
|
63242
64875
|
return `${returnType} ${functionName}(${params}) {
|
|
@@ -63347,7 +64980,7 @@ ${indented};
|
|
|
63347
64980
|
return `fn ${functionName}(${params}) -> ${toWGSLType(
|
|
63348
64981
|
returnType
|
|
63349
64982
|
)} {
|
|
63350
|
-
${indented}
|
|
64983
|
+
${indented}
|
|
63351
64984
|
}`;
|
|
63352
64985
|
}
|
|
63353
64986
|
return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
|
|
@@ -67754,6 +69387,7 @@ ${code}`;
|
|
|
67754
69387
|
this.pushScope(void 0, "global");
|
|
67755
69388
|
this._compilationTargets.registerDefaults();
|
|
67756
69389
|
if (options?.latexSyntax) this._latexSyntax = options.latexSyntax;
|
|
69390
|
+
if (options?.latexOptions) this._latexOptions = { ...options.latexOptions };
|
|
67757
69391
|
hidePrivateProperties(this);
|
|
67758
69392
|
}
|
|
67759
69393
|
toJSON() {
|
|
@@ -68168,6 +69802,15 @@ ${code}`;
|
|
|
68168
69802
|
lookupDefinition(id) {
|
|
68169
69803
|
return lookupDefinition(this, id);
|
|
68170
69804
|
}
|
|
69805
|
+
operatorInfo(head) {
|
|
69806
|
+
const def = this.lookupDefinition(head);
|
|
69807
|
+
if (!def || !isOperatorDef(def)) return void 0;
|
|
69808
|
+
const op = def.operator;
|
|
69809
|
+
return {
|
|
69810
|
+
kind: op.evaluate || op.collection ? "function" : "opaque",
|
|
69811
|
+
signature: op.signature
|
|
69812
|
+
};
|
|
69813
|
+
}
|
|
68171
69814
|
/**
|
|
68172
69815
|
* Associate a new definition to a symbol in the current context.
|
|
68173
69816
|
*
|
|
@@ -68414,6 +70057,29 @@ ${code}`;
|
|
|
68414
70057
|
);
|
|
68415
70058
|
return this._latexSyntax;
|
|
68416
70059
|
}
|
|
70060
|
+
/** @internal Engine-wide LaTeX parse/serialize options (e.g. decimalSeparator).
|
|
70061
|
+
* Merged into every `parse()` and `toLatex()` call between the LatexSyntax
|
|
70062
|
+
* instance defaults and any per-call overrides. */
|
|
70063
|
+
_latexOptions = {};
|
|
70064
|
+
/** Engine-wide LaTeX parse/serialize options.
|
|
70065
|
+
*
|
|
70066
|
+
* These options are merged into every `parse()` and `toLatex()` call.
|
|
70067
|
+
* Precedence (most-specific wins):
|
|
70068
|
+
* 1. LatexSyntax instance defaults (set at its construction)
|
|
70069
|
+
* 2. `ce.latexOptions` (this property)
|
|
70070
|
+
* 3. Per-call options passed to `ce.parse()` / `expr.toLatex()`
|
|
70071
|
+
*
|
|
70072
|
+
* Assigning replaces the whole bag. Use spread to merge:
|
|
70073
|
+
* ```ts
|
|
70074
|
+
* ce.latexOptions = { ...ce.latexOptions, decimalSeparator: '{,}' };
|
|
70075
|
+
* ```
|
|
70076
|
+
*/
|
|
70077
|
+
get latexOptions() {
|
|
70078
|
+
return this._latexOptions;
|
|
70079
|
+
}
|
|
70080
|
+
set latexOptions(options) {
|
|
70081
|
+
this._latexOptions = { ...options };
|
|
70082
|
+
}
|
|
68417
70083
|
parse(latex, options) {
|
|
68418
70084
|
if (latex === null || latex === void 0) return null;
|
|
68419
70085
|
if (typeof latex !== "string")
|
|
@@ -68421,7 +70087,6 @@ ${code}`;
|
|
|
68421
70087
|
const syntax = this._requireLatexSyntax();
|
|
68422
70088
|
const { form, ...parseOpts } = options ?? {};
|
|
68423
70089
|
const result = syntax.parse(latex, {
|
|
68424
|
-
decimalSeparator: ".",
|
|
68425
70090
|
getSymbolType: (id) => {
|
|
68426
70091
|
const def = this.lookupDefinition(id);
|
|
68427
70092
|
if (!def) return BoxedType.unknown;
|
|
@@ -68433,6 +70098,8 @@ ${code}`;
|
|
|
68433
70098
|
const def = this.lookupDefinition(id);
|
|
68434
70099
|
return !!(isValueDef(def) && def.value.subscriptEvaluate);
|
|
68435
70100
|
},
|
|
70101
|
+
tolerance: this.tolerance,
|
|
70102
|
+
...this._latexOptions,
|
|
68436
70103
|
...parseOpts
|
|
68437
70104
|
});
|
|
68438
70105
|
if (result === null) return null;
|
|
@@ -68596,14 +70263,14 @@ ${code}`;
|
|
|
68596
70263
|
_setDefaultEngineFactory(() => new ComputeEngine());
|
|
68597
70264
|
|
|
68598
70265
|
// src/compute-engine.ts
|
|
68599
|
-
var version = "0.
|
|
70266
|
+
var version = "0.57.0";
|
|
68600
70267
|
ComputeEngine._latexSyntaxFactory = () => new LatexSyntax();
|
|
68601
70268
|
_setDefaultEngineFactory(
|
|
68602
70269
|
() => new ComputeEngine({ latexSyntax: new LatexSyntax() })
|
|
68603
70270
|
);
|
|
68604
70271
|
globalThis[/* @__PURE__ */ Symbol.for("io.cortexjs.compute-engine")] = {
|
|
68605
70272
|
ComputeEngine: ComputeEngine.prototype.constructor,
|
|
68606
|
-
version: "0.
|
|
70273
|
+
version: "0.57.0"
|
|
68607
70274
|
};
|
|
68608
70275
|
return __toCommonJS(compute_engine_exports);
|
|
68609
70276
|
})();
|