@cortex-js/compute-engine 0.55.6 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compile.esm.js +1224 -179
- package/dist/compile.min.esm.js +290 -91
- package/dist/compile.min.umd.cjs +291 -92
- package/dist/compile.umd.cjs +1224 -179
- package/dist/compute-engine.esm.js +1973 -306
- package/dist/compute-engine.min.esm.js +301 -102
- package/dist/compute-engine.min.umd.cjs +301 -102
- package/dist/compute-engine.umd.cjs +1973 -306
- package/dist/core.esm.js +1972 -305
- package/dist/core.min.esm.js +300 -101
- package/dist/core.min.umd.cjs +300 -101
- package/dist/core.umd.cjs +1972 -305
- package/dist/interval.esm.js +360 -19
- package/dist/interval.min.esm.js +6 -6
- package/dist/interval.min.umd.cjs +6 -6
- package/dist/interval.umd.cjs +360 -19
- package/dist/latex-syntax.esm.js +427 -25
- package/dist/latex-syntax.min.esm.js +7 -7
- package/dist/latex-syntax.min.umd.cjs +7 -7
- package/dist/latex-syntax.umd.cjs +427 -25
- package/dist/math-json.esm.js +2 -2
- package/dist/math-json.min.esm.js +2 -2
- package/dist/math-json.min.umd.cjs +2 -2
- package/dist/math-json.umd.cjs +2 -2
- package/dist/numerics.esm.js +4 -2
- package/dist/numerics.min.esm.js +3 -3
- package/dist/numerics.min.umd.cjs +3 -3
- package/dist/numerics.umd.cjs +4 -2
- package/dist/types/big-decimal/big-decimal.d.ts +1 -1
- package/dist/types/big-decimal/index.d.ts +1 -1
- package/dist/types/big-decimal/transcendentals.d.ts +1 -1
- package/dist/types/big-decimal/utils.d.ts +1 -1
- package/dist/types/common/ansi-codes.d.ts +1 -1
- package/dist/types/common/configuration-change.d.ts +1 -1
- package/dist/types/common/fuzzy-string-match.d.ts +1 -1
- package/dist/types/common/grapheme-splitter.d.ts +1 -1
- package/dist/types/common/interruptible.d.ts +1 -1
- package/dist/types/common/one-of.d.ts +1 -1
- package/dist/types/common/signals.d.ts +1 -1
- package/dist/types/common/type/ast-nodes.d.ts +1 -1
- package/dist/types/common/type/boxed-type.d.ts +1 -1
- package/dist/types/common/type/lexer.d.ts +1 -1
- package/dist/types/common/type/parse.d.ts +1 -1
- package/dist/types/common/type/parser.d.ts +1 -1
- package/dist/types/common/type/primitive.d.ts +1 -1
- package/dist/types/common/type/reduce.d.ts +1 -1
- package/dist/types/common/type/serialize.d.ts +1 -1
- package/dist/types/common/type/subtype.d.ts +1 -1
- package/dist/types/common/type/type-builder.d.ts +1 -1
- package/dist/types/common/type/types.d.ts +2 -2
- package/dist/types/common/type/utils.d.ts +1 -1
- package/dist/types/common/utils.d.ts +1 -1
- package/dist/types/compile.d.ts +1 -1
- package/dist/types/compute-engine/assume.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +6 -1
- package/dist/types/compute-engine/boxed-expression/apply.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-add.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-mul-div.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/arithmetic-power.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/ascii-math.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-operator-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-tensor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/boxed-value-definition.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/cache.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/canonical.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/compare.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/constants.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/expand.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/factor.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/flatten.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/hold.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/inequality-bounds.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/init-lazy-refs.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/invisible-operator.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/match.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/negate.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/numerics.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/pattern-utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomial-degree.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/predicates.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/rules.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/sgn.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/simplify.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve-linear-system.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/solve.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/stochastic-equal.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/type-guards.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -1
- package/dist/types/compute-engine/boxed-expression/validate.d.ts +1 -1
- package/dist/types/compute-engine/collection-utils.d.ts +1 -1
- package/dist/types/compute-engine/compilation/base-compiler.d.ts +55 -6
- package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
- package/dist/types/compute-engine/compilation/constant-folding.d.ts +1 -1
- package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/gpu-target.d.ts +15 -5
- package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/javascript-target.d.ts +25 -3
- package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/types.d.ts +1 -1
- package/dist/types/compute-engine/compilation/wgsl-target.d.ts +1 -1
- package/dist/types/compute-engine/cost-function.d.ts +1 -1
- package/dist/types/compute-engine/engine-assumptions.d.ts +1 -1
- package/dist/types/compute-engine/engine-cache.d.ts +1 -1
- package/dist/types/compute-engine/engine-common-symbols.d.ts +1 -1
- package/dist/types/compute-engine/engine-compilation-targets.d.ts +1 -1
- package/dist/types/compute-engine/engine-configuration-lifecycle.d.ts +1 -1
- package/dist/types/compute-engine/engine-declarations.d.ts +1 -1
- package/dist/types/compute-engine/engine-expression-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/engine-extension-contracts.d.ts +1 -1
- package/dist/types/compute-engine/engine-library-bootstrap.d.ts +1 -1
- package/dist/types/compute-engine/engine-numeric-configuration.d.ts +1 -1
- package/dist/types/compute-engine/engine-runtime-state.d.ts +1 -1
- package/dist/types/compute-engine/engine-scope.d.ts +1 -1
- package/dist/types/compute-engine/engine-sequences.d.ts +1 -1
- package/dist/types/compute-engine/engine-simplification-rules.d.ts +1 -1
- package/dist/types/compute-engine/engine-startup-coordinator.d.ts +1 -1
- package/dist/types/compute-engine/engine-type-resolver.d.ts +1 -1
- package/dist/types/compute-engine/engine-validation-entrypoints.d.ts +1 -1
- package/dist/types/compute-engine/free-functions.d.ts +1 -1
- package/dist/types/compute-engine/function-utils.d.ts +1 -1
- package/dist/types/compute-engine/global-types.d.ts +1 -1
- package/dist/types/compute-engine/index.d.ts +24 -3
- package/dist/types/compute-engine/interval/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/interval/comparison.d.ts +1 -1
- package/dist/types/compute-engine/interval/elementary.d.ts +1 -1
- package/dist/types/compute-engine/interval/index.d.ts +1 -1
- package/dist/types/compute-engine/interval/trigonometric.d.ts +1 -1
- package/dist/types/compute-engine/interval/types.d.ts +1 -1
- package/dist/types/compute-engine/interval/util.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/default-dictionary.d.ts +4 -3
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-colors.d.ts +10 -0
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-relational-operators.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions-units.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/dictionary/indexed-types.d.ts +9 -1
- package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse-symbol.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-dms.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
- package/dist/types/compute-engine/latex-syntax/types.d.ts +40 -1
- package/dist/types/compute-engine/latex-syntax/utils.d.ts +1 -1
- package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/calculus.d.ts +1 -1
- package/dist/types/compute-engine/library/collections.d.ts +5 -3
- package/dist/types/compute-engine/library/colors.d.ts +1 -1
- package/dist/types/compute-engine/library/combinatorics.d.ts +1 -1
- package/dist/types/compute-engine/library/complex.d.ts +1 -1
- package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
- package/dist/types/compute-engine/library/core.d.ts +1 -1
- package/dist/types/compute-engine/library/fractals.d.ts +1 -1
- package/dist/types/compute-engine/library/library.d.ts +1 -1
- package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/library/logic-analysis.d.ts +1 -1
- package/dist/types/compute-engine/library/logic.d.ts +1 -1
- package/dist/types/compute-engine/library/number-theory.d.ts +1 -1
- package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
- package/dist/types/compute-engine/library/quantity-arithmetic.d.ts +1 -1
- package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
- package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
- package/dist/types/compute-engine/library/sets.d.ts +1 -1
- package/dist/types/compute-engine/library/statistics.d.ts +1 -1
- package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
- package/dist/types/compute-engine/library/type-handlers.d.ts +1 -1
- package/dist/types/compute-engine/library/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/library/units.d.ts +1 -1
- package/dist/types/compute-engine/library/utils.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/big-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/exact-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/machine-numeric-value.d.ts +1 -1
- package/dist/types/compute-engine/numeric-value/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/expression.d.ts +1 -1
- package/dist/types/compute-engine/numerics/interval.d.ts +1 -1
- package/dist/types/compute-engine/numerics/linear-algebra.d.ts +1 -1
- package/dist/types/compute-engine/numerics/monte-carlo.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
- package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
- package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
- package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
- package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
- package/dist/types/compute-engine/numerics/special-functions.d.ts +1 -1
- package/dist/types/compute-engine/numerics/statistics.d.ts +1 -1
- package/dist/types/compute-engine/numerics/strings.d.ts +1 -1
- package/dist/types/compute-engine/numerics/types.d.ts +1 -1
- package/dist/types/compute-engine/numerics/unit-data.d.ts +1 -1
- package/dist/types/compute-engine/oeis.d.ts +1 -1
- package/dist/types/compute-engine/sequence.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/antiderivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/distribute.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-cost.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu-transforms.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/fu.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/logic-utils.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-abs.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-divide.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-factorial.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-hyperbolic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-infinity.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-log.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-logic.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-power.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-product.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-rules.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-sum.d.ts +1 -1
- package/dist/types/compute-engine/symbolic/simplify-trig.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensor-fields.d.ts +1 -1
- package/dist/types/compute-engine/tensor/tensors.d.ts +1 -1
- package/dist/types/compute-engine/types-definitions.d.ts +1 -1
- package/dist/types/compute-engine/types-engine.d.ts +23 -2
- package/dist/types/compute-engine/types-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-expression.d.ts +1 -1
- package/dist/types/compute-engine/types-kernel-evaluation.d.ts +1 -1
- package/dist/types/compute-engine/types-kernel-serialization.d.ts +1 -1
- package/dist/types/compute-engine/types-serialization.d.ts +1 -1
- package/dist/types/compute-engine/types.d.ts +1 -1
- package/dist/types/compute-engine.d.ts +1 -2
- package/dist/types/core.d.ts +1 -1
- package/dist/types/interval.d.ts +1 -1
- package/dist/types/latex-syntax.d.ts +2 -2
- package/dist/types/math-json/symbols.d.ts +1 -1
- package/dist/types/math-json/types.d.ts +1 -1
- package/dist/types/math-json/utils.d.ts +1 -1
- package/dist/types/math-json.d.ts +2 -2
- package/dist/types/numerics.d.ts +1 -1
- package/package.json +2 -2
package/dist/compile.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compute Engine 0.
|
|
1
|
+
/** Compute Engine 0.57.0 */
|
|
2
2
|
|
|
3
3
|
// src/compute-engine/numerics/richardson.ts
|
|
4
4
|
function extrapolate(f, x0, options = {}) {
|
|
@@ -1511,6 +1511,7 @@ var SCALAR_TYPES = [
|
|
|
1511
1511
|
];
|
|
1512
1512
|
var VALUE_TYPES = [
|
|
1513
1513
|
"value",
|
|
1514
|
+
"color",
|
|
1514
1515
|
...COLLECTION_TYPES,
|
|
1515
1516
|
...SCALAR_TYPES
|
|
1516
1517
|
];
|
|
@@ -3206,6 +3207,7 @@ var PRIMITIVE_SUBTYPES = {
|
|
|
3206
3207
|
symbol: [],
|
|
3207
3208
|
boolean: [],
|
|
3208
3209
|
string: [],
|
|
3210
|
+
color: [],
|
|
3209
3211
|
expression: EXPRESSION_TYPES
|
|
3210
3212
|
};
|
|
3211
3213
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
@@ -5176,6 +5178,64 @@ function parseQuantifier(kind) {
|
|
|
5176
5178
|
}
|
|
5177
5179
|
|
|
5178
5180
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
5181
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
5182
|
+
x: "First",
|
|
5183
|
+
y: "Second",
|
|
5184
|
+
z: "Third",
|
|
5185
|
+
real: "Real",
|
|
5186
|
+
re: "Real",
|
|
5187
|
+
imag: "Imaginary",
|
|
5188
|
+
im: "Imaginary",
|
|
5189
|
+
count: "Length",
|
|
5190
|
+
total: "Sum",
|
|
5191
|
+
max: "Max",
|
|
5192
|
+
min: "Min"
|
|
5193
|
+
};
|
|
5194
|
+
function memberHead(name) {
|
|
5195
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
5196
|
+
}
|
|
5197
|
+
function parseComponentAccess(parser, lhs) {
|
|
5198
|
+
parser.skipVisualSpace();
|
|
5199
|
+
if (parser.match("\\operatorname")) {
|
|
5200
|
+
const name = parser.parseStringGroup();
|
|
5201
|
+
if (name === null) return null;
|
|
5202
|
+
const head = memberHead(name.trim());
|
|
5203
|
+
if (head === null) return null;
|
|
5204
|
+
return [head, lhs];
|
|
5205
|
+
}
|
|
5206
|
+
const tok = parser.peek;
|
|
5207
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
5208
|
+
const bare = tok.slice(1);
|
|
5209
|
+
const head = memberHead(bare);
|
|
5210
|
+
if (head !== null) {
|
|
5211
|
+
parser.nextToken();
|
|
5212
|
+
return [head, lhs];
|
|
5213
|
+
}
|
|
5214
|
+
return null;
|
|
5215
|
+
}
|
|
5216
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
5217
|
+
const head = memberHead(tok);
|
|
5218
|
+
if (head === null) return null;
|
|
5219
|
+
parser.nextToken();
|
|
5220
|
+
return [head, lhs];
|
|
5221
|
+
}
|
|
5222
|
+
return null;
|
|
5223
|
+
}
|
|
5224
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
5225
|
+
parser.addBoundary(close);
|
|
5226
|
+
parser.skipVisualSpace();
|
|
5227
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
5228
|
+
if (cond === null) {
|
|
5229
|
+
parser.removeBoundary();
|
|
5230
|
+
return null;
|
|
5231
|
+
}
|
|
5232
|
+
parser.skipVisualSpace();
|
|
5233
|
+
if (!parser.matchBoundary()) {
|
|
5234
|
+
parser.removeBoundary();
|
|
5235
|
+
return null;
|
|
5236
|
+
}
|
|
5237
|
+
return ["When", lhs, cond];
|
|
5238
|
+
}
|
|
5179
5239
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
5180
5240
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
5181
5241
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -5647,6 +5707,15 @@ var DEFINITIONS_CORE = [
|
|
|
5647
5707
|
}
|
|
5648
5708
|
},
|
|
5649
5709
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
5710
|
+
// Component-access postfix: expr.member (C3)
|
|
5711
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
5712
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
5713
|
+
{
|
|
5714
|
+
kind: "postfix",
|
|
5715
|
+
precedence: 850,
|
|
5716
|
+
latexTrigger: ["."],
|
|
5717
|
+
parse: parseComponentAccess
|
|
5718
|
+
},
|
|
5650
5719
|
{
|
|
5651
5720
|
name: "At",
|
|
5652
5721
|
kind: "postfix",
|
|
@@ -5667,6 +5736,29 @@ var DEFINITIONS_CORE = [
|
|
|
5667
5736
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
5668
5737
|
parse: parseAt("\\right", "\\rbrack")
|
|
5669
5738
|
},
|
|
5739
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
5740
|
+
{
|
|
5741
|
+
name: "When",
|
|
5742
|
+
kind: "postfix",
|
|
5743
|
+
precedence: 800,
|
|
5744
|
+
latexTrigger: ["\\left", "\\{"],
|
|
5745
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
5746
|
+
serialize: (serializer, expr) => {
|
|
5747
|
+
const e = operand(expr, 1);
|
|
5748
|
+
const cond = operand(expr, 2);
|
|
5749
|
+
if (!e || !cond) return "";
|
|
5750
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
5751
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
5752
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
5753
|
+
}
|
|
5754
|
+
},
|
|
5755
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
5756
|
+
{
|
|
5757
|
+
kind: "postfix",
|
|
5758
|
+
precedence: 800,
|
|
5759
|
+
latexTrigger: ["\\{"],
|
|
5760
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
5761
|
+
},
|
|
5670
5762
|
{
|
|
5671
5763
|
kind: "postfix",
|
|
5672
5764
|
latexTrigger: ["_"],
|
|
@@ -5749,6 +5841,29 @@ var DEFINITIONS_CORE = [
|
|
|
5749
5841
|
return "";
|
|
5750
5842
|
}
|
|
5751
5843
|
},
|
|
5844
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
5845
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
5846
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
5847
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
5848
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
5849
|
+
{
|
|
5850
|
+
latexTrigger: [".", ".", "."],
|
|
5851
|
+
kind: "infix",
|
|
5852
|
+
precedence: 800,
|
|
5853
|
+
parse: parseRange
|
|
5854
|
+
},
|
|
5855
|
+
{
|
|
5856
|
+
latexTrigger: ["\\ldots"],
|
|
5857
|
+
kind: "infix",
|
|
5858
|
+
precedence: 800,
|
|
5859
|
+
parse: parseRange
|
|
5860
|
+
},
|
|
5861
|
+
{
|
|
5862
|
+
latexTrigger: ["\\dots"],
|
|
5863
|
+
kind: "infix",
|
|
5864
|
+
precedence: 800,
|
|
5865
|
+
parse: parseRange
|
|
5866
|
+
},
|
|
5752
5867
|
{
|
|
5753
5868
|
latexTrigger: [";"],
|
|
5754
5869
|
kind: "infix",
|
|
@@ -5933,13 +6048,24 @@ var DEFINITIONS_CORE = [
|
|
|
5933
6048
|
const args = operands(expr);
|
|
5934
6049
|
if (!args || args.length < 2) return "";
|
|
5935
6050
|
const body = args[0];
|
|
5936
|
-
const
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
6051
|
+
const elements = args.slice(1);
|
|
6052
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
6053
|
+
if (!allElements) {
|
|
6054
|
+
return joinLatex([
|
|
6055
|
+
"\\operatorname{Loop}(",
|
|
6056
|
+
serializer.serialize(body),
|
|
6057
|
+
", ",
|
|
6058
|
+
serializer.serialize(elements[0]),
|
|
6059
|
+
")"
|
|
6060
|
+
]);
|
|
6061
|
+
}
|
|
6062
|
+
if (elements.length === 1) {
|
|
6063
|
+
const elem = elements[0];
|
|
6064
|
+
const index = operand(elem, 1);
|
|
6065
|
+
const coll = operand(elem, 2);
|
|
6066
|
+
if (operator(coll) === "Range") {
|
|
6067
|
+
const lo = operand(coll, 1);
|
|
6068
|
+
const hi = operand(coll, 2);
|
|
5943
6069
|
return joinLatex([
|
|
5944
6070
|
"\\text{for }",
|
|
5945
6071
|
serializer.serialize(index),
|
|
@@ -5951,13 +6077,27 @@ var DEFINITIONS_CORE = [
|
|
|
5951
6077
|
serializer.serialize(body)
|
|
5952
6078
|
]);
|
|
5953
6079
|
}
|
|
6080
|
+
return joinLatex([
|
|
6081
|
+
serializer.serialize(body),
|
|
6082
|
+
" \\operatorname{for} ",
|
|
6083
|
+
serializer.serialize(index),
|
|
6084
|
+
" = ",
|
|
6085
|
+
serializer.serialize(coll)
|
|
6086
|
+
]);
|
|
5954
6087
|
}
|
|
6088
|
+
const bindings = elements.map((elem) => {
|
|
6089
|
+
const name = operand(elem, 1);
|
|
6090
|
+
const coll = operand(elem, 2);
|
|
6091
|
+
return joinLatex([
|
|
6092
|
+
serializer.serialize(name),
|
|
6093
|
+
" = ",
|
|
6094
|
+
serializer.serialize(coll)
|
|
6095
|
+
]);
|
|
6096
|
+
}).join(", ");
|
|
5955
6097
|
return joinLatex([
|
|
5956
|
-
"\\operatorname{Loop}(",
|
|
5957
6098
|
serializer.serialize(body),
|
|
5958
|
-
"
|
|
5959
|
-
|
|
5960
|
-
")"
|
|
6099
|
+
" \\operatorname{for} ",
|
|
6100
|
+
bindings
|
|
5961
6101
|
]);
|
|
5962
6102
|
}
|
|
5963
6103
|
},
|
|
@@ -5990,6 +6130,18 @@ var DEFINITIONS_CORE = [
|
|
|
5990
6130
|
precedence: 245,
|
|
5991
6131
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
5992
6132
|
},
|
|
6133
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
6134
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
6135
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
6136
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
6137
|
+
// bindings can be comma-separated below us.
|
|
6138
|
+
{
|
|
6139
|
+
symbolTrigger: "for",
|
|
6140
|
+
kind: "infix",
|
|
6141
|
+
associativity: "none",
|
|
6142
|
+
precedence: 19,
|
|
6143
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
6144
|
+
},
|
|
5993
6145
|
// \operatorname{break}
|
|
5994
6146
|
{
|
|
5995
6147
|
symbolTrigger: "break",
|
|
@@ -6194,7 +6346,10 @@ var DEFINITIONS_CORE = [
|
|
|
6194
6346
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
6195
6347
|
parser.addBoundary([")"]);
|
|
6196
6348
|
const expr = parser.parseExpression(until);
|
|
6197
|
-
if (!parser.matchBoundary())
|
|
6349
|
+
if (!parser.matchBoundary()) {
|
|
6350
|
+
parser.removeBoundary();
|
|
6351
|
+
return null;
|
|
6352
|
+
}
|
|
6198
6353
|
if (!parser.match("<}>")) return null;
|
|
6199
6354
|
return ["Derivative", lhs, expr];
|
|
6200
6355
|
}
|
|
@@ -6635,7 +6790,12 @@ function parseBrackets(parser, body) {
|
|
|
6635
6790
|
if (isEmptySequence(body)) return ["List"];
|
|
6636
6791
|
const h = operator(body);
|
|
6637
6792
|
if (h === "Range" || h === "Linspace") return body;
|
|
6638
|
-
if (h === "Sequence")
|
|
6793
|
+
if (h === "Sequence") {
|
|
6794
|
+
const elems = operands(body);
|
|
6795
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6796
|
+
if (inferred) return inferred;
|
|
6797
|
+
return ["List", ...elems];
|
|
6798
|
+
}
|
|
6639
6799
|
if (h === "Delimiter") {
|
|
6640
6800
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
6641
6801
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -6648,12 +6808,37 @@ function parseBrackets(parser, body) {
|
|
|
6648
6808
|
}
|
|
6649
6809
|
if (delim === "," || delim === ".,.") {
|
|
6650
6810
|
body = operand(body, 1);
|
|
6651
|
-
if (operator(body) === "Sequence")
|
|
6811
|
+
if (operator(body) === "Sequence") {
|
|
6812
|
+
const elems = operands(body);
|
|
6813
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6814
|
+
if (inferred) return inferred;
|
|
6815
|
+
return ["List", ...elems];
|
|
6816
|
+
}
|
|
6652
6817
|
return ["List", body ?? "Nothing"];
|
|
6653
6818
|
}
|
|
6654
6819
|
}
|
|
6655
6820
|
return ["List", body];
|
|
6656
6821
|
}
|
|
6822
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
6823
|
+
if (elems.length < 4) return null;
|
|
6824
|
+
const penultimate = elems[elems.length - 2];
|
|
6825
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
6826
|
+
const samples = elems.slice(0, -2);
|
|
6827
|
+
const endExpr = elems[elems.length - 1];
|
|
6828
|
+
if (samples.length < 2) return null;
|
|
6829
|
+
const sampleNums = samples.map(machineValue);
|
|
6830
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
6831
|
+
const nums = sampleNums;
|
|
6832
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
6833
|
+
const tol = parser.options.tolerance;
|
|
6834
|
+
if (Math.abs(step) < tol)
|
|
6835
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
6836
|
+
for (let i = 1; i < nums.length; i++) {
|
|
6837
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
6838
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
6839
|
+
}
|
|
6840
|
+
return ["Range", nums[0], endExpr, step];
|
|
6841
|
+
}
|
|
6657
6842
|
function serializeList(serializer, expr) {
|
|
6658
6843
|
if (nops(expr) > 1 && operands(expr).every((x) => {
|
|
6659
6844
|
const op = operator(x);
|
|
@@ -6905,6 +7090,35 @@ function parseForExpression(parser, until) {
|
|
|
6905
7090
|
["Element", index, ["Range", lower, upper]]
|
|
6906
7091
|
];
|
|
6907
7092
|
}
|
|
7093
|
+
function parseForComprehension(parser, lhs, until) {
|
|
7094
|
+
const bindingTerminator = {
|
|
7095
|
+
minPrec: 21,
|
|
7096
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
7097
|
+
condition: (p) => {
|
|
7098
|
+
if (until?.condition?.(p)) return true;
|
|
7099
|
+
const saved = p.index;
|
|
7100
|
+
p.skipVisualSpace();
|
|
7101
|
+
const isComma = p.peek === ",";
|
|
7102
|
+
p.index = saved;
|
|
7103
|
+
return isComma;
|
|
7104
|
+
}
|
|
7105
|
+
};
|
|
7106
|
+
const elements = [];
|
|
7107
|
+
do {
|
|
7108
|
+
parser.skipVisualSpace();
|
|
7109
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
7110
|
+
if (binding === null) break;
|
|
7111
|
+
const op = operator(binding);
|
|
7112
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
7113
|
+
const name = operand(binding, 1);
|
|
7114
|
+
const list = operand(binding, 2);
|
|
7115
|
+
if (!name || !list) return null;
|
|
7116
|
+
elements.push(["Element", name, list]);
|
|
7117
|
+
parser.skipVisualSpace();
|
|
7118
|
+
} while (parser.match(","));
|
|
7119
|
+
if (elements.length === 0) return null;
|
|
7120
|
+
return ["Loop", lhs, ...elements];
|
|
7121
|
+
}
|
|
6908
7122
|
function parseWhereExpression(parser, lhs, until) {
|
|
6909
7123
|
const bindingTerminator = {
|
|
6910
7124
|
minPrec: 21,
|
|
@@ -8793,6 +9007,8 @@ var DEFINITIONS_ARITHMETIC = [
|
|
|
8793
9007
|
precedence: DIVISION_PRECEDENCE,
|
|
8794
9008
|
parse: "Mod"
|
|
8795
9009
|
},
|
|
9010
|
+
// Function-style alias: `\operatorname{mod}(a, b)`
|
|
9011
|
+
{ latexTrigger: "\\operatorname{mod}", parse: "Mod" },
|
|
8796
9012
|
{
|
|
8797
9013
|
latexTrigger: "\\pmod",
|
|
8798
9014
|
kind: "prefix",
|
|
@@ -9033,6 +9249,13 @@ var DEFINITIONS_ARITHMETIC = [
|
|
|
9033
9249
|
const rhs = serializer.wrap(operand(expr, 2), ADDITION_PRECEDENCE + 3);
|
|
9034
9250
|
return joinLatex([lhs, "-", rhs]);
|
|
9035
9251
|
}
|
|
9252
|
+
},
|
|
9253
|
+
// Euclidean distance between two points (tuples of numbers).
|
|
9254
|
+
{
|
|
9255
|
+
name: "Distance",
|
|
9256
|
+
latexTrigger: ["\\operatorname{distance}"],
|
|
9257
|
+
kind: "function",
|
|
9258
|
+
serialize: (serializer, expr) => "\\operatorname{distance}" + serializer.wrapArguments(expr)
|
|
9036
9259
|
}
|
|
9037
9260
|
];
|
|
9038
9261
|
function getIndexAssignment(expr, upper) {
|
|
@@ -10457,7 +10680,9 @@ var DEFINITIONS_STATISTICS = [
|
|
|
10457
10680
|
if (!expr || !symbol(expr)) return null;
|
|
10458
10681
|
return ["Mean", expr];
|
|
10459
10682
|
}
|
|
10460
|
-
}
|
|
10683
|
+
},
|
|
10684
|
+
// Function-style alias: `\operatorname{var}(...)`
|
|
10685
|
+
{ latexTrigger: "\\operatorname{var}", parse: "Variance" }
|
|
10461
10686
|
];
|
|
10462
10687
|
|
|
10463
10688
|
// src/compute-engine/numerics/unit-data.ts
|
|
@@ -11465,7 +11690,7 @@ var DEFINITIONS_OTHERS = [
|
|
|
11465
11690
|
36: "\\qquad"
|
|
11466
11691
|
}[v] ?? "";
|
|
11467
11692
|
}
|
|
11468
|
-
}
|
|
11693
|
+
},
|
|
11469
11694
|
// if (
|
|
11470
11695
|
// [
|
|
11471
11696
|
// '\\!',
|
|
@@ -11489,6 +11714,121 @@ var DEFINITIONS_OTHERS = [
|
|
|
11489
11714
|
// name: '',
|
|
11490
11715
|
// trigger: '\\check',
|
|
11491
11716
|
// },
|
|
11717
|
+
// ---------------------------------------------------------------------------
|
|
11718
|
+
// Function-style aliases for collection / random operators that some
|
|
11719
|
+
// notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
|
|
11720
|
+
// The capitalized library entries already exist; these are pure parse
|
|
11721
|
+
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11722
|
+
// ---------------------------------------------------------------------------
|
|
11723
|
+
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11724
|
+
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11725
|
+
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11726
|
+
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
11727
|
+
// ---------------------------------------------------------------------------
|
|
11728
|
+
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11729
|
+
// can branch on the operator name; CE itself doesn't render them. The
|
|
11730
|
+
// library entries (with no evaluator) live in `library/core.ts`.
|
|
11731
|
+
// ---------------------------------------------------------------------------
|
|
11732
|
+
{
|
|
11733
|
+
name: "Triangle",
|
|
11734
|
+
latexTrigger: ["\\operatorname{triangle}"],
|
|
11735
|
+
kind: "function",
|
|
11736
|
+
serialize: (serializer, expr) => "\\operatorname{triangle}" + serializer.wrapArguments(expr)
|
|
11737
|
+
},
|
|
11738
|
+
// Desmos's geometric `vector(p1, p2)` — a directed segment between two
|
|
11739
|
+
// points. Routed to a dedicated head (not the existing column-vector
|
|
11740
|
+
// `Vector`, which has a narrower `(number+) -> vector` signature).
|
|
11741
|
+
{
|
|
11742
|
+
name: "GeometricVector",
|
|
11743
|
+
latexTrigger: ["\\operatorname{vector}"],
|
|
11744
|
+
kind: "function",
|
|
11745
|
+
serialize: (serializer, expr) => "\\operatorname{vector}" + serializer.wrapArguments(expr)
|
|
11746
|
+
},
|
|
11747
|
+
{
|
|
11748
|
+
name: "Sphere",
|
|
11749
|
+
latexTrigger: ["\\operatorname{sphere}"],
|
|
11750
|
+
kind: "function",
|
|
11751
|
+
serialize: (serializer, expr) => "\\operatorname{sphere}" + serializer.wrapArguments(expr)
|
|
11752
|
+
},
|
|
11753
|
+
{
|
|
11754
|
+
name: "Segment",
|
|
11755
|
+
latexTrigger: ["\\operatorname{segment}"],
|
|
11756
|
+
kind: "function",
|
|
11757
|
+
serialize: (serializer, expr) => "\\operatorname{segment}" + serializer.wrapArguments(expr)
|
|
11758
|
+
}
|
|
11759
|
+
];
|
|
11760
|
+
|
|
11761
|
+
// src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
|
|
11762
|
+
var DEFINITIONS_COLORS = [
|
|
11763
|
+
// Color constructors (one per colorspace, preserves space on evaluation)
|
|
11764
|
+
{
|
|
11765
|
+
name: "Rgb",
|
|
11766
|
+
latexTrigger: ["\\operatorname{rgb}"],
|
|
11767
|
+
kind: "function",
|
|
11768
|
+
serialize: (serializer, expr) => "\\operatorname{rgb}" + serializer.wrapArguments(expr)
|
|
11769
|
+
},
|
|
11770
|
+
{
|
|
11771
|
+
name: "Hsv",
|
|
11772
|
+
latexTrigger: ["\\operatorname{hsv}"],
|
|
11773
|
+
kind: "function",
|
|
11774
|
+
serialize: (serializer, expr) => "\\operatorname{hsv}" + serializer.wrapArguments(expr)
|
|
11775
|
+
},
|
|
11776
|
+
{
|
|
11777
|
+
name: "Hsl",
|
|
11778
|
+
latexTrigger: ["\\operatorname{hsl}"],
|
|
11779
|
+
kind: "function",
|
|
11780
|
+
serialize: (serializer, expr) => "\\operatorname{hsl}" + serializer.wrapArguments(expr)
|
|
11781
|
+
},
|
|
11782
|
+
{
|
|
11783
|
+
name: "Oklab",
|
|
11784
|
+
latexTrigger: ["\\operatorname{oklab}"],
|
|
11785
|
+
kind: "function",
|
|
11786
|
+
serialize: (serializer, expr) => "\\operatorname{oklab}" + serializer.wrapArguments(expr)
|
|
11787
|
+
},
|
|
11788
|
+
{
|
|
11789
|
+
name: "Oklch",
|
|
11790
|
+
latexTrigger: ["\\operatorname{oklch}"],
|
|
11791
|
+
kind: "function",
|
|
11792
|
+
serialize: (serializer, expr) => "\\operatorname{oklch}" + serializer.wrapArguments(expr)
|
|
11793
|
+
},
|
|
11794
|
+
// Conversion functions (color → color in the named space)
|
|
11795
|
+
{
|
|
11796
|
+
name: "AsRgb",
|
|
11797
|
+
latexTrigger: ["\\operatorname{asRgb}"],
|
|
11798
|
+
kind: "function",
|
|
11799
|
+
serialize: (serializer, expr) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr)
|
|
11800
|
+
},
|
|
11801
|
+
{
|
|
11802
|
+
name: "AsHsv",
|
|
11803
|
+
latexTrigger: ["\\operatorname{asHsv}"],
|
|
11804
|
+
kind: "function",
|
|
11805
|
+
serialize: (serializer, expr) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr)
|
|
11806
|
+
},
|
|
11807
|
+
{
|
|
11808
|
+
name: "AsHsl",
|
|
11809
|
+
latexTrigger: ["\\operatorname{asHsl}"],
|
|
11810
|
+
kind: "function",
|
|
11811
|
+
serialize: (serializer, expr) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr)
|
|
11812
|
+
},
|
|
11813
|
+
{
|
|
11814
|
+
name: "AsOklab",
|
|
11815
|
+
latexTrigger: ["\\operatorname{asOklab}"],
|
|
11816
|
+
kind: "function",
|
|
11817
|
+
serialize: (serializer, expr) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr)
|
|
11818
|
+
},
|
|
11819
|
+
{
|
|
11820
|
+
name: "AsOklch",
|
|
11821
|
+
latexTrigger: ["\\operatorname{asOklch}"],
|
|
11822
|
+
kind: "function",
|
|
11823
|
+
serialize: (serializer, expr) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr)
|
|
11824
|
+
},
|
|
11825
|
+
// Perceptual difference (returns a scalar in [0, ~1])
|
|
11826
|
+
{
|
|
11827
|
+
name: "ColorDelta",
|
|
11828
|
+
latexTrigger: ["\\operatorname{colorDelta}"],
|
|
11829
|
+
kind: "function",
|
|
11830
|
+
serialize: (serializer, expr) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr)
|
|
11831
|
+
}
|
|
11492
11832
|
];
|
|
11493
11833
|
|
|
11494
11834
|
// src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
|
|
@@ -11519,7 +11859,8 @@ var LATEX_DICTIONARY = [
|
|
|
11519
11859
|
...DEFINITIONS_STATISTICS,
|
|
11520
11860
|
...DEFINITIONS_UNITS,
|
|
11521
11861
|
...DEFINITIONS_OTHERS,
|
|
11522
|
-
...DEFINITIONS_PHYSICS
|
|
11862
|
+
...DEFINITIONS_PHYSICS,
|
|
11863
|
+
...DEFINITIONS_COLORS
|
|
11523
11864
|
];
|
|
11524
11865
|
|
|
11525
11866
|
// src/math-json/symbols.ts
|
|
@@ -12674,7 +13015,11 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12674
13015
|
//
|
|
12675
13016
|
Range: {
|
|
12676
13017
|
complexity: 8200,
|
|
12677
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
13018
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
13019
|
+
type: (ops) => {
|
|
13020
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
13021
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
13022
|
+
},
|
|
12678
13023
|
canonical: (ops, { engine: ce }) => {
|
|
12679
13024
|
if (ops.length === 0) return null;
|
|
12680
13025
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -12698,19 +13043,26 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12698
13043
|
const [lower, upper, step] = range(expr);
|
|
12699
13044
|
if (step === 0) return 0;
|
|
12700
13045
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
12701
|
-
return
|
|
13046
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12702
13047
|
},
|
|
12703
13048
|
contains: (expr, target) => {
|
|
12704
|
-
if (!target.type.matches("integer")) return false;
|
|
12705
13049
|
const t = target.re;
|
|
13050
|
+
if (!isFinite(t)) return false;
|
|
12706
13051
|
const [lower, upper, step] = range(expr);
|
|
12707
13052
|
if (step === 0) return false;
|
|
12708
|
-
if (step > 0)
|
|
12709
|
-
|
|
13053
|
+
if (step > 0) {
|
|
13054
|
+
if (t < lower || t > upper) return false;
|
|
13055
|
+
} else {
|
|
13056
|
+
if (t > lower || t < upper) return false;
|
|
13057
|
+
}
|
|
13058
|
+
const k = (t - lower) / step;
|
|
13059
|
+
const tol = expr.engine.tolerance;
|
|
13060
|
+
const kRounded = Math.round(k);
|
|
13061
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
12710
13062
|
},
|
|
12711
13063
|
iterator: (expr) => {
|
|
12712
13064
|
const [lower, upper, step] = range(expr);
|
|
12713
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
13065
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12714
13066
|
let index = 1;
|
|
12715
13067
|
return {
|
|
12716
13068
|
next: () => {
|
|
@@ -12728,7 +13080,9 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12728
13080
|
at: (expr, index) => {
|
|
12729
13081
|
if (typeof index !== "number") return void 0;
|
|
12730
13082
|
const [lower, upper, step] = range(expr);
|
|
12731
|
-
if (
|
|
13083
|
+
if (step === 0) return void 0;
|
|
13084
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
13085
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
12732
13086
|
return expr.engine.number(lower + step * (index - 1));
|
|
12733
13087
|
},
|
|
12734
13088
|
indexWhere: void 0,
|
|
@@ -12753,7 +13107,13 @@ var COLLECTIONS_LIBRARY = {
|
|
|
12753
13107
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
12754
13108
|
return lower >= upper ? "positive" : "negative";
|
|
12755
13109
|
},
|
|
12756
|
-
elttype: (
|
|
13110
|
+
elttype: (expr) => {
|
|
13111
|
+
if (!isFunction2(expr)) return "finite_integer";
|
|
13112
|
+
for (let i = 1; i <= expr.nops; i++) {
|
|
13113
|
+
if (!expr[`op${i}`].isInteger) return "finite_real";
|
|
13114
|
+
}
|
|
13115
|
+
return "finite_integer";
|
|
13116
|
+
}
|
|
12757
13117
|
}
|
|
12758
13118
|
},
|
|
12759
13119
|
Interval: {
|
|
@@ -13351,15 +13711,45 @@ var COLLECTIONS_LIBRARY = {
|
|
|
13351
13711
|
},
|
|
13352
13712
|
First: {
|
|
13353
13713
|
complexity: 8200,
|
|
13354
|
-
signature: "(
|
|
13714
|
+
signature: "(any) -> any",
|
|
13355
13715
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13356
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13716
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13717
|
+
if (!xs.isCollection)
|
|
13718
|
+
return ce.error([
|
|
13719
|
+
"incompatible-type",
|
|
13720
|
+
`'collection'`,
|
|
13721
|
+
xs.type.toString()
|
|
13722
|
+
]);
|
|
13723
|
+
return xs.at(1) ?? ce.Nothing;
|
|
13724
|
+
}
|
|
13357
13725
|
},
|
|
13358
13726
|
Second: {
|
|
13359
13727
|
complexity: 8200,
|
|
13360
|
-
signature: "(
|
|
13728
|
+
signature: "(any) -> any",
|
|
13361
13729
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13362
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13730
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13731
|
+
if (!xs.isCollection)
|
|
13732
|
+
return ce.error([
|
|
13733
|
+
"incompatible-type",
|
|
13734
|
+
`'collection'`,
|
|
13735
|
+
xs.type.toString()
|
|
13736
|
+
]);
|
|
13737
|
+
return xs.at(2) ?? ce.Nothing;
|
|
13738
|
+
}
|
|
13739
|
+
},
|
|
13740
|
+
Third: {
|
|
13741
|
+
complexity: 8200,
|
|
13742
|
+
signature: "(any) -> any",
|
|
13743
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13744
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13745
|
+
if (!xs.isCollection)
|
|
13746
|
+
return ce.error([
|
|
13747
|
+
"incompatible-type",
|
|
13748
|
+
`'collection'`,
|
|
13749
|
+
xs.type.toString()
|
|
13750
|
+
]);
|
|
13751
|
+
return xs.at(3) ?? ce.Nothing;
|
|
13752
|
+
}
|
|
13363
13753
|
},
|
|
13364
13754
|
Last: {
|
|
13365
13755
|
complexity: 8200,
|
|
@@ -14338,17 +14728,14 @@ function range(expr) {
|
|
|
14338
14728
|
if (!isFunction2(expr)) return [1, 0, 0];
|
|
14339
14729
|
if (expr.nops === 0) return [1, 0, 0];
|
|
14340
14730
|
let op1 = expr.op1.re;
|
|
14341
|
-
if (!isFinite(op1)) op1 = 1;
|
|
14342
|
-
else op1 = Math.round(op1);
|
|
14731
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
14343
14732
|
if (expr.nops === 1) return [1, op1, 1];
|
|
14344
14733
|
let op2 = expr.op2.re;
|
|
14345
14734
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
14346
|
-
|
|
14347
|
-
if (expr.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
14735
|
+
if (expr.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
14348
14736
|
let op3 = expr.op3.re;
|
|
14349
|
-
if (!isFinite(op3)) op3 = 1;
|
|
14350
|
-
|
|
14351
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
14737
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
14738
|
+
return [op1, op2, op3];
|
|
14352
14739
|
}
|
|
14353
14740
|
function canonicalList(ops, { engine: ce }) {
|
|
14354
14741
|
const op1 = ops[0];
|
|
@@ -14697,6 +15084,23 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14697
15084
|
};
|
|
14698
15085
|
return compilePair(0);
|
|
14699
15086
|
}
|
|
15087
|
+
if (h === "When") {
|
|
15088
|
+
if (args.length !== 2)
|
|
15089
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
15090
|
+
const fn2 = target.functions?.(h);
|
|
15091
|
+
if (fn2) {
|
|
15092
|
+
if (typeof fn2 === "function") {
|
|
15093
|
+
return fn2(args, (expr) => _BaseCompiler.compile(expr, target), target);
|
|
15094
|
+
}
|
|
15095
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
15096
|
+
}
|
|
15097
|
+
if (isSymbol2(args[1], "True"))
|
|
15098
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
15099
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
15100
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
15101
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
15102
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
15103
|
+
}
|
|
14700
15104
|
if (h === "Block") {
|
|
14701
15105
|
return _BaseCompiler.compileBlock(args, target);
|
|
14702
15106
|
}
|
|
@@ -14771,17 +15175,91 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14771
15175
|
)}${target.ws("\n")}})()`;
|
|
14772
15176
|
}
|
|
14773
15177
|
/**
|
|
14774
|
-
* Compile a Loop expression
|
|
14775
|
-
*
|
|
15178
|
+
* Compile a Loop expression.
|
|
15179
|
+
*
|
|
15180
|
+
* Two forms are supported:
|
|
15181
|
+
*
|
|
15182
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
15183
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
15184
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
15185
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
15186
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
15187
|
+
* references to the loop index inside the body are re-wrapped via
|
|
15188
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
15189
|
+
*
|
|
15190
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
15191
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
15192
|
+
* When two or more `Element` clauses are present — or when the single
|
|
15193
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
15194
|
+
* comprehension that collects results into an array. Each clause
|
|
15195
|
+
* produces a `for (const name of collection)` loop, nested
|
|
15196
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
15197
|
+
*
|
|
15198
|
+
* Example output (JS):
|
|
15199
|
+
* ```js
|
|
15200
|
+
* (() => { const result = [];
|
|
15201
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
15202
|
+
* return result; })()
|
|
15203
|
+
* ```
|
|
14776
15204
|
*
|
|
14777
|
-
*
|
|
14778
|
-
*
|
|
14779
|
-
*
|
|
15205
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
15206
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15207
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15208
|
+
* array or by unrolling when bounds are known at compile time.
|
|
14780
15209
|
*/
|
|
14781
15210
|
static compileForLoop(args, target) {
|
|
14782
15211
|
if (!args[0]) throw new Error("Loop: no body");
|
|
14783
15212
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
14784
|
-
const
|
|
15213
|
+
const body = args[0];
|
|
15214
|
+
const elements = args.slice(1);
|
|
15215
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
15216
|
+
if (useComprehension) {
|
|
15217
|
+
const lang = target.language ?? "";
|
|
15218
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
15219
|
+
throw new Error(
|
|
15220
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
15221
|
+
);
|
|
15222
|
+
}
|
|
15223
|
+
const narrowedElements = [];
|
|
15224
|
+
for (let i = 0; i < elements.length; i++) {
|
|
15225
|
+
const elem = elements[i];
|
|
15226
|
+
if (!isFunction2(elem, "Element"))
|
|
15227
|
+
throw new Error(
|
|
15228
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
15229
|
+
);
|
|
15230
|
+
if (!isSymbol2(elem.ops[0]))
|
|
15231
|
+
throw new Error(
|
|
15232
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
15233
|
+
);
|
|
15234
|
+
narrowedElements.push(elem);
|
|
15235
|
+
}
|
|
15236
|
+
const loopVarSet = new Set(
|
|
15237
|
+
narrowedElements.map(
|
|
15238
|
+
(e) => e.ops[0].symbol
|
|
15239
|
+
)
|
|
15240
|
+
);
|
|
15241
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
15242
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
15243
|
+
...target,
|
|
15244
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
15245
|
+
} : target;
|
|
15246
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
15247
|
+
let inner = `result.push(${bodyCode});`;
|
|
15248
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
15249
|
+
const elem = narrowedElements[i];
|
|
15250
|
+
const name = elem.ops[0].symbol;
|
|
15251
|
+
const collExpr = elem.ops[1];
|
|
15252
|
+
let collection;
|
|
15253
|
+
if (isFunction2(collExpr, "Range")) {
|
|
15254
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
15255
|
+
} else {
|
|
15256
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
15257
|
+
}
|
|
15258
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
15259
|
+
}
|
|
15260
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
15261
|
+
}
|
|
15262
|
+
const indexing = elements[0];
|
|
14785
15263
|
if (!isFunction2(indexing, "Element"))
|
|
14786
15264
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
14787
15265
|
const indexExpr = indexing.ops[0];
|
|
@@ -14799,13 +15277,72 @@ var BaseCompiler = class _BaseCompiler {
|
|
|
14799
15277
|
...target,
|
|
14800
15278
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
14801
15279
|
};
|
|
14802
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
15280
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
14803
15281
|
return `(() => {${target.ws(
|
|
14804
15282
|
"\n"
|
|
14805
15283
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
14806
15284
|
"\n"
|
|
14807
15285
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
14808
15286
|
}
|
|
15287
|
+
/**
|
|
15288
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
15289
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
15290
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
15291
|
+
*
|
|
15292
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
15293
|
+
* are not statically numeric we accept the Range (the historical
|
|
15294
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
15295
|
+
* left as a known limitation; callers can force the iterable path by
|
|
15296
|
+
* supplying an explicit step.
|
|
15297
|
+
*/
|
|
15298
|
+
static isLegacyCompatibleRange(coll) {
|
|
15299
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
15300
|
+
if (coll.ops.length >= 3) {
|
|
15301
|
+
const stepExpr = coll.ops[2];
|
|
15302
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
15303
|
+
}
|
|
15304
|
+
const lo = coll.ops[0];
|
|
15305
|
+
const hi = coll.ops[1];
|
|
15306
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
15307
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
15308
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
15309
|
+
return true;
|
|
15310
|
+
}
|
|
15311
|
+
/**
|
|
15312
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
15313
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
15314
|
+
* `library/collections.ts` Range:
|
|
15315
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
15316
|
+
* element = lo + step * k (0-indexed)
|
|
15317
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
15318
|
+
*
|
|
15319
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
15320
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
15321
|
+
*/
|
|
15322
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
15323
|
+
const loExpr = rangeExpr.ops[0];
|
|
15324
|
+
const hiExpr = rangeExpr.ops[1];
|
|
15325
|
+
const stepExpr = rangeExpr.ops[2];
|
|
15326
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
15327
|
+
const lo2 = loExpr.re;
|
|
15328
|
+
const hi2 = hiExpr.re;
|
|
15329
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
15330
|
+
if (step2 === 0) return "[]";
|
|
15331
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
15332
|
+
if (step2 === 1) {
|
|
15333
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
15334
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
15335
|
+
}
|
|
15336
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
15337
|
+
}
|
|
15338
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
15339
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
15340
|
+
if (stepExpr === void 0) {
|
|
15341
|
+
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})`;
|
|
15342
|
+
}
|
|
15343
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
15344
|
+
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})`;
|
|
15345
|
+
}
|
|
14809
15346
|
/**
|
|
14810
15347
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
14811
15348
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -15154,8 +15691,7 @@ function compile(expr, options) {
|
|
|
15154
15691
|
ce.pushScope();
|
|
15155
15692
|
try {
|
|
15156
15693
|
if (vars && typeof vars === "object") {
|
|
15157
|
-
for (const [k, v] of Object.entries(vars))
|
|
15158
|
-
ce.assign(k, v);
|
|
15694
|
+
for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
|
|
15159
15695
|
}
|
|
15160
15696
|
return expr.evaluate().re;
|
|
15161
15697
|
} finally {
|
|
@@ -15242,8 +15778,7 @@ function tryGetComplexParts(expr, compile2) {
|
|
|
15242
15778
|
return { re: null, im: formatFloat(iScale) };
|
|
15243
15779
|
}
|
|
15244
15780
|
const compiledFactors = remaining.map((r) => compile2(r));
|
|
15245
|
-
if (iScale !== 1)
|
|
15246
|
-
compiledFactors.unshift(formatFloat(iScale));
|
|
15781
|
+
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
15247
15782
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
15248
15783
|
return { re: null, im: imCode };
|
|
15249
15784
|
}
|
|
@@ -15308,6 +15843,40 @@ function rgbToHsl(r, g, b) {
|
|
|
15308
15843
|
else h = ((r - g) / d + 4) / 6;
|
|
15309
15844
|
return { h: h * 360, s, l };
|
|
15310
15845
|
}
|
|
15846
|
+
function hsvToRgb(h, s, v) {
|
|
15847
|
+
h = (h % 360 + 360) % 360;
|
|
15848
|
+
s = Math.max(0, Math.min(1, s));
|
|
15849
|
+
v = Math.max(0, Math.min(1, v));
|
|
15850
|
+
const c = v * s;
|
|
15851
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
15852
|
+
const m = v - c;
|
|
15853
|
+
let r = 0, g = 0, b = 0;
|
|
15854
|
+
if (h < 60) [r, g, b] = [c, x, 0];
|
|
15855
|
+
else if (h < 120) [r, g, b] = [x, c, 0];
|
|
15856
|
+
else if (h < 180) [r, g, b] = [0, c, x];
|
|
15857
|
+
else if (h < 240) [r, g, b] = [0, x, c];
|
|
15858
|
+
else if (h < 300) [r, g, b] = [x, 0, c];
|
|
15859
|
+
else [r, g, b] = [c, 0, x];
|
|
15860
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
15861
|
+
}
|
|
15862
|
+
function rgbToHsv(r, g, b) {
|
|
15863
|
+
r /= 255;
|
|
15864
|
+
g /= 255;
|
|
15865
|
+
b /= 255;
|
|
15866
|
+
const max2 = Math.max(r, g, b);
|
|
15867
|
+
const min2 = Math.min(r, g, b);
|
|
15868
|
+
const d = max2 - min2;
|
|
15869
|
+
let h = 0;
|
|
15870
|
+
if (d > 0) {
|
|
15871
|
+
if (max2 === r) h = (g - b) / d % 6;
|
|
15872
|
+
else if (max2 === g) h = (b - r) / d + 2;
|
|
15873
|
+
else h = (r - g) / d + 4;
|
|
15874
|
+
h *= 60;
|
|
15875
|
+
if (h < 0) h += 360;
|
|
15876
|
+
}
|
|
15877
|
+
const s = max2 === 0 ? 0 : d / max2;
|
|
15878
|
+
return { h, s, v: max2 };
|
|
15879
|
+
}
|
|
15311
15880
|
function parseHexColor(s) {
|
|
15312
15881
|
const hex = s.startsWith("#") ? s.substring(1) : s;
|
|
15313
15882
|
let r, g, b;
|
|
@@ -15763,6 +16332,13 @@ var NAMED_COLORS = {
|
|
|
15763
16332
|
};
|
|
15764
16333
|
function parseColor(s, darkMode) {
|
|
15765
16334
|
const str = s.trim().toLowerCase();
|
|
16335
|
+
const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
|
|
16336
|
+
if (opacityMatch) {
|
|
16337
|
+
const base = parseColor(opacityMatch[1].trim(), darkMode);
|
|
16338
|
+
const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
|
|
16339
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
16340
|
+
return base & 4294967040 | alpha;
|
|
16341
|
+
}
|
|
15766
16342
|
if (str.startsWith("#")) {
|
|
15767
16343
|
const hex = str.substring(1);
|
|
15768
16344
|
let r, g, b, a = 255;
|
|
@@ -15895,14 +16471,6 @@ function parseColor(s, darkMode) {
|
|
|
15895
16471
|
console.warn(`parseColor: unrecognized color "${s}"`);
|
|
15896
16472
|
return 0;
|
|
15897
16473
|
}
|
|
15898
|
-
function parseColorToRgb01(s, darkMode) {
|
|
15899
|
-
const color = parseColor(s, darkMode);
|
|
15900
|
-
return [
|
|
15901
|
-
(color >>> 24 & 255) / 255,
|
|
15902
|
-
(color >>> 16 & 255) / 255,
|
|
15903
|
-
(color >>> 8 & 255) / 255
|
|
15904
|
-
];
|
|
15905
|
-
}
|
|
15906
16474
|
function apca(bgColor, fgColor) {
|
|
15907
16475
|
const bgRgb = asRgb(bgColor);
|
|
15908
16476
|
const fgRgb = asRgb(fgColor);
|
|
@@ -15961,6 +16529,12 @@ function contrastingColor(arg) {
|
|
|
15961
16529
|
const contrast2 = Math.abs(apca(fg2, bg));
|
|
15962
16530
|
return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
|
|
15963
16531
|
}
|
|
16532
|
+
function oklabDeltaE(a, b) {
|
|
16533
|
+
const dL = a.L - b.L;
|
|
16534
|
+
const da = a.a - b.a;
|
|
16535
|
+
const db = a.b - b.b;
|
|
16536
|
+
return Math.sqrt(dL * dL + da * da + db * db);
|
|
16537
|
+
}
|
|
15964
16538
|
var TYCHO_11 = [
|
|
15965
16539
|
"#4e79a7",
|
|
15966
16540
|
// Blue
|
|
@@ -20172,39 +20746,130 @@ var JAVASCRIPT_FUNCTIONS = {
|
|
|
20172
20746
|
if (args.length >= 2)
|
|
20173
20747
|
return `_SYS.colormap(${compile2(args[0])}, ${compile2(args[1])})`;
|
|
20174
20748
|
return `_SYS.colormap(${compile2(args[0])})`;
|
|
20749
|
+
},
|
|
20750
|
+
// -----------------------------------------------------------------------
|
|
20751
|
+
// Color constructor heads. All compile to OKLCh arrays at runtime — the
|
|
20752
|
+
// canonical color representation in this target. The constructors take
|
|
20753
|
+
// their own colorspace's components and convert internally.
|
|
20754
|
+
// (Mirrors the GPU target's design: color values are vec3 OKLCh.)
|
|
20755
|
+
// -----------------------------------------------------------------------
|
|
20756
|
+
Rgb: (args, compile2) => {
|
|
20757
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
20758
|
+
return `_SYS.rgb(${args.map(compile2).join(", ")})`;
|
|
20759
|
+
},
|
|
20760
|
+
Hsv: (args, compile2) => {
|
|
20761
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
20762
|
+
return `_SYS.hsv(${args.map(compile2).join(", ")})`;
|
|
20763
|
+
},
|
|
20764
|
+
Hsl: (args, compile2) => {
|
|
20765
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
20766
|
+
return `_SYS.hsl(${args.map(compile2).join(", ")})`;
|
|
20767
|
+
},
|
|
20768
|
+
Oklab: (args, compile2) => {
|
|
20769
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
20770
|
+
return `_SYS.oklab(${args.map(compile2).join(", ")})`;
|
|
20771
|
+
},
|
|
20772
|
+
Oklch: (args, compile2) => {
|
|
20773
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
20774
|
+
return `_SYS.oklch(${args.map(compile2).join(", ")})`;
|
|
20775
|
+
},
|
|
20776
|
+
// -----------------------------------------------------------------------
|
|
20777
|
+
// As* converters. Compile-time output convention matches the engine and
|
|
20778
|
+
// the GPU target: each returns components in the named space as a 3- or
|
|
20779
|
+
// 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
|
|
20780
|
+
// layers). `AsOklch` is the identity (canonical form).
|
|
20781
|
+
// -----------------------------------------------------------------------
|
|
20782
|
+
AsRgb: ([c], compile2) => {
|
|
20783
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
20784
|
+
return `_SYS.asRgb(${compile2(c)})`;
|
|
20785
|
+
},
|
|
20786
|
+
AsHsv: ([c], compile2) => {
|
|
20787
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
20788
|
+
return `_SYS.asHsv(${compile2(c)})`;
|
|
20789
|
+
},
|
|
20790
|
+
AsHsl: ([c], compile2) => {
|
|
20791
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
20792
|
+
return `_SYS.asHsl(${compile2(c)})`;
|
|
20793
|
+
},
|
|
20794
|
+
AsOklab: ([c], compile2) => {
|
|
20795
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
20796
|
+
return `_SYS.asOklab(${compile2(c)})`;
|
|
20797
|
+
},
|
|
20798
|
+
AsOklch: ([c], compile2) => {
|
|
20799
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
20800
|
+
return compile2(c);
|
|
20801
|
+
},
|
|
20802
|
+
// Perceptual color difference (ΔE_OK).
|
|
20803
|
+
ColorDelta: ([a, b], compile2) => {
|
|
20804
|
+
if (a === null || b === null)
|
|
20805
|
+
throw new Error("ColorDelta: need two colors");
|
|
20806
|
+
return `_SYS.colorDelta(${compile2(a)}, ${compile2(b)})`;
|
|
20807
|
+
},
|
|
20808
|
+
// Euclidean distance between two tuples (any positive dimension).
|
|
20809
|
+
// The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
|
|
20810
|
+
// (vec-only); this JS handler works on plain arrays of any length.
|
|
20811
|
+
Distance: ([a, b], compile2) => {
|
|
20812
|
+
if (a === null || b === null) throw new Error("Distance: need two points");
|
|
20813
|
+
return `_SYS.distance(${compile2(a)}, ${compile2(b)})`;
|
|
20175
20814
|
}
|
|
20176
20815
|
};
|
|
20177
20816
|
function toRI(c) {
|
|
20178
20817
|
return { re: c.re, im: c.im };
|
|
20179
20818
|
}
|
|
20819
|
+
function normalizeAlpha(a) {
|
|
20820
|
+
if (a === void 0) return void 0;
|
|
20821
|
+
if (!Number.isFinite(a)) return void 0;
|
|
20822
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
20823
|
+
return a;
|
|
20824
|
+
}
|
|
20180
20825
|
function toRgb255(input) {
|
|
20181
20826
|
if (typeof input === "string") {
|
|
20182
20827
|
const c = parseColor(input);
|
|
20183
|
-
|
|
20828
|
+
const rgb2 = {
|
|
20184
20829
|
r: c >>> 24 & 255,
|
|
20185
20830
|
g: c >>> 16 & 255,
|
|
20186
|
-
b: c >>> 8 & 255
|
|
20187
|
-
alpha: (c & 255) / 255
|
|
20831
|
+
b: c >>> 8 & 255
|
|
20188
20832
|
};
|
|
20833
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20834
|
+
if (alpha !== void 0) rgb2.alpha = alpha;
|
|
20835
|
+
return rgb2;
|
|
20836
|
+
}
|
|
20837
|
+
const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
|
|
20838
|
+
if (input.length >= 4) {
|
|
20839
|
+
const alpha = normalizeAlpha(input[3]);
|
|
20840
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
20189
20841
|
}
|
|
20190
|
-
const rgb = {
|
|
20191
|
-
r: input[0] * 255,
|
|
20192
|
-
g: input[1] * 255,
|
|
20193
|
-
b: input[2] * 255
|
|
20194
|
-
};
|
|
20195
|
-
if (input.length >= 4) rgb.alpha = input[3];
|
|
20196
20842
|
return rgb;
|
|
20197
20843
|
}
|
|
20198
|
-
function
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
|
|
20203
|
-
|
|
20844
|
+
function toOklch(input) {
|
|
20845
|
+
if (typeof input === "string") {
|
|
20846
|
+
const c = parseColor(input);
|
|
20847
|
+
const r = c >>> 24 & 255;
|
|
20848
|
+
const g = c >>> 16 & 255;
|
|
20849
|
+
const b = c >>> 8 & 255;
|
|
20850
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
20851
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20852
|
+
if (alpha !== void 0) oklch2.alpha = alpha;
|
|
20853
|
+
return oklch2;
|
|
20854
|
+
}
|
|
20855
|
+
return {
|
|
20856
|
+
L: input[0],
|
|
20857
|
+
C: input[1],
|
|
20858
|
+
H: input[2],
|
|
20859
|
+
alpha: input.length >= 4 ? normalizeAlpha(input[3]) : void 0
|
|
20860
|
+
};
|
|
20861
|
+
}
|
|
20862
|
+
function packedToOklch(c) {
|
|
20863
|
+
const r = c >>> 24 & 255;
|
|
20864
|
+
const g = c >>> 16 & 255;
|
|
20865
|
+
const b = c >>> 8 & 255;
|
|
20866
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
20867
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20868
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
20204
20869
|
}
|
|
20205
20870
|
var colorHelpers = {
|
|
20206
20871
|
color(input) {
|
|
20207
|
-
return
|
|
20872
|
+
return packedToOklch(parseColor(input));
|
|
20208
20873
|
},
|
|
20209
20874
|
colorToString(input, format) {
|
|
20210
20875
|
const rgb = toRgb255(input);
|
|
@@ -20215,7 +20880,7 @@ var colorHelpers = {
|
|
|
20215
20880
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
20216
20881
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
20217
20882
|
let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
20218
|
-
if (rgb.alpha !== void 0
|
|
20883
|
+
if (rgb.alpha !== void 0) {
|
|
20219
20884
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
20220
20885
|
hex += a.toString(16).padStart(2, "0");
|
|
20221
20886
|
}
|
|
@@ -20225,7 +20890,7 @@ var colorHelpers = {
|
|
|
20225
20890
|
const r = Math.round(rgb.r);
|
|
20226
20891
|
const g = Math.round(rgb.g);
|
|
20227
20892
|
const b = Math.round(rgb.b);
|
|
20228
|
-
if (rgb.alpha !== void 0
|
|
20893
|
+
if (rgb.alpha !== void 0)
|
|
20229
20894
|
return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
|
|
20230
20895
|
return `rgb(${r} ${g} ${b})`;
|
|
20231
20896
|
}
|
|
@@ -20234,7 +20899,7 @@ var colorHelpers = {
|
|
|
20234
20899
|
const h = Math.round(hsl.h * 10) / 10;
|
|
20235
20900
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
20236
20901
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
20237
|
-
if (rgb.alpha !== void 0
|
|
20902
|
+
if (rgb.alpha !== void 0)
|
|
20238
20903
|
return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
|
|
20239
20904
|
return `hsl(${h} ${s}% ${l}%)`;
|
|
20240
20905
|
}
|
|
@@ -20243,7 +20908,7 @@ var colorHelpers = {
|
|
|
20243
20908
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
20244
20909
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
20245
20910
|
const H = Math.round(c.H * 10) / 10;
|
|
20246
|
-
if (rgb.alpha !== void 0
|
|
20911
|
+
if (rgb.alpha !== void 0)
|
|
20247
20912
|
return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
|
|
20248
20913
|
return `oklch(${L} ${C} ${H})`;
|
|
20249
20914
|
}
|
|
@@ -20252,29 +20917,29 @@ var colorHelpers = {
|
|
|
20252
20917
|
}
|
|
20253
20918
|
},
|
|
20254
20919
|
colorMix(input1, input2, ratio = 0.5) {
|
|
20255
|
-
const
|
|
20256
|
-
const
|
|
20920
|
+
const c1 = toOklch(input1);
|
|
20921
|
+
const c2 = toOklch(input2);
|
|
20257
20922
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
20258
|
-
const
|
|
20259
|
-
const
|
|
20260
|
-
let
|
|
20261
|
-
if (
|
|
20262
|
-
if (
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
H
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
const
|
|
20273
|
-
const
|
|
20274
|
-
const a1 =
|
|
20275
|
-
const a2 =
|
|
20276
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
20277
|
-
return
|
|
20923
|
+
const c1Achromatic = c1.C < 1e-6;
|
|
20924
|
+
const c2Achromatic = c2.C < 1e-6;
|
|
20925
|
+
let H;
|
|
20926
|
+
if (c1Achromatic && c2Achromatic) H = c1.H;
|
|
20927
|
+
else if (c1Achromatic) H = c2.H;
|
|
20928
|
+
else if (c2Achromatic) H = c1.H;
|
|
20929
|
+
else {
|
|
20930
|
+
let dh = c2.H - c1.H;
|
|
20931
|
+
if (dh > 180) dh -= 360;
|
|
20932
|
+
if (dh < -180) dh += 360;
|
|
20933
|
+
H = c1.H + dh * ratio;
|
|
20934
|
+
if (H < 0) H += 360;
|
|
20935
|
+
if (H >= 360) H -= 360;
|
|
20936
|
+
}
|
|
20937
|
+
const L = c1.L + (c2.L - c1.L) * ratio;
|
|
20938
|
+
const C = c1.C + (c2.C - c1.C) * ratio;
|
|
20939
|
+
const a1 = c1.alpha ?? 1;
|
|
20940
|
+
const a2 = c2.alpha ?? 1;
|
|
20941
|
+
const alpha = normalizeAlpha(a1 + (a2 - a1) * ratio);
|
|
20942
|
+
return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
|
|
20278
20943
|
},
|
|
20279
20944
|
colorContrast(bg, fg) {
|
|
20280
20945
|
return apca(toRgb255(bg), toRgb255(fg));
|
|
@@ -20282,11 +20947,11 @@ var colorHelpers = {
|
|
|
20282
20947
|
contrastingColor(bg, fg1, fg2) {
|
|
20283
20948
|
const bgRgb = toRgb255(bg);
|
|
20284
20949
|
if (fg1 !== void 0 && fg2 !== void 0) {
|
|
20285
|
-
return
|
|
20950
|
+
return packedToOklch(
|
|
20286
20951
|
contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
|
|
20287
20952
|
);
|
|
20288
20953
|
}
|
|
20289
|
-
return
|
|
20954
|
+
return packedToOklch(contrastingColor(bgRgb));
|
|
20290
20955
|
},
|
|
20291
20956
|
colorToColorspace(input, space) {
|
|
20292
20957
|
const rgb = toRgb255(input);
|
|
@@ -20315,7 +20980,7 @@ var colorHelpers = {
|
|
|
20315
20980
|
default:
|
|
20316
20981
|
throw new Error(`Unknown color space: ${space}`);
|
|
20317
20982
|
}
|
|
20318
|
-
if (alpha !== void 0
|
|
20983
|
+
if (alpha !== void 0) result.push(alpha);
|
|
20319
20984
|
return result;
|
|
20320
20985
|
},
|
|
20321
20986
|
colormap(name, arg) {
|
|
@@ -20327,7 +20992,7 @@ var colorHelpers = {
|
|
|
20327
20992
|
const palette = allPalettes[name];
|
|
20328
20993
|
if (!palette) throw new Error(`Unknown palette: ${name}`);
|
|
20329
20994
|
const colors = palette.map(
|
|
20330
|
-
(hex) =>
|
|
20995
|
+
(hex) => packedToOklch(parseColor(hex))
|
|
20331
20996
|
);
|
|
20332
20997
|
if (arg === void 0) return colors;
|
|
20333
20998
|
if (Number.isInteger(arg) && arg >= 2) {
|
|
@@ -20351,62 +21016,128 @@ var colorHelpers = {
|
|
|
20351
21016
|
const frac = pos - i;
|
|
20352
21017
|
if (frac === 0 || i >= colors.length - 1)
|
|
20353
21018
|
return [...colors[Math.min(i, colors.length - 1)]];
|
|
20354
|
-
const
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
|
|
20370
|
-
|
|
20371
|
-
if (H >= 360) H -= 360;
|
|
20372
|
-
const mixed = oklchToRgb({
|
|
20373
|
-
L: c1.L + (c2.L - c1.L) * frac,
|
|
20374
|
-
C: c1.C + (c2.C - c1.C) * frac,
|
|
20375
|
-
H
|
|
20376
|
-
});
|
|
20377
|
-
return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
|
|
21019
|
+
const [L1, C1, H1] = colors[i];
|
|
21020
|
+
const [L2, C2, H2] = colors[i + 1];
|
|
21021
|
+
const c1Achromatic = C1 < 1e-6;
|
|
21022
|
+
const c2Achromatic = C2 < 1e-6;
|
|
21023
|
+
let H;
|
|
21024
|
+
if (c1Achromatic && c2Achromatic) H = H1;
|
|
21025
|
+
else if (c1Achromatic) H = H2;
|
|
21026
|
+
else if (c2Achromatic) H = H1;
|
|
21027
|
+
else {
|
|
21028
|
+
let dh = H2 - H1;
|
|
21029
|
+
if (dh > 180) dh -= 360;
|
|
21030
|
+
if (dh < -180) dh += 360;
|
|
21031
|
+
H = H1 + dh * frac;
|
|
21032
|
+
if (H < 0) H += 360;
|
|
21033
|
+
if (H >= 360) H -= 360;
|
|
21034
|
+
}
|
|
21035
|
+
return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
|
|
20378
21036
|
},
|
|
20379
21037
|
colorFromColorspace(components, space) {
|
|
20380
21038
|
const c0 = components[0];
|
|
20381
21039
|
const c1 = components[1];
|
|
20382
21040
|
const c2 = components[2];
|
|
20383
21041
|
const alpha = components.length >= 4 ? components[3] : void 0;
|
|
20384
|
-
let
|
|
21042
|
+
let oklch2;
|
|
20385
21043
|
switch (space.toLowerCase()) {
|
|
20386
21044
|
case "rgb":
|
|
20387
|
-
|
|
21045
|
+
oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
|
|
20388
21046
|
break;
|
|
20389
21047
|
case "hsl": {
|
|
20390
|
-
const
|
|
20391
|
-
|
|
21048
|
+
const rgb = hslToRgb(c0, c1, c2);
|
|
21049
|
+
oklch2 = rgbToOklch(rgb);
|
|
20392
21050
|
break;
|
|
20393
21051
|
}
|
|
20394
|
-
case "oklch":
|
|
20395
|
-
|
|
20396
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
21052
|
+
case "oklch":
|
|
21053
|
+
oklch2 = { L: c0, C: c1, H: c2 };
|
|
20397
21054
|
break;
|
|
20398
|
-
}
|
|
20399
21055
|
case "oklab":
|
|
20400
|
-
case "lab":
|
|
20401
|
-
|
|
20402
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
21056
|
+
case "lab":
|
|
21057
|
+
oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
|
|
20403
21058
|
break;
|
|
20404
|
-
}
|
|
20405
21059
|
default:
|
|
20406
21060
|
throw new Error(`Unknown color space: ${space}`);
|
|
20407
21061
|
}
|
|
20408
|
-
|
|
20409
|
-
|
|
21062
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
21063
|
+
},
|
|
21064
|
+
// -----------------------------------------------------------------------
|
|
21065
|
+
// Color constructors. Each accepts components in its colorspace's natural
|
|
21066
|
+
// units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
|
|
21067
|
+
// -----------------------------------------------------------------------
|
|
21068
|
+
rgb(r, g, b, alpha) {
|
|
21069
|
+
const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
|
|
21070
|
+
const a = normalizeAlpha(alpha);
|
|
21071
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21072
|
+
},
|
|
21073
|
+
hsv(h, s, v, alpha) {
|
|
21074
|
+
const rgb = hsvToRgb(h, s, v);
|
|
21075
|
+
const c = rgbToOklch(rgb);
|
|
21076
|
+
const a = normalizeAlpha(alpha);
|
|
21077
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21078
|
+
},
|
|
21079
|
+
hsl(h, s, l, alpha) {
|
|
21080
|
+
const rgb = hslToRgb(h, s, l);
|
|
21081
|
+
const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
|
|
21082
|
+
const a = normalizeAlpha(alpha);
|
|
21083
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21084
|
+
},
|
|
21085
|
+
oklab(L, a, b, alpha) {
|
|
21086
|
+
const c = oklabToOklch({ L, a, b });
|
|
21087
|
+
const al = normalizeAlpha(alpha);
|
|
21088
|
+
return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
|
|
21089
|
+
},
|
|
21090
|
+
oklch(L, C, H, alpha) {
|
|
21091
|
+
const a = normalizeAlpha(alpha);
|
|
21092
|
+
return a !== void 0 ? [L, C, H, a] : [L, C, H];
|
|
21093
|
+
},
|
|
21094
|
+
// -----------------------------------------------------------------------
|
|
21095
|
+
// As* converters. Inputs are anything `toOklch` accepts (string, packed
|
|
21096
|
+
// int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
|
|
21097
|
+
// space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
|
|
21098
|
+
// consistency with the GPU target's shader convention.
|
|
21099
|
+
// -----------------------------------------------------------------------
|
|
21100
|
+
asRgb(input) {
|
|
21101
|
+
const rgb = toRgb255(input);
|
|
21102
|
+
const r = rgb.r / 255;
|
|
21103
|
+
const g = rgb.g / 255;
|
|
21104
|
+
const b = rgb.b / 255;
|
|
21105
|
+
return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
|
|
21106
|
+
},
|
|
21107
|
+
asHsv(input) {
|
|
21108
|
+
const rgb = toRgb255(input);
|
|
21109
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
21110
|
+
return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
|
|
21111
|
+
},
|
|
21112
|
+
asHsl(input) {
|
|
21113
|
+
const rgb = toRgb255(input);
|
|
21114
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
21115
|
+
return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
|
|
21116
|
+
},
|
|
21117
|
+
asOklab(input) {
|
|
21118
|
+
const c = toOklch(input);
|
|
21119
|
+
const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
|
|
21120
|
+
return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
|
|
21121
|
+
},
|
|
21122
|
+
// asOklch is identity — handled at compile time as a pass-through
|
|
21123
|
+
// Perceptual color difference (ΔE_OK).
|
|
21124
|
+
colorDelta(a, b) {
|
|
21125
|
+
const labA = oklchToOklab(toOklch(a));
|
|
21126
|
+
const labB = oklchToOklab(toOklch(b));
|
|
21127
|
+
return oklabDeltaE(labA, labB);
|
|
21128
|
+
},
|
|
21129
|
+
// Euclidean distance between two tuples. Plain numeric — not a color
|
|
21130
|
+
// operation despite living in the same helpers block.
|
|
21131
|
+
distance(a, b) {
|
|
21132
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
21133
|
+
throw new Error("Distance: expected two arrays");
|
|
21134
|
+
if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
|
|
21135
|
+
let sumSq = 0;
|
|
21136
|
+
for (let i = 0; i < a.length; i++) {
|
|
21137
|
+
const d = a[i] - b[i];
|
|
21138
|
+
sumSq += d * d;
|
|
21139
|
+
}
|
|
21140
|
+
return Math.sqrt(sumSq);
|
|
20410
21141
|
}
|
|
20411
21142
|
};
|
|
20412
21143
|
var SYS_HELPERS = {
|
|
@@ -20845,6 +21576,13 @@ var GPU_OPERATORS = {
|
|
|
20845
21576
|
function gpuVec2(target) {
|
|
20846
21577
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
20847
21578
|
}
|
|
21579
|
+
function gpuVec3(target) {
|
|
21580
|
+
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
21581
|
+
}
|
|
21582
|
+
function readStringLiteral(expr) {
|
|
21583
|
+
if (!isString(expr)) return null;
|
|
21584
|
+
return expr.string?.toLowerCase() ?? null;
|
|
21585
|
+
}
|
|
20848
21586
|
function compileIntArg(expr, compile2, target) {
|
|
20849
21587
|
const c = tryGetConstant(expr);
|
|
20850
21588
|
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
@@ -20903,7 +21641,7 @@ function compileGPUSumProduct(kind, args, _compile, target) {
|
|
|
20903
21641
|
`for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
|
|
20904
21642
|
` ${acc} ${op}= ${body};`,
|
|
20905
21643
|
`}`,
|
|
20906
|
-
`return ${acc}
|
|
21644
|
+
`return ${acc};`
|
|
20907
21645
|
];
|
|
20908
21646
|
return lines.join("\n");
|
|
20909
21647
|
}
|
|
@@ -20957,8 +21695,7 @@ var GPU_FUNCTIONS = {
|
|
|
20957
21695
|
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
20958
21696
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
20959
21697
|
const v2 = gpuVec2(target);
|
|
20960
|
-
if (realFactors.length === 0)
|
|
20961
|
-
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
21698
|
+
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
20962
21699
|
const factors = realFactors.map((f) => compile2(f));
|
|
20963
21700
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
20964
21701
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
@@ -21011,8 +21748,7 @@ var GPU_FUNCTIONS = {
|
|
|
21011
21748
|
if (isNumber(x) && x.im !== 0) {
|
|
21012
21749
|
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
21013
21750
|
}
|
|
21014
|
-
if (isSymbol2(x, "ImaginaryUnit"))
|
|
21015
|
-
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
21751
|
+
if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
21016
21752
|
return `(-${compile2(x)})`;
|
|
21017
21753
|
},
|
|
21018
21754
|
// Standard math functions with complex dispatch
|
|
@@ -21385,17 +22121,127 @@ var GPU_FUNCTIONS = {
|
|
|
21385
22121
|
}
|
|
21386
22122
|
const isWGSL = target?.language === "wgsl";
|
|
21387
22123
|
const v3 = isWGSL ? "vec3f" : "vec3";
|
|
21388
|
-
|
|
22124
|
+
const black = `${v3}(0.0)`;
|
|
22125
|
+
const white = `${v3}(1.0, 0.0, 0.0)`;
|
|
22126
|
+
return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
|
|
21389
22127
|
},
|
|
21390
22128
|
ColorToColorspace: ([color, space], compile2) => {
|
|
21391
22129
|
if (color === null || space === null)
|
|
21392
22130
|
throw new Error("ColorToColorspace: need color and space");
|
|
21393
|
-
|
|
22131
|
+
const spaceName = readStringLiteral(space);
|
|
22132
|
+
if (spaceName === null)
|
|
22133
|
+
throw new Error("ColorToColorspace: space must be a string literal");
|
|
22134
|
+
const c = compile2(color);
|
|
22135
|
+
switch (spaceName) {
|
|
22136
|
+
case "oklch":
|
|
22137
|
+
return c;
|
|
22138
|
+
case "oklab":
|
|
22139
|
+
case "lab":
|
|
22140
|
+
return `_gpu_oklch_to_oklab(${c})`;
|
|
22141
|
+
case "rgb":
|
|
22142
|
+
return `_gpu_oklch_to_srgb(${c})`;
|
|
22143
|
+
case "hsl":
|
|
22144
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
|
|
22145
|
+
case "hsv":
|
|
22146
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
|
|
22147
|
+
default:
|
|
22148
|
+
throw new Error(
|
|
22149
|
+
`ColorToColorspace: unsupported space "${spaceName}" on GPU target`
|
|
22150
|
+
);
|
|
22151
|
+
}
|
|
21394
22152
|
},
|
|
21395
22153
|
ColorFromColorspace: ([components, space], compile2) => {
|
|
21396
22154
|
if (components === null || space === null)
|
|
21397
22155
|
throw new Error("ColorFromColorspace: need components and space");
|
|
21398
|
-
|
|
22156
|
+
const spaceName = readStringLiteral(space);
|
|
22157
|
+
if (spaceName === null)
|
|
22158
|
+
throw new Error("ColorFromColorspace: space must be a string literal");
|
|
22159
|
+
const c = compile2(components);
|
|
22160
|
+
switch (spaceName) {
|
|
22161
|
+
case "oklch":
|
|
22162
|
+
return c;
|
|
22163
|
+
case "oklab":
|
|
22164
|
+
case "lab":
|
|
22165
|
+
return `_gpu_oklab_to_oklch(${c})`;
|
|
22166
|
+
case "rgb":
|
|
22167
|
+
return `_gpu_srgb_to_oklch(${c})`;
|
|
22168
|
+
case "hsl":
|
|
22169
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
|
|
22170
|
+
case "hsv":
|
|
22171
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
|
|
22172
|
+
default:
|
|
22173
|
+
throw new Error(
|
|
22174
|
+
`ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
|
|
22175
|
+
);
|
|
22176
|
+
}
|
|
22177
|
+
},
|
|
22178
|
+
// ---------------------------------------------------------------------------
|
|
22179
|
+
// Color literals. Each typed head compiles to a canonical OKLCh vec3.
|
|
22180
|
+
// Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
|
|
22181
|
+
// alpha as a separate uniform if it's needed at the framebuffer boundary.
|
|
22182
|
+
// ---------------------------------------------------------------------------
|
|
22183
|
+
Color: ([s], _compile, target) => {
|
|
22184
|
+
if (s === null) throw new Error("Color: no argument");
|
|
22185
|
+
const str = readStringLiteral(s);
|
|
22186
|
+
if (str === null)
|
|
22187
|
+
throw new Error("Color: argument must be a string literal on GPU target");
|
|
22188
|
+
const packed = parseColor(str);
|
|
22189
|
+
if (packed === 0 && str.trim().toLowerCase() !== "transparent")
|
|
22190
|
+
throw new Error(`Color: invalid color string "${str}"`);
|
|
22191
|
+
const r = packed >>> 24 & 255;
|
|
22192
|
+
const g = packed >>> 16 & 255;
|
|
22193
|
+
const b = packed >>> 8 & 255;
|
|
22194
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
22195
|
+
return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
|
|
22196
|
+
},
|
|
22197
|
+
Rgb: (args, compile2, target) => {
|
|
22198
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
22199
|
+
const v3 = gpuVec3(target);
|
|
22200
|
+
return `_gpu_srgb_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
|
|
22201
|
+
},
|
|
22202
|
+
Hsv: (args, compile2, target) => {
|
|
22203
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
22204
|
+
const v3 = gpuVec3(target);
|
|
22205
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
|
|
22206
|
+
},
|
|
22207
|
+
Hsl: (args, compile2, target) => {
|
|
22208
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
22209
|
+
const v3 = gpuVec3(target);
|
|
22210
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
|
|
22211
|
+
},
|
|
22212
|
+
Oklab: (args, compile2, target) => {
|
|
22213
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
22214
|
+
const v3 = gpuVec3(target);
|
|
22215
|
+
return `_gpu_oklab_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
|
|
22216
|
+
},
|
|
22217
|
+
Oklch: (args, compile2, target) => {
|
|
22218
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
22219
|
+
const v3 = gpuVec3(target);
|
|
22220
|
+
return `${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})`;
|
|
22221
|
+
},
|
|
22222
|
+
// ---------------------------------------------------------------------------
|
|
22223
|
+
// As* operators. AsOklch is identity (canonical). The other As* return
|
|
22224
|
+
// components in the named space, equivalent to ColorToColorspace(c, 'x').
|
|
22225
|
+
// ---------------------------------------------------------------------------
|
|
22226
|
+
AsOklch: ([c], compile2) => {
|
|
22227
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
22228
|
+
return compile2(c);
|
|
22229
|
+
},
|
|
22230
|
+
AsOklab: ([c], compile2) => {
|
|
22231
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
22232
|
+
return `_gpu_oklch_to_oklab(${compile2(c)})`;
|
|
22233
|
+
},
|
|
22234
|
+
AsRgb: ([c], compile2) => {
|
|
22235
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
22236
|
+
return `_gpu_oklch_to_srgb(${compile2(c)})`;
|
|
22237
|
+
},
|
|
22238
|
+
AsHsv: ([c], compile2) => {
|
|
22239
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
22240
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile2(c)}))`;
|
|
22241
|
+
},
|
|
22242
|
+
AsHsl: ([c], compile2) => {
|
|
22243
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
22244
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile2(c)}))`;
|
|
21399
22245
|
},
|
|
21400
22246
|
// Fractal functions
|
|
21401
22247
|
Mandelbrot: ([c, maxIter], compile2, target) => {
|
|
@@ -22088,28 +22934,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
|
|
|
22088
22934
|
|
|
22089
22935
|
vec3 _gpu_oklab_to_oklch(vec3 lab) {
|
|
22090
22936
|
float C = length(lab.yz);
|
|
22091
|
-
float H = atan(lab.z, lab.y);
|
|
22937
|
+
float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
22938
|
+
if (H < 0.0) H += 360.0;
|
|
22092
22939
|
return vec3(lab.x, C, H);
|
|
22093
22940
|
}
|
|
22094
22941
|
|
|
22095
22942
|
vec3 _gpu_oklch_to_oklab(vec3 lch) {
|
|
22096
|
-
|
|
22943
|
+
float h_rad = lch.z * (3.14159265359 / 180.0);
|
|
22944
|
+
return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
22945
|
+
}
|
|
22946
|
+
|
|
22947
|
+
vec3 _gpu_srgb_to_oklch(vec3 rgb) {
|
|
22948
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
22949
|
+
}
|
|
22950
|
+
|
|
22951
|
+
vec3 _gpu_oklch_to_srgb(vec3 lch) {
|
|
22952
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
22953
|
+
}
|
|
22954
|
+
|
|
22955
|
+
// HSL conversion. Hue in degrees, saturation/lightness in 0-1.
|
|
22956
|
+
vec3 _gpu_hsl_to_rgb(vec3 hsl) {
|
|
22957
|
+
float h = hsl.x;
|
|
22958
|
+
float s = hsl.y;
|
|
22959
|
+
float l = hsl.z;
|
|
22960
|
+
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
22961
|
+
float h6 = h / 60.0;
|
|
22962
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
22963
|
+
float r = 0.0;
|
|
22964
|
+
float g = 0.0;
|
|
22965
|
+
float b = 0.0;
|
|
22966
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
22967
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
22968
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
22969
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
22970
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
22971
|
+
else { r = c; g = 0.0; b = x; }
|
|
22972
|
+
float m = l - c / 2.0;
|
|
22973
|
+
return vec3(r + m, g + m, b + m);
|
|
22097
22974
|
}
|
|
22098
22975
|
|
|
22099
|
-
vec3
|
|
22100
|
-
|
|
22101
|
-
|
|
22976
|
+
vec3 _gpu_rgb_to_hsl(vec3 rgb) {
|
|
22977
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
22978
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
22979
|
+
float l = (maxc + minc) / 2.0;
|
|
22980
|
+
float d = maxc - minc;
|
|
22981
|
+
if (d < 1e-6) return vec3(0.0, 0.0, l);
|
|
22982
|
+
float s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
22983
|
+
float h;
|
|
22984
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
22985
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
22986
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
22987
|
+
h *= 60.0;
|
|
22988
|
+
if (h < 0.0) h += 360.0;
|
|
22989
|
+
return vec3(h, s, l);
|
|
22990
|
+
}
|
|
22991
|
+
|
|
22992
|
+
// HSV conversion. Hue in degrees, saturation/value in 0-1.
|
|
22993
|
+
vec3 _gpu_hsv_to_rgb(vec3 hsv) {
|
|
22994
|
+
float h = hsv.x;
|
|
22995
|
+
float s = hsv.y;
|
|
22996
|
+
float v = hsv.z;
|
|
22997
|
+
float c = v * s;
|
|
22998
|
+
float h6 = h / 60.0;
|
|
22999
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
23000
|
+
float r = 0.0;
|
|
23001
|
+
float g = 0.0;
|
|
23002
|
+
float b = 0.0;
|
|
23003
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23004
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23005
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23006
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23007
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23008
|
+
else { r = c; g = 0.0; b = x; }
|
|
23009
|
+
float m = v - c;
|
|
23010
|
+
return vec3(r + m, g + m, b + m);
|
|
23011
|
+
}
|
|
23012
|
+
|
|
23013
|
+
vec3 _gpu_rgb_to_hsv(vec3 rgb) {
|
|
23014
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23015
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23016
|
+
float v = maxc;
|
|
23017
|
+
float d = maxc - minc;
|
|
23018
|
+
if (d < 1e-6) return vec3(0.0, 0.0, v);
|
|
23019
|
+
float s = (maxc < 1e-6) ? 0.0 : d / maxc;
|
|
23020
|
+
float h;
|
|
23021
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
23022
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
23023
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
23024
|
+
h *= 60.0;
|
|
23025
|
+
if (h < 0.0) h += 360.0;
|
|
23026
|
+
return vec3(h, s, v);
|
|
23027
|
+
}
|
|
23028
|
+
|
|
23029
|
+
vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
|
|
22102
23030
|
float L = mix(lch1.x, lch2.x, t);
|
|
22103
23031
|
float C = mix(lch1.y, lch2.y, t);
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
if (
|
|
22108
|
-
|
|
22109
|
-
|
|
23032
|
+
bool a1 = lch1.y < 1e-6;
|
|
23033
|
+
bool a2 = lch2.y < 1e-6;
|
|
23034
|
+
float H;
|
|
23035
|
+
if (a1 && a2) {
|
|
23036
|
+
H = lch1.z;
|
|
23037
|
+
} else if (a1) {
|
|
23038
|
+
H = lch2.z;
|
|
23039
|
+
} else if (a2) {
|
|
23040
|
+
H = lch1.z;
|
|
23041
|
+
} else {
|
|
23042
|
+
float dh = lch2.z - lch1.z;
|
|
23043
|
+
if (dh > 180.0) dh -= 360.0;
|
|
23044
|
+
if (dh < -180.0) dh += 360.0;
|
|
23045
|
+
H = lch1.z + dh * t;
|
|
23046
|
+
if (H < 0.0) H += 360.0;
|
|
23047
|
+
if (H >= 360.0) H -= 360.0;
|
|
23048
|
+
}
|
|
23049
|
+
return vec3(L, C, H);
|
|
22110
23050
|
}
|
|
22111
23051
|
|
|
22112
|
-
float _gpu_apca(vec3
|
|
23052
|
+
float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
|
|
23053
|
+
vec3 bg = _gpu_oklch_to_srgb(lch_bg);
|
|
23054
|
+
vec3 fg = _gpu_oklch_to_srgb(lch_fg);
|
|
22113
23055
|
float bgR = _gpu_srgb_to_linear(bg.x);
|
|
22114
23056
|
float bgG = _gpu_srgb_to_linear(bg.y);
|
|
22115
23057
|
float bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -22120,9 +23062,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
|
|
|
22120
23062
|
float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
|
|
22121
23063
|
float bgC = pow(bgY, 0.56);
|
|
22122
23064
|
float fgC = pow(fgY, 0.57);
|
|
22123
|
-
float contrast = (bgC
|
|
22124
|
-
? (bgC - fgC) * 1.14
|
|
22125
|
-
: (bgC - fgC) * 1.14;
|
|
23065
|
+
float contrast = (bgC - fgC) * 1.14;
|
|
22126
23066
|
return contrast * 100.0;
|
|
22127
23067
|
}
|
|
22128
23068
|
`;
|
|
@@ -22166,28 +23106,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
|
|
|
22166
23106
|
|
|
22167
23107
|
fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
|
|
22168
23108
|
let C = length(lab.yz);
|
|
22169
|
-
|
|
23109
|
+
var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
23110
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
22170
23111
|
return vec3f(lab.x, C, H);
|
|
22171
23112
|
}
|
|
22172
23113
|
|
|
22173
23114
|
fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
|
|
22174
|
-
|
|
23115
|
+
let h_rad = lch.z * (3.14159265359 / 180.0);
|
|
23116
|
+
return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
22175
23117
|
}
|
|
22176
23118
|
|
|
22177
|
-
fn
|
|
22178
|
-
|
|
22179
|
-
|
|
23119
|
+
fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
|
|
23120
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
23121
|
+
}
|
|
23122
|
+
|
|
23123
|
+
fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
|
|
23124
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
23125
|
+
}
|
|
23126
|
+
|
|
23127
|
+
fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
|
|
23128
|
+
let h = hsl.x;
|
|
23129
|
+
let s = hsl.y;
|
|
23130
|
+
let l = hsl.z;
|
|
23131
|
+
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
23132
|
+
let h6 = h / 60.0;
|
|
23133
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
23134
|
+
var r: f32 = 0.0;
|
|
23135
|
+
var g: f32 = 0.0;
|
|
23136
|
+
var b: f32 = 0.0;
|
|
23137
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23138
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23139
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23140
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23141
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23142
|
+
else { r = c; g = 0.0; b = x; }
|
|
23143
|
+
let m = l - c / 2.0;
|
|
23144
|
+
return vec3f(r + m, g + m, b + m);
|
|
23145
|
+
}
|
|
23146
|
+
|
|
23147
|
+
fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
|
|
23148
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23149
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23150
|
+
let l = (maxc + minc) / 2.0;
|
|
23151
|
+
let d = maxc - minc;
|
|
23152
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
|
|
23153
|
+
let s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
23154
|
+
var h: f32;
|
|
23155
|
+
if (maxc == rgb.x) {
|
|
23156
|
+
let v = (rgb.y - rgb.z) / d;
|
|
23157
|
+
h = v - 6.0 * floor(v / 6.0);
|
|
23158
|
+
} else if (maxc == rgb.y) {
|
|
23159
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
23160
|
+
} else {
|
|
23161
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
23162
|
+
}
|
|
23163
|
+
h = h * 60.0;
|
|
23164
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
23165
|
+
return vec3f(h, s, l);
|
|
23166
|
+
}
|
|
23167
|
+
|
|
23168
|
+
fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
|
|
23169
|
+
let h = hsv.x;
|
|
23170
|
+
let s = hsv.y;
|
|
23171
|
+
let v = hsv.z;
|
|
23172
|
+
let c = v * s;
|
|
23173
|
+
let h6 = h / 60.0;
|
|
23174
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
23175
|
+
var r: f32 = 0.0;
|
|
23176
|
+
var g: f32 = 0.0;
|
|
23177
|
+
var b: f32 = 0.0;
|
|
23178
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23179
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23180
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23181
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23182
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23183
|
+
else { r = c; g = 0.0; b = x; }
|
|
23184
|
+
let m = v - c;
|
|
23185
|
+
return vec3f(r + m, g + m, b + m);
|
|
23186
|
+
}
|
|
23187
|
+
|
|
23188
|
+
fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
|
|
23189
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23190
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23191
|
+
let v = maxc;
|
|
23192
|
+
let d = maxc - minc;
|
|
23193
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
|
|
23194
|
+
var s: f32 = 0.0;
|
|
23195
|
+
if (maxc >= 1e-6) { s = d / maxc; }
|
|
23196
|
+
var h: f32;
|
|
23197
|
+
if (maxc == rgb.x) {
|
|
23198
|
+
let q = (rgb.y - rgb.z) / d;
|
|
23199
|
+
h = q - 6.0 * floor(q / 6.0);
|
|
23200
|
+
} else if (maxc == rgb.y) {
|
|
23201
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
23202
|
+
} else {
|
|
23203
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
23204
|
+
}
|
|
23205
|
+
h = h * 60.0;
|
|
23206
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
23207
|
+
return vec3f(h, s, v);
|
|
23208
|
+
}
|
|
23209
|
+
|
|
23210
|
+
fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
|
|
22180
23211
|
let L = mix(lch1.x, lch2.x, t);
|
|
22181
23212
|
let C = mix(lch1.y, lch2.y, t);
|
|
22182
|
-
let
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
if (
|
|
22186
|
-
|
|
22187
|
-
|
|
23213
|
+
let a1 = lch1.y < 1e-6;
|
|
23214
|
+
let a2 = lch2.y < 1e-6;
|
|
23215
|
+
var H: f32;
|
|
23216
|
+
if (a1 && a2) {
|
|
23217
|
+
H = lch1.z;
|
|
23218
|
+
} else if (a1) {
|
|
23219
|
+
H = lch2.z;
|
|
23220
|
+
} else if (a2) {
|
|
23221
|
+
H = lch1.z;
|
|
23222
|
+
} else {
|
|
23223
|
+
var dh = lch2.z - lch1.z;
|
|
23224
|
+
if (dh > 180.0) { dh = dh - 360.0; }
|
|
23225
|
+
if (dh < -180.0) { dh = dh + 360.0; }
|
|
23226
|
+
H = lch1.z + dh * t;
|
|
23227
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
23228
|
+
if (H >= 360.0) { H = H - 360.0; }
|
|
23229
|
+
}
|
|
23230
|
+
return vec3f(L, C, H);
|
|
22188
23231
|
}
|
|
22189
23232
|
|
|
22190
|
-
fn _gpu_apca(
|
|
23233
|
+
fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
23234
|
+
let bg = _gpu_oklch_to_srgb(lch_bg);
|
|
23235
|
+
let fg = _gpu_oklch_to_srgb(lch_fg);
|
|
22191
23236
|
let bgR = _gpu_srgb_to_linear(bg.x);
|
|
22192
23237
|
let bgG = _gpu_srgb_to_linear(bg.y);
|
|
22193
23238
|
let bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -22475,7 +23520,7 @@ var GPUShaderTarget = class {
|
|
|
22475
23520
|
if (stmts.length === 0) return "";
|
|
22476
23521
|
const last = stmts.length - 1;
|
|
22477
23522
|
stmts[last] = `return ${stmts[last]}`;
|
|
22478
|
-
return stmts.join(";\n");
|
|
23523
|
+
return stmts.join(";\n") + ";";
|
|
22479
23524
|
},
|
|
22480
23525
|
...options
|
|
22481
23526
|
};
|
|
@@ -22574,7 +23619,7 @@ var GLSLTarget = class extends GPUShaderTarget {
|
|
|
22574
23619
|
if (body.includes("\n")) {
|
|
22575
23620
|
const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
|
|
22576
23621
|
return `${returnType} ${functionName}(${params}) {
|
|
22577
|
-
${indented}
|
|
23622
|
+
${indented}
|
|
22578
23623
|
}`;
|
|
22579
23624
|
}
|
|
22580
23625
|
return `${returnType} ${functionName}(${params}) {
|
|
@@ -22685,7 +23730,7 @@ var WGSLTarget = class extends GPUShaderTarget {
|
|
|
22685
23730
|
return `fn ${functionName}(${params}) -> ${toWGSLType(
|
|
22686
23731
|
returnType
|
|
22687
23732
|
)} {
|
|
22688
|
-
${indented}
|
|
23733
|
+
${indented}
|
|
22689
23734
|
}`;
|
|
22690
23735
|
}
|
|
22691
23736
|
return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
|
|
@@ -24864,7 +25909,7 @@ function compileToIntervalTarget(expr, target) {
|
|
|
24864
25909
|
}
|
|
24865
25910
|
|
|
24866
25911
|
// src/compile.ts
|
|
24867
|
-
var version = "0.
|
|
25912
|
+
var version = "0.57.0";
|
|
24868
25913
|
export {
|
|
24869
25914
|
BaseCompiler,
|
|
24870
25915
|
GLSLTarget,
|