fp64 Newton fractal
Newton’s method for z³ = 1, colour = which cube root a pixel falls into.
// ═══ typeshade example — fp64 Newton fractal (z³ = 1) ═══//// The fp64 family's DIVISION showcase: Newton's method z ← z − (z³−1)/(3z²)// runs a full complex division every iteration, and the f64 side does it with// df64_div (the long-division EFT) — the one emulated op an add/mul-only demo// never touches. The camera sits on a basin boundary of the three cube roots;// the boundary is the Julia set of the Newton map and has the Wada property// (every boundary point touches ALL THREE basins), so any zoom depth shows the// three colours interleaved — CPU-verified to 50+ distinct (root, steps) cells// per 48² window down to a 1e-11 span. The plain-f32 left half collapses once// the span drops under one ulp of the center (~1e-7).//// The `_fp64` guard uniform is auto-injected by the lowering; the render// harnesses bind it to 1.0f by probing the program for the Fp64Guard block.
import { fn, module, vec3, vec4, f32, f64, pow, mix, toF32, toF64, f32T, vec2fT, vec2f64T, If, Loop, Var, Let, u32, uniformStruct,} from '../src/index.js';import { VsOut, vs } from './_fullscreen.js';import type { ShaderExample } from './_shared.js';
// A boundary point between the basins of 1 and e^{2πi/3} (CPU bisection to// ~1e-19, so the window straddles the boundary at every reachable zoom).const CENTER_X = 0.17616732990860245;const CENTER_Y = 0.7111381151066305;const ITER = 48;// Cube roots of unity (exactly representable enough for f32 CLASSIFICATION —// the roots are attracting, so classification is precision-insensitive).const R_IM = 0.8660254037844386; // √3/2
const U = uniformStruct( 'Uniforms', { group: 0, binding: 0, as: 'u' }, { center: vec2f64T, // one DF64Vec2 slot — host packs [hi.x, hi.y, lo.x, lo.y] resolution: vec2fT, zoom_exp: f32T, // view span = 10^-zoom_exp complex units fp64: f32T, // toggle: 1 = split-screen f32 | f64 (canonical), 0 = all-f32 },);
const fsNewton = fn( 'fs_newton', { vo: VsOut }, (p) => { const span = Let(pow(f32(10.0), U.field.zoom_exp.neg())); const half = Let(p.vo.uv.x.mul(2.0)); const sx = Let(half.sub(p.vo.uv.x.lt(0.5).select(0.0, 1.0))); const dx = Let(sx.sub(0.5).mul(span)); const dy = Let( p.vo.uv.y.sub(0.5).mul(span).mul(U.field.resolution.y.div(U.field.resolution.x).mul(2.0)), );
// Iterate to convergence; hand the FINAL z (narrowed) + step count out. const fx = Var(f32(0)); // final Re z const fy = Var(f32(0)); // final Im z const it = Var(f32(0)); // steps until the update went sub-epsilon If(p.vo.uv.x.lt(0.5).or(U.field.fp64.lt(0.5)), () => { // f32 twin — z₀ from the narrowed center: at deep zoom every pixel // starts at the SAME quantized point and the basins collapse flat. const zx = Var(toF32(U.field.center.x).add(dx)); const zy = Var(toF32(U.field.center.y).add(dy)); Loop( u32(0), (j) => j.lt(u32(ITER)), () => { const z2x = Let(zx.mul(zx).sub(zy.mul(zy))); const z2y = Let(zx.mul(zy).mul(2.0)); const nx = Let(z2x.mul(zx).sub(z2y.mul(zy)).sub(1.0)); // Re(z³−1) const ny = Let(z2x.mul(zy).add(z2y.mul(zx))); // Im(z³−1) const gx = Let(z2x.mul(3.0)); // Re(3z²) const gy = Let(z2y.mul(3.0)); const inv = Let(f32(1.0).div(gx.mul(gx).add(gy.mul(gy)))); const qx = Let(nx.mul(gx).add(ny.mul(gy)).mul(inv)); const qy = Let(ny.mul(gx).sub(nx.mul(gy)).mul(inv)); zx.assign(zx.sub(qx)); zy.assign(zy.sub(qy)); If(qx.mul(qx).add(qy.mul(qy)).gt(1e-14), () => { it.assign(it.add(1.0)); }); }, ); fx.assign(zx); fy.assign(zy); }).else(() => { // f64 — the SAME Newton step; the quotient runs through df64_div. const zx = Var(U.field.center.x.add(toF64(dx))); const zy = Var(U.field.center.y.add(toF64(dy))); Loop( u32(0), (j) => j.lt(u32(ITER)), () => { const z2x = Let(zx.mul(zx).sub(zy.mul(zy))); const z2y = Let(zx.mul(zy).mul(2.0)); const nx = Let(z2x.mul(zx).sub(z2y.mul(zy)).sub(1.0)); const ny = Let(z2x.mul(zy).add(z2y.mul(zx))); const gx = Let(z2x.mul(3.0)); const gy = Let(z2y.mul(3.0)); const inv = Let(f64(1.0).div(gx.mul(gx).add(gy.mul(gy)))); const qx = Let(nx.mul(gx).add(ny.mul(gy)).mul(inv)); const qy = Let(ny.mul(gx).sub(nx.mul(gy)).mul(inv)); zx.assign(zx.sub(qx)); zy.assign(zy.sub(qy)); If(toF32(qx.mul(qx).add(qy.mul(qy))).gt(1e-14), () => { it.assign(it.add(1.0)); }); }, ); fx.assign(toF32(zx)); fy.assign(toF32(zy)); });
// Classify the landing root (attracting fixed points — f32 suffices) and // shade by convergence speed: boundary-hugging pixels stay near-black. const d0 = Let(fx.sub(1.0).mul(fx.sub(1.0)).add(fy.mul(fy))); const d1 = Let( fx .add(0.5) .mul(fx.add(0.5)) .add(fy.sub(R_IM).mul(fy.sub(R_IM))), ); const d2 = Let( fx .add(0.5) .mul(fx.add(0.5)) .add(fy.add(R_IM).mul(fy.add(R_IM))), ); const c0 = vec3(0.91, 0.34, 0.22); // root 1 — vermilion const c1 = vec3(0.2, 0.66, 0.88); // root e^{2πi/3} — sky const c2 = vec3(0.98, 0.78, 0.22); // root e^{−2πi/3} — gold const base = Let(d0.le(d1).and(d0.le(d2)).select(c0, d1.le(d2).select(c1, c2))); const speed = Let(f32(1).sub(it.div(ITER))); const rgb = base.mul(mix(f32(0.25), f32(1.0), speed)); return vec4(rgb, f32(1)); }, { stage: 'fragment', retAttr: '@location(0)' },);
// `_fp64` guard lands at (group 0, binding 1) automatically.const fp64NewtonModule = module({ funcs: [vs, fsNewton], uses: [U, VsOut],});
export const fp64Newton: ShaderExample = { id: 'fp64-newton', title: 'fp64 Newton fractal', blurb: 'Newton’s method for z³ = 1, colour = which cube root a pixel falls into — a full complex DIVISION per step, running through df64_div on the f64 side. The basin boundary has the Wada property (all three colours touch at every boundary point), so the interleaving persists to any depth: the f32 left half collapses flat past a ~1e-7 span while the emulated-double right half keeps dividing cleanly. Drag to pan, wheel to zoom, flip the fp64 toggle to compare.', category: 'generic', file: 'fp64-newton.ts', module: fp64NewtonModule, renderable: true, splitLabels: ['f32', 'f64 (emulated)'], controls: { center: { kind: 'pan2d', value: [CENTER_X, CENTER_Y], zoomExpField: 'zoom_exp', unitsPerWidth: 2, }, resolution: { kind: 'resolution' }, zoom_exp: { kind: 'slider', label: 'Zoom 10^-x', min: 1, max: 13, step: 0.05, value: 4, wheel: true, }, fp64: { kind: 'toggle', label: 'fp64 emulation', value: true }, },};struct Uniforms { @align(16) center: DF64Vec2, resolution: vec2<f32>, zoom_exp: f32, fp64: f32,}
struct VsOut { @builtin(position) pos: vec4<f32>, @location(0) uv: vec2<f32>,}
struct DF64Vec2 { hi: vec2<f32>, lo: vec2<f32>,}
@group(0) @binding(0) var<uniform> u: Uniforms;@group(0) @binding(1) var _fp64: texture_2d<f32>;
@vertexfn vs(@builtin(vertex_index) vi: u32) -> VsOut { let _cse0 = ((f32((vi & 1u)) * 4.0) - 1.0); let _cse1 = ((f32((vi >> 1u)) * 4.0) - 1.0); return VsOut(vec4<f32>(_cse0, _cse1, 0.0, 1.0), vec2<f32>(((_cse0 * 0.5) + 0.5), ((_cse1 * 0.5) + 0.5)));}
@fragmentfn fs_newton(vo: VsOut) -> @location(0) vec4<f32> { let _fp64_g = textureLoad(_fp64, vec2<i32>(0, 0), 0).x; let _cse5 = bitcast<f32>(bitcast<u32>(0.0)); let _licm0 = vec2<f32>(_cse5, _cse5); let _v0 = pow(10.0, (-u.zoom_exp)); let _v1 = (vo.uv.x * 2.0); let _cse0 = (vo.uv.x < 0.5); let _v2 = (_v1 - select(1.0, 0.0, _cse0)); let _v3 = ((_v2 - 0.5) * _v0); let _v4 = (((vo.uv.y - 0.5) * _v0) * ((u.resolution.y / u.resolution.x) * 2.0)); var _v5: f32 = 0.0; var _v6: f32 = 0.0; var _v7: f32 = 0.0; let _cse1 = vec2<f32>(u.center.hi.x, u.center.lo.x); let _cse2 = vec2<f32>(u.center.hi.y, u.center.lo.y); if ((_cse0 || (u.fp64 < 0.5))) { var _v8: f32 = (df64_narrow(_cse1) + _v3); var _v9: f32 = (df64_narrow(_cse2) + _v4); for (var _v10: u32 = 0u; (_v10 < 48u); _v10 = (_v10 + 1u)) { let _v11 = ((_v8 * _v8) - (_v9 * _v9)); let _v12 = ((_v8 * _v9) * 2.0); let _v13 = (((_v11 * _v8) - (_v12 * _v9)) - 1.0); let _v14 = ((_v11 * _v9) + (_v12 * _v8)); let _v15 = (_v11 * 3.0); let _v16 = (_v12 * 3.0); let _v17 = (1.0 / ((_v15 * _v15) + (_v16 * _v16))); let _v18 = (((_v13 * _v15) + (_v14 * _v16)) * _v17); let _v19 = (((_v14 * _v15) - (_v13 * _v16)) * _v17); _v8 = (_v8 - _v18); _v9 = (_v9 - _v19); if ((((_v18 * _v18) + (_v19 * _v19)) > 1e-14)) { _v7 = (_v7 + 1.0); } } _v5 = _v8; _v6 = _v9; } else { var _v20: vec2<f32> = df64_add(_cse1, vec2<f32>(_v3, 0.0), _fp64_g); var _v21: vec2<f32> = df64_add(_cse2, vec2<f32>(_v4, 0.0), _fp64_g); let _cse3 = df64_add(vec2<f32>(1.0, 0.0), _licm0, _fp64_g); let _cse4 = vec2<f32>(3.0, 0.0); for (var _v22: u32 = 0u; (_v22 < 48u); _v22 = (_v22 + 1u)) { let _v23 = df64_sub(df64_sqr(_v20, _fp64_g), df64_sqr(_v21, _fp64_g), _fp64_g); let _v24 = (df64_mul(_v20, _v21, _fp64_g) * 2.0); let _v25 = df64_sub(df64_sub(df64_mul(_v23, _v20, _fp64_g), df64_mul(_v24, _v21, _fp64_g), _fp64_g), _cse3, _fp64_g); let _v26 = df64_add(df64_mul(_v23, _v21, _fp64_g), df64_mul(_v24, _v20, _fp64_g), _fp64_g); let _v27 = df64_mul(_v23, _cse4, _fp64_g); let _v28 = df64_mul(_v24, _cse4, _fp64_g); let _v29 = df64_div(_cse3, df64_add(df64_sqr(_v27, _fp64_g), df64_sqr(_v28, _fp64_g), _fp64_g), _fp64_g); let _v30 = df64_mul(df64_add(df64_mul(_v25, _v27, _fp64_g), df64_mul(_v26, _v28, _fp64_g), _fp64_g), _v29, _fp64_g); let _v31 = df64_mul(df64_sub(df64_mul(_v26, _v27, _fp64_g), df64_mul(_v25, _v28, _fp64_g), _fp64_g), _v29, _fp64_g); _v20 = df64_sub(df64_add(_v20, _licm0, _fp64_g), df64_add(_v30, _licm0, _fp64_g), _fp64_g); _v21 = df64_sub(df64_add(_v21, _licm0, _fp64_g), df64_add(_v31, _licm0, _fp64_g), _fp64_g); if ((df64_narrow(df64_add(df64_sqr(_v30, _fp64_g), df64_sqr(_v31, _fp64_g), _fp64_g)) > 1e-14)) { _v7 = (_v7 + 1.0); } } _v5 = df64_narrow(_v20); _v6 = df64_narrow(_v21); } let _lc0 = (_v5 - 1.0); let _v32 = ((_lc0 * _lc0) + (_v6 * _v6)); let _gv0 = (_v5 + 0.5); let _lc2 = (_v6 - 0.8660254037844386); let _gv1 = (_gv0 * _gv0); let _v33 = (_gv1 + (_lc2 * _lc2)); let _lc4 = (_v6 + 0.8660254037844386); let _v34 = (_gv1 + (_lc4 * _lc4)); let _v35 = select(select(vec3<f32>(0.98, 0.78, 0.22), vec3<f32>(0.2, 0.66, 0.88), (_v33 <= _v34)), vec3<f32>(0.91, 0.34, 0.22), ((_v32 <= _v33) && (_v32 <= _v34))); let _v36 = (1.0 - (_v7 / 48.0)); return vec4<f32>((_v35 * mix(0.25, 1.0, _v36)), 1.0);}
fn df64_twoSum(a: f32, b: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = (a + b); let _v1 = (((_v0 * _fp64_g) - a) * _fp64_g); let _v2 = (((a - ((_v0 - _v1) * _fp64_g)) * _fp64_g) + (b - _v1)); return vec2<f32>(_v0, _v2);}
fn df64_quickTwoSum(a: f32, b: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = ((a + b) * _fp64_g); let _v1 = (b - ((_v0 - a) * _fp64_g)); return vec2<f32>(_v0, _v1);}
fn df64_split(a: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = (a * (_fp64_g * 4097.0)); let _v1 = ((_v0 * _fp64_g) - (_v0 - a)); let _v2 = ((a * _fp64_g) - _v1); return vec2<f32>(_v1, _v2);}
fn df64_twoProd(a: f32, b: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = (a * b); let _v1 = df64_split(a, _fp64_g); let _v2 = df64_split(b, _fp64_g); let _v3 = (((((_v1.x * _v2.x) - _v0) + (_v1.x * _v2.y)) + (_v1.y * _v2.x)) + (_v1.y * _v2.y)); return vec2<f32>(_v0, _v3);}
fn df64_twoSqr(a: f32, _fp64_g: f32) -> vec2<f32> { let _v0 = (a * a); let _v1 = df64_split(a, _fp64_g); let _v2 = (((((_v1.x * _v1.x) - _v0) * _fp64_g) + (((_v1.x * _v1.y) * 2.0) * _fp64_g)) + ((_v1.y * _v1.y) * _fp64_g)); return vec2<f32>(_v0, _v2);}
fn df64_add(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { var _v0: vec2<f32> = df64_twoSum(a.x, b.x, _fp64_g); let _v1 = df64_twoSum(a.y, b.y, _fp64_g); _v0.y = (_v0.y + _v1.x); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + _v1.y); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); return _v0;}
fn df64_sub(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { return df64_add(a, (-b), _fp64_g);}
fn df64_mul(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { var _v0: vec2<f32> = df64_twoProd(a.x, b.x, _fp64_g); _v0.y = (_v0.y + (a.x * b.y)); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + (a.y * b.x)); return df64_quickTwoSum(_v0.x, _v0.y, _fp64_g);}
fn df64_sqr(a: vec2<f32>, _fp64_g: f32) -> vec2<f32> { var _v0: vec2<f32> = df64_twoSqr(a.x, _fp64_g); _v0.y = (_v0.y + ((a.x * a.y) * 2.0)); return df64_quickTwoSum(_v0.x, _v0.y, _fp64_g);}
fn df64_div(a: vec2<f32>, b: vec2<f32>, _fp64_g: f32) -> vec2<f32> { let _v0 = (_fp64_g / b.x); let _v1 = (a * _v0); let _v2 = df64_sub(a, df64_mul(b, _v1, _fp64_g), _fp64_g).x; let _v3 = df64_twoProd(_v0, _v2, _fp64_g); return df64_add(_v1, _v3, _fp64_g);}
fn df64_narrow(a: vec2<f32>) -> f32 { return (a.x + a.y);}#version 300 esprecision highp float;precision highp int;
out vec2 uv;
void main() { uint vi = uint(gl_VertexID); float _cse0 = ((float((vi & 1u)) * 4.0) - 1.0); float _cse1 = ((float((vi >> 1u)) * 4.0) - 1.0); gl_Position = vec4(_cse0, _cse1, 0.0, 1.0); uv = vec2(((_cse0 * 0.5) + 0.5), ((_cse1 * 0.5) + 0.5));}#version 300 esprecision highp float;precision highp int;
struct DF64Vec2 { vec2 hi; vec2 lo;};layout(std140) uniform Uniforms { DF64Vec2 center; vec2 resolution; float zoom_exp; float fp64;} u;
uniform highp sampler2D _fp64;vec2 df64_twoSum(float a, float b, float _fp64_g) { float _v0 = (a + b); float _v1 = (((_v0 * _fp64_g) - a) * _fp64_g); float _v2 = (((a - ((_v0 - _v1) * _fp64_g)) * _fp64_g) + (b - _v1)); return vec2(_v0, _v2);}
vec2 df64_quickTwoSum(float a, float b, float _fp64_g) { float _v0 = ((a + b) * _fp64_g); float _v1 = (b - ((_v0 - a) * _fp64_g)); return vec2(_v0, _v1);}
vec2 df64_split(float a, float _fp64_g) { float _v0 = (a * (_fp64_g * 4097.0)); float _v1 = ((_v0 * _fp64_g) - (_v0 - a)); float _v2 = ((a * _fp64_g) - _v1); return vec2(_v1, _v2);}
vec2 df64_twoProd(float a, float b, float _fp64_g) { float _v0 = (a * b); vec2 _v1 = df64_split(a, _fp64_g); vec2 _v2 = df64_split(b, _fp64_g); float _v3 = (((((_v1.x * _v2.x) - _v0) + (_v1.x * _v2.y)) + (_v1.y * _v2.x)) + (_v1.y * _v2.y)); return vec2(_v0, _v3);}
vec2 df64_twoSqr(float a, float _fp64_g) { float _v0 = (a * a); vec2 _v1 = df64_split(a, _fp64_g); float _v2 = (((((_v1.x * _v1.x) - _v0) * _fp64_g) + (((_v1.x * _v1.y) * 2.0) * _fp64_g)) + ((_v1.y * _v1.y) * _fp64_g)); return vec2(_v0, _v2);}
vec2 df64_add(vec2 a, vec2 b, float _fp64_g) { vec2 _v0 = df64_twoSum(a.x, b.x, _fp64_g); vec2 _v1 = df64_twoSum(a.y, b.y, _fp64_g); _v0.y = (_v0.y + _v1.x); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + _v1.y); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); return _v0;}
vec2 df64_sub(vec2 a, vec2 b, float _fp64_g) { return df64_add(a, (-b), _fp64_g);}
vec2 df64_mul(vec2 a, vec2 b, float _fp64_g) { vec2 _v0 = df64_twoProd(a.x, b.x, _fp64_g); _v0.y = (_v0.y + (a.x * b.y)); _v0 = df64_quickTwoSum(_v0.x, _v0.y, _fp64_g); _v0.y = (_v0.y + (a.y * b.x)); return df64_quickTwoSum(_v0.x, _v0.y, _fp64_g);}
vec2 df64_sqr(vec2 a, float _fp64_g) { vec2 _v0 = df64_twoSqr(a.x, _fp64_g); _v0.y = (_v0.y + ((a.x * a.y) * 2.0)); return df64_quickTwoSum(_v0.x, _v0.y, _fp64_g);}
vec2 df64_div(vec2 a, vec2 b, float _fp64_g) { float _v0 = (_fp64_g / b.x); vec2 _v1 = (a * _v0); float _v2 = df64_sub(a, df64_mul(b, _v1, _fp64_g), _fp64_g).x; vec2 _v3 = df64_twoProd(_v0, _v2, _fp64_g); return df64_add(_v1, _v3, _fp64_g);}
float df64_narrow(vec2 a) { return (a.x + a.y);}in vec2 uv;layout(location = 0) out vec4 _ret;
void main() { float _fp64_g = texelFetch(_fp64, ivec2(0, 0), 0).x; float _cse5 = uintBitsToFloat(floatBitsToUint(0.0)); vec2 _licm0 = vec2(_cse5, _cse5); float _v0 = pow(10.0, (-u.zoom_exp)); float _v1 = (uv.x * 2.0); bool _cse0 = (uv.x < 0.5); float _v2 = (_v1 - (_cse0 ? 0.0 : 1.0)); float _v3 = ((_v2 - 0.5) * _v0); float _v4 = (((uv.y - 0.5) * _v0) * ((u.resolution.y / u.resolution.x) * 2.0)); float _v5 = 0.0; float _v6 = 0.0; float _v7 = 0.0; vec2 _cse1 = vec2(u.center.hi.x, u.center.lo.x); vec2 _cse2 = vec2(u.center.hi.y, u.center.lo.y); if ((_cse0 || (u.fp64 < 0.5))) { float _v8 = (df64_narrow(_cse1) + _v3); float _v9 = (df64_narrow(_cse2) + _v4); for (uint _v10 = 0u; (_v10 < 48u); _v10 = (_v10 + 1u)) { float _v11 = ((_v8 * _v8) - (_v9 * _v9)); float _v12 = ((_v8 * _v9) * 2.0); float _v13 = (((_v11 * _v8) - (_v12 * _v9)) - 1.0); float _v14 = ((_v11 * _v9) + (_v12 * _v8)); float _v15 = (_v11 * 3.0); float _v16 = (_v12 * 3.0); float _v17 = (1.0 / ((_v15 * _v15) + (_v16 * _v16))); float _v18 = (((_v13 * _v15) + (_v14 * _v16)) * _v17); float _v19 = (((_v14 * _v15) - (_v13 * _v16)) * _v17); _v8 = (_v8 - _v18); _v9 = (_v9 - _v19); if ((((_v18 * _v18) + (_v19 * _v19)) > 1e-14)) { _v7 = (_v7 + 1.0); } } _v5 = _v8; _v6 = _v9; } else { vec2 _v20 = df64_add(_cse1, vec2(_v3, 0.0), _fp64_g); vec2 _v21 = df64_add(_cse2, vec2(_v4, 0.0), _fp64_g); vec2 _cse3 = df64_add(vec2(1.0, 0.0), _licm0, _fp64_g); vec2 _cse4 = vec2(3.0, 0.0); for (uint _v22 = 0u; (_v22 < 48u); _v22 = (_v22 + 1u)) { vec2 _v23 = df64_sub(df64_sqr(_v20, _fp64_g), df64_sqr(_v21, _fp64_g), _fp64_g); vec2 _v24 = (df64_mul(_v20, _v21, _fp64_g) * 2.0); vec2 _v25 = df64_sub(df64_sub(df64_mul(_v23, _v20, _fp64_g), df64_mul(_v24, _v21, _fp64_g), _fp64_g), _cse3, _fp64_g); vec2 _v26 = df64_add(df64_mul(_v23, _v21, _fp64_g), df64_mul(_v24, _v20, _fp64_g), _fp64_g); vec2 _v27 = df64_mul(_v23, _cse4, _fp64_g); vec2 _v28 = df64_mul(_v24, _cse4, _fp64_g); vec2 _v29 = df64_div(_cse3, df64_add(df64_sqr(_v27, _fp64_g), df64_sqr(_v28, _fp64_g), _fp64_g), _fp64_g); vec2 _v30 = df64_mul(df64_add(df64_mul(_v25, _v27, _fp64_g), df64_mul(_v26, _v28, _fp64_g), _fp64_g), _v29, _fp64_g); vec2 _v31 = df64_mul(df64_sub(df64_mul(_v26, _v27, _fp64_g), df64_mul(_v25, _v28, _fp64_g), _fp64_g), _v29, _fp64_g); _v20 = df64_sub(df64_add(_v20, _licm0, _fp64_g), df64_add(_v30, _licm0, _fp64_g), _fp64_g); _v21 = df64_sub(df64_add(_v21, _licm0, _fp64_g), df64_add(_v31, _licm0, _fp64_g), _fp64_g); if ((df64_narrow(df64_add(df64_sqr(_v30, _fp64_g), df64_sqr(_v31, _fp64_g), _fp64_g)) > 1e-14)) { _v7 = (_v7 + 1.0); } } _v5 = df64_narrow(_v20); _v6 = df64_narrow(_v21); } float _lc0 = (_v5 - 1.0); float _v32 = ((_lc0 * _lc0) + (_v6 * _v6)); float _gv0 = (_v5 + 0.5); float _lc2 = (_v6 - 0.8660254037844386); float _gv1 = (_gv0 * _gv0); float _v33 = (_gv1 + (_lc2 * _lc2)); float _lc4 = (_v6 + 0.8660254037844386); float _v34 = (_gv1 + (_lc4 * _lc4)); vec3 _v35 = (((_v32 <= _v33) && (_v32 <= _v34)) ? vec3(0.91, 0.34, 0.22) : ((_v33 <= _v34) ? vec3(0.2, 0.66, 0.88) : vec3(0.98, 0.78, 0.22))); float _v36 = (1.0 - (_v7 / 48.0)); _ret = vec4((_v35 * mix(0.25, 1.0, _v36)), 1.0);}This example is steered by a control the page has no value for, so the page shows no picture.
The WGSL and GLSL tabs are the compiler's own output at commit 26de7be8, read from the goldens its emit suite bakes (emit-goldens.test.ts).
This example is written against the fn() builder API, which the editor in the Playground does not take.