@cortex-js/compute-engine 0.55.2 → 0.55.4
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 +908 -176
- package/dist/compile.min.esm.js +441 -71
- package/dist/compile.min.umd.cjs +442 -72
- package/dist/compile.umd.cjs +908 -176
- package/dist/compute-engine.esm.js +954 -185
- package/dist/compute-engine.min.esm.js +444 -74
- package/dist/compute-engine.min.umd.cjs +444 -74
- package/dist/compute-engine.umd.cjs +954 -185
- package/dist/core.esm.js +951 -174
- package/dist/core.min.esm.js +442 -72
- package/dist/core.min.umd.cjs +442 -72
- package/dist/core.umd.cjs +951 -174
- package/dist/interval.esm.js +2 -2
- package/dist/interval.min.esm.js +2 -2
- package/dist/interval.min.umd.cjs +2 -2
- package/dist/interval.umd.cjs +2 -2
- package/dist/latex-syntax.esm.js +43 -13
- package/dist/latex-syntax.min.esm.js +5 -5
- package/dist/latex-syntax.min.umd.cjs +5 -5
- package/dist/latex-syntax.umd.cjs +43 -13
- 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 +2 -2
- package/dist/numerics.min.esm.js +2 -2
- package/dist/numerics.min.umd.cjs +2 -2
- package/dist/numerics.umd.cjs +2 -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 +1 -1
- 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 +1 -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 +8 -7
- package/dist/types/compute-engine/compilation/compile-expression.d.ts +1 -1
- package/dist/types/compute-engine/compilation/constant-folding.d.ts +50 -0
- package/dist/types/compute-engine/compilation/fractal-orbit.d.ts +13 -0
- package/dist/types/compute-engine/compilation/glsl-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/gpu-target.d.ts +47 -1
- package/dist/types/compute-engine/compilation/interval-javascript-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/javascript-target.d.ts +23 -1
- package/dist/types/compute-engine/compilation/python-target.d.ts +1 -1
- package/dist/types/compute-engine/compilation/types.d.ts +48 -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 +1 -1
- 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 +1 -1
- 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-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 +1 -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 +1 -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 +1 -1
- 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 +1 -1
- 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 -1
- 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 +3 -3
package/dist/compile.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Compile 0.55.
|
|
1
|
+
/** Compile 0.55.4 */
|
|
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;
|
|
@@ -3969,12 +3969,6 @@ var Compile = (() => {
|
|
|
3969
3969
|
function applicable(fn) {
|
|
3970
3970
|
return makeLambda(fn) ?? ((xs) => fn.engine.function("Apply", [fn, ...xs]).evaluate());
|
|
3971
3971
|
}
|
|
3972
|
-
function applicableN1(fn) {
|
|
3973
|
-
const lambda = makeLambda(fn);
|
|
3974
|
-
const ce = fn.engine;
|
|
3975
|
-
if (lambda) return (x) => lambda([ce.number(x)])?.re ?? NaN;
|
|
3976
|
-
return (x) => ce.function("Apply", [fn, ce.number(x)]).evaluate().re;
|
|
3977
|
-
}
|
|
3978
3972
|
|
|
3979
3973
|
// src/compute-engine/collection-utils.ts
|
|
3980
3974
|
function isFiniteIndexedCollection(col) {
|
|
@@ -14699,8 +14693,11 @@ ${lines.join("\n")}`;
|
|
|
14699
14693
|
for (const local of locals) {
|
|
14700
14694
|
for (const arg of args) {
|
|
14701
14695
|
if (isFunction2(arg, "Assign") && isSymbol2(arg.ops[0], local)) {
|
|
14702
|
-
|
|
14696
|
+
const rhs = arg.ops[1];
|
|
14697
|
+
if (_BaseCompiler.isComplexValued(rhs)) {
|
|
14703
14698
|
typeHints[local] = isWGSL ? "vec2f" : "vec2";
|
|
14699
|
+
} else if (_BaseCompiler.isIntegerValued(rhs)) {
|
|
14700
|
+
typeHints[local] = isWGSL ? "i32" : "int";
|
|
14704
14701
|
}
|
|
14705
14702
|
break;
|
|
14706
14703
|
}
|
|
@@ -14905,12 +14902,9 @@ ${lines.join("\n")}`;
|
|
|
14905
14902
|
/**
|
|
14906
14903
|
* Determine at compile time whether an expression produces a complex value.
|
|
14907
14904
|
*
|
|
14908
|
-
*
|
|
14909
|
-
*
|
|
14910
|
-
*
|
|
14911
|
-
* (undefined is treated as real -- assume-real policy)
|
|
14912
|
-
* - Functions: Abs, Arg, Re, Im always return real.
|
|
14913
|
-
* All others: complex if any operand is complex.
|
|
14905
|
+
* Uses the expression's declared type (from operator signatures) when
|
|
14906
|
+
* available. Falls back to operand inspection for functions whose
|
|
14907
|
+
* return type is unknown.
|
|
14914
14908
|
*/
|
|
14915
14909
|
static isComplexValued(expr) {
|
|
14916
14910
|
if (isNumber(expr)) return expr.im !== 0;
|
|
@@ -14921,13 +14915,24 @@ ${lines.join("\n")}`;
|
|
|
14921
14915
|
return t.matches("complex") && !t.matches("real");
|
|
14922
14916
|
}
|
|
14923
14917
|
if (isFunction2(expr)) {
|
|
14924
|
-
const
|
|
14925
|
-
if (
|
|
14926
|
-
|
|
14918
|
+
const t = expr.type;
|
|
14919
|
+
if (t.matches("complex") && !t.matches("real")) return true;
|
|
14920
|
+
if (t.matches("real")) return false;
|
|
14927
14921
|
return expr.ops.some((arg) => _BaseCompiler.isComplexValued(arg));
|
|
14928
14922
|
}
|
|
14929
14923
|
return false;
|
|
14930
14924
|
}
|
|
14925
|
+
/** True if the expression is provably integer-typed. */
|
|
14926
|
+
static isIntegerValued(expr) {
|
|
14927
|
+
if (isNumber(expr)) return expr.im === 0 && Number.isInteger(expr.re);
|
|
14928
|
+
const t = expr.type;
|
|
14929
|
+
return t ? t.matches("integer") : false;
|
|
14930
|
+
}
|
|
14931
|
+
/** True if the expression is provably non-negative (sign ≥ 0). */
|
|
14932
|
+
static isNonNegative(expr) {
|
|
14933
|
+
if (isNumber(expr)) return expr.im === 0 && expr.re >= 0;
|
|
14934
|
+
return expr.isNonNegative === true;
|
|
14935
|
+
}
|
|
14931
14936
|
/**
|
|
14932
14937
|
* Generate a temporary variable name
|
|
14933
14938
|
*/
|
|
@@ -15099,20 +15104,113 @@ ${lines.join("\n")}`;
|
|
|
15099
15104
|
} catch (e) {
|
|
15100
15105
|
if (options?.fallback ?? true) {
|
|
15101
15106
|
console.warn(
|
|
15102
|
-
`Compilation fallback for "${expr.operator}": ${e.message}`
|
|
15107
|
+
`Compilation fallback for "${expr.operator}" (target: ${options?.to ?? "javascript"}): ${e.message}`
|
|
15103
15108
|
);
|
|
15109
|
+
const ce = expr.engine;
|
|
15110
|
+
const fallbackRun = ((vars) => {
|
|
15111
|
+
ce.pushScope();
|
|
15112
|
+
try {
|
|
15113
|
+
if (vars && typeof vars === "object") {
|
|
15114
|
+
for (const [k, v] of Object.entries(vars))
|
|
15115
|
+
ce.assign(k, v);
|
|
15116
|
+
}
|
|
15117
|
+
return expr.evaluate().re;
|
|
15118
|
+
} finally {
|
|
15119
|
+
ce.popScope();
|
|
15120
|
+
}
|
|
15121
|
+
});
|
|
15104
15122
|
return {
|
|
15105
15123
|
target: options?.to ?? "javascript",
|
|
15106
15124
|
success: false,
|
|
15107
15125
|
code: "",
|
|
15108
15126
|
calling: "expression",
|
|
15109
|
-
run:
|
|
15127
|
+
run: fallbackRun
|
|
15110
15128
|
};
|
|
15111
15129
|
}
|
|
15112
15130
|
throw e;
|
|
15113
15131
|
}
|
|
15114
15132
|
}
|
|
15115
15133
|
|
|
15134
|
+
// src/compute-engine/compilation/constant-folding.ts
|
|
15135
|
+
function formatFloat(n) {
|
|
15136
|
+
const str = n.toString();
|
|
15137
|
+
if (!str.includes(".") && !str.includes("e") && !str.includes("E")) {
|
|
15138
|
+
return `${str}.0`;
|
|
15139
|
+
}
|
|
15140
|
+
return str;
|
|
15141
|
+
}
|
|
15142
|
+
function tryGetConstant(expr) {
|
|
15143
|
+
if (!isNumber(expr)) return void 0;
|
|
15144
|
+
if (expr.im !== 0) return void 0;
|
|
15145
|
+
const re = expr.re;
|
|
15146
|
+
if (!isFinite(re)) return void 0;
|
|
15147
|
+
return re;
|
|
15148
|
+
}
|
|
15149
|
+
var NUMERIC_LITERAL_RE = /^-?\d+(\.\d+)?$/;
|
|
15150
|
+
function foldTerms(terms, identity, op) {
|
|
15151
|
+
const identityValue = op === "+" ? 0 : 1;
|
|
15152
|
+
let numericAcc = null;
|
|
15153
|
+
const symbolic = [];
|
|
15154
|
+
for (const term of terms) {
|
|
15155
|
+
if (NUMERIC_LITERAL_RE.test(term)) {
|
|
15156
|
+
const val = parseFloat(term);
|
|
15157
|
+
if (op === "*" && val === 0) return "0.0";
|
|
15158
|
+
if (numericAcc === null) {
|
|
15159
|
+
numericAcc = val;
|
|
15160
|
+
} else {
|
|
15161
|
+
numericAcc = op === "+" ? numericAcc + val : numericAcc * val;
|
|
15162
|
+
}
|
|
15163
|
+
} else {
|
|
15164
|
+
symbolic.push(term);
|
|
15165
|
+
}
|
|
15166
|
+
}
|
|
15167
|
+
if (numericAcc !== null && numericAcc !== identityValue) {
|
|
15168
|
+
symbolic.unshift(formatFloat(numericAcc));
|
|
15169
|
+
}
|
|
15170
|
+
if (symbolic.length === 0) {
|
|
15171
|
+
if (numericAcc !== null) return formatFloat(numericAcc);
|
|
15172
|
+
return identity;
|
|
15173
|
+
}
|
|
15174
|
+
if (symbolic.length === 1) return symbolic[0];
|
|
15175
|
+
return symbolic.join(op === "+" ? " + " : " * ");
|
|
15176
|
+
}
|
|
15177
|
+
function tryGetComplexParts(expr, compile2) {
|
|
15178
|
+
if (isSymbol2(expr, "ImaginaryUnit")) {
|
|
15179
|
+
return { re: null, im: "1.0" };
|
|
15180
|
+
}
|
|
15181
|
+
if (isNumber(expr) && expr.im !== 0) {
|
|
15182
|
+
const re = expr.re;
|
|
15183
|
+
const im = expr.im;
|
|
15184
|
+
return {
|
|
15185
|
+
re: re !== 0 ? formatFloat(re) : null,
|
|
15186
|
+
im: formatFloat(im)
|
|
15187
|
+
};
|
|
15188
|
+
}
|
|
15189
|
+
if (isFunction2(expr, "Multiply")) {
|
|
15190
|
+
const ops = expr.ops;
|
|
15191
|
+
const iIndex = ops.findIndex(
|
|
15192
|
+
(op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
|
|
15193
|
+
);
|
|
15194
|
+
if (iIndex >= 0) {
|
|
15195
|
+
const iFactor = ops[iIndex];
|
|
15196
|
+
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
15197
|
+
const remaining = ops.filter((_, idx) => idx !== iIndex);
|
|
15198
|
+
if (remaining.length === 0) {
|
|
15199
|
+
return { re: null, im: formatFloat(iScale) };
|
|
15200
|
+
}
|
|
15201
|
+
const compiledFactors = remaining.map((r) => compile2(r));
|
|
15202
|
+
if (iScale !== 1)
|
|
15203
|
+
compiledFactors.unshift(formatFloat(iScale));
|
|
15204
|
+
const imCode = foldTerms(compiledFactors, "1.0", "*");
|
|
15205
|
+
return { re: null, im: imCode };
|
|
15206
|
+
}
|
|
15207
|
+
}
|
|
15208
|
+
if (BaseCompiler.isComplexValued(expr)) {
|
|
15209
|
+
return null;
|
|
15210
|
+
}
|
|
15211
|
+
return { re: compile2(expr), im: null };
|
|
15212
|
+
}
|
|
15213
|
+
|
|
15116
15214
|
// node_modules/@arnog/colors/dist/index.mjs
|
|
15117
15215
|
function gammaCorrect(channel) {
|
|
15118
15216
|
const abs2 = Math.abs(channel);
|
|
@@ -16407,30 +16505,6 @@ ${lines.join("\n")}`;
|
|
|
16407
16505
|
"#ae2036",
|
|
16408
16506
|
"#b40426"
|
|
16409
16507
|
];
|
|
16410
|
-
var OCEAN_BALANCE = [
|
|
16411
|
-
"#00441b",
|
|
16412
|
-
"#006d5b",
|
|
16413
|
-
"#1a8c7d",
|
|
16414
|
-
"#2fa394",
|
|
16415
|
-
"#4fb3a3",
|
|
16416
|
-
"#6fc1b3",
|
|
16417
|
-
"#8dcfc3",
|
|
16418
|
-
"#a6dbd1",
|
|
16419
|
-
"#bfe6de",
|
|
16420
|
-
"#d7f0ea",
|
|
16421
|
-
"#f7f7f7",
|
|
16422
|
-
"#eeeeee",
|
|
16423
|
-
"#ddd8e6",
|
|
16424
|
-
"#c7bcda",
|
|
16425
|
-
"#b3a0d0",
|
|
16426
|
-
"#9f86c7",
|
|
16427
|
-
"#8d6dbd",
|
|
16428
|
-
"#7b56b1",
|
|
16429
|
-
"#6a42a3",
|
|
16430
|
-
"#5a3093",
|
|
16431
|
-
"#4a1f82",
|
|
16432
|
-
"#3b0f70"
|
|
16433
|
-
];
|
|
16434
16508
|
var reversePalette = (palette) => palette.slice().reverse();
|
|
16435
16509
|
var DIVERGING_PALETTES = {
|
|
16436
16510
|
roma: ROMA,
|
|
@@ -16442,9 +16516,7 @@ ${lines.join("\n")}`;
|
|
|
16442
16516
|
rdbu: RDBU,
|
|
16443
16517
|
"rdbu-reversed": reversePalette(RDBU),
|
|
16444
16518
|
coolwarm: COOLWARM,
|
|
16445
|
-
"coolwarm-reversed": reversePalette(COOLWARM)
|
|
16446
|
-
"ocean-balance": OCEAN_BALANCE,
|
|
16447
|
-
"ocean-balance-reversed": reversePalette(OCEAN_BALANCE)
|
|
16519
|
+
"coolwarm-reversed": reversePalette(COOLWARM)
|
|
16448
16520
|
};
|
|
16449
16521
|
var TURBO = [
|
|
16450
16522
|
"#30123b",
|
|
@@ -18528,6 +18600,40 @@ ${lines.join("\n")}`;
|
|
|
18528
18600
|
"#eeeeee",
|
|
18529
18601
|
"#ffffff"
|
|
18530
18602
|
];
|
|
18603
|
+
var CMOCEAN_PHASE = [
|
|
18604
|
+
"#a8780d",
|
|
18605
|
+
"#b3701b",
|
|
18606
|
+
"#be6828",
|
|
18607
|
+
"#c75f35",
|
|
18608
|
+
"#cf5643",
|
|
18609
|
+
"#d54b53",
|
|
18610
|
+
"#db4066",
|
|
18611
|
+
"#de357b",
|
|
18612
|
+
"#df2a93",
|
|
18613
|
+
"#dc25ad",
|
|
18614
|
+
"#d529c4",
|
|
18615
|
+
"#cc34d7",
|
|
18616
|
+
"#c041e5",
|
|
18617
|
+
"#b24fef",
|
|
18618
|
+
"#a25cf3",
|
|
18619
|
+
"#9168f4",
|
|
18620
|
+
"#7d73f0",
|
|
18621
|
+
"#687ce8",
|
|
18622
|
+
"#5285dc",
|
|
18623
|
+
"#3d8bcd",
|
|
18624
|
+
"#2c90bc",
|
|
18625
|
+
"#2093ac",
|
|
18626
|
+
"#19959c",
|
|
18627
|
+
"#12978c",
|
|
18628
|
+
"#0c987c",
|
|
18629
|
+
"#119a69",
|
|
18630
|
+
"#249a52",
|
|
18631
|
+
"#409839",
|
|
18632
|
+
"#5e9420",
|
|
18633
|
+
"#778d12",
|
|
18634
|
+
"#8b860d",
|
|
18635
|
+
"#9b7f0d"
|
|
18636
|
+
];
|
|
18531
18637
|
var reversePalette2 = (palette) => palette.slice().reverse();
|
|
18532
18638
|
var SEQUENTIAL_PALETTES = {
|
|
18533
18639
|
turbo: TURBO,
|
|
@@ -18551,7 +18657,9 @@ ${lines.join("\n")}`;
|
|
|
18551
18657
|
"rocket-reversed": reversePalette2(ROCKET),
|
|
18552
18658
|
mako: MAKO,
|
|
18553
18659
|
// blue to teal
|
|
18554
|
-
"mako-reversed": reversePalette2(MAKO)
|
|
18660
|
+
"mako-reversed": reversePalette2(MAKO),
|
|
18661
|
+
"cmocean-phase": CMOCEAN_PHASE,
|
|
18662
|
+
"cmocean-phase-reversed": reversePalette2(CMOCEAN_PHASE)
|
|
18555
18663
|
};
|
|
18556
18664
|
|
|
18557
18665
|
// src/compute-engine/numerics/special-functions.ts
|
|
@@ -19451,12 +19559,21 @@ ${lines.join("\n")}`;
|
|
|
19451
19559
|
Abs: (args, compile2) => {
|
|
19452
19560
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
19453
19561
|
return `_SYS.cabs(${compile2(args[0])})`;
|
|
19562
|
+
if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
|
|
19454
19563
|
return `Math.abs(${compile2(args[0])})`;
|
|
19455
19564
|
},
|
|
19456
19565
|
Add: (args, compile2) => {
|
|
19457
19566
|
if (args.length === 1) return compile2(args[0]);
|
|
19458
19567
|
const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
|
|
19459
|
-
if (!anyComplex)
|
|
19568
|
+
if (!anyComplex) {
|
|
19569
|
+
const constants = args.map(tryGetConstant);
|
|
19570
|
+
if (constants.every((c) => c !== void 0))
|
|
19571
|
+
return String(constants.reduce((a, b) => a + b, 0));
|
|
19572
|
+
const nonZero = args.filter((a) => tryGetConstant(a) !== 0);
|
|
19573
|
+
if (nonZero.length === 0) return "0";
|
|
19574
|
+
if (nonZero.length === 1) return compile2(nonZero[0]);
|
|
19575
|
+
return `(${nonZero.map((x) => compile2(x)).join(" + ")})`;
|
|
19576
|
+
}
|
|
19460
19577
|
const parts = args.map((a) => {
|
|
19461
19578
|
const code = compile2(a);
|
|
19462
19579
|
return { code, isComplex: BaseCompiler.isComplexValued(a) };
|
|
@@ -19513,7 +19630,10 @@ ${lines.join("\n")}`;
|
|
|
19513
19630
|
return `Math.atan(${compile2(args[0])})`;
|
|
19514
19631
|
},
|
|
19515
19632
|
Artanh: "Math.atanh",
|
|
19516
|
-
Ceil:
|
|
19633
|
+
Ceil: (args, compile2) => {
|
|
19634
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19635
|
+
return `Math.ceil(${compile2(args[0])})`;
|
|
19636
|
+
},
|
|
19517
19637
|
Chop: "_SYS.chop",
|
|
19518
19638
|
Cos: (args, compile2) => {
|
|
19519
19639
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
@@ -19556,7 +19676,10 @@ ${lines.join("\n")}`;
|
|
|
19556
19676
|
return `_SYS.cexp(${compile2(args[0])})`;
|
|
19557
19677
|
return `Math.exp(${compile2(args[0])})`;
|
|
19558
19678
|
},
|
|
19559
|
-
Floor:
|
|
19679
|
+
Floor: (args, compile2) => {
|
|
19680
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19681
|
+
return `Math.floor(${compile2(args[0])})`;
|
|
19682
|
+
},
|
|
19560
19683
|
Fract: ([x], compile2) => {
|
|
19561
19684
|
if (x === null) throw new Error("Fract: no argument");
|
|
19562
19685
|
return BaseCompiler.inlineExpression("${x} - Math.floor(${x})", compile2(x));
|
|
@@ -19652,12 +19775,20 @@ ${lines.join("\n")}`;
|
|
|
19652
19775
|
if (BaseCompiler.isComplexValued(base) || BaseCompiler.isComplexValued(exp3)) {
|
|
19653
19776
|
return `_SYS.cpow(${compile2(base)}, ${compile2(exp3)})`;
|
|
19654
19777
|
}
|
|
19655
|
-
const
|
|
19656
|
-
|
|
19657
|
-
if (
|
|
19658
|
-
|
|
19659
|
-
if (
|
|
19660
|
-
if (
|
|
19778
|
+
const bConst = tryGetConstant(base);
|
|
19779
|
+
const eConst = tryGetConstant(exp3);
|
|
19780
|
+
if (bConst !== void 0 && eConst !== void 0)
|
|
19781
|
+
return String(Math.pow(bConst, eConst));
|
|
19782
|
+
if (eConst === 0) return "1";
|
|
19783
|
+
if (eConst === 1) return compile2(base);
|
|
19784
|
+
if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
|
|
19785
|
+
const code = compile2(base);
|
|
19786
|
+
return `(${code} * ${code})`;
|
|
19787
|
+
}
|
|
19788
|
+
if (eConst === -1) return `(1 / (${compile2(base)}))`;
|
|
19789
|
+
if (eConst === 0.5) return `Math.sqrt(${compile2(base)})`;
|
|
19790
|
+
if (eConst === 1 / 3) return `Math.cbrt(${compile2(base)})`;
|
|
19791
|
+
if (eConst === -0.5) return `(1 / Math.sqrt(${compile2(base)}))`;
|
|
19661
19792
|
return `Math.pow(${compile2(base)}, ${compile2(exp3)})`;
|
|
19662
19793
|
},
|
|
19663
19794
|
Range: (args, compile2) => {
|
|
@@ -19694,16 +19825,29 @@ ${lines.join("\n")}`;
|
|
|
19694
19825
|
Root: ([arg, exp3], compile2) => {
|
|
19695
19826
|
if (arg === null) throw new Error("Root: no argument");
|
|
19696
19827
|
if (exp3 === null) return `Math.sqrt(${compile2(arg)})`;
|
|
19697
|
-
|
|
19698
|
-
|
|
19699
|
-
if (
|
|
19828
|
+
const aConst = tryGetConstant(arg);
|
|
19829
|
+
const nConst = tryGetConstant(exp3);
|
|
19830
|
+
if (aConst !== void 0 && nConst !== void 0 && nConst !== 0)
|
|
19831
|
+
return String(Math.pow(aConst, 1 / nConst));
|
|
19832
|
+
if (nConst === 2) return `Math.sqrt(${compile2(arg)})`;
|
|
19833
|
+
if (nConst === 3) return `Math.cbrt(${compile2(arg)})`;
|
|
19834
|
+
if (nConst !== void 0) return `Math.pow(${compile2(arg)}, ${1 / nConst})`;
|
|
19700
19835
|
return `Math.pow(${compile2(arg)}, 1 / (${compile2(exp3)}))`;
|
|
19701
19836
|
},
|
|
19702
19837
|
Random: "Math.random",
|
|
19703
|
-
Round:
|
|
19838
|
+
Round: (args, compile2) => {
|
|
19839
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19840
|
+
return `Math.round(${compile2(args[0])})`;
|
|
19841
|
+
},
|
|
19704
19842
|
Square: (args, compile2) => {
|
|
19705
19843
|
const arg = args[0];
|
|
19706
19844
|
if (arg === null) throw new Error("Square: no argument");
|
|
19845
|
+
const c = tryGetConstant(arg);
|
|
19846
|
+
if (c !== void 0) return String(c * c);
|
|
19847
|
+
if (isSymbol2(arg)) {
|
|
19848
|
+
const code = compile2(arg);
|
|
19849
|
+
return `(${code} * ${code})`;
|
|
19850
|
+
}
|
|
19707
19851
|
return `Math.pow(${compile2(arg)}, 2)`;
|
|
19708
19852
|
},
|
|
19709
19853
|
Sec: (args, compile2) => {
|
|
@@ -19736,6 +19880,8 @@ ${lines.join("\n")}`;
|
|
|
19736
19880
|
Sqrt: (args, compile2) => {
|
|
19737
19881
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
19738
19882
|
return `_SYS.csqrt(${compile2(args[0])})`;
|
|
19883
|
+
const c = tryGetConstant(args[0]);
|
|
19884
|
+
if (c !== void 0) return String(Math.sqrt(c));
|
|
19739
19885
|
return `Math.sqrt(${compile2(args[0])})`;
|
|
19740
19886
|
},
|
|
19741
19887
|
Tan: (args, compile2) => {
|
|
@@ -19752,9 +19898,14 @@ ${lines.join("\n")}`;
|
|
|
19752
19898
|
if (a === null || b === null) throw new Error("Mod: missing argument");
|
|
19753
19899
|
const ca = compile2(a);
|
|
19754
19900
|
const cb = compile2(b);
|
|
19901
|
+
if (BaseCompiler.isIntegerValued(a) && BaseCompiler.isIntegerValued(b) && BaseCompiler.isNonNegative(a))
|
|
19902
|
+
return `(${ca} % ${cb})`;
|
|
19755
19903
|
return `((${ca} % ${cb}) + ${cb}) % ${cb}`;
|
|
19756
19904
|
},
|
|
19757
|
-
Truncate:
|
|
19905
|
+
Truncate: (args, compile2) => {
|
|
19906
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
19907
|
+
return `Math.trunc(${compile2(args[0])})`;
|
|
19908
|
+
},
|
|
19758
19909
|
Remainder: ([a, b], compile2) => {
|
|
19759
19910
|
if (a === null || b === null)
|
|
19760
19911
|
throw new Error("Remainder: missing argument");
|
|
@@ -19762,25 +19913,20 @@ ${lines.join("\n")}`;
|
|
|
19762
19913
|
a
|
|
19763
19914
|
)} / ${compile2(b)}))`;
|
|
19764
19915
|
},
|
|
19765
|
-
//
|
|
19766
|
-
|
|
19767
|
-
if (a === null || b === null) throw new Error("Subtract: missing argument");
|
|
19768
|
-
const ac = BaseCompiler.isComplexValued(a);
|
|
19769
|
-
const bc = BaseCompiler.isComplexValued(b);
|
|
19770
|
-
if (!ac && !bc) return `(${compile2(a)} - ${compile2(b)})`;
|
|
19771
|
-
const ca = compile2(a);
|
|
19772
|
-
const cb = compile2(b);
|
|
19773
|
-
const reA = ac ? `(${ca}).re` : ca;
|
|
19774
|
-
const imA = ac ? `(${ca}).im` : "0";
|
|
19775
|
-
const reB = bc ? `(${cb}).re` : cb;
|
|
19776
|
-
const imB = bc ? `(${cb}).im` : "0";
|
|
19777
|
-
return `({ re: ${reA} - ${reB}, im: ${imA} - ${imB} })`;
|
|
19778
|
-
},
|
|
19916
|
+
// No Subtract function handler — Subtract canonicalizes to Add+Negate.
|
|
19917
|
+
// The operator entry in JAVASCRIPT_OPERATORS handles any edge cases.
|
|
19779
19918
|
Divide: ([a, b], compile2) => {
|
|
19780
19919
|
if (a === null || b === null) throw new Error("Divide: missing argument");
|
|
19781
19920
|
const ac = BaseCompiler.isComplexValued(a);
|
|
19782
19921
|
const bc = BaseCompiler.isComplexValued(b);
|
|
19783
|
-
if (!ac && !bc)
|
|
19922
|
+
if (!ac && !bc) {
|
|
19923
|
+
const ca = tryGetConstant(a);
|
|
19924
|
+
const cb = tryGetConstant(b);
|
|
19925
|
+
if (ca !== void 0 && cb !== void 0 && cb !== 0)
|
|
19926
|
+
return String(ca / cb);
|
|
19927
|
+
if (cb === 1) return compile2(a);
|
|
19928
|
+
return `(${compile2(a)} / ${compile2(b)})`;
|
|
19929
|
+
}
|
|
19784
19930
|
if (ac && bc) {
|
|
19785
19931
|
return `(() => { const _a = ${compile2(a)}, _b = ${compile2(
|
|
19786
19932
|
b
|
|
@@ -19797,13 +19943,26 @@ ${lines.join("\n")}`;
|
|
|
19797
19943
|
},
|
|
19798
19944
|
Negate: ([x], compile2) => {
|
|
19799
19945
|
if (x === null) throw new Error("Negate: no argument");
|
|
19800
|
-
if (!BaseCompiler.isComplexValued(x))
|
|
19946
|
+
if (!BaseCompiler.isComplexValued(x)) {
|
|
19947
|
+
const c = tryGetConstant(x);
|
|
19948
|
+
if (c !== void 0) return String(-c);
|
|
19949
|
+
return `(-${compile2(x)})`;
|
|
19950
|
+
}
|
|
19801
19951
|
return `_SYS.cneg(${compile2(x)})`;
|
|
19802
19952
|
},
|
|
19803
19953
|
Multiply: (args, compile2) => {
|
|
19804
19954
|
if (args.length === 1) return compile2(args[0]);
|
|
19805
19955
|
const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
|
|
19806
|
-
if (!anyComplex)
|
|
19956
|
+
if (!anyComplex) {
|
|
19957
|
+
if (args.some((a) => tryGetConstant(a) === 0)) return "0";
|
|
19958
|
+
const constants = args.map(tryGetConstant);
|
|
19959
|
+
if (constants.every((c) => c !== void 0))
|
|
19960
|
+
return String(constants.reduce((a, b) => a * b, 1));
|
|
19961
|
+
const nonOne = args.filter((a) => tryGetConstant(a) !== 1);
|
|
19962
|
+
if (nonOne.length === 0) return "1";
|
|
19963
|
+
if (nonOne.length === 1) return compile2(nonOne[0]);
|
|
19964
|
+
return `(${nonOne.map((x) => compile2(x)).join(" * ")})`;
|
|
19965
|
+
}
|
|
19807
19966
|
if (args.length === 2) {
|
|
19808
19967
|
const ac = BaseCompiler.isComplexValued(args[0]);
|
|
19809
19968
|
const bc = BaseCompiler.isComplexValued(args[1]);
|
|
@@ -19888,20 +20047,30 @@ ${lines.join("\n")}`;
|
|
|
19888
20047
|
AiryAi: "_SYS.airyAi",
|
|
19889
20048
|
AiryBi: "_SYS.airyBi",
|
|
19890
20049
|
// Combinatorics
|
|
20050
|
+
Mandelbrot: ([c, maxIter], compile2) => {
|
|
20051
|
+
if (c === null || maxIter === null)
|
|
20052
|
+
throw new Error("Mandelbrot: missing arguments");
|
|
20053
|
+
return `_SYS.mandelbrot(${compile2(c)}, ${compile2(maxIter)})`;
|
|
20054
|
+
},
|
|
20055
|
+
Julia: ([z, c, maxIter], compile2) => {
|
|
20056
|
+
if (z === null || c === null || maxIter === null)
|
|
20057
|
+
throw new Error("Julia: missing arguments");
|
|
20058
|
+
return `_SYS.julia(${compile2(z)}, ${compile2(c)}, ${compile2(maxIter)})`;
|
|
20059
|
+
},
|
|
19891
20060
|
Binomial: (args, compile2) => `_SYS.binomial(${compile2(args[0])}, ${compile2(args[1])})`,
|
|
19892
20061
|
Fibonacci: "_SYS.fibonacci",
|
|
19893
20062
|
// Complex-specific functions
|
|
19894
|
-
|
|
20063
|
+
Real: (args, compile2) => {
|
|
19895
20064
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
19896
20065
|
return `(${compile2(args[0])}).re`;
|
|
19897
20066
|
return compile2(args[0]);
|
|
19898
20067
|
},
|
|
19899
|
-
|
|
20068
|
+
Imaginary: (args, compile2) => {
|
|
19900
20069
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
19901
20070
|
return `(${compile2(args[0])}).im`;
|
|
19902
20071
|
return "0";
|
|
19903
20072
|
},
|
|
19904
|
-
|
|
20073
|
+
Argument: (args, compile2) => {
|
|
19905
20074
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
19906
20075
|
return `_SYS.carg(${compile2(args[0])})`;
|
|
19907
20076
|
return `(${compile2(args[0])} >= 0 ? 0 : Math.PI)`;
|
|
@@ -20237,6 +20406,41 @@ ${lines.join("\n")}`;
|
|
|
20237
20406
|
sinc,
|
|
20238
20407
|
fresnelS,
|
|
20239
20408
|
fresnelC,
|
|
20409
|
+
mandelbrot: (c, maxIter) => {
|
|
20410
|
+
let zx = 0, zy = 0;
|
|
20411
|
+
const cx = typeof c === "number" ? c : c.re;
|
|
20412
|
+
const cy = typeof c === "number" ? 0 : c.im;
|
|
20413
|
+
const n = Math.round(maxIter);
|
|
20414
|
+
for (let i = 0; i < n; i++) {
|
|
20415
|
+
const newZx = zx * zx - zy * zy + cx;
|
|
20416
|
+
zy = 2 * zx * zy + cy;
|
|
20417
|
+
zx = newZx;
|
|
20418
|
+
const mag2 = zx * zx + zy * zy;
|
|
20419
|
+
if (mag2 > 4) {
|
|
20420
|
+
const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
|
|
20421
|
+
return Math.max(0, Math.min(1, smooth));
|
|
20422
|
+
}
|
|
20423
|
+
}
|
|
20424
|
+
return 1;
|
|
20425
|
+
},
|
|
20426
|
+
julia: (z, c, maxIter) => {
|
|
20427
|
+
let zx = typeof z === "number" ? z : z.re;
|
|
20428
|
+
let zy = typeof z === "number" ? 0 : z.im;
|
|
20429
|
+
const cx = typeof c === "number" ? c : c.re;
|
|
20430
|
+
const cy = typeof c === "number" ? 0 : c.im;
|
|
20431
|
+
const n = Math.round(maxIter);
|
|
20432
|
+
for (let i = 0; i < n; i++) {
|
|
20433
|
+
const newZx = zx * zx - zy * zy + cx;
|
|
20434
|
+
zy = 2 * zx * zy + cy;
|
|
20435
|
+
zx = newZx;
|
|
20436
|
+
const mag2 = zx * zx + zy * zy;
|
|
20437
|
+
if (mag2 > 4) {
|
|
20438
|
+
const smooth = (i - Math.log2(Math.log2(mag2)) + 4) / n;
|
|
20439
|
+
return Math.max(0, Math.min(1, smooth));
|
|
20440
|
+
}
|
|
20441
|
+
}
|
|
20442
|
+
return 1;
|
|
20443
|
+
},
|
|
20240
20444
|
binomial: choose,
|
|
20241
20445
|
fibonacci,
|
|
20242
20446
|
// Complex helpers
|
|
@@ -20577,11 +20781,39 @@ ${lines.join("\n")}`;
|
|
|
20577
20781
|
return b;
|
|
20578
20782
|
}
|
|
20579
20783
|
|
|
20784
|
+
// src/compute-engine/compilation/fractal-orbit.ts
|
|
20785
|
+
function computeReferenceOrbit(center, maxIter, precision) {
|
|
20786
|
+
const prevPrecision = BigDecimal.precision;
|
|
20787
|
+
BigDecimal.precision = precision;
|
|
20788
|
+
try {
|
|
20789
|
+
const cr = new BigDecimal(center[0]);
|
|
20790
|
+
const ci = new BigDecimal(center[1]);
|
|
20791
|
+
let zr = BigDecimal.ZERO;
|
|
20792
|
+
let zi = BigDecimal.ZERO;
|
|
20793
|
+
const ESCAPE = new BigDecimal(256);
|
|
20794
|
+
const points = [];
|
|
20795
|
+
for (let i = 0; i < maxIter; i++) {
|
|
20796
|
+
points.push(zr.toNumber(), zi.toNumber());
|
|
20797
|
+
const zr2 = zr.mul(zr).toPrecision(precision);
|
|
20798
|
+
const zi2 = zi.mul(zi).toPrecision(precision);
|
|
20799
|
+
const mag2 = zr2.add(zi2);
|
|
20800
|
+
if (mag2.cmp(ESCAPE) > 0) break;
|
|
20801
|
+
const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
|
|
20802
|
+
zr = zr2.sub(zi2).add(cr);
|
|
20803
|
+
zi = new_zi;
|
|
20804
|
+
}
|
|
20805
|
+
return new Float32Array(points);
|
|
20806
|
+
} finally {
|
|
20807
|
+
BigDecimal.precision = prevPrecision;
|
|
20808
|
+
}
|
|
20809
|
+
}
|
|
20810
|
+
|
|
20580
20811
|
// src/compute-engine/compilation/gpu-target.ts
|
|
20581
20812
|
var GPU_OPERATORS = {
|
|
20582
20813
|
Add: ["+", 11],
|
|
20583
20814
|
Negate: ["-", 14],
|
|
20584
20815
|
Subtract: ["-", 11],
|
|
20816
|
+
// Subtract canonicalizes to Add+Negate; kept as fallback
|
|
20585
20817
|
Multiply: ["*", 12],
|
|
20586
20818
|
Divide: ["/", 13],
|
|
20587
20819
|
Equal: ["==", 8],
|
|
@@ -20597,6 +20829,12 @@ ${lines.join("\n")}`;
|
|
|
20597
20829
|
function gpuVec2(target) {
|
|
20598
20830
|
return target?.language === "wgsl" ? "vec2f" : "vec2";
|
|
20599
20831
|
}
|
|
20832
|
+
function compileIntArg(expr, compile2, target) {
|
|
20833
|
+
const c = tryGetConstant(expr);
|
|
20834
|
+
if (c !== void 0 && Number.isInteger(c)) return c.toString();
|
|
20835
|
+
const intCast = target?.language === "wgsl" ? "i32" : "int";
|
|
20836
|
+
return `${intCast}(${compile2(expr)})`;
|
|
20837
|
+
}
|
|
20600
20838
|
var GPU_UNROLL_LIMIT = 100;
|
|
20601
20839
|
function compileGPUSumProduct(kind, args, _compile, target) {
|
|
20602
20840
|
if (!args[0]) throw new Error(`${kind}: no body`);
|
|
@@ -20653,94 +20891,126 @@ ${lines.join("\n")}`;
|
|
|
20653
20891
|
];
|
|
20654
20892
|
return lines.join("\n");
|
|
20655
20893
|
}
|
|
20894
|
+
function selectFractalStrategy(target) {
|
|
20895
|
+
const radius = target.hints?.viewport?.radius;
|
|
20896
|
+
if (radius === void 0) return "single";
|
|
20897
|
+
if (radius > 1e-6) return "single";
|
|
20898
|
+
if (radius > 1e-14) return "double";
|
|
20899
|
+
return "perturbation";
|
|
20900
|
+
}
|
|
20656
20901
|
var GPU_FUNCTIONS = {
|
|
20657
20902
|
// Variadic arithmetic (for function-call form, e.g., with vectors)
|
|
20658
20903
|
Add: (args, compile2, target) => {
|
|
20659
20904
|
if (args.length === 0) return "0.0";
|
|
20660
20905
|
if (args.length === 1) return compile2(args[0]);
|
|
20661
20906
|
const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
|
|
20662
|
-
if (!anyComplex)
|
|
20663
|
-
|
|
20664
|
-
|
|
20665
|
-
|
|
20666
|
-
|
|
20667
|
-
|
|
20668
|
-
},
|
|
20669
|
-
Multiply: (args, compile2, _target) => {
|
|
20670
|
-
if (args.length === 0) return "1.0";
|
|
20671
|
-
if (args.length === 1) return compile2(args[0]);
|
|
20672
|
-
const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
|
|
20673
|
-
if (!anyComplex) return args.map((x) => compile2(x)).join(" * ");
|
|
20674
|
-
let result = compile2(args[0]);
|
|
20675
|
-
let resultIsComplex = BaseCompiler.isComplexValued(args[0]);
|
|
20676
|
-
for (let i = 1; i < args.length; i++) {
|
|
20677
|
-
const code = compile2(args[i]);
|
|
20678
|
-
const argIsComplex = BaseCompiler.isComplexValued(args[i]);
|
|
20679
|
-
if (!resultIsComplex && !argIsComplex) {
|
|
20680
|
-
result = `(${result} * ${code})`;
|
|
20681
|
-
} else if (resultIsComplex && !argIsComplex) {
|
|
20682
|
-
result = `(${code} * ${result})`;
|
|
20683
|
-
} else if (!resultIsComplex && argIsComplex) {
|
|
20684
|
-
result = `(${result} * ${code})`;
|
|
20685
|
-
resultIsComplex = true;
|
|
20686
|
-
} else {
|
|
20687
|
-
result = `_gpu_cmul(${result}, ${code})`;
|
|
20688
|
-
}
|
|
20907
|
+
if (!anyComplex) {
|
|
20908
|
+
return foldTerms(
|
|
20909
|
+
args.map((x) => compile2(x)),
|
|
20910
|
+
"0.0",
|
|
20911
|
+
"+"
|
|
20912
|
+
);
|
|
20689
20913
|
}
|
|
20690
|
-
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
|
|
20914
|
+
const parts = args.map((a) => tryGetComplexParts(a, compile2));
|
|
20915
|
+
if (parts.some((p) => p === null)) {
|
|
20916
|
+
const v2 = gpuVec2(target);
|
|
20917
|
+
return args.map((a) => {
|
|
20918
|
+
const code = compile2(a);
|
|
20919
|
+
return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
|
|
20920
|
+
}).join(" + ");
|
|
20921
|
+
}
|
|
20922
|
+
const reParts = [];
|
|
20923
|
+
const imParts = [];
|
|
20924
|
+
for (const p of parts) {
|
|
20925
|
+
if (p.re !== null) reParts.push(p.re);
|
|
20926
|
+
if (p.im !== null) imParts.push(p.im);
|
|
20927
|
+
}
|
|
20928
|
+
const reSum = foldTerms(reParts, "0.0", "+");
|
|
20929
|
+
const imSum = foldTerms(imParts, "0.0", "+");
|
|
20930
|
+
return `${gpuVec2(target)}(${reSum}, ${imSum})`;
|
|
20931
|
+
},
|
|
20932
|
+
Multiply: (args, compile2, target) => {
|
|
20933
|
+
if (args.length === 0) return "1.0";
|
|
20694
20934
|
if (args.length === 1) return compile2(args[0]);
|
|
20695
20935
|
const anyComplex = args.some((a) => BaseCompiler.isComplexValued(a));
|
|
20696
20936
|
if (!anyComplex) {
|
|
20697
|
-
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
return result2;
|
|
20703
|
-
}
|
|
20704
|
-
const v2 = gpuVec2(target);
|
|
20705
|
-
const promote = (a) => {
|
|
20706
|
-
const code = compile2(a);
|
|
20707
|
-
return BaseCompiler.isComplexValued(a) ? code : `${v2}(${code}, 0.0)`;
|
|
20708
|
-
};
|
|
20709
|
-
if (args.length === 2) return `${promote(args[0])} - ${promote(args[1])}`;
|
|
20710
|
-
let result = promote(args[0]);
|
|
20711
|
-
for (let i = 1; i < args.length; i++) {
|
|
20712
|
-
result = `${result} - ${promote(args[i])}`;
|
|
20937
|
+
return foldTerms(
|
|
20938
|
+
args.map((x) => compile2(x)),
|
|
20939
|
+
"1.0",
|
|
20940
|
+
"*"
|
|
20941
|
+
);
|
|
20713
20942
|
}
|
|
20943
|
+
const iIndex = args.findIndex(
|
|
20944
|
+
(op) => isSymbol2(op, "ImaginaryUnit") || isNumber(op) && op.re === 0 && op.im !== 0
|
|
20945
|
+
);
|
|
20946
|
+
if (iIndex >= 0) {
|
|
20947
|
+
const iFactor = args[iIndex];
|
|
20948
|
+
const iScale = isSymbol2(iFactor, "ImaginaryUnit") ? 1 : iFactor.im;
|
|
20949
|
+
const realFactors = args.filter((_, i) => i !== iIndex);
|
|
20950
|
+
const v2 = gpuVec2(target);
|
|
20951
|
+
if (realFactors.length === 0)
|
|
20952
|
+
return `${v2}(0.0, ${formatFloat(iScale)})`;
|
|
20953
|
+
const factors = realFactors.map((f) => compile2(f));
|
|
20954
|
+
if (iScale !== 1) factors.unshift(formatFloat(iScale));
|
|
20955
|
+
const imCode = foldTerms(factors, "1.0", "*");
|
|
20956
|
+
return `${v2}(0.0, ${imCode})`;
|
|
20957
|
+
}
|
|
20958
|
+
const realCodes = [];
|
|
20959
|
+
const complexCodes = [];
|
|
20960
|
+
for (const a of args) {
|
|
20961
|
+
if (BaseCompiler.isComplexValued(a)) complexCodes.push(compile2(a));
|
|
20962
|
+
else realCodes.push(compile2(a));
|
|
20963
|
+
}
|
|
20964
|
+
const scalarCode = foldTerms(realCodes, "1.0", "*");
|
|
20965
|
+
let result = complexCodes[0];
|
|
20966
|
+
for (let i = 1; i < complexCodes.length; i++) {
|
|
20967
|
+
result = `_gpu_cmul(${result}, ${complexCodes[i]})`;
|
|
20968
|
+
}
|
|
20969
|
+
if (scalarCode !== "1.0") result = `(${scalarCode} * ${result})`;
|
|
20714
20970
|
return result;
|
|
20715
20971
|
},
|
|
20972
|
+
// No Subtract function handler — Subtract canonicalizes to Add+Negate.
|
|
20973
|
+
// The operator entry in GPU_OPERATORS handles any edge cases.
|
|
20716
20974
|
Divide: (args, compile2, target) => {
|
|
20717
20975
|
if (args.length === 0) return "1.0";
|
|
20718
20976
|
if (args.length === 1) return compile2(args[0]);
|
|
20719
20977
|
const ac = BaseCompiler.isComplexValued(args[0]);
|
|
20720
20978
|
const bc = args.length >= 2 && BaseCompiler.isComplexValued(args[1]);
|
|
20721
20979
|
if (!ac && !bc) {
|
|
20722
|
-
if (args.length === 2)
|
|
20980
|
+
if (args.length === 2) {
|
|
20981
|
+
const a = tryGetConstant(args[0]);
|
|
20982
|
+
const b = tryGetConstant(args[1]);
|
|
20983
|
+
if (a !== void 0 && b !== void 0 && b !== 0)
|
|
20984
|
+
return formatFloat(a / b);
|
|
20985
|
+
if (b === 1) return compile2(args[0]);
|
|
20986
|
+
return `${compile2(args[0])} / ${compile2(args[1])}`;
|
|
20987
|
+
}
|
|
20723
20988
|
let result = compile2(args[0]);
|
|
20724
|
-
for (let i = 1; i < args.length; i++)
|
|
20989
|
+
for (let i = 1; i < args.length; i++)
|
|
20725
20990
|
result = `${result} / ${compile2(args[i])}`;
|
|
20726
|
-
}
|
|
20727
20991
|
return result;
|
|
20728
20992
|
}
|
|
20729
20993
|
if (ac && bc) return `_gpu_cdiv(${compile2(args[0])}, ${compile2(args[1])})`;
|
|
20730
|
-
if (ac && !bc) {
|
|
20731
|
-
return `(${compile2(args[0])} / ${compile2(args[1])})`;
|
|
20732
|
-
}
|
|
20994
|
+
if (ac && !bc) return `(${compile2(args[0])} / ${compile2(args[1])})`;
|
|
20733
20995
|
const v2 = gpuVec2(target);
|
|
20734
20996
|
return `_gpu_cdiv(${v2}(${compile2(args[0])}, 0.0), ${compile2(args[1])})`;
|
|
20735
20997
|
},
|
|
20736
|
-
Negate: ([x], compile2) => {
|
|
20998
|
+
Negate: ([x], compile2, target) => {
|
|
20737
20999
|
if (x === null) throw new Error("Negate: no argument");
|
|
21000
|
+
const c = tryGetConstant(x);
|
|
21001
|
+
if (c !== void 0) return formatFloat(-c);
|
|
21002
|
+
if (isNumber(x) && x.im !== 0) {
|
|
21003
|
+
return `${gpuVec2(target)}(${formatFloat(-x.re)}, ${formatFloat(-x.im)})`;
|
|
21004
|
+
}
|
|
21005
|
+
if (isSymbol2(x, "ImaginaryUnit"))
|
|
21006
|
+
return `${gpuVec2(target)}(0.0, -1.0)`;
|
|
20738
21007
|
return `(-${compile2(x)})`;
|
|
20739
21008
|
},
|
|
20740
21009
|
// Standard math functions with complex dispatch
|
|
20741
21010
|
Abs: (args, compile2) => {
|
|
20742
21011
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
20743
21012
|
return `length(${compile2(args[0])})`;
|
|
21013
|
+
if (BaseCompiler.isNonNegative(args[0])) return compile2(args[0]);
|
|
20744
21014
|
return `abs(${compile2(args[0])})`;
|
|
20745
21015
|
},
|
|
20746
21016
|
Arccos: (args, compile2) => {
|
|
@@ -20758,7 +21028,10 @@ ${lines.join("\n")}`;
|
|
|
20758
21028
|
return `_gpu_catan(${compile2(args[0])})`;
|
|
20759
21029
|
return `atan(${compile2(args[0])})`;
|
|
20760
21030
|
},
|
|
20761
|
-
Ceil:
|
|
21031
|
+
Ceil: (args, compile2) => {
|
|
21032
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21033
|
+
return `ceil(${compile2(args[0])})`;
|
|
21034
|
+
},
|
|
20762
21035
|
Clamp: "clamp",
|
|
20763
21036
|
Cos: (args, compile2) => {
|
|
20764
21037
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
@@ -20772,7 +21045,10 @@ ${lines.join("\n")}`;
|
|
|
20772
21045
|
return `exp(${compile2(args[0])})`;
|
|
20773
21046
|
},
|
|
20774
21047
|
Exp2: "exp2",
|
|
20775
|
-
Floor:
|
|
21048
|
+
Floor: (args, compile2) => {
|
|
21049
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21050
|
+
return `floor(${compile2(args[0])})`;
|
|
21051
|
+
},
|
|
20776
21052
|
Fract: "fract",
|
|
20777
21053
|
Ln: (args, compile2) => {
|
|
20778
21054
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
@@ -20794,10 +21070,25 @@ ${lines.join("\n")}`;
|
|
|
20794
21070
|
const eCode = BaseCompiler.isComplexValued(exp3) ? compile2(exp3) : `${v2}(${compile2(exp3)}, 0.0)`;
|
|
20795
21071
|
return `_gpu_cpow(${bCode}, ${eCode})`;
|
|
20796
21072
|
}
|
|
21073
|
+
const bConst = tryGetConstant(base);
|
|
21074
|
+
const eConst = tryGetConstant(exp3);
|
|
21075
|
+
if (bConst !== void 0 && eConst !== void 0)
|
|
21076
|
+
return formatFloat(Math.pow(bConst, eConst));
|
|
21077
|
+
if (eConst === 0) return "1.0";
|
|
21078
|
+
if (eConst === 1) return compile2(base);
|
|
21079
|
+
if (eConst === 2 && (isSymbol2(base) || isNumber(base))) {
|
|
21080
|
+
const code = compile2(base);
|
|
21081
|
+
return `(${code} * ${code})`;
|
|
21082
|
+
}
|
|
21083
|
+
if (eConst === -1) return `(1.0 / ${compile2(base)})`;
|
|
21084
|
+
if (eConst === 0.5) return `sqrt(${compile2(base)})`;
|
|
20797
21085
|
return `pow(${compile2(base)}, ${compile2(exp3)})`;
|
|
20798
21086
|
},
|
|
20799
21087
|
Radians: "radians",
|
|
20800
|
-
Round:
|
|
21088
|
+
Round: (args, compile2) => {
|
|
21089
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21090
|
+
return `round(${compile2(args[0])})`;
|
|
21091
|
+
},
|
|
20801
21092
|
Sign: "sign",
|
|
20802
21093
|
Sin: (args, compile2) => {
|
|
20803
21094
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
@@ -20808,6 +21099,8 @@ ${lines.join("\n")}`;
|
|
|
20808
21099
|
Sqrt: (args, compile2) => {
|
|
20809
21100
|
if (BaseCompiler.isComplexValued(args[0]))
|
|
20810
21101
|
return `_gpu_csqrt(${compile2(args[0])})`;
|
|
21102
|
+
const c = tryGetConstant(args[0]);
|
|
21103
|
+
if (c !== void 0) return formatFloat(Math.sqrt(c));
|
|
20811
21104
|
return `sqrt(${compile2(args[0])})`;
|
|
20812
21105
|
},
|
|
20813
21106
|
Step: "step",
|
|
@@ -20816,17 +21109,20 @@ ${lines.join("\n")}`;
|
|
|
20816
21109
|
return `_gpu_ctan(${compile2(args[0])})`;
|
|
20817
21110
|
return `tan(${compile2(args[0])})`;
|
|
20818
21111
|
},
|
|
20819
|
-
Truncate:
|
|
21112
|
+
Truncate: (args, compile2) => {
|
|
21113
|
+
if (BaseCompiler.isIntegerValued(args[0])) return compile2(args[0]);
|
|
21114
|
+
return `trunc(${compile2(args[0])})`;
|
|
21115
|
+
},
|
|
20820
21116
|
// Complex-specific functions
|
|
20821
|
-
|
|
21117
|
+
Real: (args, compile2) => {
|
|
20822
21118
|
if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).x`;
|
|
20823
21119
|
return compile2(args[0]);
|
|
20824
21120
|
},
|
|
20825
|
-
|
|
21121
|
+
Imaginary: (args, compile2) => {
|
|
20826
21122
|
if (BaseCompiler.isComplexValued(args[0])) return `(${compile2(args[0])}).y`;
|
|
20827
21123
|
return "0.0";
|
|
20828
21124
|
},
|
|
20829
|
-
|
|
21125
|
+
Argument: (args, compile2) => {
|
|
20830
21126
|
if (BaseCompiler.isComplexValued(args[0])) {
|
|
20831
21127
|
const code = compile2(args[0]);
|
|
20832
21128
|
return `atan(${code}.y, ${code}.x)`;
|
|
@@ -21041,13 +21337,20 @@ ${lines.join("\n")}`;
|
|
|
21041
21337
|
},
|
|
21042
21338
|
Square: ([x], compile2) => {
|
|
21043
21339
|
if (x === null) throw new Error("Square: no argument");
|
|
21044
|
-
|
|
21045
|
-
|
|
21340
|
+
if (isSymbol2(x) || isNumber(x)) {
|
|
21341
|
+
const arg = compile2(x);
|
|
21342
|
+
return `(${arg} * ${arg})`;
|
|
21343
|
+
}
|
|
21344
|
+
return `pow(${compile2(x)}, 2.0)`;
|
|
21046
21345
|
},
|
|
21047
21346
|
Root: ([x, n], compile2) => {
|
|
21048
21347
|
if (x === null) throw new Error("Root: no argument");
|
|
21049
21348
|
if (n === null || n === void 0) return `sqrt(${compile2(x)})`;
|
|
21050
|
-
|
|
21349
|
+
const nConst = tryGetConstant(n);
|
|
21350
|
+
if (nConst === 2) return `sqrt(${compile2(x)})`;
|
|
21351
|
+
const xConst = tryGetConstant(x);
|
|
21352
|
+
if (xConst !== void 0 && nConst !== void 0)
|
|
21353
|
+
return formatFloat(Math.pow(xConst, 1 / nConst));
|
|
21051
21354
|
return `pow(${compile2(x)}, 1.0 / ${compile2(n)})`;
|
|
21052
21355
|
},
|
|
21053
21356
|
// Color functions (pure-math, GPU-compilable)
|
|
@@ -21089,18 +21392,34 @@ ${lines.join("\n")}`;
|
|
|
21089
21392
|
Mandelbrot: ([c, maxIter], compile2, target) => {
|
|
21090
21393
|
if (c === null || maxIter === null)
|
|
21091
21394
|
throw new Error("Mandelbrot: missing arguments");
|
|
21092
|
-
const
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21395
|
+
const iterCode = compileIntArg(maxIter, compile2, target);
|
|
21396
|
+
const strategy = selectFractalStrategy(target);
|
|
21397
|
+
if (strategy === "double") {
|
|
21398
|
+
const cCode = compile2(c);
|
|
21399
|
+
return `_fractal_mandelbrot_dp(vec4(${cCode}, vec2(0.0)), ${iterCode})`;
|
|
21400
|
+
}
|
|
21401
|
+
if (strategy === "perturbation") {
|
|
21402
|
+
const cCode = compile2(c);
|
|
21403
|
+
return `_fractal_mandelbrot_pt(${cCode}, ${iterCode})`;
|
|
21404
|
+
}
|
|
21405
|
+
return `_fractal_mandelbrot(${compile2(c)}, ${iterCode})`;
|
|
21096
21406
|
},
|
|
21097
21407
|
Julia: ([z, c, maxIter], compile2, target) => {
|
|
21098
21408
|
if (z === null || c === null || maxIter === null)
|
|
21099
21409
|
throw new Error("Julia: missing arguments");
|
|
21100
|
-
const
|
|
21101
|
-
|
|
21102
|
-
|
|
21103
|
-
|
|
21410
|
+
const iterCode = compileIntArg(maxIter, compile2, target);
|
|
21411
|
+
const strategy = selectFractalStrategy(target);
|
|
21412
|
+
if (strategy === "double") {
|
|
21413
|
+
const zCode = compile2(z);
|
|
21414
|
+
const cCode = compile2(c);
|
|
21415
|
+
return `_fractal_julia_dp(vec4(${zCode}, vec2(0.0)), vec4(${cCode}, vec2(0.0)), ${iterCode})`;
|
|
21416
|
+
}
|
|
21417
|
+
if (strategy === "perturbation") {
|
|
21418
|
+
const zCode = compile2(z);
|
|
21419
|
+
const cCode = compile2(c);
|
|
21420
|
+
return `_fractal_julia_pt(${zCode}, ${cCode}, ${iterCode})`;
|
|
21421
|
+
}
|
|
21422
|
+
return `_fractal_julia(${compile2(z)}, ${compile2(c)}, ${iterCode})`;
|
|
21104
21423
|
},
|
|
21105
21424
|
// Vector/Matrix operations
|
|
21106
21425
|
Cross: "cross",
|
|
@@ -21696,6 +22015,200 @@ fn _gpu_besselJ(n_in: i32, x_in: f32) -> f32 {
|
|
|
21696
22015
|
for (var k2: i32 = 2; k2 <= M; k2 += 2) { norm += 2.0 * vals[k2]; }
|
|
21697
22016
|
return sgn * vals[n] / norm;
|
|
21698
22017
|
}
|
|
22018
|
+
`;
|
|
22019
|
+
var GPU_DS_ARITHMETIC_PREAMBLE_GLSL = `
|
|
22020
|
+
// Split a float into high and low parts for exact multiplication
|
|
22021
|
+
vec2 ds_split(float a) {
|
|
22022
|
+
const float SPLIT = 4097.0; // 2^12 + 1
|
|
22023
|
+
float t = SPLIT * a;
|
|
22024
|
+
float hi = t - (t - a);
|
|
22025
|
+
float lo = a - hi;
|
|
22026
|
+
return vec2(hi, lo);
|
|
22027
|
+
}
|
|
22028
|
+
|
|
22029
|
+
// Create a double-single from a single float
|
|
22030
|
+
vec2 ds_from(float a) {
|
|
22031
|
+
return vec2(a, 0.0);
|
|
22032
|
+
}
|
|
22033
|
+
|
|
22034
|
+
// Error-free addition (Knuth TwoSum)
|
|
22035
|
+
vec2 ds_add(vec2 a, vec2 b) {
|
|
22036
|
+
float s = a.x + b.x;
|
|
22037
|
+
float v = s - a.x;
|
|
22038
|
+
float e = (a.x - (s - v)) + (b.x - v);
|
|
22039
|
+
float lo = (a.y + b.y) + e;
|
|
22040
|
+
float hi = s + lo;
|
|
22041
|
+
lo = lo - (hi - s);
|
|
22042
|
+
return vec2(hi, lo);
|
|
22043
|
+
}
|
|
22044
|
+
|
|
22045
|
+
// Double-single subtraction
|
|
22046
|
+
vec2 ds_sub(vec2 a, vec2 b) {
|
|
22047
|
+
return ds_add(a, vec2(-b.x, -b.y));
|
|
22048
|
+
}
|
|
22049
|
+
|
|
22050
|
+
// Error-free multiplication (Dekker TwoProduct)
|
|
22051
|
+
vec2 ds_mul(vec2 a, vec2 b) {
|
|
22052
|
+
float p = a.x * b.x;
|
|
22053
|
+
vec2 sa = ds_split(a.x);
|
|
22054
|
+
vec2 sb = ds_split(b.x);
|
|
22055
|
+
float err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
|
|
22056
|
+
err += a.x * b.y + a.y * b.x;
|
|
22057
|
+
float hi = p + err;
|
|
22058
|
+
float lo = err - (hi - p);
|
|
22059
|
+
return vec2(hi, lo);
|
|
22060
|
+
}
|
|
22061
|
+
|
|
22062
|
+
// Optimized self-multiply
|
|
22063
|
+
vec2 ds_sqr(vec2 a) {
|
|
22064
|
+
float p = a.x * a.x;
|
|
22065
|
+
vec2 sa = ds_split(a.x);
|
|
22066
|
+
float err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
|
|
22067
|
+
err += 2.0 * a.x * a.y;
|
|
22068
|
+
float hi = p + err;
|
|
22069
|
+
float lo = err - (hi - p);
|
|
22070
|
+
return vec2(hi, lo);
|
|
22071
|
+
}
|
|
22072
|
+
|
|
22073
|
+
// Compare magnitude: returns -1, 0, or 1
|
|
22074
|
+
float ds_cmp(vec2 a, vec2 b) {
|
|
22075
|
+
float d = a.x - b.x;
|
|
22076
|
+
if (d != 0.0) return sign(d);
|
|
22077
|
+
return sign(a.y - b.y);
|
|
22078
|
+
}
|
|
22079
|
+
`;
|
|
22080
|
+
var GPU_DS_ARITHMETIC_PREAMBLE_WGSL = `
|
|
22081
|
+
fn ds_split(a: f32) -> vec2f {
|
|
22082
|
+
const SPLIT: f32 = 4097.0;
|
|
22083
|
+
let t = SPLIT * a;
|
|
22084
|
+
let hi = t - (t - a);
|
|
22085
|
+
let lo = a - hi;
|
|
22086
|
+
return vec2f(hi, lo);
|
|
22087
|
+
}
|
|
22088
|
+
|
|
22089
|
+
fn ds_from(a: f32) -> vec2f {
|
|
22090
|
+
return vec2f(a, 0.0);
|
|
22091
|
+
}
|
|
22092
|
+
|
|
22093
|
+
fn ds_add(a: vec2f, b: vec2f) -> vec2f {
|
|
22094
|
+
let s = a.x + b.x;
|
|
22095
|
+
let v = s - a.x;
|
|
22096
|
+
let e = (a.x - (s - v)) + (b.x - v);
|
|
22097
|
+
let lo_t = (a.y + b.y) + e;
|
|
22098
|
+
let hi = s + lo_t;
|
|
22099
|
+
let lo = lo_t - (hi - s);
|
|
22100
|
+
return vec2f(hi, lo);
|
|
22101
|
+
}
|
|
22102
|
+
|
|
22103
|
+
fn ds_sub(a: vec2f, b: vec2f) -> vec2f {
|
|
22104
|
+
return ds_add(a, vec2f(-b.x, -b.y));
|
|
22105
|
+
}
|
|
22106
|
+
|
|
22107
|
+
fn ds_mul(a: vec2f, b: vec2f) -> vec2f {
|
|
22108
|
+
let p = a.x * b.x;
|
|
22109
|
+
let sa = ds_split(a.x);
|
|
22110
|
+
let sb = ds_split(b.x);
|
|
22111
|
+
var err = ((sa.x * sb.x - p) + sa.x * sb.y + sa.y * sb.x) + sa.y * sb.y;
|
|
22112
|
+
err += a.x * b.y + a.y * b.x;
|
|
22113
|
+
let hi = p + err;
|
|
22114
|
+
let lo = err - (hi - p);
|
|
22115
|
+
return vec2f(hi, lo);
|
|
22116
|
+
}
|
|
22117
|
+
|
|
22118
|
+
fn ds_sqr(a: vec2f) -> vec2f {
|
|
22119
|
+
let p = a.x * a.x;
|
|
22120
|
+
let sa = ds_split(a.x);
|
|
22121
|
+
var err = ((sa.x * sa.x - p) + 2.0 * sa.x * sa.y) + sa.y * sa.y;
|
|
22122
|
+
err += 2.0 * a.x * a.y;
|
|
22123
|
+
let hi = p + err;
|
|
22124
|
+
let lo = err - (hi - p);
|
|
22125
|
+
return vec2f(hi, lo);
|
|
22126
|
+
}
|
|
22127
|
+
|
|
22128
|
+
fn ds_cmp(a: vec2f, b: vec2f) -> f32 {
|
|
22129
|
+
let d = a.x - b.x;
|
|
22130
|
+
if (d != 0.0) { return sign(d); }
|
|
22131
|
+
return sign(a.y - b.y);
|
|
22132
|
+
}
|
|
22133
|
+
`;
|
|
22134
|
+
var GPU_FRACTAL_DP_PREAMBLE_GLSL = `
|
|
22135
|
+
float _fractal_mandelbrot_dp(vec4 c, int maxIter) {
|
|
22136
|
+
// c = (re_hi, im_hi, re_lo, im_lo)
|
|
22137
|
+
vec2 cr = vec2(c.x, c.z); // real part as ds
|
|
22138
|
+
vec2 ci = vec2(c.y, c.w); // imag part as ds
|
|
22139
|
+
vec2 zr = vec2(0.0, 0.0);
|
|
22140
|
+
vec2 zi = vec2(0.0, 0.0);
|
|
22141
|
+
for (int i = 0; i < maxIter; i++) {
|
|
22142
|
+
vec2 zr2 = ds_sqr(zr);
|
|
22143
|
+
vec2 zi2 = ds_sqr(zi);
|
|
22144
|
+
// |z|^2 > 4.0 ?
|
|
22145
|
+
vec2 mag2 = ds_add(zr2, zi2);
|
|
22146
|
+
if (mag2.x > 4.0)
|
|
22147
|
+
return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22148
|
+
// z = z^2 + c
|
|
22149
|
+
vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci); // 2*zr*zi + ci
|
|
22150
|
+
zr = ds_add(ds_sub(zr2, zi2), cr); // zr^2 - zi^2 + cr
|
|
22151
|
+
zi = new_zi;
|
|
22152
|
+
}
|
|
22153
|
+
return 1.0;
|
|
22154
|
+
}
|
|
22155
|
+
|
|
22156
|
+
float _fractal_julia_dp(vec4 z_in, vec4 c, int maxIter) {
|
|
22157
|
+
vec2 zr = vec2(z_in.x, z_in.z);
|
|
22158
|
+
vec2 zi = vec2(z_in.y, z_in.w);
|
|
22159
|
+
vec2 cr = vec2(c.x, c.z);
|
|
22160
|
+
vec2 ci = vec2(c.y, c.w);
|
|
22161
|
+
for (int i = 0; i < maxIter; i++) {
|
|
22162
|
+
vec2 zr2 = ds_sqr(zr);
|
|
22163
|
+
vec2 zi2 = ds_sqr(zi);
|
|
22164
|
+
vec2 mag2 = ds_add(zr2, zi2);
|
|
22165
|
+
if (mag2.x > 4.0)
|
|
22166
|
+
return clamp((float(i) - log2(log2(mag2.x)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22167
|
+
vec2 new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
|
|
22168
|
+
zr = ds_add(ds_sub(zr2, zi2), cr);
|
|
22169
|
+
zi = new_zi;
|
|
22170
|
+
}
|
|
22171
|
+
return 1.0;
|
|
22172
|
+
}
|
|
22173
|
+
`;
|
|
22174
|
+
var GPU_FRACTAL_DP_PREAMBLE_WGSL = `
|
|
22175
|
+
fn _fractal_mandelbrot_dp(c: vec4f, maxIter: i32) -> f32 {
|
|
22176
|
+
let cr = vec2f(c.x, c.z);
|
|
22177
|
+
let ci = vec2f(c.y, c.w);
|
|
22178
|
+
var zr = vec2f(0.0, 0.0);
|
|
22179
|
+
var zi = vec2f(0.0, 0.0);
|
|
22180
|
+
for (var i: i32 = 0; i < maxIter; i++) {
|
|
22181
|
+
let zr2 = ds_sqr(zr);
|
|
22182
|
+
let zi2 = ds_sqr(zi);
|
|
22183
|
+
let mag2 = ds_add(zr2, zi2);
|
|
22184
|
+
if (mag2.x > 4.0) {
|
|
22185
|
+
return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22186
|
+
}
|
|
22187
|
+
let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
|
|
22188
|
+
zr = ds_add(ds_sub(zr2, zi2), cr);
|
|
22189
|
+
zi = new_zi;
|
|
22190
|
+
}
|
|
22191
|
+
return 1.0;
|
|
22192
|
+
}
|
|
22193
|
+
|
|
22194
|
+
fn _fractal_julia_dp(z_in: vec4f, c: vec4f, maxIter: i32) -> f32 {
|
|
22195
|
+
var zr = vec2f(z_in.x, z_in.z);
|
|
22196
|
+
var zi = vec2f(z_in.y, z_in.w);
|
|
22197
|
+
let cr = vec2f(c.x, c.z);
|
|
22198
|
+
let ci = vec2f(c.y, c.w);
|
|
22199
|
+
for (var i: i32 = 0; i < maxIter; i++) {
|
|
22200
|
+
let zr2 = ds_sqr(zr);
|
|
22201
|
+
let zi2 = ds_sqr(zi);
|
|
22202
|
+
let mag2 = ds_add(zr2, zi2);
|
|
22203
|
+
if (mag2.x > 4.0) {
|
|
22204
|
+
return clamp((f32(i) - log2(log2(mag2.x)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22205
|
+
}
|
|
22206
|
+
let new_zi = ds_add(ds_mul(ds_add(zr, zr), zi), ci);
|
|
22207
|
+
zr = ds_add(ds_sub(zr2, zi2), cr);
|
|
22208
|
+
zi = new_zi;
|
|
22209
|
+
}
|
|
22210
|
+
return 1.0;
|
|
22211
|
+
}
|
|
21699
22212
|
`;
|
|
21700
22213
|
var GPU_FRACTAL_PREAMBLE_GLSL = `
|
|
21701
22214
|
float _fractal_mandelbrot(vec2 c, int maxIter) {
|
|
@@ -21739,6 +22252,188 @@ fn _fractal_julia(z_in: vec2f, c: vec2f, maxIter: i32) -> f32 {
|
|
|
21739
22252
|
}
|
|
21740
22253
|
return 1.0;
|
|
21741
22254
|
}
|
|
22255
|
+
`;
|
|
22256
|
+
var GPU_FRACTAL_PT_PREAMBLE_GLSL = `
|
|
22257
|
+
uniform sampler2D _refOrbit;
|
|
22258
|
+
uniform int _refOrbitLen;
|
|
22259
|
+
uniform int _refOrbitTexWidth;
|
|
22260
|
+
|
|
22261
|
+
vec2 _pt_fetch_orbit(int i) {
|
|
22262
|
+
int y = i / _refOrbitTexWidth;
|
|
22263
|
+
int x = i - y * _refOrbitTexWidth;
|
|
22264
|
+
return texelFetch(_refOrbit, ivec2(x, y), 0).rg;
|
|
22265
|
+
}
|
|
22266
|
+
|
|
22267
|
+
float _fractal_mandelbrot_pt(vec2 delta_c, int maxIter) {
|
|
22268
|
+
float dr = 0.0;
|
|
22269
|
+
float di = 0.0;
|
|
22270
|
+
int orbitLen = min(maxIter, _refOrbitLen);
|
|
22271
|
+
for (int i = 0; i < orbitLen; i++) {
|
|
22272
|
+
vec2 Zn = _pt_fetch_orbit(i);
|
|
22273
|
+
// delta_{n+1} = 2*Z_n*delta_n + delta_n^2 + delta_c
|
|
22274
|
+
float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
|
|
22275
|
+
float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
|
|
22276
|
+
dr = new_dr;
|
|
22277
|
+
di = new_di;
|
|
22278
|
+
// Full z = Z_{n+1} + delta for escape check
|
|
22279
|
+
vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
|
|
22280
|
+
float zr = Zn1.x + dr;
|
|
22281
|
+
float zi = Zn1.y + di;
|
|
22282
|
+
float mag2 = zr * zr + zi * zi;
|
|
22283
|
+
if (mag2 > 4.0)
|
|
22284
|
+
return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22285
|
+
// Glitch detection: |delta|^2 > |Z|^2
|
|
22286
|
+
float dmag2 = dr * dr + di * di;
|
|
22287
|
+
float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
|
|
22288
|
+
if (dmag2 > Zmag2 && Zmag2 > 0.0) {
|
|
22289
|
+
// Rebase to absolute coordinates and continue with single-float
|
|
22290
|
+
float abs_zr = Zn1.x + dr;
|
|
22291
|
+
float abs_zi = Zn1.y + di;
|
|
22292
|
+
// Reconstruct absolute c from reference + delta
|
|
22293
|
+
// (Use ds_from for the concept, but single-float suffices for fallback)
|
|
22294
|
+
float cx = abs_zr - dr + delta_c.x;
|
|
22295
|
+
float cy = abs_zi - di + delta_c.y;
|
|
22296
|
+
for (int j = i + 1; j < maxIter; j++) {
|
|
22297
|
+
float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
|
|
22298
|
+
abs_zi = 2.0 * abs_zr * abs_zi + cy;
|
|
22299
|
+
abs_zr = new_zr;
|
|
22300
|
+
mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
|
|
22301
|
+
if (mag2 > 4.0)
|
|
22302
|
+
return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22303
|
+
}
|
|
22304
|
+
return 1.0;
|
|
22305
|
+
}
|
|
22306
|
+
}
|
|
22307
|
+
return 1.0;
|
|
22308
|
+
}
|
|
22309
|
+
|
|
22310
|
+
float _fractal_julia_pt(vec2 z_delta, vec2 delta_c, int maxIter) {
|
|
22311
|
+
float dr = z_delta.x;
|
|
22312
|
+
float di = z_delta.y;
|
|
22313
|
+
int orbitLen = min(maxIter, _refOrbitLen);
|
|
22314
|
+
for (int i = 0; i < orbitLen; i++) {
|
|
22315
|
+
vec2 Zn = _pt_fetch_orbit(i);
|
|
22316
|
+
float new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
|
|
22317
|
+
float new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
|
|
22318
|
+
dr = new_dr;
|
|
22319
|
+
di = new_di;
|
|
22320
|
+
vec2 Zn1 = (i + 1 < orbitLen) ? _pt_fetch_orbit(i + 1) : vec2(0.0);
|
|
22321
|
+
float zr = Zn1.x + dr;
|
|
22322
|
+
float zi = Zn1.y + di;
|
|
22323
|
+
float mag2 = zr * zr + zi * zi;
|
|
22324
|
+
if (mag2 > 4.0)
|
|
22325
|
+
return clamp((float(i) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22326
|
+
float dmag2 = dr * dr + di * di;
|
|
22327
|
+
float Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
|
|
22328
|
+
if (dmag2 > Zmag2 && Zmag2 > 0.0) {
|
|
22329
|
+
float abs_zr = Zn1.x + dr;
|
|
22330
|
+
float abs_zi = Zn1.y + di;
|
|
22331
|
+
float cx = delta_c.x;
|
|
22332
|
+
float cy = delta_c.y;
|
|
22333
|
+
for (int j = i + 1; j < maxIter; j++) {
|
|
22334
|
+
float new_zr = abs_zr * abs_zr - abs_zi * abs_zi + cx;
|
|
22335
|
+
abs_zi = 2.0 * abs_zr * abs_zi + cy;
|
|
22336
|
+
abs_zr = new_zr;
|
|
22337
|
+
mag2 = abs_zr * abs_zr + abs_zi * abs_zi;
|
|
22338
|
+
if (mag2 > 4.0)
|
|
22339
|
+
return clamp((float(j) - log2(log2(mag2)) + 4.0) / float(maxIter), 0.0, 1.0);
|
|
22340
|
+
}
|
|
22341
|
+
return 1.0;
|
|
22342
|
+
}
|
|
22343
|
+
}
|
|
22344
|
+
return 1.0;
|
|
22345
|
+
}
|
|
22346
|
+
`;
|
|
22347
|
+
var GPU_FRACTAL_PT_PREAMBLE_WGSL = `
|
|
22348
|
+
@group(0) @binding(1) var _refOrbit: texture_2d<f32>;
|
|
22349
|
+
var<uniform> _refOrbitLen: i32;
|
|
22350
|
+
var<uniform> _refOrbitTexWidth: i32;
|
|
22351
|
+
|
|
22352
|
+
fn _pt_fetch_orbit(i: i32) -> vec2f {
|
|
22353
|
+
let y = i / _refOrbitTexWidth;
|
|
22354
|
+
let x = i - y * _refOrbitTexWidth;
|
|
22355
|
+
return textureLoad(_refOrbit, vec2i(x, y), 0).rg;
|
|
22356
|
+
}
|
|
22357
|
+
|
|
22358
|
+
fn _fractal_mandelbrot_pt(delta_c: vec2f, maxIter: i32) -> f32 {
|
|
22359
|
+
var dr: f32 = 0.0;
|
|
22360
|
+
var di: f32 = 0.0;
|
|
22361
|
+
let orbitLen = min(maxIter, _refOrbitLen);
|
|
22362
|
+
for (var i: i32 = 0; i < orbitLen; i++) {
|
|
22363
|
+
let Zn = _pt_fetch_orbit(i);
|
|
22364
|
+
let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
|
|
22365
|
+
let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
|
|
22366
|
+
dr = new_dr;
|
|
22367
|
+
di = new_di;
|
|
22368
|
+
var Zn1 = vec2f(0.0);
|
|
22369
|
+
if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
|
|
22370
|
+
let zr = Zn1.x + dr;
|
|
22371
|
+
let zi = Zn1.y + di;
|
|
22372
|
+
var mag2 = zr * zr + zi * zi;
|
|
22373
|
+
if (mag2 > 4.0) {
|
|
22374
|
+
return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22375
|
+
}
|
|
22376
|
+
let dmag2 = dr * dr + di * di;
|
|
22377
|
+
let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
|
|
22378
|
+
if (dmag2 > Zmag2 && Zmag2 > 0.0) {
|
|
22379
|
+
var f_zr = Zn1.x + dr;
|
|
22380
|
+
var f_zi = Zn1.y + di;
|
|
22381
|
+
let cx = delta_c.x;
|
|
22382
|
+
let cy = delta_c.y;
|
|
22383
|
+
for (var j: i32 = i + 1; j < maxIter; j++) {
|
|
22384
|
+
let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
|
|
22385
|
+
f_zi = 2.0 * f_zr * f_zi + cy;
|
|
22386
|
+
f_zr = t_zr;
|
|
22387
|
+
mag2 = f_zr * f_zr + f_zi * f_zi;
|
|
22388
|
+
if (mag2 > 4.0) {
|
|
22389
|
+
return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22390
|
+
}
|
|
22391
|
+
}
|
|
22392
|
+
return 1.0;
|
|
22393
|
+
}
|
|
22394
|
+
}
|
|
22395
|
+
return 1.0;
|
|
22396
|
+
}
|
|
22397
|
+
|
|
22398
|
+
fn _fractal_julia_pt(z_delta: vec2f, delta_c: vec2f, maxIter: i32) -> f32 {
|
|
22399
|
+
var dr = z_delta.x;
|
|
22400
|
+
var di = z_delta.y;
|
|
22401
|
+
let orbitLen = min(maxIter, _refOrbitLen);
|
|
22402
|
+
for (var i: i32 = 0; i < orbitLen; i++) {
|
|
22403
|
+
let Zn = _pt_fetch_orbit(i);
|
|
22404
|
+
let new_dr = 2.0 * (Zn.x * dr - Zn.y * di) + dr * dr - di * di + delta_c.x;
|
|
22405
|
+
let new_di = 2.0 * (Zn.x * di + Zn.y * dr) + 2.0 * dr * di + delta_c.y;
|
|
22406
|
+
dr = new_dr;
|
|
22407
|
+
di = new_di;
|
|
22408
|
+
var Zn1 = vec2f(0.0);
|
|
22409
|
+
if (i + 1 < orbitLen) { Zn1 = _pt_fetch_orbit(i + 1); }
|
|
22410
|
+
let zr = Zn1.x + dr;
|
|
22411
|
+
let zi = Zn1.y + di;
|
|
22412
|
+
var mag2 = zr * zr + zi * zi;
|
|
22413
|
+
if (mag2 > 4.0) {
|
|
22414
|
+
return clamp((f32(i) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22415
|
+
}
|
|
22416
|
+
let dmag2 = dr * dr + di * di;
|
|
22417
|
+
let Zmag2 = Zn.x * Zn.x + Zn.y * Zn.y;
|
|
22418
|
+
if (dmag2 > Zmag2 && Zmag2 > 0.0) {
|
|
22419
|
+
var f_zr = Zn1.x + dr;
|
|
22420
|
+
var f_zi = Zn1.y + di;
|
|
22421
|
+
let cx = delta_c.x;
|
|
22422
|
+
let cy = delta_c.y;
|
|
22423
|
+
for (var j: i32 = i + 1; j < maxIter; j++) {
|
|
22424
|
+
let t_zr = f_zr * f_zr - f_zi * f_zi + cx;
|
|
22425
|
+
f_zi = 2.0 * f_zr * f_zi + cy;
|
|
22426
|
+
f_zr = t_zr;
|
|
22427
|
+
mag2 = f_zr * f_zr + f_zi * f_zi;
|
|
22428
|
+
if (mag2 > 4.0) {
|
|
22429
|
+
return clamp((f32(j) - log2(log2(mag2)) + 4.0) / f32(maxIter), 0.0, 1.0);
|
|
22430
|
+
}
|
|
22431
|
+
}
|
|
22432
|
+
return 1.0;
|
|
22433
|
+
}
|
|
22434
|
+
}
|
|
22435
|
+
return 1.0;
|
|
22436
|
+
}
|
|
21742
22437
|
`;
|
|
21743
22438
|
var GPU_COLOR_PREAMBLE_GLSL = `
|
|
21744
22439
|
float _gpu_srgb_to_linear(float c) {
|
|
@@ -22178,6 +22873,7 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
22178
22873
|
const constants = this.getConstants();
|
|
22179
22874
|
const v2 = this.languageId === "wgsl" ? "vec2f" : "vec2";
|
|
22180
22875
|
const target = this.createTarget({
|
|
22876
|
+
hints: options.hints,
|
|
22181
22877
|
functions: (id) => {
|
|
22182
22878
|
if (userFunctions && id in userFunctions) {
|
|
22183
22879
|
const fn = userFunctions[id];
|
|
@@ -22216,12 +22912,65 @@ fn _gpu_apca(bg: vec3f, fg: vec3f) -> f32 {
|
|
|
22216
22912
|
if (code.includes("_gpu_besselJ"))
|
|
22217
22913
|
preamble += this.languageId === "wgsl" ? GPU_BESSELJ_PREAMBLE_WGSL : GPU_BESSELJ_PREAMBLE_GLSL;
|
|
22218
22914
|
if (code.includes("_fractal_")) {
|
|
22219
|
-
|
|
22915
|
+
if (code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) {
|
|
22916
|
+
preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
|
|
22917
|
+
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PT_PREAMBLE_WGSL : GPU_FRACTAL_PT_PREAMBLE_GLSL;
|
|
22918
|
+
} else if (code.includes("_fractal_mandelbrot_dp") || code.includes("_fractal_julia_dp")) {
|
|
22919
|
+
preamble += this.languageId === "wgsl" ? GPU_DS_ARITHMETIC_PREAMBLE_WGSL : GPU_DS_ARITHMETIC_PREAMBLE_GLSL;
|
|
22920
|
+
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_DP_PREAMBLE_WGSL : GPU_FRACTAL_DP_PREAMBLE_GLSL;
|
|
22921
|
+
} else {
|
|
22922
|
+
preamble += this.languageId === "wgsl" ? GPU_FRACTAL_PREAMBLE_WGSL : GPU_FRACTAL_PREAMBLE_GLSL;
|
|
22923
|
+
}
|
|
22220
22924
|
}
|
|
22221
22925
|
if (code.includes("_gpu_srgb_to") || code.includes("_gpu_oklab") || code.includes("_gpu_oklch") || code.includes("_gpu_color_mix") || code.includes("_gpu_apca")) {
|
|
22222
22926
|
preamble += this.languageId === "wgsl" ? GPU_COLOR_PREAMBLE_WGSL : GPU_COLOR_PREAMBLE_GLSL;
|
|
22223
22927
|
}
|
|
22224
22928
|
if (preamble) result.preamble = preamble;
|
|
22929
|
+
if (code.includes("_fractal_") && options.hints?.viewport) {
|
|
22930
|
+
const strategy = selectFractalStrategy(target);
|
|
22931
|
+
const radius = options.hints.viewport.radius;
|
|
22932
|
+
switch (strategy) {
|
|
22933
|
+
case "single":
|
|
22934
|
+
result.staleWhen = { radiusBelow: 1e-6 };
|
|
22935
|
+
break;
|
|
22936
|
+
case "double":
|
|
22937
|
+
result.staleWhen = { radiusBelow: 1e-14, radiusAbove: 1e-5 };
|
|
22938
|
+
break;
|
|
22939
|
+
case "perturbation":
|
|
22940
|
+
result.staleWhen = {
|
|
22941
|
+
radiusAbove: 1e-5,
|
|
22942
|
+
radiusBelow: radius * 0.01,
|
|
22943
|
+
centerDistance: radius * 2
|
|
22944
|
+
};
|
|
22945
|
+
break;
|
|
22946
|
+
}
|
|
22947
|
+
}
|
|
22948
|
+
if ((code.includes("_fractal_mandelbrot_pt") || code.includes("_fractal_julia_pt")) && options.hints?.viewport) {
|
|
22949
|
+
const viewport = options.hints.viewport;
|
|
22950
|
+
const digits = Math.max(50, Math.ceil(-Math.log10(viewport.radius)) + 10);
|
|
22951
|
+
const maxIter = 1e3;
|
|
22952
|
+
const orbit = computeReferenceOrbit(
|
|
22953
|
+
viewport.center,
|
|
22954
|
+
maxIter,
|
|
22955
|
+
digits
|
|
22956
|
+
);
|
|
22957
|
+
const orbitLen = orbit.length / 2;
|
|
22958
|
+
const texWidth = Math.min(orbitLen, 4096);
|
|
22959
|
+
const texHeight = Math.ceil(orbitLen / texWidth);
|
|
22960
|
+
result.textures = {
|
|
22961
|
+
_refOrbit: {
|
|
22962
|
+
data: orbit,
|
|
22963
|
+
width: texWidth,
|
|
22964
|
+
height: texHeight,
|
|
22965
|
+
format: "rg32f"
|
|
22966
|
+
}
|
|
22967
|
+
};
|
|
22968
|
+
result.uniforms = {
|
|
22969
|
+
...result.uniforms,
|
|
22970
|
+
_refOrbitLen: orbitLen,
|
|
22971
|
+
_refOrbitTexWidth: texWidth
|
|
22972
|
+
};
|
|
22973
|
+
}
|
|
22225
22974
|
return result;
|
|
22226
22975
|
}
|
|
22227
22976
|
compileToSource(expr, _options = {}) {
|
|
@@ -22455,6 +23204,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
22455
23204
|
Negate: ["-", 14],
|
|
22456
23205
|
// Unary operator
|
|
22457
23206
|
Subtract: ["-", 11],
|
|
23207
|
+
// Subtract canonicalizes to Add+Negate; kept as fallback
|
|
22458
23208
|
Multiply: ["*", 12],
|
|
22459
23209
|
Divide: ["/", 13],
|
|
22460
23210
|
Power: ["**", 15],
|
|
@@ -22482,16 +23232,7 @@ ${workgroupAttr}fn main(${paramStr})${returnStr} {
|
|
|
22482
23232
|
if (args.length === 1) return compile2(args[0]);
|
|
22483
23233
|
return args.map((x) => compile2(x)).join(" * ");
|
|
22484
23234
|
},
|
|
22485
|
-
Subtract
|
|
22486
|
-
if (args.length === 0) return "0";
|
|
22487
|
-
if (args.length === 1) return compile2(args[0]);
|
|
22488
|
-
if (args.length === 2) return `${compile2(args[0])} - ${compile2(args[1])}`;
|
|
22489
|
-
let result = compile2(args[0]);
|
|
22490
|
-
for (let i = 1; i < args.length; i++) {
|
|
22491
|
-
result = `${result} - ${compile2(args[i])}`;
|
|
22492
|
-
}
|
|
22493
|
-
return result;
|
|
22494
|
-
},
|
|
23235
|
+
// No Subtract handler — canonicalizes to Add+Negate before compilation.
|
|
22495
23236
|
Divide: (args, compile2) => {
|
|
22496
23237
|
if (args.length === 0) return "1";
|
|
22497
23238
|
if (args.length === 1) return compile2(args[0]);
|
|
@@ -24156,6 +24897,7 @@ ${code}`;
|
|
|
24156
24897
|
Add: ["_IA.add", 20],
|
|
24157
24898
|
Negate: ["_IA.negate", 20],
|
|
24158
24899
|
Subtract: ["_IA.sub", 20],
|
|
24900
|
+
// Subtract canonicalizes to Add+Negate; kept as fallback
|
|
24159
24901
|
Multiply: ["_IA.mul", 20],
|
|
24160
24902
|
Divide: ["_IA.div", 20],
|
|
24161
24903
|
// Comparisons return BoolInterval
|
|
@@ -24180,17 +24922,7 @@ ${code}`;
|
|
|
24180
24922
|
}
|
|
24181
24923
|
return result;
|
|
24182
24924
|
},
|
|
24183
|
-
Subtract
|
|
24184
|
-
if (args.length === 0) return "_IA.point(0)";
|
|
24185
|
-
if (args.length === 1) return `_IA.negate(${compile2(args[0])})`;
|
|
24186
|
-
if (args.length === 2)
|
|
24187
|
-
return `_IA.sub(${compile2(args[0])}, ${compile2(args[1])})`;
|
|
24188
|
-
let result = compile2(args[0]);
|
|
24189
|
-
for (let i = 1; i < args.length; i++) {
|
|
24190
|
-
result = `_IA.sub(${result}, ${compile2(args[i])})`;
|
|
24191
|
-
}
|
|
24192
|
-
return result;
|
|
24193
|
-
},
|
|
24925
|
+
// No Subtract handler — canonicalizes to Add+Negate before compilation.
|
|
24194
24926
|
Multiply: (args, compile2) => {
|
|
24195
24927
|
if (args.length === 0) return "_IA.point(1)";
|
|
24196
24928
|
if (args.length === 1) return compile2(args[0]);
|
|
@@ -24573,7 +25305,7 @@ ${code}`;
|
|
|
24573
25305
|
}
|
|
24574
25306
|
|
|
24575
25307
|
// src/compile.ts
|
|
24576
|
-
var version = "0.55.
|
|
25308
|
+
var version = "0.55.4";
|
|
24577
25309
|
return __toCommonJS(compile_exports);
|
|
24578
25310
|
})();
|
|
24579
25311
|
/*! Bundled license information:
|