Task 2 of 5

The Escape-Time Loop

The Mandelbrot set asks one question at every point c: start z = 0 and repeat z → z² + c — does z stay near the origin forever, or fly off to infinity? Points that stay bounded are in the set; for the rest, the interesting number is how many iterations they survived.

Two facts make this computable. Once |z| > 2, escape is guaranteed — so we can stop watching. And we cap the loop at 100 passes: anything still bounded by then we declare "inside". With z = zr + zi·i, one step is zr² − zi² + cr for the new real part and 2·zr·zi + ci for the new imaginary part.

iterate z² + c and watch: settle in, or fly off — the count is the answer
Goal: iterate z → z² + c up to 100 times, but only while zr² + zi² < 4, and return how many iterations actually ran.

Requirements

Hint 1 — the shape of the loop

gpu.js's WebGL backend needs a fixed loop bound, so instead of breaking out we guard the body:

for (let i = 0; i < 100; i++) {
  if (zr * zr + zi * zi < 4) {
    // …step and count…
  }
}

After escape the guard fails on every remaining pass, so z freezes and count stops.

Hint 2 — don't clobber zr

Both formulas read the old zr, so stash the new real part first:

const zrNext = zr * zr - zi * zi + cr;
zi = 2 * zr * zi + ci;
zr = zrNext;
count = count + 1;

Same idea elsewhere

Data-dependent loops like this are where divergence lives: in CUDA and ROCm, threads of a warp that escape early still march in lockstep with their slowest neighbor, so a tile renders at the speed of its deepest pixel. WGSL and Metal shading language allow exactly this kind of bounded loop in fragment and compute stages.

All tasks in Escape-Time Fractals

  1. Map Pixels to the Complex Plane
  2. The Escape-Time Loop
  3. Paint by Iteration Count
  4. Smooth Out the Bands
  5. Julia Sets: Turn the Dial

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.