@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.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compile 0.
|
|
1
|
+
/** Compile 0.57.0 */
|
|
2
2
|
(function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Compile = {}));})(this, (function (exports) { 'use strict';
|
|
3
3
|
var Compile = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1544,6 +1544,7 @@ var Compile = (() => {
|
|
|
1544
1544
|
];
|
|
1545
1545
|
var VALUE_TYPES = [
|
|
1546
1546
|
"value",
|
|
1547
|
+
"color",
|
|
1547
1548
|
...COLLECTION_TYPES,
|
|
1548
1549
|
...SCALAR_TYPES
|
|
1549
1550
|
];
|
|
@@ -3239,6 +3240,7 @@ var Compile = (() => {
|
|
|
3239
3240
|
symbol: [],
|
|
3240
3241
|
boolean: [],
|
|
3241
3242
|
string: [],
|
|
3243
|
+
color: [],
|
|
3242
3244
|
expression: EXPRESSION_TYPES
|
|
3243
3245
|
};
|
|
3244
3246
|
function isPrimitiveSubtype(lhs, rhs) {
|
|
@@ -5209,6 +5211,64 @@ var Compile = (() => {
|
|
|
5209
5211
|
}
|
|
5210
5212
|
|
|
5211
5213
|
// src/compute-engine/latex-syntax/dictionary/definitions-core.ts
|
|
5214
|
+
var COMPONENT_ACCESS_HEADS = {
|
|
5215
|
+
x: "First",
|
|
5216
|
+
y: "Second",
|
|
5217
|
+
z: "Third",
|
|
5218
|
+
real: "Real",
|
|
5219
|
+
re: "Real",
|
|
5220
|
+
imag: "Imaginary",
|
|
5221
|
+
im: "Imaginary",
|
|
5222
|
+
count: "Length",
|
|
5223
|
+
total: "Sum",
|
|
5224
|
+
max: "Max",
|
|
5225
|
+
min: "Min"
|
|
5226
|
+
};
|
|
5227
|
+
function memberHead(name) {
|
|
5228
|
+
return COMPONENT_ACCESS_HEADS[name] ?? null;
|
|
5229
|
+
}
|
|
5230
|
+
function parseComponentAccess(parser, lhs) {
|
|
5231
|
+
parser.skipVisualSpace();
|
|
5232
|
+
if (parser.match("\\operatorname")) {
|
|
5233
|
+
const name = parser.parseStringGroup();
|
|
5234
|
+
if (name === null) return null;
|
|
5235
|
+
const head = memberHead(name.trim());
|
|
5236
|
+
if (head === null) return null;
|
|
5237
|
+
return [head, lhs];
|
|
5238
|
+
}
|
|
5239
|
+
const tok = parser.peek;
|
|
5240
|
+
if (typeof tok === "string" && tok.startsWith("\\")) {
|
|
5241
|
+
const bare = tok.slice(1);
|
|
5242
|
+
const head = memberHead(bare);
|
|
5243
|
+
if (head !== null) {
|
|
5244
|
+
parser.nextToken();
|
|
5245
|
+
return [head, lhs];
|
|
5246
|
+
}
|
|
5247
|
+
return null;
|
|
5248
|
+
}
|
|
5249
|
+
if (typeof tok === "string" && /^[a-zA-Z]$/.test(tok)) {
|
|
5250
|
+
const head = memberHead(tok);
|
|
5251
|
+
if (head === null) return null;
|
|
5252
|
+
parser.nextToken();
|
|
5253
|
+
return [head, lhs];
|
|
5254
|
+
}
|
|
5255
|
+
return null;
|
|
5256
|
+
}
|
|
5257
|
+
function parseWhenRestriction(parser, lhs, close) {
|
|
5258
|
+
parser.addBoundary(close);
|
|
5259
|
+
parser.skipVisualSpace();
|
|
5260
|
+
const cond = parser.parseExpression({ minPrec: 0 });
|
|
5261
|
+
if (cond === null) {
|
|
5262
|
+
parser.removeBoundary();
|
|
5263
|
+
return null;
|
|
5264
|
+
}
|
|
5265
|
+
parser.skipVisualSpace();
|
|
5266
|
+
if (!parser.matchBoundary()) {
|
|
5267
|
+
parser.removeBoundary();
|
|
5268
|
+
return null;
|
|
5269
|
+
}
|
|
5270
|
+
return ["When", lhs, cond];
|
|
5271
|
+
}
|
|
5212
5272
|
function parseSequence(parser, terminator, lhs, prec, sep) {
|
|
5213
5273
|
if (terminator && terminator.minPrec >= prec) return null;
|
|
5214
5274
|
const result = lhs ? [lhs] : ["Nothing"];
|
|
@@ -5680,6 +5740,15 @@ var Compile = (() => {
|
|
|
5680
5740
|
}
|
|
5681
5741
|
},
|
|
5682
5742
|
{ name: "LatexTokens", serialize: serializeLatexTokens },
|
|
5743
|
+
// Component-access postfix: expr.member (C3)
|
|
5744
|
+
// The '.' trigger is consumed before the parse function is called.
|
|
5745
|
+
// Precedence 850 > 810 (At/indexing) so .x chains tightly.
|
|
5746
|
+
{
|
|
5747
|
+
kind: "postfix",
|
|
5748
|
+
precedence: 850,
|
|
5749
|
+
latexTrigger: ["."],
|
|
5750
|
+
parse: parseComponentAccess
|
|
5751
|
+
},
|
|
5683
5752
|
{
|
|
5684
5753
|
name: "At",
|
|
5685
5754
|
kind: "postfix",
|
|
@@ -5700,6 +5769,29 @@ var Compile = (() => {
|
|
|
5700
5769
|
latexTrigger: ["\\left", "\\lbrack"],
|
|
5701
5770
|
parse: parseAt("\\right", "\\rbrack")
|
|
5702
5771
|
},
|
|
5772
|
+
// When-restriction: `expr\left\{cond\right\}` → `When(expr, cond)` (D3)
|
|
5773
|
+
{
|
|
5774
|
+
name: "When",
|
|
5775
|
+
kind: "postfix",
|
|
5776
|
+
precedence: 800,
|
|
5777
|
+
latexTrigger: ["\\left", "\\{"],
|
|
5778
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\right", "\\}"]),
|
|
5779
|
+
serialize: (serializer, expr) => {
|
|
5780
|
+
const e = operand(expr, 1);
|
|
5781
|
+
const cond = operand(expr, 2);
|
|
5782
|
+
if (!e || !cond) return "";
|
|
5783
|
+
const clauses = operator(cond) === "And" ? operands(cond) ?? [] : [cond];
|
|
5784
|
+
const inner = clauses.map((c) => `\\left\\{${serializer.serialize(c)}\\right\\}`).join("");
|
|
5785
|
+
return `${serializer.serialize(e)}${inner}`;
|
|
5786
|
+
}
|
|
5787
|
+
},
|
|
5788
|
+
// When-restriction: bare `expr\{cond\}` → `When(expr, cond)`
|
|
5789
|
+
{
|
|
5790
|
+
kind: "postfix",
|
|
5791
|
+
precedence: 800,
|
|
5792
|
+
latexTrigger: ["\\{"],
|
|
5793
|
+
parse: (parser, lhs) => parseWhenRestriction(parser, lhs, ["\\}"])
|
|
5794
|
+
},
|
|
5703
5795
|
{
|
|
5704
5796
|
kind: "postfix",
|
|
5705
5797
|
latexTrigger: ["_"],
|
|
@@ -5782,6 +5874,29 @@ var Compile = (() => {
|
|
|
5782
5874
|
return "";
|
|
5783
5875
|
}
|
|
5784
5876
|
},
|
|
5877
|
+
// Additional triggers for Range: `...`, `\ldots`, and `\dots` are
|
|
5878
|
+
// equivalent to `..` when used as infix operators (e.g. `[1...9]`).
|
|
5879
|
+
// No `name` field here — names must be unique per the dictionary rules;
|
|
5880
|
+
// the first Range entry owns the name. When there is no LHS the symbol
|
|
5881
|
+
// entries near the top of the file still fire (ContinuationPlaceholder).
|
|
5882
|
+
{
|
|
5883
|
+
latexTrigger: [".", ".", "."],
|
|
5884
|
+
kind: "infix",
|
|
5885
|
+
precedence: 800,
|
|
5886
|
+
parse: parseRange
|
|
5887
|
+
},
|
|
5888
|
+
{
|
|
5889
|
+
latexTrigger: ["\\ldots"],
|
|
5890
|
+
kind: "infix",
|
|
5891
|
+
precedence: 800,
|
|
5892
|
+
parse: parseRange
|
|
5893
|
+
},
|
|
5894
|
+
{
|
|
5895
|
+
latexTrigger: ["\\dots"],
|
|
5896
|
+
kind: "infix",
|
|
5897
|
+
precedence: 800,
|
|
5898
|
+
parse: parseRange
|
|
5899
|
+
},
|
|
5785
5900
|
{
|
|
5786
5901
|
latexTrigger: [";"],
|
|
5787
5902
|
kind: "infix",
|
|
@@ -5966,13 +6081,24 @@ var Compile = (() => {
|
|
|
5966
6081
|
const args = operands(expr);
|
|
5967
6082
|
if (!args || args.length < 2) return "";
|
|
5968
6083
|
const body = args[0];
|
|
5969
|
-
const
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
6084
|
+
const elements = args.slice(1);
|
|
6085
|
+
const allElements = elements.every((e) => operator(e) === "Element");
|
|
6086
|
+
if (!allElements) {
|
|
6087
|
+
return joinLatex([
|
|
6088
|
+
"\\operatorname{Loop}(",
|
|
6089
|
+
serializer.serialize(body),
|
|
6090
|
+
", ",
|
|
6091
|
+
serializer.serialize(elements[0]),
|
|
6092
|
+
")"
|
|
6093
|
+
]);
|
|
6094
|
+
}
|
|
6095
|
+
if (elements.length === 1) {
|
|
6096
|
+
const elem = elements[0];
|
|
6097
|
+
const index = operand(elem, 1);
|
|
6098
|
+
const coll = operand(elem, 2);
|
|
6099
|
+
if (operator(coll) === "Range") {
|
|
6100
|
+
const lo = operand(coll, 1);
|
|
6101
|
+
const hi = operand(coll, 2);
|
|
5976
6102
|
return joinLatex([
|
|
5977
6103
|
"\\text{for }",
|
|
5978
6104
|
serializer.serialize(index),
|
|
@@ -5984,13 +6110,27 @@ var Compile = (() => {
|
|
|
5984
6110
|
serializer.serialize(body)
|
|
5985
6111
|
]);
|
|
5986
6112
|
}
|
|
6113
|
+
return joinLatex([
|
|
6114
|
+
serializer.serialize(body),
|
|
6115
|
+
" \\operatorname{for} ",
|
|
6116
|
+
serializer.serialize(index),
|
|
6117
|
+
" = ",
|
|
6118
|
+
serializer.serialize(coll)
|
|
6119
|
+
]);
|
|
5987
6120
|
}
|
|
6121
|
+
const bindings = elements.map((elem) => {
|
|
6122
|
+
const name = operand(elem, 1);
|
|
6123
|
+
const coll = operand(elem, 2);
|
|
6124
|
+
return joinLatex([
|
|
6125
|
+
serializer.serialize(name),
|
|
6126
|
+
" = ",
|
|
6127
|
+
serializer.serialize(coll)
|
|
6128
|
+
]);
|
|
6129
|
+
}).join(", ");
|
|
5988
6130
|
return joinLatex([
|
|
5989
|
-
"\\operatorname{Loop}(",
|
|
5990
6131
|
serializer.serialize(body),
|
|
5991
|
-
"
|
|
5992
|
-
|
|
5993
|
-
")"
|
|
6132
|
+
" \\operatorname{for} ",
|
|
6133
|
+
bindings
|
|
5994
6134
|
]);
|
|
5995
6135
|
}
|
|
5996
6136
|
},
|
|
@@ -6023,6 +6163,18 @@ var Compile = (() => {
|
|
|
6023
6163
|
precedence: 245,
|
|
6024
6164
|
parse: (parser, until) => parseForExpression(parser, until)
|
|
6025
6165
|
},
|
|
6166
|
+
// \operatorname{for} as postfix infix (list comprehension):
|
|
6167
|
+
// `body \operatorname{for} x = L_1, y = L_2`
|
|
6168
|
+
// Precedence 19 — just below comma (20) so the body is allowed to use
|
|
6169
|
+
// any operator (including comma sequencing) up to the keyword, and the
|
|
6170
|
+
// bindings can be comma-separated below us.
|
|
6171
|
+
{
|
|
6172
|
+
symbolTrigger: "for",
|
|
6173
|
+
kind: "infix",
|
|
6174
|
+
associativity: "none",
|
|
6175
|
+
precedence: 19,
|
|
6176
|
+
parse: (parser, lhs, until) => parseForComprehension(parser, lhs, until)
|
|
6177
|
+
},
|
|
6026
6178
|
// \operatorname{break}
|
|
6027
6179
|
{
|
|
6028
6180
|
symbolTrigger: "break",
|
|
@@ -6227,7 +6379,10 @@ var Compile = (() => {
|
|
|
6227
6379
|
if (!sym2 || !parser.getSymbolType(sym2).matches("function")) return null;
|
|
6228
6380
|
parser.addBoundary([")"]);
|
|
6229
6381
|
const expr = parser.parseExpression(until);
|
|
6230
|
-
if (!parser.matchBoundary())
|
|
6382
|
+
if (!parser.matchBoundary()) {
|
|
6383
|
+
parser.removeBoundary();
|
|
6384
|
+
return null;
|
|
6385
|
+
}
|
|
6231
6386
|
if (!parser.match("<}>")) return null;
|
|
6232
6387
|
return ["Derivative", lhs, expr];
|
|
6233
6388
|
}
|
|
@@ -6668,7 +6823,12 @@ var Compile = (() => {
|
|
|
6668
6823
|
if (isEmptySequence(body)) return ["List"];
|
|
6669
6824
|
const h = operator(body);
|
|
6670
6825
|
if (h === "Range" || h === "Linspace") return body;
|
|
6671
|
-
if (h === "Sequence")
|
|
6826
|
+
if (h === "Sequence") {
|
|
6827
|
+
const elems = operands(body);
|
|
6828
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6829
|
+
if (inferred) return inferred;
|
|
6830
|
+
return ["List", ...elems];
|
|
6831
|
+
}
|
|
6672
6832
|
if (h === "Delimiter") {
|
|
6673
6833
|
const delim = stringValue(operand(body, 2)) ?? "...";
|
|
6674
6834
|
if (delim === ";" || delim === ".;.") {
|
|
@@ -6681,12 +6841,37 @@ var Compile = (() => {
|
|
|
6681
6841
|
}
|
|
6682
6842
|
if (delim === "," || delim === ".,.") {
|
|
6683
6843
|
body = operand(body, 1);
|
|
6684
|
-
if (operator(body) === "Sequence")
|
|
6844
|
+
if (operator(body) === "Sequence") {
|
|
6845
|
+
const elems = operands(body);
|
|
6846
|
+
const inferred = tryInferRangeFromElements(elems, parser);
|
|
6847
|
+
if (inferred) return inferred;
|
|
6848
|
+
return ["List", ...elems];
|
|
6849
|
+
}
|
|
6685
6850
|
return ["List", body ?? "Nothing"];
|
|
6686
6851
|
}
|
|
6687
6852
|
}
|
|
6688
6853
|
return ["List", body];
|
|
6689
6854
|
}
|
|
6855
|
+
function tryInferRangeFromElements(elems, parser) {
|
|
6856
|
+
if (elems.length < 4) return null;
|
|
6857
|
+
const penultimate = elems[elems.length - 2];
|
|
6858
|
+
if (symbol(penultimate) !== "ContinuationPlaceholder") return null;
|
|
6859
|
+
const samples = elems.slice(0, -2);
|
|
6860
|
+
const endExpr = elems[elems.length - 1];
|
|
6861
|
+
if (samples.length < 2) return null;
|
|
6862
|
+
const sampleNums = samples.map(machineValue);
|
|
6863
|
+
if (sampleNums.some((n) => n === null)) return null;
|
|
6864
|
+
const nums = sampleNums;
|
|
6865
|
+
const step = nums[nums.length - 1] - nums[nums.length - 2];
|
|
6866
|
+
const tol = parser.options.tolerance;
|
|
6867
|
+
if (Math.abs(step) < tol)
|
|
6868
|
+
return parser.error("degenerate-range-step", parser.index);
|
|
6869
|
+
for (let i = 1; i < nums.length; i++) {
|
|
6870
|
+
if (Math.abs(nums[i] - nums[i - 1] - step) > tol)
|
|
6871
|
+
return parser.error("inconsistent-range-samples", parser.index);
|
|
6872
|
+
}
|
|
6873
|
+
return ["Range", nums[0], endExpr, step];
|
|
6874
|
+
}
|
|
6690
6875
|
function serializeList(serializer, expr) {
|
|
6691
6876
|
if (nops(expr) > 1 && operands(expr).every((x) => {
|
|
6692
6877
|
const op = operator(x);
|
|
@@ -6938,6 +7123,35 @@ var Compile = (() => {
|
|
|
6938
7123
|
["Element", index, ["Range", lower, upper]]
|
|
6939
7124
|
];
|
|
6940
7125
|
}
|
|
7126
|
+
function parseForComprehension(parser, lhs, until) {
|
|
7127
|
+
const bindingTerminator = {
|
|
7128
|
+
minPrec: 21,
|
|
7129
|
+
// Above comma (20) and ; (19), so `x = L_1` is captured whole
|
|
7130
|
+
condition: (p) => {
|
|
7131
|
+
if (until?.condition?.(p)) return true;
|
|
7132
|
+
const saved = p.index;
|
|
7133
|
+
p.skipVisualSpace();
|
|
7134
|
+
const isComma = p.peek === ",";
|
|
7135
|
+
p.index = saved;
|
|
7136
|
+
return isComma;
|
|
7137
|
+
}
|
|
7138
|
+
};
|
|
7139
|
+
const elements = [];
|
|
7140
|
+
do {
|
|
7141
|
+
parser.skipVisualSpace();
|
|
7142
|
+
const binding = parser.parseExpression(bindingTerminator);
|
|
7143
|
+
if (binding === null) break;
|
|
7144
|
+
const op = operator(binding);
|
|
7145
|
+
if (op !== "Equal" && op !== "Assign") return null;
|
|
7146
|
+
const name = operand(binding, 1);
|
|
7147
|
+
const list = operand(binding, 2);
|
|
7148
|
+
if (!name || !list) return null;
|
|
7149
|
+
elements.push(["Element", name, list]);
|
|
7150
|
+
parser.skipVisualSpace();
|
|
7151
|
+
} while (parser.match(","));
|
|
7152
|
+
if (elements.length === 0) return null;
|
|
7153
|
+
return ["Loop", lhs, ...elements];
|
|
7154
|
+
}
|
|
6941
7155
|
function parseWhereExpression(parser, lhs, until) {
|
|
6942
7156
|
const bindingTerminator = {
|
|
6943
7157
|
minPrec: 21,
|
|
@@ -8826,6 +9040,8 @@ var Compile = (() => {
|
|
|
8826
9040
|
precedence: DIVISION_PRECEDENCE,
|
|
8827
9041
|
parse: "Mod"
|
|
8828
9042
|
},
|
|
9043
|
+
// Function-style alias: `\operatorname{mod}(a, b)`
|
|
9044
|
+
{ latexTrigger: "\\operatorname{mod}", parse: "Mod" },
|
|
8829
9045
|
{
|
|
8830
9046
|
latexTrigger: "\\pmod",
|
|
8831
9047
|
kind: "prefix",
|
|
@@ -9066,6 +9282,13 @@ var Compile = (() => {
|
|
|
9066
9282
|
const rhs = serializer.wrap(operand(expr, 2), ADDITION_PRECEDENCE + 3);
|
|
9067
9283
|
return joinLatex([lhs, "-", rhs]);
|
|
9068
9284
|
}
|
|
9285
|
+
},
|
|
9286
|
+
// Euclidean distance between two points (tuples of numbers).
|
|
9287
|
+
{
|
|
9288
|
+
name: "Distance",
|
|
9289
|
+
latexTrigger: ["\\operatorname{distance}"],
|
|
9290
|
+
kind: "function",
|
|
9291
|
+
serialize: (serializer, expr) => "\\operatorname{distance}" + serializer.wrapArguments(expr)
|
|
9069
9292
|
}
|
|
9070
9293
|
];
|
|
9071
9294
|
function getIndexAssignment(expr, upper) {
|
|
@@ -10490,7 +10713,9 @@ var Compile = (() => {
|
|
|
10490
10713
|
if (!expr || !symbol(expr)) return null;
|
|
10491
10714
|
return ["Mean", expr];
|
|
10492
10715
|
}
|
|
10493
|
-
}
|
|
10716
|
+
},
|
|
10717
|
+
// Function-style alias: `\operatorname{var}(...)`
|
|
10718
|
+
{ latexTrigger: "\\operatorname{var}", parse: "Variance" }
|
|
10494
10719
|
];
|
|
10495
10720
|
|
|
10496
10721
|
// src/compute-engine/numerics/unit-data.ts
|
|
@@ -11498,7 +11723,7 @@ var Compile = (() => {
|
|
|
11498
11723
|
36: "\\qquad"
|
|
11499
11724
|
}[v] ?? "";
|
|
11500
11725
|
}
|
|
11501
|
-
}
|
|
11726
|
+
},
|
|
11502
11727
|
// if (
|
|
11503
11728
|
// [
|
|
11504
11729
|
// '\\!',
|
|
@@ -11522,6 +11747,121 @@ var Compile = (() => {
|
|
|
11522
11747
|
// name: '',
|
|
11523
11748
|
// trigger: '\\check',
|
|
11524
11749
|
// },
|
|
11750
|
+
// ---------------------------------------------------------------------------
|
|
11751
|
+
// Function-style aliases for collection / random operators that some
|
|
11752
|
+
// notations write in lowercase (e.g. `\operatorname{shuffle}(L)`).
|
|
11753
|
+
// The capitalized library entries already exist; these are pure parse
|
|
11754
|
+
// aliases so the lowercase names don't land in `unsupported-operator`.
|
|
11755
|
+
// ---------------------------------------------------------------------------
|
|
11756
|
+
{ latexTrigger: "\\operatorname{random}", parse: "Random" },
|
|
11757
|
+
{ latexTrigger: "\\operatorname{shuffle}", parse: "Shuffle" },
|
|
11758
|
+
{ latexTrigger: "\\operatorname{repeat}", parse: "Repeat" },
|
|
11759
|
+
{ latexTrigger: "\\operatorname{join}", parse: "Join" },
|
|
11760
|
+
// ---------------------------------------------------------------------------
|
|
11761
|
+
// Geometric primitive heads. Registered as known typed heads so consumers
|
|
11762
|
+
// can branch on the operator name; CE itself doesn't render them. The
|
|
11763
|
+
// library entries (with no evaluator) live in `library/core.ts`.
|
|
11764
|
+
// ---------------------------------------------------------------------------
|
|
11765
|
+
{
|
|
11766
|
+
name: "Triangle",
|
|
11767
|
+
latexTrigger: ["\\operatorname{triangle}"],
|
|
11768
|
+
kind: "function",
|
|
11769
|
+
serialize: (serializer, expr) => "\\operatorname{triangle}" + serializer.wrapArguments(expr)
|
|
11770
|
+
},
|
|
11771
|
+
// Desmos's geometric `vector(p1, p2)` — a directed segment between two
|
|
11772
|
+
// points. Routed to a dedicated head (not the existing column-vector
|
|
11773
|
+
// `Vector`, which has a narrower `(number+) -> vector` signature).
|
|
11774
|
+
{
|
|
11775
|
+
name: "GeometricVector",
|
|
11776
|
+
latexTrigger: ["\\operatorname{vector}"],
|
|
11777
|
+
kind: "function",
|
|
11778
|
+
serialize: (serializer, expr) => "\\operatorname{vector}" + serializer.wrapArguments(expr)
|
|
11779
|
+
},
|
|
11780
|
+
{
|
|
11781
|
+
name: "Sphere",
|
|
11782
|
+
latexTrigger: ["\\operatorname{sphere}"],
|
|
11783
|
+
kind: "function",
|
|
11784
|
+
serialize: (serializer, expr) => "\\operatorname{sphere}" + serializer.wrapArguments(expr)
|
|
11785
|
+
},
|
|
11786
|
+
{
|
|
11787
|
+
name: "Segment",
|
|
11788
|
+
latexTrigger: ["\\operatorname{segment}"],
|
|
11789
|
+
kind: "function",
|
|
11790
|
+
serialize: (serializer, expr) => "\\operatorname{segment}" + serializer.wrapArguments(expr)
|
|
11791
|
+
}
|
|
11792
|
+
];
|
|
11793
|
+
|
|
11794
|
+
// src/compute-engine/latex-syntax/dictionary/definitions-colors.ts
|
|
11795
|
+
var DEFINITIONS_COLORS = [
|
|
11796
|
+
// Color constructors (one per colorspace, preserves space on evaluation)
|
|
11797
|
+
{
|
|
11798
|
+
name: "Rgb",
|
|
11799
|
+
latexTrigger: ["\\operatorname{rgb}"],
|
|
11800
|
+
kind: "function",
|
|
11801
|
+
serialize: (serializer, expr) => "\\operatorname{rgb}" + serializer.wrapArguments(expr)
|
|
11802
|
+
},
|
|
11803
|
+
{
|
|
11804
|
+
name: "Hsv",
|
|
11805
|
+
latexTrigger: ["\\operatorname{hsv}"],
|
|
11806
|
+
kind: "function",
|
|
11807
|
+
serialize: (serializer, expr) => "\\operatorname{hsv}" + serializer.wrapArguments(expr)
|
|
11808
|
+
},
|
|
11809
|
+
{
|
|
11810
|
+
name: "Hsl",
|
|
11811
|
+
latexTrigger: ["\\operatorname{hsl}"],
|
|
11812
|
+
kind: "function",
|
|
11813
|
+
serialize: (serializer, expr) => "\\operatorname{hsl}" + serializer.wrapArguments(expr)
|
|
11814
|
+
},
|
|
11815
|
+
{
|
|
11816
|
+
name: "Oklab",
|
|
11817
|
+
latexTrigger: ["\\operatorname{oklab}"],
|
|
11818
|
+
kind: "function",
|
|
11819
|
+
serialize: (serializer, expr) => "\\operatorname{oklab}" + serializer.wrapArguments(expr)
|
|
11820
|
+
},
|
|
11821
|
+
{
|
|
11822
|
+
name: "Oklch",
|
|
11823
|
+
latexTrigger: ["\\operatorname{oklch}"],
|
|
11824
|
+
kind: "function",
|
|
11825
|
+
serialize: (serializer, expr) => "\\operatorname{oklch}" + serializer.wrapArguments(expr)
|
|
11826
|
+
},
|
|
11827
|
+
// Conversion functions (color → color in the named space)
|
|
11828
|
+
{
|
|
11829
|
+
name: "AsRgb",
|
|
11830
|
+
latexTrigger: ["\\operatorname{asRgb}"],
|
|
11831
|
+
kind: "function",
|
|
11832
|
+
serialize: (serializer, expr) => "\\operatorname{asRgb}" + serializer.wrapArguments(expr)
|
|
11833
|
+
},
|
|
11834
|
+
{
|
|
11835
|
+
name: "AsHsv",
|
|
11836
|
+
latexTrigger: ["\\operatorname{asHsv}"],
|
|
11837
|
+
kind: "function",
|
|
11838
|
+
serialize: (serializer, expr) => "\\operatorname{asHsv}" + serializer.wrapArguments(expr)
|
|
11839
|
+
},
|
|
11840
|
+
{
|
|
11841
|
+
name: "AsHsl",
|
|
11842
|
+
latexTrigger: ["\\operatorname{asHsl}"],
|
|
11843
|
+
kind: "function",
|
|
11844
|
+
serialize: (serializer, expr) => "\\operatorname{asHsl}" + serializer.wrapArguments(expr)
|
|
11845
|
+
},
|
|
11846
|
+
{
|
|
11847
|
+
name: "AsOklab",
|
|
11848
|
+
latexTrigger: ["\\operatorname{asOklab}"],
|
|
11849
|
+
kind: "function",
|
|
11850
|
+
serialize: (serializer, expr) => "\\operatorname{asOklab}" + serializer.wrapArguments(expr)
|
|
11851
|
+
},
|
|
11852
|
+
{
|
|
11853
|
+
name: "AsOklch",
|
|
11854
|
+
latexTrigger: ["\\operatorname{asOklch}"],
|
|
11855
|
+
kind: "function",
|
|
11856
|
+
serialize: (serializer, expr) => "\\operatorname{asOklch}" + serializer.wrapArguments(expr)
|
|
11857
|
+
},
|
|
11858
|
+
// Perceptual difference (returns a scalar in [0, ~1])
|
|
11859
|
+
{
|
|
11860
|
+
name: "ColorDelta",
|
|
11861
|
+
latexTrigger: ["\\operatorname{colorDelta}"],
|
|
11862
|
+
kind: "function",
|
|
11863
|
+
serialize: (serializer, expr) => "\\operatorname{colorDelta}" + serializer.wrapArguments(expr)
|
|
11864
|
+
}
|
|
11525
11865
|
];
|
|
11526
11866
|
|
|
11527
11867
|
// src/compute-engine/latex-syntax/dictionary/default-dictionary.ts
|
|
@@ -11552,7 +11892,8 @@ var Compile = (() => {
|
|
|
11552
11892
|
...DEFINITIONS_STATISTICS,
|
|
11553
11893
|
...DEFINITIONS_UNITS,
|
|
11554
11894
|
...DEFINITIONS_OTHERS,
|
|
11555
|
-
...DEFINITIONS_PHYSICS
|
|
11895
|
+
...DEFINITIONS_PHYSICS,
|
|
11896
|
+
...DEFINITIONS_COLORS
|
|
11556
11897
|
];
|
|
11557
11898
|
|
|
11558
11899
|
// src/math-json/symbols.ts
|
|
@@ -12707,7 +13048,11 @@ ${lines.join("\n")}`;
|
|
|
12707
13048
|
//
|
|
12708
13049
|
Range: {
|
|
12709
13050
|
complexity: 8200,
|
|
12710
|
-
signature: "(number, number?, step: number?) -> indexed_collection<
|
|
13051
|
+
signature: "(number, number?, step: number?) -> indexed_collection<number>",
|
|
13052
|
+
type: (ops) => {
|
|
13053
|
+
const allInt = ops.every((op) => op.isInteger);
|
|
13054
|
+
return allInt ? parseType("indexed_collection<integer>") : parseType("indexed_collection<number>");
|
|
13055
|
+
},
|
|
12711
13056
|
canonical: (ops, { engine: ce }) => {
|
|
12712
13057
|
if (ops.length === 0) return null;
|
|
12713
13058
|
if (ops.length === 1) return ce._fn("Range", [ce.One, ops[0].canonical]);
|
|
@@ -12731,19 +13076,26 @@ ${lines.join("\n")}`;
|
|
|
12731
13076
|
const [lower, upper, step] = range(expr);
|
|
12732
13077
|
if (step === 0) return 0;
|
|
12733
13078
|
if (!isFinite(lower) || !isFinite(upper)) return Infinity;
|
|
12734
|
-
return
|
|
13079
|
+
return Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12735
13080
|
},
|
|
12736
13081
|
contains: (expr, target) => {
|
|
12737
|
-
if (!target.type.matches("integer")) return false;
|
|
12738
13082
|
const t = target.re;
|
|
13083
|
+
if (!isFinite(t)) return false;
|
|
12739
13084
|
const [lower, upper, step] = range(expr);
|
|
12740
13085
|
if (step === 0) return false;
|
|
12741
|
-
if (step > 0)
|
|
12742
|
-
|
|
13086
|
+
if (step > 0) {
|
|
13087
|
+
if (t < lower || t > upper) return false;
|
|
13088
|
+
} else {
|
|
13089
|
+
if (t > lower || t < upper) return false;
|
|
13090
|
+
}
|
|
13091
|
+
const k = (t - lower) / step;
|
|
13092
|
+
const tol = expr.engine.tolerance;
|
|
13093
|
+
const kRounded = Math.round(k);
|
|
13094
|
+
return kRounded >= 0 && Math.abs(k - kRounded) < tol;
|
|
12743
13095
|
},
|
|
12744
13096
|
iterator: (expr) => {
|
|
12745
13097
|
const [lower, upper, step] = range(expr);
|
|
12746
|
-
const maxCount = step === 0 ? 0 : Math.floor((upper - lower) / step) + 1;
|
|
13098
|
+
const maxCount = step === 0 ? 0 : Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
12747
13099
|
let index = 1;
|
|
12748
13100
|
return {
|
|
12749
13101
|
next: () => {
|
|
@@ -12761,7 +13113,9 @@ ${lines.join("\n")}`;
|
|
|
12761
13113
|
at: (expr, index) => {
|
|
12762
13114
|
if (typeof index !== "number") return void 0;
|
|
12763
13115
|
const [lower, upper, step] = range(expr);
|
|
12764
|
-
if (
|
|
13116
|
+
if (step === 0) return void 0;
|
|
13117
|
+
const maxCount = Math.max(0, Math.floor((upper - lower) / step) + 1);
|
|
13118
|
+
if (index < 1 || index > maxCount) return void 0;
|
|
12765
13119
|
return expr.engine.number(lower + step * (index - 1));
|
|
12766
13120
|
},
|
|
12767
13121
|
indexWhere: void 0,
|
|
@@ -12786,7 +13140,13 @@ ${lines.join("\n")}`;
|
|
|
12786
13140
|
if (step > 0) return lower <= upper ? "positive" : "negative";
|
|
12787
13141
|
return lower >= upper ? "positive" : "negative";
|
|
12788
13142
|
},
|
|
12789
|
-
elttype: (
|
|
13143
|
+
elttype: (expr) => {
|
|
13144
|
+
if (!isFunction2(expr)) return "finite_integer";
|
|
13145
|
+
for (let i = 1; i <= expr.nops; i++) {
|
|
13146
|
+
if (!expr[`op${i}`].isInteger) return "finite_real";
|
|
13147
|
+
}
|
|
13148
|
+
return "finite_integer";
|
|
13149
|
+
}
|
|
12790
13150
|
}
|
|
12791
13151
|
},
|
|
12792
13152
|
Interval: {
|
|
@@ -13384,15 +13744,45 @@ ${lines.join("\n")}`;
|
|
|
13384
13744
|
},
|
|
13385
13745
|
First: {
|
|
13386
13746
|
complexity: 8200,
|
|
13387
|
-
signature: "(
|
|
13747
|
+
signature: "(any) -> any",
|
|
13388
13748
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13389
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13749
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13750
|
+
if (!xs.isCollection)
|
|
13751
|
+
return ce.error([
|
|
13752
|
+
"incompatible-type",
|
|
13753
|
+
`'collection'`,
|
|
13754
|
+
xs.type.toString()
|
|
13755
|
+
]);
|
|
13756
|
+
return xs.at(1) ?? ce.Nothing;
|
|
13757
|
+
}
|
|
13390
13758
|
},
|
|
13391
13759
|
Second: {
|
|
13392
13760
|
complexity: 8200,
|
|
13393
|
-
signature: "(
|
|
13761
|
+
signature: "(any) -> any",
|
|
13762
|
+
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13763
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13764
|
+
if (!xs.isCollection)
|
|
13765
|
+
return ce.error([
|
|
13766
|
+
"incompatible-type",
|
|
13767
|
+
`'collection'`,
|
|
13768
|
+
xs.type.toString()
|
|
13769
|
+
]);
|
|
13770
|
+
return xs.at(2) ?? ce.Nothing;
|
|
13771
|
+
}
|
|
13772
|
+
},
|
|
13773
|
+
Third: {
|
|
13774
|
+
complexity: 8200,
|
|
13775
|
+
signature: "(any) -> any",
|
|
13394
13776
|
type: ([xs]) => xs.operatorDefinition?.collection?.elttype?.(xs) ?? "any",
|
|
13395
|
-
evaluate: ([xs], { engine: ce }) =>
|
|
13777
|
+
evaluate: ([xs], { engine: ce }) => {
|
|
13778
|
+
if (!xs.isCollection)
|
|
13779
|
+
return ce.error([
|
|
13780
|
+
"incompatible-type",
|
|
13781
|
+
`'collection'`,
|
|
13782
|
+
xs.type.toString()
|
|
13783
|
+
]);
|
|
13784
|
+
return xs.at(3) ?? ce.Nothing;
|
|
13785
|
+
}
|
|
13396
13786
|
},
|
|
13397
13787
|
Last: {
|
|
13398
13788
|
complexity: 8200,
|
|
@@ -14371,17 +14761,14 @@ ${lines.join("\n")}`;
|
|
|
14371
14761
|
if (!isFunction2(expr)) return [1, 0, 0];
|
|
14372
14762
|
if (expr.nops === 0) return [1, 0, 0];
|
|
14373
14763
|
let op1 = expr.op1.re;
|
|
14374
|
-
if (!isFinite(op1)) op1 = 1;
|
|
14375
|
-
else op1 = Math.round(op1);
|
|
14764
|
+
if (!isFinite(op1) && !op1) op1 = 1;
|
|
14376
14765
|
if (expr.nops === 1) return [1, op1, 1];
|
|
14377
14766
|
let op2 = expr.op2.re;
|
|
14378
14767
|
if (!isFinite(op2) && !op2) op2 = 1;
|
|
14379
|
-
|
|
14380
|
-
if (expr.nops === 2) return [op1, op2, op2 > op1 ? 1 : -1];
|
|
14768
|
+
if (expr.nops === 2) return [op1, op2, op2 >= op1 ? 1 : -1];
|
|
14381
14769
|
let op3 = expr.op3.re;
|
|
14382
|
-
if (!isFinite(op3)) op3 = 1;
|
|
14383
|
-
|
|
14384
|
-
return [op1, op2, op1 < op2 ? op3 : -op3];
|
|
14770
|
+
if (!isFinite(op3) && !op3) op3 = 1;
|
|
14771
|
+
return [op1, op2, op3];
|
|
14385
14772
|
}
|
|
14386
14773
|
function canonicalList(ops, { engine: ce }) {
|
|
14387
14774
|
const op1 = ops[0];
|
|
@@ -14730,6 +15117,23 @@ ${lines.join("\n")}`;
|
|
|
14730
15117
|
};
|
|
14731
15118
|
return compilePair(0);
|
|
14732
15119
|
}
|
|
15120
|
+
if (h === "When") {
|
|
15121
|
+
if (args.length !== 2)
|
|
15122
|
+
throw new Error("When: expected exactly 2 arguments (expr, cond)");
|
|
15123
|
+
const fn2 = target.functions?.(h);
|
|
15124
|
+
if (fn2) {
|
|
15125
|
+
if (typeof fn2 === "function") {
|
|
15126
|
+
return fn2(args, (expr) => _BaseCompiler.compile(expr, target), target);
|
|
15127
|
+
}
|
|
15128
|
+
return `${fn2}(${args.map((x) => _BaseCompiler.compile(x, target)).join(", ")})`;
|
|
15129
|
+
}
|
|
15130
|
+
if (isSymbol2(args[1], "True"))
|
|
15131
|
+
return `(${_BaseCompiler.compile(args[0], target)})`;
|
|
15132
|
+
if (isSymbol2(args[1], "False")) return "NaN";
|
|
15133
|
+
const val = _BaseCompiler.compile(args[0], target);
|
|
15134
|
+
const cond = _BaseCompiler.compile(args[1], target);
|
|
15135
|
+
return `((${cond}) ? (${val}) : NaN)`;
|
|
15136
|
+
}
|
|
14733
15137
|
if (h === "Block") {
|
|
14734
15138
|
return _BaseCompiler.compileBlock(args, target);
|
|
14735
15139
|
}
|
|
@@ -14804,17 +15208,91 @@ ${lines.join("\n")}`;
|
|
|
14804
15208
|
)}${target.ws("\n")}})()`;
|
|
14805
15209
|
}
|
|
14806
15210
|
/**
|
|
14807
|
-
* Compile a Loop expression
|
|
14808
|
-
*
|
|
15211
|
+
* Compile a Loop expression.
|
|
15212
|
+
*
|
|
15213
|
+
* Two forms are supported:
|
|
15214
|
+
*
|
|
15215
|
+
* 1. **Imperative / single-Element form** (existing behaviour):
|
|
15216
|
+
* `Loop(body, Element(i, Range(lo, hi)))`
|
|
15217
|
+
* Generates a raw `for (let i = lo; i <= hi; i++) { body }` loop wrapped
|
|
15218
|
+
* in an IIFE. The loop counter is always a plain number. For targets
|
|
15219
|
+
* that wrap numeric values (e.g. interval-js uses `_IA.point()`),
|
|
15220
|
+
* references to the loop index inside the body are re-wrapped via
|
|
15221
|
+
* `target.number`. `break` / `continue` / `return` are preserved.
|
|
15222
|
+
*
|
|
15223
|
+
* 2. **Comprehension / variadic-Element form** (new):
|
|
15224
|
+
* `Loop(body, Element(x, coll1), Element(y, coll2), …)`
|
|
15225
|
+
* When two or more `Element` clauses are present — or when the single
|
|
15226
|
+
* Element's collection is not a `Range` — the loop is compiled as a
|
|
15227
|
+
* comprehension that collects results into an array. Each clause
|
|
15228
|
+
* produces a `for (const name of collection)` loop, nested
|
|
15229
|
+
* outermost-to-innermost, and the innermost body pushes into `result`.
|
|
15230
|
+
*
|
|
15231
|
+
* Example output (JS):
|
|
15232
|
+
* ```js
|
|
15233
|
+
* (() => { const result = [];
|
|
15234
|
+
* for (const x of [1,2]) { for (const y of [3,4]) { result.push(body); } }
|
|
15235
|
+
* return result; })()
|
|
15236
|
+
* ```
|
|
14809
15237
|
*
|
|
14810
|
-
*
|
|
14811
|
-
*
|
|
14812
|
-
*
|
|
15238
|
+
* GLSL: multi-Element comprehension is not trivially representable in
|
|
15239
|
+
* GLSL (no dynamic arrays, no push). A compile-time error is thrown.
|
|
15240
|
+
* TODO(E3-GLSL): support GLSL multi-Element via a pre-declared fixed-size
|
|
15241
|
+
* array or by unrolling when bounds are known at compile time.
|
|
14813
15242
|
*/
|
|
14814
15243
|
static compileForLoop(args, target) {
|
|
14815
15244
|
if (!args[0]) throw new Error("Loop: no body");
|
|
14816
15245
|
if (!args[1]) throw new Error("Loop: no indexing set");
|
|
14817
|
-
const
|
|
15246
|
+
const body = args[0];
|
|
15247
|
+
const elements = args.slice(1);
|
|
15248
|
+
const useComprehension = elements.length > 1 || elements.length === 1 && isFunction2(elements[0], "Element") && !_BaseCompiler.isLegacyCompatibleRange(elements[0].ops[1]);
|
|
15249
|
+
if (useComprehension) {
|
|
15250
|
+
const lang = target.language ?? "";
|
|
15251
|
+
if (lang === "glsl" || lang === "wgsl") {
|
|
15252
|
+
throw new Error(
|
|
15253
|
+
`${lang.toUpperCase()}: multi-Element Loop comprehension is not yet supported. TODO(E3-GLSL): unroll or use a fixed-size array.`
|
|
15254
|
+
);
|
|
15255
|
+
}
|
|
15256
|
+
const narrowedElements = [];
|
|
15257
|
+
for (let i = 0; i < elements.length; i++) {
|
|
15258
|
+
const elem = elements[i];
|
|
15259
|
+
if (!isFunction2(elem, "Element"))
|
|
15260
|
+
throw new Error(
|
|
15261
|
+
`Loop: argument ${i + 1} must be an Element clause, got ${elem.operator ?? "?"}`
|
|
15262
|
+
);
|
|
15263
|
+
if (!isSymbol2(elem.ops[0]))
|
|
15264
|
+
throw new Error(
|
|
15265
|
+
`Loop: Element index (argument ${i + 1}) must be a symbol`
|
|
15266
|
+
);
|
|
15267
|
+
narrowedElements.push(elem);
|
|
15268
|
+
}
|
|
15269
|
+
const loopVarSet = new Set(
|
|
15270
|
+
narrowedElements.map(
|
|
15271
|
+
(e) => e.ops[0].symbol
|
|
15272
|
+
)
|
|
15273
|
+
);
|
|
15274
|
+
const needsWrap2 = target.number(0) !== "0";
|
|
15275
|
+
const bodyTarget2 = needsWrap2 ? {
|
|
15276
|
+
...target,
|
|
15277
|
+
var: (id) => loopVarSet.has(id) ? target.number(0).replace("0", id) : target.var(id)
|
|
15278
|
+
} : target;
|
|
15279
|
+
const bodyCode = _BaseCompiler.compile(body, bodyTarget2);
|
|
15280
|
+
let inner = `result.push(${bodyCode});`;
|
|
15281
|
+
for (let i = narrowedElements.length - 1; i >= 0; i--) {
|
|
15282
|
+
const elem = narrowedElements[i];
|
|
15283
|
+
const name = elem.ops[0].symbol;
|
|
15284
|
+
const collExpr = elem.ops[1];
|
|
15285
|
+
let collection;
|
|
15286
|
+
if (isFunction2(collExpr, "Range")) {
|
|
15287
|
+
collection = _BaseCompiler.compileRangeIterable(collExpr, bodyTarget2);
|
|
15288
|
+
} else {
|
|
15289
|
+
collection = _BaseCompiler.compile(collExpr, bodyTarget2);
|
|
15290
|
+
}
|
|
15291
|
+
inner = `for (const ${name} of ${collection}) { ${inner} }`;
|
|
15292
|
+
}
|
|
15293
|
+
return `(() => { const result = []; ${inner} return result; })()`;
|
|
15294
|
+
}
|
|
15295
|
+
const indexing = elements[0];
|
|
14818
15296
|
if (!isFunction2(indexing, "Element"))
|
|
14819
15297
|
throw new Error("Loop: expected Element(index, Range(lo, hi))");
|
|
14820
15298
|
const indexExpr = indexing.ops[0];
|
|
@@ -14832,13 +15310,72 @@ ${lines.join("\n")}`;
|
|
|
14832
15310
|
...target,
|
|
14833
15311
|
var: (id) => id === index ? needsWrap ? target.number(0).replace("0", index) : index : target.var(id)
|
|
14834
15312
|
};
|
|
14835
|
-
const bodyStmts = _BaseCompiler.compileLoopBody(
|
|
15313
|
+
const bodyStmts = _BaseCompiler.compileLoopBody(body, bodyTarget);
|
|
14836
15314
|
return `(() => {${target.ws(
|
|
14837
15315
|
"\n"
|
|
14838
15316
|
)}for (let ${index} = ${lower}; ${index} <= ${upper}; ${index}++) {${target.ws(
|
|
14839
15317
|
"\n"
|
|
14840
15318
|
)}${bodyStmts}${target.ws("\n")}}${target.ws("\n")}})()`;
|
|
14841
15319
|
}
|
|
15320
|
+
/**
|
|
15321
|
+
* Returns `true` when the given collection expression is a `Range` whose
|
|
15322
|
+
* runtime semantics match the legacy imperative for-loop shape
|
|
15323
|
+
* `for (let i = lo; i <= hi; i++)`.
|
|
15324
|
+
*
|
|
15325
|
+
* Concretely: integer-ascending bounds and step omitted-or-1. When bounds
|
|
15326
|
+
* are not statically numeric we accept the Range (the historical
|
|
15327
|
+
* behaviour) — runtime mismatch in the descending-unknown-bounds case is
|
|
15328
|
+
* left as a known limitation; callers can force the iterable path by
|
|
15329
|
+
* supplying an explicit step.
|
|
15330
|
+
*/
|
|
15331
|
+
static isLegacyCompatibleRange(coll) {
|
|
15332
|
+
if (!isFunction2(coll, "Range")) return false;
|
|
15333
|
+
if (coll.ops.length >= 3) {
|
|
15334
|
+
const stepExpr = coll.ops[2];
|
|
15335
|
+
if (!isNumber(stepExpr) || stepExpr.re !== 1) return false;
|
|
15336
|
+
}
|
|
15337
|
+
const lo = coll.ops[0];
|
|
15338
|
+
const hi = coll.ops[1];
|
|
15339
|
+
if (isNumber(lo) && !Number.isInteger(lo.re)) return false;
|
|
15340
|
+
if (isNumber(hi) && !Number.isInteger(hi.re)) return false;
|
|
15341
|
+
if (isNumber(lo) && isNumber(hi) && lo.re > hi.re) return false;
|
|
15342
|
+
return true;
|
|
15343
|
+
}
|
|
15344
|
+
/**
|
|
15345
|
+
* Compile a `Range(lo, hi)` or `Range(lo, hi, step)` expression into a JS
|
|
15346
|
+
* iterable expression. Mirrors the runtime semantics in
|
|
15347
|
+
* `library/collections.ts` Range:
|
|
15348
|
+
* count = step === 0 ? 0 : max(0, floor((hi - lo) / step) + 1)
|
|
15349
|
+
* element = lo + step * k (0-indexed)
|
|
15350
|
+
* Default step is 1 when omitted. Bounds and step may be fractional.
|
|
15351
|
+
*
|
|
15352
|
+
* Only used from the comprehension path in `compileForLoop`.
|
|
15353
|
+
* Caller must have already verified `isFunction(rangeExpr, 'Range')`.
|
|
15354
|
+
*/
|
|
15355
|
+
static compileRangeIterable(rangeExpr, target) {
|
|
15356
|
+
const loExpr = rangeExpr.ops[0];
|
|
15357
|
+
const hiExpr = rangeExpr.ops[1];
|
|
15358
|
+
const stepExpr = rangeExpr.ops[2];
|
|
15359
|
+
if (isNumber(loExpr) && isNumber(hiExpr) && (stepExpr === void 0 || isNumber(stepExpr))) {
|
|
15360
|
+
const lo2 = loExpr.re;
|
|
15361
|
+
const hi2 = hiExpr.re;
|
|
15362
|
+
const step2 = stepExpr === void 0 ? hi2 >= lo2 ? 1 : -1 : stepExpr.re;
|
|
15363
|
+
if (step2 === 0) return "[]";
|
|
15364
|
+
const len = Math.max(0, Math.floor((hi2 - lo2) / step2) + 1);
|
|
15365
|
+
if (step2 === 1) {
|
|
15366
|
+
if (lo2 === 0) return `Array.from({length:${len}},(_,k)=>k)`;
|
|
15367
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+k)`;
|
|
15368
|
+
}
|
|
15369
|
+
return `Array.from({length:${len}},(_,k)=>${lo2}+(${step2})*k)`;
|
|
15370
|
+
}
|
|
15371
|
+
const lo = _BaseCompiler.compile(loExpr, target);
|
|
15372
|
+
const hi = _BaseCompiler.compile(hiExpr, target);
|
|
15373
|
+
if (stepExpr === void 0) {
|
|
15374
|
+
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})`;
|
|
15375
|
+
}
|
|
15376
|
+
const step = _BaseCompiler.compile(stepExpr, target);
|
|
15377
|
+
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})`;
|
|
15378
|
+
}
|
|
14842
15379
|
/**
|
|
14843
15380
|
* Compile a loop body expression as statements (not wrapped in IIFE).
|
|
14844
15381
|
* Handles Break, Continue, Return as statements, and If as if-else when
|
|
@@ -15187,8 +15724,7 @@ ${lines.join("\n")}`;
|
|
|
15187
15724
|
ce.pushScope();
|
|
15188
15725
|
try {
|
|
15189
15726
|
if (vars && typeof vars === "object") {
|
|
15190
|
-
for (const [k, v] of Object.entries(vars))
|
|
15191
|
-
ce.assign(k, v);
|
|
15727
|
+
for (const [k, v] of Object.entries(vars)) ce.assign(k, v);
|
|
15192
15728
|
}
|
|
15193
15729
|
return expr.evaluate().re;
|
|
15194
15730
|
} finally {
|
|
@@ -15275,8 +15811,7 @@ ${lines.join("\n")}`;
|
|
|
15275
15811
|
return { re: null, im: formatFloat(iScale) };
|
|
15276
15812
|
}
|
|
15277
15813
|
const compiledFactors = remaining.map((r) => compile2(r));
|
|
15278
|
-
if (iScale !== 1)
|
|
15279
|
-
compiledFactors.unshift(formatFloat(iScale));
|
|
15814
|
+
if (iScale !== 1) compiledFactors.unshift(formatFloat(iScale));
|
|
15280
15815
|
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
15281
15816
|
return { re: null, im: imCode };
|
|
15282
15817
|
}
|
|
@@ -15341,6 +15876,40 @@ ${lines.join("\n")}`;
|
|
|
15341
15876
|
else h = ((r - g) / d + 4) / 6;
|
|
15342
15877
|
return { h: h * 360, s, l };
|
|
15343
15878
|
}
|
|
15879
|
+
function hsvToRgb(h, s, v) {
|
|
15880
|
+
h = (h % 360 + 360) % 360;
|
|
15881
|
+
s = Math.max(0, Math.min(1, s));
|
|
15882
|
+
v = Math.max(0, Math.min(1, v));
|
|
15883
|
+
const c = v * s;
|
|
15884
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
15885
|
+
const m = v - c;
|
|
15886
|
+
let r = 0, g = 0, b = 0;
|
|
15887
|
+
if (h < 60) [r, g, b] = [c, x, 0];
|
|
15888
|
+
else if (h < 120) [r, g, b] = [x, c, 0];
|
|
15889
|
+
else if (h < 180) [r, g, b] = [0, c, x];
|
|
15890
|
+
else if (h < 240) [r, g, b] = [0, x, c];
|
|
15891
|
+
else if (h < 300) [r, g, b] = [x, 0, c];
|
|
15892
|
+
else [r, g, b] = [c, 0, x];
|
|
15893
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
15894
|
+
}
|
|
15895
|
+
function rgbToHsv(r, g, b) {
|
|
15896
|
+
r /= 255;
|
|
15897
|
+
g /= 255;
|
|
15898
|
+
b /= 255;
|
|
15899
|
+
const max2 = Math.max(r, g, b);
|
|
15900
|
+
const min2 = Math.min(r, g, b);
|
|
15901
|
+
const d = max2 - min2;
|
|
15902
|
+
let h = 0;
|
|
15903
|
+
if (d > 0) {
|
|
15904
|
+
if (max2 === r) h = (g - b) / d % 6;
|
|
15905
|
+
else if (max2 === g) h = (b - r) / d + 2;
|
|
15906
|
+
else h = (r - g) / d + 4;
|
|
15907
|
+
h *= 60;
|
|
15908
|
+
if (h < 0) h += 360;
|
|
15909
|
+
}
|
|
15910
|
+
const s = max2 === 0 ? 0 : d / max2;
|
|
15911
|
+
return { h, s, v: max2 };
|
|
15912
|
+
}
|
|
15344
15913
|
function parseHexColor(s) {
|
|
15345
15914
|
const hex = s.startsWith("#") ? s.substring(1) : s;
|
|
15346
15915
|
let r, g, b;
|
|
@@ -15796,6 +16365,13 @@ ${lines.join("\n")}`;
|
|
|
15796
16365
|
};
|
|
15797
16366
|
function parseColor(s, darkMode) {
|
|
15798
16367
|
const str = s.trim().toLowerCase();
|
|
16368
|
+
const opacityMatch = str.match(/^(.+?)\s*\/\s*(\d+(?:\.\d+)?)%?\s*$/);
|
|
16369
|
+
if (opacityMatch) {
|
|
16370
|
+
const base = parseColor(opacityMatch[1].trim(), darkMode);
|
|
16371
|
+
const opacity = Math.max(0, Math.min(100, parseFloat(opacityMatch[2])));
|
|
16372
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
16373
|
+
return base & 4294967040 | alpha;
|
|
16374
|
+
}
|
|
15799
16375
|
if (str.startsWith("#")) {
|
|
15800
16376
|
const hex = str.substring(1);
|
|
15801
16377
|
let r, g, b, a = 255;
|
|
@@ -15928,14 +16504,6 @@ ${lines.join("\n")}`;
|
|
|
15928
16504
|
console.warn(`parseColor: unrecognized color "${s}"`);
|
|
15929
16505
|
return 0;
|
|
15930
16506
|
}
|
|
15931
|
-
function parseColorToRgb01(s, darkMode) {
|
|
15932
|
-
const color = parseColor(s, darkMode);
|
|
15933
|
-
return [
|
|
15934
|
-
(color >>> 24 & 255) / 255,
|
|
15935
|
-
(color >>> 16 & 255) / 255,
|
|
15936
|
-
(color >>> 8 & 255) / 255
|
|
15937
|
-
];
|
|
15938
|
-
}
|
|
15939
16507
|
function apca(bgColor, fgColor) {
|
|
15940
16508
|
const bgRgb = asRgb(bgColor);
|
|
15941
16509
|
const fgRgb = asRgb(fgColor);
|
|
@@ -15994,6 +16562,12 @@ ${lines.join("\n")}`;
|
|
|
15994
16562
|
const contrast2 = Math.abs(apca(fg2, bg));
|
|
15995
16563
|
return contrast1 >= contrast2 ? asColorNumber(fg1) : asColorNumber(fg2);
|
|
15996
16564
|
}
|
|
16565
|
+
function oklabDeltaE(a, b) {
|
|
16566
|
+
const dL = a.L - b.L;
|
|
16567
|
+
const da = a.a - b.a;
|
|
16568
|
+
const db = a.b - b.b;
|
|
16569
|
+
return Math.sqrt(dL * dL + da * da + db * db);
|
|
16570
|
+
}
|
|
15997
16571
|
var TYCHO_11 = [
|
|
15998
16572
|
"#4e79a7",
|
|
15999
16573
|
// Blue
|
|
@@ -20205,39 +20779,130 @@ ${lines.join("\n")}`;
|
|
|
20205
20779
|
if (args.length >= 2)
|
|
20206
20780
|
return `_SYS.colormap(${compile2(args[0])}, ${compile2(args[1])})`;
|
|
20207
20781
|
return `_SYS.colormap(${compile2(args[0])})`;
|
|
20782
|
+
},
|
|
20783
|
+
// -----------------------------------------------------------------------
|
|
20784
|
+
// Color constructor heads. All compile to OKLCh arrays at runtime — the
|
|
20785
|
+
// canonical color representation in this target. The constructors take
|
|
20786
|
+
// their own colorspace's components and convert internally.
|
|
20787
|
+
// (Mirrors the GPU target's design: color values are vec3 OKLCh.)
|
|
20788
|
+
// -----------------------------------------------------------------------
|
|
20789
|
+
Rgb: (args, compile2) => {
|
|
20790
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
20791
|
+
return `_SYS.rgb(${args.map(compile2).join(", ")})`;
|
|
20792
|
+
},
|
|
20793
|
+
Hsv: (args, compile2) => {
|
|
20794
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
20795
|
+
return `_SYS.hsv(${args.map(compile2).join(", ")})`;
|
|
20796
|
+
},
|
|
20797
|
+
Hsl: (args, compile2) => {
|
|
20798
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
20799
|
+
return `_SYS.hsl(${args.map(compile2).join(", ")})`;
|
|
20800
|
+
},
|
|
20801
|
+
Oklab: (args, compile2) => {
|
|
20802
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
20803
|
+
return `_SYS.oklab(${args.map(compile2).join(", ")})`;
|
|
20804
|
+
},
|
|
20805
|
+
Oklch: (args, compile2) => {
|
|
20806
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
20807
|
+
return `_SYS.oklch(${args.map(compile2).join(", ")})`;
|
|
20808
|
+
},
|
|
20809
|
+
// -----------------------------------------------------------------------
|
|
20810
|
+
// As* converters. Compile-time output convention matches the engine and
|
|
20811
|
+
// the GPU target: each returns components in the named space as a 3- or
|
|
20812
|
+
// 4-element array. `AsRgb` uses 0-1 sRGB channels (consistent across all
|
|
20813
|
+
// layers). `AsOklch` is the identity (canonical form).
|
|
20814
|
+
// -----------------------------------------------------------------------
|
|
20815
|
+
AsRgb: ([c], compile2) => {
|
|
20816
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
20817
|
+
return `_SYS.asRgb(${compile2(c)})`;
|
|
20818
|
+
},
|
|
20819
|
+
AsHsv: ([c], compile2) => {
|
|
20820
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
20821
|
+
return `_SYS.asHsv(${compile2(c)})`;
|
|
20822
|
+
},
|
|
20823
|
+
AsHsl: ([c], compile2) => {
|
|
20824
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
20825
|
+
return `_SYS.asHsl(${compile2(c)})`;
|
|
20826
|
+
},
|
|
20827
|
+
AsOklab: ([c], compile2) => {
|
|
20828
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
20829
|
+
return `_SYS.asOklab(${compile2(c)})`;
|
|
20830
|
+
},
|
|
20831
|
+
AsOklch: ([c], compile2) => {
|
|
20832
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
20833
|
+
return compile2(c);
|
|
20834
|
+
},
|
|
20835
|
+
// Perceptual color difference (ΔE_OK).
|
|
20836
|
+
ColorDelta: ([a, b], compile2) => {
|
|
20837
|
+
if (a === null || b === null)
|
|
20838
|
+
throw new Error("ColorDelta: need two colors");
|
|
20839
|
+
return `_SYS.colorDelta(${compile2(a)}, ${compile2(b)})`;
|
|
20840
|
+
},
|
|
20841
|
+
// Euclidean distance between two tuples (any positive dimension).
|
|
20842
|
+
// The GPU target maps `Distance` to the GLSL/WGSL `distance()` builtin
|
|
20843
|
+
// (vec-only); this JS handler works on plain arrays of any length.
|
|
20844
|
+
Distance: ([a, b], compile2) => {
|
|
20845
|
+
if (a === null || b === null) throw new Error("Distance: need two points");
|
|
20846
|
+
return `_SYS.distance(${compile2(a)}, ${compile2(b)})`;
|
|
20208
20847
|
}
|
|
20209
20848
|
};
|
|
20210
20849
|
function toRI(c) {
|
|
20211
20850
|
return { re: c.re, im: c.im };
|
|
20212
20851
|
}
|
|
20852
|
+
function normalizeAlpha(a) {
|
|
20853
|
+
if (a === void 0) return void 0;
|
|
20854
|
+
if (!Number.isFinite(a)) return void 0;
|
|
20855
|
+
if (Math.abs(a - 1) < 1e-9) return void 0;
|
|
20856
|
+
return a;
|
|
20857
|
+
}
|
|
20213
20858
|
function toRgb255(input) {
|
|
20214
20859
|
if (typeof input === "string") {
|
|
20215
20860
|
const c = parseColor(input);
|
|
20216
|
-
|
|
20861
|
+
const rgb2 = {
|
|
20217
20862
|
r: c >>> 24 & 255,
|
|
20218
20863
|
g: c >>> 16 & 255,
|
|
20219
|
-
b: c >>> 8 & 255
|
|
20220
|
-
alpha: (c & 255) / 255
|
|
20864
|
+
b: c >>> 8 & 255
|
|
20221
20865
|
};
|
|
20866
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20867
|
+
if (alpha !== void 0) rgb2.alpha = alpha;
|
|
20868
|
+
return rgb2;
|
|
20869
|
+
}
|
|
20870
|
+
const rgb = oklchToRgb({ L: input[0], C: input[1], H: input[2] });
|
|
20871
|
+
if (input.length >= 4) {
|
|
20872
|
+
const alpha = normalizeAlpha(input[3]);
|
|
20873
|
+
if (alpha !== void 0) rgb.alpha = alpha;
|
|
20222
20874
|
}
|
|
20223
|
-
const rgb = {
|
|
20224
|
-
r: input[0] * 255,
|
|
20225
|
-
g: input[1] * 255,
|
|
20226
|
-
b: input[2] * 255
|
|
20227
|
-
};
|
|
20228
|
-
if (input.length >= 4) rgb.alpha = input[3];
|
|
20229
20875
|
return rgb;
|
|
20230
20876
|
}
|
|
20231
|
-
function
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
20235
|
-
|
|
20236
|
-
|
|
20877
|
+
function toOklch(input) {
|
|
20878
|
+
if (typeof input === "string") {
|
|
20879
|
+
const c = parseColor(input);
|
|
20880
|
+
const r = c >>> 24 & 255;
|
|
20881
|
+
const g = c >>> 16 & 255;
|
|
20882
|
+
const b = c >>> 8 & 255;
|
|
20883
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
20884
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20885
|
+
if (alpha !== void 0) oklch2.alpha = alpha;
|
|
20886
|
+
return oklch2;
|
|
20887
|
+
}
|
|
20888
|
+
return {
|
|
20889
|
+
L: input[0],
|
|
20890
|
+
C: input[1],
|
|
20891
|
+
H: input[2],
|
|
20892
|
+
alpha: input.length >= 4 ? normalizeAlpha(input[3]) : void 0
|
|
20893
|
+
};
|
|
20894
|
+
}
|
|
20895
|
+
function packedToOklch(c) {
|
|
20896
|
+
const r = c >>> 24 & 255;
|
|
20897
|
+
const g = c >>> 16 & 255;
|
|
20898
|
+
const b = c >>> 8 & 255;
|
|
20899
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
20900
|
+
const alpha = normalizeAlpha((c & 255) / 255);
|
|
20901
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
20237
20902
|
}
|
|
20238
20903
|
var colorHelpers = {
|
|
20239
20904
|
color(input) {
|
|
20240
|
-
return
|
|
20905
|
+
return packedToOklch(parseColor(input));
|
|
20241
20906
|
},
|
|
20242
20907
|
colorToString(input, format) {
|
|
20243
20908
|
const rgb = toRgb255(input);
|
|
@@ -20248,7 +20913,7 @@ ${lines.join("\n")}`;
|
|
|
20248
20913
|
const g = Math.round(Math.max(0, Math.min(255, rgb.g)));
|
|
20249
20914
|
const b = Math.round(Math.max(0, Math.min(255, rgb.b)));
|
|
20250
20915
|
let hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
20251
|
-
if (rgb.alpha !== void 0
|
|
20916
|
+
if (rgb.alpha !== void 0) {
|
|
20252
20917
|
const a = Math.round(Math.max(0, Math.min(255, rgb.alpha * 255)));
|
|
20253
20918
|
hex += a.toString(16).padStart(2, "0");
|
|
20254
20919
|
}
|
|
@@ -20258,7 +20923,7 @@ ${lines.join("\n")}`;
|
|
|
20258
20923
|
const r = Math.round(rgb.r);
|
|
20259
20924
|
const g = Math.round(rgb.g);
|
|
20260
20925
|
const b = Math.round(rgb.b);
|
|
20261
|
-
if (rgb.alpha !== void 0
|
|
20926
|
+
if (rgb.alpha !== void 0)
|
|
20262
20927
|
return `rgb(${r} ${g} ${b} / ${rgb.alpha})`;
|
|
20263
20928
|
return `rgb(${r} ${g} ${b})`;
|
|
20264
20929
|
}
|
|
@@ -20267,7 +20932,7 @@ ${lines.join("\n")}`;
|
|
|
20267
20932
|
const h = Math.round(hsl.h * 10) / 10;
|
|
20268
20933
|
const s = Math.round(hsl.s * 1e3) / 10;
|
|
20269
20934
|
const l = Math.round(hsl.l * 1e3) / 10;
|
|
20270
|
-
if (rgb.alpha !== void 0
|
|
20935
|
+
if (rgb.alpha !== void 0)
|
|
20271
20936
|
return `hsl(${h} ${s}% ${l}% / ${rgb.alpha})`;
|
|
20272
20937
|
return `hsl(${h} ${s}% ${l}%)`;
|
|
20273
20938
|
}
|
|
@@ -20276,7 +20941,7 @@ ${lines.join("\n")}`;
|
|
|
20276
20941
|
const L = Math.round(c.L * 1e3) / 1e3;
|
|
20277
20942
|
const C = Math.round(c.C * 1e3) / 1e3;
|
|
20278
20943
|
const H = Math.round(c.H * 10) / 10;
|
|
20279
|
-
if (rgb.alpha !== void 0
|
|
20944
|
+
if (rgb.alpha !== void 0)
|
|
20280
20945
|
return `oklch(${L} ${C} ${H} / ${rgb.alpha})`;
|
|
20281
20946
|
return `oklch(${L} ${C} ${H})`;
|
|
20282
20947
|
}
|
|
@@ -20285,29 +20950,29 @@ ${lines.join("\n")}`;
|
|
|
20285
20950
|
}
|
|
20286
20951
|
},
|
|
20287
20952
|
colorMix(input1, input2, ratio = 0.5) {
|
|
20288
|
-
const
|
|
20289
|
-
const
|
|
20953
|
+
const c1 = toOklch(input1);
|
|
20954
|
+
const c2 = toOklch(input2);
|
|
20290
20955
|
ratio = Math.max(0, Math.min(1, ratio));
|
|
20291
|
-
const
|
|
20292
|
-
const
|
|
20293
|
-
let
|
|
20294
|
-
if (
|
|
20295
|
-
if (
|
|
20296
|
-
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
H
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
const
|
|
20306
|
-
const
|
|
20307
|
-
const a1 =
|
|
20308
|
-
const a2 =
|
|
20309
|
-
const alpha = a1 + (a2 - a1) * ratio;
|
|
20310
|
-
return
|
|
20956
|
+
const c1Achromatic = c1.C < 1e-6;
|
|
20957
|
+
const c2Achromatic = c2.C < 1e-6;
|
|
20958
|
+
let H;
|
|
20959
|
+
if (c1Achromatic && c2Achromatic) H = c1.H;
|
|
20960
|
+
else if (c1Achromatic) H = c2.H;
|
|
20961
|
+
else if (c2Achromatic) H = c1.H;
|
|
20962
|
+
else {
|
|
20963
|
+
let dh = c2.H - c1.H;
|
|
20964
|
+
if (dh > 180) dh -= 360;
|
|
20965
|
+
if (dh < -180) dh += 360;
|
|
20966
|
+
H = c1.H + dh * ratio;
|
|
20967
|
+
if (H < 0) H += 360;
|
|
20968
|
+
if (H >= 360) H -= 360;
|
|
20969
|
+
}
|
|
20970
|
+
const L = c1.L + (c2.L - c1.L) * ratio;
|
|
20971
|
+
const C = c1.C + (c2.C - c1.C) * ratio;
|
|
20972
|
+
const a1 = c1.alpha ?? 1;
|
|
20973
|
+
const a2 = c2.alpha ?? 1;
|
|
20974
|
+
const alpha = normalizeAlpha(a1 + (a2 - a1) * ratio);
|
|
20975
|
+
return alpha !== void 0 ? [L, C, H, alpha] : [L, C, H];
|
|
20311
20976
|
},
|
|
20312
20977
|
colorContrast(bg, fg) {
|
|
20313
20978
|
return apca(toRgb255(bg), toRgb255(fg));
|
|
@@ -20315,11 +20980,11 @@ ${lines.join("\n")}`;
|
|
|
20315
20980
|
contrastingColor(bg, fg1, fg2) {
|
|
20316
20981
|
const bgRgb = toRgb255(bg);
|
|
20317
20982
|
if (fg1 !== void 0 && fg2 !== void 0) {
|
|
20318
|
-
return
|
|
20983
|
+
return packedToOklch(
|
|
20319
20984
|
contrastingColor({ bg: bgRgb, fg1: toRgb255(fg1), fg2: toRgb255(fg2) })
|
|
20320
20985
|
);
|
|
20321
20986
|
}
|
|
20322
|
-
return
|
|
20987
|
+
return packedToOklch(contrastingColor(bgRgb));
|
|
20323
20988
|
},
|
|
20324
20989
|
colorToColorspace(input, space) {
|
|
20325
20990
|
const rgb = toRgb255(input);
|
|
@@ -20348,7 +21013,7 @@ ${lines.join("\n")}`;
|
|
|
20348
21013
|
default:
|
|
20349
21014
|
throw new Error(`Unknown color space: ${space}`);
|
|
20350
21015
|
}
|
|
20351
|
-
if (alpha !== void 0
|
|
21016
|
+
if (alpha !== void 0) result.push(alpha);
|
|
20352
21017
|
return result;
|
|
20353
21018
|
},
|
|
20354
21019
|
colormap(name, arg) {
|
|
@@ -20360,7 +21025,7 @@ ${lines.join("\n")}`;
|
|
|
20360
21025
|
const palette = allPalettes[name];
|
|
20361
21026
|
if (!palette) throw new Error(`Unknown palette: ${name}`);
|
|
20362
21027
|
const colors = palette.map(
|
|
20363
|
-
(hex) =>
|
|
21028
|
+
(hex) => packedToOklch(parseColor(hex))
|
|
20364
21029
|
);
|
|
20365
21030
|
if (arg === void 0) return colors;
|
|
20366
21031
|
if (Number.isInteger(arg) && arg >= 2) {
|
|
@@ -20384,62 +21049,128 @@ ${lines.join("\n")}`;
|
|
|
20384
21049
|
const frac = pos - i;
|
|
20385
21050
|
if (frac === 0 || i >= colors.length - 1)
|
|
20386
21051
|
return [...colors[Math.min(i, colors.length - 1)]];
|
|
20387
|
-
const
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20394
|
-
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
20401
|
-
|
|
20402
|
-
|
|
20403
|
-
|
|
20404
|
-
if (H >= 360) H -= 360;
|
|
20405
|
-
const mixed = oklchToRgb({
|
|
20406
|
-
L: c1.L + (c2.L - c1.L) * frac,
|
|
20407
|
-
C: c1.C + (c2.C - c1.C) * frac,
|
|
20408
|
-
H
|
|
20409
|
-
});
|
|
20410
|
-
return [mixed.r / 255, mixed.g / 255, mixed.b / 255];
|
|
21052
|
+
const [L1, C1, H1] = colors[i];
|
|
21053
|
+
const [L2, C2, H2] = colors[i + 1];
|
|
21054
|
+
const c1Achromatic = C1 < 1e-6;
|
|
21055
|
+
const c2Achromatic = C2 < 1e-6;
|
|
21056
|
+
let H;
|
|
21057
|
+
if (c1Achromatic && c2Achromatic) H = H1;
|
|
21058
|
+
else if (c1Achromatic) H = H2;
|
|
21059
|
+
else if (c2Achromatic) H = H1;
|
|
21060
|
+
else {
|
|
21061
|
+
let dh = H2 - H1;
|
|
21062
|
+
if (dh > 180) dh -= 360;
|
|
21063
|
+
if (dh < -180) dh += 360;
|
|
21064
|
+
H = H1 + dh * frac;
|
|
21065
|
+
if (H < 0) H += 360;
|
|
21066
|
+
if (H >= 360) H -= 360;
|
|
21067
|
+
}
|
|
21068
|
+
return [L1 + (L2 - L1) * frac, C1 + (C2 - C1) * frac, H];
|
|
20411
21069
|
},
|
|
20412
21070
|
colorFromColorspace(components, space) {
|
|
20413
21071
|
const c0 = components[0];
|
|
20414
21072
|
const c1 = components[1];
|
|
20415
21073
|
const c2 = components[2];
|
|
20416
21074
|
const alpha = components.length >= 4 ? components[3] : void 0;
|
|
20417
|
-
let
|
|
21075
|
+
let oklch2;
|
|
20418
21076
|
switch (space.toLowerCase()) {
|
|
20419
21077
|
case "rgb":
|
|
20420
|
-
|
|
21078
|
+
oklch2 = rgbToOklch({ r: c0 * 255, g: c1 * 255, b: c2 * 255 });
|
|
20421
21079
|
break;
|
|
20422
21080
|
case "hsl": {
|
|
20423
|
-
const
|
|
20424
|
-
|
|
21081
|
+
const rgb = hslToRgb(c0, c1, c2);
|
|
21082
|
+
oklch2 = rgbToOklch(rgb);
|
|
20425
21083
|
break;
|
|
20426
21084
|
}
|
|
20427
|
-
case "oklch":
|
|
20428
|
-
|
|
20429
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
21085
|
+
case "oklch":
|
|
21086
|
+
oklch2 = { L: c0, C: c1, H: c2 };
|
|
20430
21087
|
break;
|
|
20431
|
-
}
|
|
20432
21088
|
case "oklab":
|
|
20433
|
-
case "lab":
|
|
20434
|
-
|
|
20435
|
-
result = [r.r / 255, r.g / 255, r.b / 255];
|
|
21089
|
+
case "lab":
|
|
21090
|
+
oklch2 = oklabToOklch({ L: c0, a: c1, b: c2 });
|
|
20436
21091
|
break;
|
|
20437
|
-
}
|
|
20438
21092
|
default:
|
|
20439
21093
|
throw new Error(`Unknown color space: ${space}`);
|
|
20440
21094
|
}
|
|
20441
|
-
|
|
20442
|
-
|
|
21095
|
+
return alpha !== void 0 ? [oklch2.L, oklch2.C, oklch2.H, alpha] : [oklch2.L, oklch2.C, oklch2.H];
|
|
21096
|
+
},
|
|
21097
|
+
// -----------------------------------------------------------------------
|
|
21098
|
+
// Color constructors. Each accepts components in its colorspace's natural
|
|
21099
|
+
// units and returns the canonical OKLCh array `[L, C, H]` (or with alpha).
|
|
21100
|
+
// -----------------------------------------------------------------------
|
|
21101
|
+
rgb(r, g, b, alpha) {
|
|
21102
|
+
const c = rgbToOklch({ r: r * 255, g: g * 255, b: b * 255 });
|
|
21103
|
+
const a = normalizeAlpha(alpha);
|
|
21104
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21105
|
+
},
|
|
21106
|
+
hsv(h, s, v, alpha) {
|
|
21107
|
+
const rgb = hsvToRgb(h, s, v);
|
|
21108
|
+
const c = rgbToOklch(rgb);
|
|
21109
|
+
const a = normalizeAlpha(alpha);
|
|
21110
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21111
|
+
},
|
|
21112
|
+
hsl(h, s, l, alpha) {
|
|
21113
|
+
const rgb = hslToRgb(h, s, l);
|
|
21114
|
+
const c = rgbToOklch({ r: rgb.r, g: rgb.g, b: rgb.b });
|
|
21115
|
+
const a = normalizeAlpha(alpha);
|
|
21116
|
+
return a !== void 0 ? [c.L, c.C, c.H, a] : [c.L, c.C, c.H];
|
|
21117
|
+
},
|
|
21118
|
+
oklab(L, a, b, alpha) {
|
|
21119
|
+
const c = oklabToOklch({ L, a, b });
|
|
21120
|
+
const al = normalizeAlpha(alpha);
|
|
21121
|
+
return al !== void 0 ? [c.L, c.C, c.H, al] : [c.L, c.C, c.H];
|
|
21122
|
+
},
|
|
21123
|
+
oklch(L, C, H, alpha) {
|
|
21124
|
+
const a = normalizeAlpha(alpha);
|
|
21125
|
+
return a !== void 0 ? [L, C, H, a] : [L, C, H];
|
|
21126
|
+
},
|
|
21127
|
+
// -----------------------------------------------------------------------
|
|
21128
|
+
// As* converters. Inputs are anything `toOklch` accepts (string, packed
|
|
21129
|
+
// int, or OKLCh array). Outputs are 3- or 4-element arrays in the named
|
|
21130
|
+
// space. sRGB-based outputs (asRgb/asHsv/asHsl) use 0-1 channels for
|
|
21131
|
+
// consistency with the GPU target's shader convention.
|
|
21132
|
+
// -----------------------------------------------------------------------
|
|
21133
|
+
asRgb(input) {
|
|
21134
|
+
const rgb = toRgb255(input);
|
|
21135
|
+
const r = rgb.r / 255;
|
|
21136
|
+
const g = rgb.g / 255;
|
|
21137
|
+
const b = rgb.b / 255;
|
|
21138
|
+
return rgb.alpha !== void 0 ? [r, g, b, rgb.alpha] : [r, g, b];
|
|
21139
|
+
},
|
|
21140
|
+
asHsv(input) {
|
|
21141
|
+
const rgb = toRgb255(input);
|
|
21142
|
+
const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
21143
|
+
return rgb.alpha !== void 0 ? [hsv.h, hsv.s, hsv.v, rgb.alpha] : [hsv.h, hsv.s, hsv.v];
|
|
21144
|
+
},
|
|
21145
|
+
asHsl(input) {
|
|
21146
|
+
const rgb = toRgb255(input);
|
|
21147
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
21148
|
+
return rgb.alpha !== void 0 ? [hsl.h, hsl.s, hsl.l, rgb.alpha] : [hsl.h, hsl.s, hsl.l];
|
|
21149
|
+
},
|
|
21150
|
+
asOklab(input) {
|
|
21151
|
+
const c = toOklch(input);
|
|
21152
|
+
const lab = oklchToOklab({ L: c.L, C: c.C, H: c.H });
|
|
21153
|
+
return c.alpha !== void 0 ? [lab.L, lab.a, lab.b, c.alpha] : [lab.L, lab.a, lab.b];
|
|
21154
|
+
},
|
|
21155
|
+
// asOklch is identity — handled at compile time as a pass-through
|
|
21156
|
+
// Perceptual color difference (ΔE_OK).
|
|
21157
|
+
colorDelta(a, b) {
|
|
21158
|
+
const labA = oklchToOklab(toOklch(a));
|
|
21159
|
+
const labB = oklchToOklab(toOklch(b));
|
|
21160
|
+
return oklabDeltaE(labA, labB);
|
|
21161
|
+
},
|
|
21162
|
+
// Euclidean distance between two tuples. Plain numeric — not a color
|
|
21163
|
+
// operation despite living in the same helpers block.
|
|
21164
|
+
distance(a, b) {
|
|
21165
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
21166
|
+
throw new Error("Distance: expected two arrays");
|
|
21167
|
+
if (a.length !== b.length) throw new Error("Distance: dimension mismatch");
|
|
21168
|
+
let sumSq = 0;
|
|
21169
|
+
for (let i = 0; i < a.length; i++) {
|
|
21170
|
+
const d = a[i] - b[i];
|
|
21171
|
+
sumSq += d * d;
|
|
21172
|
+
}
|
|
21173
|
+
return Math.sqrt(sumSq);
|
|
20443
21174
|
}
|
|
20444
21175
|
};
|
|
20445
21176
|
var SYS_HELPERS = {
|
|
@@ -20878,6 +21609,13 @@ ${lines.join("\n")}`;
|
|
|
20878
21609
|
function gpuVec2(target) {
|
|
20879
21610
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
20880
21611
|
}
|
|
21612
|
+
function gpuVec3(target) {
|
|
21613
|
+
return target?.language === "wgsl" ? "vec3f" : "vec3";
|
|
21614
|
+
}
|
|
21615
|
+
function readStringLiteral(expr) {
|
|
21616
|
+
if (!isString(expr)) return null;
|
|
21617
|
+
return expr.string?.toLowerCase() ?? null;
|
|
21618
|
+
}
|
|
20881
21619
|
function compileIntArg(expr, compile2, target) {
|
|
20882
21620
|
const c = tryGetConstant(expr);
|
|
20883
21621
|
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
@@ -20936,7 +21674,7 @@ ${lines.join("\n")}`;
|
|
|
20936
21674
|
`for (${indexDecl} = ${lowerStr}; ${index} <= ${upperStr}; ${index}++) {`,
|
|
20937
21675
|
` ${acc} ${op}= ${body};`,
|
|
20938
21676
|
`}`,
|
|
20939
|
-
`return ${acc}
|
|
21677
|
+
`return ${acc};`
|
|
20940
21678
|
];
|
|
20941
21679
|
return lines.join("\n");
|
|
20942
21680
|
}
|
|
@@ -20990,8 +21728,7 @@ ${lines.join("\n")}`;
|
|
|
20990
21728
|
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
20991
21729
|
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
20992
21730
|
const v2 = gpuVec2(target);
|
|
20993
|
-
if (realFactors.length === 0)
|
|
20994
|
-
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
21731
|
+
if (realFactors.length === 0) return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
20995
21732
|
const factors = realFactors.map((f) => compile2(f));
|
|
20996
21733
|
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
20997
21734
|
const imCode = foldTerms(factors, "1.0", "*");
|
|
@@ -21044,8 +21781,7 @@ ${lines.join("\n")}`;
|
|
|
21044
21781
|
if (isNumber(x) && x.im !== 0) {
|
|
21045
21782
|
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
21046
21783
|
}
|
|
21047
|
-
if (isSymbol2(x, "ImaginaryUnit"))
|
|
21048
|
-
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
21784
|
+
if (isSymbol2(x, "ImaginaryUnit")) return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
21049
21785
|
return `(-${compile2(x)})`;
|
|
21050
21786
|
},
|
|
21051
21787
|
// Standard math functions with complex dispatch
|
|
@@ -21418,17 +22154,127 @@ ${lines.join("\n")}`;
|
|
|
21418
22154
|
}
|
|
21419
22155
|
const isWGSL = target?.language === "wgsl";
|
|
21420
22156
|
const v3 = isWGSL ? "vec3f" : "vec3";
|
|
21421
|
-
|
|
22157
|
+
const black = `${v3}(0.0)`;
|
|
22158
|
+
const white = `${v3}(1.0, 0.0, 0.0)`;
|
|
22159
|
+
return `((_gpu_apca(${bg}, ${black}) > 50.0) ? ${black} : ${white})`;
|
|
21422
22160
|
},
|
|
21423
22161
|
ColorToColorspace: ([color, space], compile2) => {
|
|
21424
22162
|
if (color === null || space === null)
|
|
21425
22163
|
throw new Error("ColorToColorspace: need color and space");
|
|
21426
|
-
|
|
22164
|
+
const spaceName = readStringLiteral(space);
|
|
22165
|
+
if (spaceName === null)
|
|
22166
|
+
throw new Error("ColorToColorspace: space must be a string literal");
|
|
22167
|
+
const c = compile2(color);
|
|
22168
|
+
switch (spaceName) {
|
|
22169
|
+
case "oklch":
|
|
22170
|
+
return c;
|
|
22171
|
+
case "oklab":
|
|
22172
|
+
case "lab":
|
|
22173
|
+
return `_gpu_oklch_to_oklab(${c})`;
|
|
22174
|
+
case "rgb":
|
|
22175
|
+
return `_gpu_oklch_to_srgb(${c})`;
|
|
22176
|
+
case "hsl":
|
|
22177
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${c}))`;
|
|
22178
|
+
case "hsv":
|
|
22179
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${c}))`;
|
|
22180
|
+
default:
|
|
22181
|
+
throw new Error(
|
|
22182
|
+
`ColorToColorspace: unsupported space "${spaceName}" on GPU target`
|
|
22183
|
+
);
|
|
22184
|
+
}
|
|
21427
22185
|
},
|
|
21428
22186
|
ColorFromColorspace: ([components, space], compile2) => {
|
|
21429
22187
|
if (components === null || space === null)
|
|
21430
22188
|
throw new Error("ColorFromColorspace: need components and space");
|
|
21431
|
-
|
|
22189
|
+
const spaceName = readStringLiteral(space);
|
|
22190
|
+
if (spaceName === null)
|
|
22191
|
+
throw new Error("ColorFromColorspace: space must be a string literal");
|
|
22192
|
+
const c = compile2(components);
|
|
22193
|
+
switch (spaceName) {
|
|
22194
|
+
case "oklch":
|
|
22195
|
+
return c;
|
|
22196
|
+
case "oklab":
|
|
22197
|
+
case "lab":
|
|
22198
|
+
return `_gpu_oklab_to_oklch(${c})`;
|
|
22199
|
+
case "rgb":
|
|
22200
|
+
return `_gpu_srgb_to_oklch(${c})`;
|
|
22201
|
+
case "hsl":
|
|
22202
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${c}))`;
|
|
22203
|
+
case "hsv":
|
|
22204
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${c}))`;
|
|
22205
|
+
default:
|
|
22206
|
+
throw new Error(
|
|
22207
|
+
`ColorFromColorspace: unsupported space "${spaceName}" on GPU target`
|
|
22208
|
+
);
|
|
22209
|
+
}
|
|
22210
|
+
},
|
|
22211
|
+
// ---------------------------------------------------------------------------
|
|
22212
|
+
// Color literals. Each typed head compiles to a canonical OKLCh vec3.
|
|
22213
|
+
// Alpha (4th argument) is dropped — GPU color values are vec3 only. Pass
|
|
22214
|
+
// alpha as a separate uniform if it's needed at the framebuffer boundary.
|
|
22215
|
+
// ---------------------------------------------------------------------------
|
|
22216
|
+
Color: ([s], _compile, target) => {
|
|
22217
|
+
if (s === null) throw new Error("Color: no argument");
|
|
22218
|
+
const str = readStringLiteral(s);
|
|
22219
|
+
if (str === null)
|
|
22220
|
+
throw new Error("Color: argument must be a string literal on GPU target");
|
|
22221
|
+
const packed = parseColor(str);
|
|
22222
|
+
if (packed === 0 && str.trim().toLowerCase() !== "transparent")
|
|
22223
|
+
throw new Error(`Color: invalid color string "${str}"`);
|
|
22224
|
+
const r = packed >>> 24 & 255;
|
|
22225
|
+
const g = packed >>> 16 & 255;
|
|
22226
|
+
const b = packed >>> 8 & 255;
|
|
22227
|
+
const oklch2 = rgbToOklch({ r, g, b });
|
|
22228
|
+
return `${gpuVec3(target)}(${formatFloat(oklch2.L)}, ${formatFloat(oklch2.C)}, ${formatFloat(oklch2.H)})`;
|
|
22229
|
+
},
|
|
22230
|
+
Rgb: (args, compile2, target) => {
|
|
22231
|
+
if (args.length < 3) throw new Error("Rgb: need 3 components");
|
|
22232
|
+
const v3 = gpuVec3(target);
|
|
22233
|
+
return `_gpu_srgb_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
|
|
22234
|
+
},
|
|
22235
|
+
Hsv: (args, compile2, target) => {
|
|
22236
|
+
if (args.length < 3) throw new Error("Hsv: need 3 components");
|
|
22237
|
+
const v3 = gpuVec3(target);
|
|
22238
|
+
return `_gpu_srgb_to_oklch(_gpu_hsv_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
|
|
22239
|
+
},
|
|
22240
|
+
Hsl: (args, compile2, target) => {
|
|
22241
|
+
if (args.length < 3) throw new Error("Hsl: need 3 components");
|
|
22242
|
+
const v3 = gpuVec3(target);
|
|
22243
|
+
return `_gpu_srgb_to_oklch(_gpu_hsl_to_rgb(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})))`;
|
|
22244
|
+
},
|
|
22245
|
+
Oklab: (args, compile2, target) => {
|
|
22246
|
+
if (args.length < 3) throw new Error("Oklab: need 3 components");
|
|
22247
|
+
const v3 = gpuVec3(target);
|
|
22248
|
+
return `_gpu_oklab_to_oklch(${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])}))`;
|
|
22249
|
+
},
|
|
22250
|
+
Oklch: (args, compile2, target) => {
|
|
22251
|
+
if (args.length < 3) throw new Error("Oklch: need 3 components");
|
|
22252
|
+
const v3 = gpuVec3(target);
|
|
22253
|
+
return `${v3}(${compile2(args[0])}, ${compile2(args[1])}, ${compile2(args[2])})`;
|
|
22254
|
+
},
|
|
22255
|
+
// ---------------------------------------------------------------------------
|
|
22256
|
+
// As* operators. AsOklch is identity (canonical). The other As* return
|
|
22257
|
+
// components in the named space, equivalent to ColorToColorspace(c, 'x').
|
|
22258
|
+
// ---------------------------------------------------------------------------
|
|
22259
|
+
AsOklch: ([c], compile2) => {
|
|
22260
|
+
if (c === null) throw new Error("AsOklch: no argument");
|
|
22261
|
+
return compile2(c);
|
|
22262
|
+
},
|
|
22263
|
+
AsOklab: ([c], compile2) => {
|
|
22264
|
+
if (c === null) throw new Error("AsOklab: no argument");
|
|
22265
|
+
return `_gpu_oklch_to_oklab(${compile2(c)})`;
|
|
22266
|
+
},
|
|
22267
|
+
AsRgb: ([c], compile2) => {
|
|
22268
|
+
if (c === null) throw new Error("AsRgb: no argument");
|
|
22269
|
+
return `_gpu_oklch_to_srgb(${compile2(c)})`;
|
|
22270
|
+
},
|
|
22271
|
+
AsHsv: ([c], compile2) => {
|
|
22272
|
+
if (c === null) throw new Error("AsHsv: no argument");
|
|
22273
|
+
return `_gpu_rgb_to_hsv(_gpu_oklch_to_srgb(${compile2(c)}))`;
|
|
22274
|
+
},
|
|
22275
|
+
AsHsl: ([c], compile2) => {
|
|
22276
|
+
if (c === null) throw new Error("AsHsl: no argument");
|
|
22277
|
+
return `_gpu_rgb_to_hsl(_gpu_oklch_to_srgb(${compile2(c)}))`;
|
|
21432
22278
|
},
|
|
21433
22279
|
// Fractal functions
|
|
21434
22280
|
Mandelbrot: ([c, maxIter], compile2, target) => {
|
|
@@ -22121,28 +22967,124 @@ vec3 _gpu_oklab_to_srgb(vec3 lab) {
|
|
|
22121
22967
|
|
|
22122
22968
|
vec3 _gpu_oklab_to_oklch(vec3 lab) {
|
|
22123
22969
|
float C = length(lab.yz);
|
|
22124
|
-
float H = atan(lab.z, lab.y);
|
|
22970
|
+
float H = atan(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
22971
|
+
if (H < 0.0) H += 360.0;
|
|
22125
22972
|
return vec3(lab.x, C, H);
|
|
22126
22973
|
}
|
|
22127
22974
|
|
|
22128
22975
|
vec3 _gpu_oklch_to_oklab(vec3 lch) {
|
|
22129
|
-
|
|
22976
|
+
float h_rad = lch.z * (3.14159265359 / 180.0);
|
|
22977
|
+
return vec3(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
22978
|
+
}
|
|
22979
|
+
|
|
22980
|
+
vec3 _gpu_srgb_to_oklch(vec3 rgb) {
|
|
22981
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
22982
|
+
}
|
|
22983
|
+
|
|
22984
|
+
vec3 _gpu_oklch_to_srgb(vec3 lch) {
|
|
22985
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
22986
|
+
}
|
|
22987
|
+
|
|
22988
|
+
// HSL conversion. Hue in degrees, saturation/lightness in 0-1.
|
|
22989
|
+
vec3 _gpu_hsl_to_rgb(vec3 hsl) {
|
|
22990
|
+
float h = hsl.x;
|
|
22991
|
+
float s = hsl.y;
|
|
22992
|
+
float l = hsl.z;
|
|
22993
|
+
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
22994
|
+
float h6 = h / 60.0;
|
|
22995
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
22996
|
+
float r = 0.0;
|
|
22997
|
+
float g = 0.0;
|
|
22998
|
+
float b = 0.0;
|
|
22999
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23000
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23001
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23002
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23003
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23004
|
+
else { r = c; g = 0.0; b = x; }
|
|
23005
|
+
float m = l - c / 2.0;
|
|
23006
|
+
return vec3(r + m, g + m, b + m);
|
|
23007
|
+
}
|
|
23008
|
+
|
|
23009
|
+
vec3 _gpu_rgb_to_hsl(vec3 rgb) {
|
|
23010
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23011
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23012
|
+
float l = (maxc + minc) / 2.0;
|
|
23013
|
+
float d = maxc - minc;
|
|
23014
|
+
if (d < 1e-6) return vec3(0.0, 0.0, l);
|
|
23015
|
+
float s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
23016
|
+
float h;
|
|
23017
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
23018
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
23019
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
23020
|
+
h *= 60.0;
|
|
23021
|
+
if (h < 0.0) h += 360.0;
|
|
23022
|
+
return vec3(h, s, l);
|
|
23023
|
+
}
|
|
23024
|
+
|
|
23025
|
+
// HSV conversion. Hue in degrees, saturation/value in 0-1.
|
|
23026
|
+
vec3 _gpu_hsv_to_rgb(vec3 hsv) {
|
|
23027
|
+
float h = hsv.x;
|
|
23028
|
+
float s = hsv.y;
|
|
23029
|
+
float v = hsv.z;
|
|
23030
|
+
float c = v * s;
|
|
23031
|
+
float h6 = h / 60.0;
|
|
23032
|
+
float x = c * (1.0 - abs(mod(h6, 2.0) - 1.0));
|
|
23033
|
+
float r = 0.0;
|
|
23034
|
+
float g = 0.0;
|
|
23035
|
+
float b = 0.0;
|
|
23036
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23037
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23038
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23039
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23040
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23041
|
+
else { r = c; g = 0.0; b = x; }
|
|
23042
|
+
float m = v - c;
|
|
23043
|
+
return vec3(r + m, g + m, b + m);
|
|
23044
|
+
}
|
|
23045
|
+
|
|
23046
|
+
vec3 _gpu_rgb_to_hsv(vec3 rgb) {
|
|
23047
|
+
float maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23048
|
+
float minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23049
|
+
float v = maxc;
|
|
23050
|
+
float d = maxc - minc;
|
|
23051
|
+
if (d < 1e-6) return vec3(0.0, 0.0, v);
|
|
23052
|
+
float s = (maxc < 1e-6) ? 0.0 : d / maxc;
|
|
23053
|
+
float h;
|
|
23054
|
+
if (maxc == rgb.x) h = mod((rgb.y - rgb.z) / d, 6.0);
|
|
23055
|
+
else if (maxc == rgb.y) h = (rgb.z - rgb.x) / d + 2.0;
|
|
23056
|
+
else h = (rgb.x - rgb.y) / d + 4.0;
|
|
23057
|
+
h *= 60.0;
|
|
23058
|
+
if (h < 0.0) h += 360.0;
|
|
23059
|
+
return vec3(h, s, v);
|
|
22130
23060
|
}
|
|
22131
23061
|
|
|
22132
|
-
vec3 _gpu_color_mix(vec3
|
|
22133
|
-
vec3 lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
|
|
22134
|
-
vec3 lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
|
|
23062
|
+
vec3 _gpu_color_mix(vec3 lch1, vec3 lch2, float t) {
|
|
22135
23063
|
float L = mix(lch1.x, lch2.x, t);
|
|
22136
23064
|
float C = mix(lch1.y, lch2.y, t);
|
|
22137
|
-
|
|
22138
|
-
|
|
22139
|
-
|
|
22140
|
-
if (
|
|
22141
|
-
|
|
22142
|
-
|
|
23065
|
+
bool a1 = lch1.y < 1e-6;
|
|
23066
|
+
bool a2 = lch2.y < 1e-6;
|
|
23067
|
+
float H;
|
|
23068
|
+
if (a1 && a2) {
|
|
23069
|
+
H = lch1.z;
|
|
23070
|
+
} else if (a1) {
|
|
23071
|
+
H = lch2.z;
|
|
23072
|
+
} else if (a2) {
|
|
23073
|
+
H = lch1.z;
|
|
23074
|
+
} else {
|
|
23075
|
+
float dh = lch2.z - lch1.z;
|
|
23076
|
+
if (dh > 180.0) dh -= 360.0;
|
|
23077
|
+
if (dh < -180.0) dh += 360.0;
|
|
23078
|
+
H = lch1.z + dh * t;
|
|
23079
|
+
if (H < 0.0) H += 360.0;
|
|
23080
|
+
if (H >= 360.0) H -= 360.0;
|
|
23081
|
+
}
|
|
23082
|
+
return vec3(L, C, H);
|
|
22143
23083
|
}
|
|
22144
23084
|
|
|
22145
|
-
float _gpu_apca(vec3
|
|
23085
|
+
float _gpu_apca(vec3 lch_bg, vec3 lch_fg) {
|
|
23086
|
+
vec3 bg = _gpu_oklch_to_srgb(lch_bg);
|
|
23087
|
+
vec3 fg = _gpu_oklch_to_srgb(lch_fg);
|
|
22146
23088
|
float bgR = _gpu_srgb_to_linear(bg.x);
|
|
22147
23089
|
float bgG = _gpu_srgb_to_linear(bg.y);
|
|
22148
23090
|
float bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -22153,9 +23095,7 @@ float _gpu_apca(vec3 bg, vec3 fg) {
|
|
|
22153
23095
|
float fgY = 0.2126729 * fgR + 0.7151522 * fgG + 0.0721750 * fgB;
|
|
22154
23096
|
float bgC = pow(bgY, 0.56);
|
|
22155
23097
|
float fgC = pow(fgY, 0.57);
|
|
22156
|
-
float contrast = (bgC
|
|
22157
|
-
? (bgC - fgC) * 1.14
|
|
22158
|
-
: (bgC - fgC) * 1.14;
|
|
23098
|
+
float contrast = (bgC - fgC) * 1.14;
|
|
22159
23099
|
return contrast * 100.0;
|
|
22160
23100
|
}
|
|
22161
23101
|
`;
|
|
@@ -22199,28 +23139,133 @@ fn _gpu_oklab_to_srgb(lab: vec3f) -> vec3f {
|
|
|
22199
23139
|
|
|
22200
23140
|
fn _gpu_oklab_to_oklch(lab: vec3f) -> vec3f {
|
|
22201
23141
|
let C = length(lab.yz);
|
|
22202
|
-
|
|
23142
|
+
var H = atan2(lab.z, lab.y) * (180.0 / 3.14159265359);
|
|
23143
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
22203
23144
|
return vec3f(lab.x, C, H);
|
|
22204
23145
|
}
|
|
22205
23146
|
|
|
22206
23147
|
fn _gpu_oklch_to_oklab(lch: vec3f) -> vec3f {
|
|
22207
|
-
|
|
23148
|
+
let h_rad = lch.z * (3.14159265359 / 180.0);
|
|
23149
|
+
return vec3f(lch.x, lch.y * cos(h_rad), lch.y * sin(h_rad));
|
|
23150
|
+
}
|
|
23151
|
+
|
|
23152
|
+
fn _gpu_srgb_to_oklch(rgb: vec3f) -> vec3f {
|
|
23153
|
+
return _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb));
|
|
23154
|
+
}
|
|
23155
|
+
|
|
23156
|
+
fn _gpu_oklch_to_srgb(lch: vec3f) -> vec3f {
|
|
23157
|
+
return _gpu_oklab_to_srgb(_gpu_oklch_to_oklab(lch));
|
|
23158
|
+
}
|
|
23159
|
+
|
|
23160
|
+
fn _gpu_hsl_to_rgb(hsl: vec3f) -> vec3f {
|
|
23161
|
+
let h = hsl.x;
|
|
23162
|
+
let s = hsl.y;
|
|
23163
|
+
let l = hsl.z;
|
|
23164
|
+
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
|
23165
|
+
let h6 = h / 60.0;
|
|
23166
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
23167
|
+
var r: f32 = 0.0;
|
|
23168
|
+
var g: f32 = 0.0;
|
|
23169
|
+
var b: f32 = 0.0;
|
|
23170
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23171
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23172
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23173
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23174
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23175
|
+
else { r = c; g = 0.0; b = x; }
|
|
23176
|
+
let m = l - c / 2.0;
|
|
23177
|
+
return vec3f(r + m, g + m, b + m);
|
|
23178
|
+
}
|
|
23179
|
+
|
|
23180
|
+
fn _gpu_rgb_to_hsl(rgb: vec3f) -> vec3f {
|
|
23181
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23182
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23183
|
+
let l = (maxc + minc) / 2.0;
|
|
23184
|
+
let d = maxc - minc;
|
|
23185
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, l); }
|
|
23186
|
+
let s = d / (1.0 - abs(2.0 * l - 1.0));
|
|
23187
|
+
var h: f32;
|
|
23188
|
+
if (maxc == rgb.x) {
|
|
23189
|
+
let v = (rgb.y - rgb.z) / d;
|
|
23190
|
+
h = v - 6.0 * floor(v / 6.0);
|
|
23191
|
+
} else if (maxc == rgb.y) {
|
|
23192
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
23193
|
+
} else {
|
|
23194
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
23195
|
+
}
|
|
23196
|
+
h = h * 60.0;
|
|
23197
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
23198
|
+
return vec3f(h, s, l);
|
|
23199
|
+
}
|
|
23200
|
+
|
|
23201
|
+
fn _gpu_hsv_to_rgb(hsv: vec3f) -> vec3f {
|
|
23202
|
+
let h = hsv.x;
|
|
23203
|
+
let s = hsv.y;
|
|
23204
|
+
let v = hsv.z;
|
|
23205
|
+
let c = v * s;
|
|
23206
|
+
let h6 = h / 60.0;
|
|
23207
|
+
let x = c * (1.0 - abs((h6 - 2.0 * floor(h6 / 2.0)) - 1.0));
|
|
23208
|
+
var r: f32 = 0.0;
|
|
23209
|
+
var g: f32 = 0.0;
|
|
23210
|
+
var b: f32 = 0.0;
|
|
23211
|
+
if (h6 < 1.0) { r = c; g = x; b = 0.0; }
|
|
23212
|
+
else if (h6 < 2.0) { r = x; g = c; b = 0.0; }
|
|
23213
|
+
else if (h6 < 3.0) { r = 0.0; g = c; b = x; }
|
|
23214
|
+
else if (h6 < 4.0) { r = 0.0; g = x; b = c; }
|
|
23215
|
+
else if (h6 < 5.0) { r = x; g = 0.0; b = c; }
|
|
23216
|
+
else { r = c; g = 0.0; b = x; }
|
|
23217
|
+
let m = v - c;
|
|
23218
|
+
return vec3f(r + m, g + m, b + m);
|
|
23219
|
+
}
|
|
23220
|
+
|
|
23221
|
+
fn _gpu_rgb_to_hsv(rgb: vec3f) -> vec3f {
|
|
23222
|
+
let maxc = max(max(rgb.x, rgb.y), rgb.z);
|
|
23223
|
+
let minc = min(min(rgb.x, rgb.y), rgb.z);
|
|
23224
|
+
let v = maxc;
|
|
23225
|
+
let d = maxc - minc;
|
|
23226
|
+
if (d < 1e-6) { return vec3f(0.0, 0.0, v); }
|
|
23227
|
+
var s: f32 = 0.0;
|
|
23228
|
+
if (maxc >= 1e-6) { s = d / maxc; }
|
|
23229
|
+
var h: f32;
|
|
23230
|
+
if (maxc == rgb.x) {
|
|
23231
|
+
let q = (rgb.y - rgb.z) / d;
|
|
23232
|
+
h = q - 6.0 * floor(q / 6.0);
|
|
23233
|
+
} else if (maxc == rgb.y) {
|
|
23234
|
+
h = (rgb.z - rgb.x) / d + 2.0;
|
|
23235
|
+
} else {
|
|
23236
|
+
h = (rgb.x - rgb.y) / d + 4.0;
|
|
23237
|
+
}
|
|
23238
|
+
h = h * 60.0;
|
|
23239
|
+
if (h < 0.0) { h = h + 360.0; }
|
|
23240
|
+
return vec3f(h, s, v);
|
|
22208
23241
|
}
|
|
22209
23242
|
|
|
22210
|
-
fn _gpu_color_mix(
|
|
22211
|
-
let lch1 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb1));
|
|
22212
|
-
let lch2 = _gpu_oklab_to_oklch(_gpu_srgb_to_oklab(rgb2));
|
|
23243
|
+
fn _gpu_color_mix(lch1: vec3f, lch2: vec3f, t: f32) -> vec3f {
|
|
22213
23244
|
let L = mix(lch1.x, lch2.x, t);
|
|
22214
23245
|
let C = mix(lch1.y, lch2.y, t);
|
|
22215
|
-
let
|
|
22216
|
-
|
|
22217
|
-
|
|
22218
|
-
if (
|
|
22219
|
-
|
|
22220
|
-
|
|
23246
|
+
let a1 = lch1.y < 1e-6;
|
|
23247
|
+
let a2 = lch2.y < 1e-6;
|
|
23248
|
+
var H: f32;
|
|
23249
|
+
if (a1 && a2) {
|
|
23250
|
+
H = lch1.z;
|
|
23251
|
+
} else if (a1) {
|
|
23252
|
+
H = lch2.z;
|
|
23253
|
+
} else if (a2) {
|
|
23254
|
+
H = lch1.z;
|
|
23255
|
+
} else {
|
|
23256
|
+
var dh = lch2.z - lch1.z;
|
|
23257
|
+
if (dh > 180.0) { dh = dh - 360.0; }
|
|
23258
|
+
if (dh < -180.0) { dh = dh + 360.0; }
|
|
23259
|
+
H = lch1.z + dh * t;
|
|
23260
|
+
if (H < 0.0) { H = H + 360.0; }
|
|
23261
|
+
if (H >= 360.0) { H = H - 360.0; }
|
|
23262
|
+
}
|
|
23263
|
+
return vec3f(L, C, H);
|
|
22221
23264
|
}
|
|
22222
23265
|
|
|
22223
|
-
fn _gpu_apca(
|
|
23266
|
+
fn _gpu_apca(lch_bg: vec3f, lch_fg: vec3f) -> f32 {
|
|
23267
|
+
let bg = _gpu_oklch_to_srgb(lch_bg);
|
|
23268
|
+
let fg = _gpu_oklch_to_srgb(lch_fg);
|
|
22224
23269
|
let bgR = _gpu_srgb_to_linear(bg.x);
|
|
22225
23270
|
let bgG = _gpu_srgb_to_linear(bg.y);
|
|
22226
23271
|
let bgB = _gpu_srgb_to_linear(bg.z);
|
|
@@ -22508,7 +23553,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
22508
23553
|
if (stmts.length === 0) return "";
|
|
22509
23554
|
const last = stmts.length - 1;
|
|
22510
23555
|
stmts[last] = `return ${stmts[last]}`;
|
|
22511
|
-
return stmts.join(";\n");
|
|
23556
|
+
return stmts.join(";\n") + ";";
|
|
22512
23557
|
},
|
|
22513
23558
|
...options
|
|
22514
23559
|
};
|
|
@@ -22607,7 +23652,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
22607
23652
|
if (body.includes("\n")) {
|
|
22608
23653
|
const indented = body.split("\n").map((l) => ` ${l}`).join("\n");
|
|
22609
23654
|
return `${returnType} ${functionName}(${params}) {
|
|
22610
|
-
${indented}
|
|
23655
|
+
${indented}
|
|
22611
23656
|
}`;
|
|
22612
23657
|
}
|
|
22613
23658
|
return `${returnType} ${functionName}(${params}) {
|
|
@@ -22718,7 +23763,7 @@ ${indented};
|
|
|
22718
23763
|
return `fn ${functionName}(${params}) -> ${toWGSLType(
|
|
22719
23764
|
returnType
|
|
22720
23765
|
)} {
|
|
22721
|
-
${indented}
|
|
23766
|
+
${indented}
|
|
22722
23767
|
}`;
|
|
22723
23768
|
}
|
|
22724
23769
|
return `fn ${functionName}(${params}) -> ${toWGSLType(returnType)} {
|
|
@@ -24897,7 +25942,7 @@ ${code}`;
|
|
|
24897
25942
|
}
|
|
24898
25943
|
|
|
24899
25944
|
// src/compile.ts
|
|
24900
|
-
var version = "0.
|
|
25945
|
+
var version = "0.57.0";
|
|
24901
25946
|
return __toCommonJS(compile_exports);
|
|
24902
25947
|
})();
|
|
24903
25948
|
/*! Bundled license information:
|