Skip to content

Commit 40de8f6

Browse files
committed
feat: enhance fractal compilation with precision strategies and reference orbit computation
- Introduced precision tiers for fractal compilation based on viewport hints, allowing for single, double, and perturbation strategies. - Added functions to select fractal strategies and compute reference orbits for perturbation methods. - Implemented double-single (DS) arithmetic preamble for GLSL and WGSL, including core functions for error-free arithmetic. - Created emulated double-precision fractal preambles for Mandelbrot and Julia in both GLSL and WGSL. - Updated compilation options to include hints for precision-adaptive strategies and added staleness checks for viewport changes. - Enhanced tests for fractal compilation, ensuring correct strategy selection and orbit computation.
1 parent 13666dd commit 40de8f6

5 files changed

Lines changed: 898 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@
22

33
#### Fixed
44

5-
- **LaTeX parsing: interval notation with `\lbrack`/`\lparen`** — parsing
6-
`\lbrack5,7)` or `\left\lbrack5,7\right)` now correctly produces an
7-
`Interval` expression. Previously, when the open delimiter was a LaTeX
8-
command (e.g., `\lbrack`), the parser incorrectly required the close
9-
delimiter to also be a LaTeX command (e.g., `\rparen` instead of `)`),
10-
causing mismatched-delimiter intervals to fail.
5+
- **[#254](https://github.com/cortex-js/compute-engine/issues/254) LaTeX
6+
parsing: interval notation with `\lbrack`/`\lparen`** — parsing `\lbrack5,7)`
7+
or `\left\lbrack5,7\right)` now correctly produces an `Interval` expression.
8+
Previously, when the open delimiter was a LaTeX command (e.g., `\lbrack`), the
9+
parser incorrectly required the close delimiter to also be a LaTeX command
10+
(e.g., `\rparen` instead of `)`), causing mismatched-delimiter intervals to
11+
fail.
12+
- **LaTeX parsing: invalid symbols in `\mathrm{}` and related prefixes**
13+
invalid content inside `\mathrm{}`, `\operatorname{}`, etc. (e.g.,
14+
`\mathrm{=}` or `\mathrm{DavidBowie👨🏻‍🎤}`) now produces the correct
15+
`invalid-symbol` error instead of cascading parse errors. Also fixed
16+
`matchPrefixedSymbol` leaking parser state on failure, and emoji sequences
17+
are now properly recognized inside symbol prefixes (e.g.,
18+
`\operatorname{😎🤏😳🕶🤏}`).
1119

1220
#### Added
1321

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { BigDecimal } from '../../big-decimal';
2+
3+
/**
4+
* Compute a Mandelbrot reference orbit at arbitrary precision.
5+
*
6+
* Iterates z -> z^2 + c starting from z = 0, using BigDecimal arithmetic
7+
* at the specified precision (decimal digits). Stops early if |z|^2 > 256
8+
* (well past the escape radius of 2, giving a margin for perturbation).
9+
*
10+
* @param center - Reference point [re, im] as numbers (converted to BigDecimal)
11+
* @param maxIter - Maximum number of iterations
12+
* @param precision - BigDecimal working precision (decimal digits)
13+
* @returns Float32Array of [re0, im0, re1, im1, ...] orbit points
14+
*/
15+
export function computeReferenceOrbit(
16+
center: [number, number],
17+
maxIter: number,
18+
precision: number
19+
): Float32Array {
20+
const prevPrecision = BigDecimal.precision;
21+
BigDecimal.precision = precision;
22+
23+
try {
24+
const cr = new BigDecimal(center[0]);
25+
const ci = new BigDecimal(center[1]);
26+
let zr = BigDecimal.ZERO;
27+
let zi = BigDecimal.ZERO;
28+
29+
const ESCAPE = new BigDecimal(256);
30+
const points: number[] = [];
31+
32+
for (let i = 0; i < maxIter; i++) {
33+
points.push(zr.toNumber(), zi.toNumber());
34+
35+
// z = z^2 + c
36+
// Truncate to working precision after each multiply to prevent
37+
// exponential significand growth (mul doubles digit count).
38+
const zr2 = zr.mul(zr).toPrecision(precision);
39+
const zi2 = zi.mul(zi).toPrecision(precision);
40+
41+
// |z|^2 > 256? (escape with margin)
42+
const mag2 = zr2.add(zi2);
43+
if (mag2.cmp(ESCAPE) > 0) break;
44+
45+
const new_zi = zr.mul(zi).toPrecision(precision).mul(2).add(ci);
46+
zr = zr2.sub(zi2).add(cr);
47+
zi = new_zi;
48+
}
49+
50+
return new Float32Array(points);
51+
} finally {
52+
BigDecimal.precision = prevPrecision;
53+
}
54+
}

0 commit comments

Comments
 (0)