Domain Colouring

Fractals

Domain colouring turns a complex function into a picture. This one is a rational map, (z²−1)/(z²+c), and where its denominator hits zero it has poles — the divide there yields infinity or NaN, which the code catches with the test x != x to paint the singularities. Software floating point on a chip with no FPU; the picture develops one row at a time, then shimmers. Runs on its own; no joypad needed. Written in C and compiled with the llvm-mos-based 65816 toolchain (+mos-a16, 16-bit accumulator mode).

loading core…

Self-running demo — the field develops a row at a time, then the palette shimmers.

Click the screen to focus, then watch. Tab away and it pauses.

What it is

A pole of a function is a point where it blows up to infinity. Numerically, that's a divide by zero — and the result is either infinity or, if the numerator is zero too, "not a number":

f(z) = (z*z - 1) / (z*z + c);      // complex rational map
// at a pole z*z + c == 0, so we divide by zero:
inv = 1.0f / 0.0f;                  // = +Inf
fr  = numerator * inv;              // Inf, or 0*Inf = NaN
if (fr != fr) colour = POLE;        // isnan: only NaN != itself

NaN has a strange property: it is not equal to anything, including itself. So x != x is the standard test for it, and it compiles to an unordered comparison — a different machine operation than the ordered less-than every other float demo used. The picture stays bit-exact across every codegen mode.

Compiler stress-test

ItemWhat it exercises
NaN / unordered comparesA pole is where the function divides by zero, producing infinity or NaN. Detecting NaN is the test x != x — true only for NaN — which the compiler lowers to an "unordered" floating-point comparison. Every earlier float demo used only ordered less-than; this is a different set of comparison routines.
fold the outcome, not the bitsA NaN's exact bit pattern is not fully pinned down by the standard, so the self-check never hashes raw float bits — it hashes the colour chosen (pole or not), which is a yes/no answer identical on the host and the console. That keeps the test about the comparison, not the payload.
soft float, one op per lineThe 65816 has no floating-point unit, so every add, multiply and reciprocal is a library call — and each is written on its own line so the compiler can't fuse a multiply-add, keeping the result bit-identical to the host.
slow on purposeSoftware floating point is heavy here (~150k cycles per cell), so the picture is a coarse 8x8 grid painted one row at a time, live on the console — proving the soft-float actually runs on hardware — then the palette cycles for a shimmer.

Written in C with the llvm-mos 65816 toolchain and verified against bsnes-jg (and MAME where the SPC700 IPL is present). Hit Verify fidelity to reproduce the build gate's WRAM assert (gate CRC 0xF3FD — a fold of pole/no-pole colour outcomes, including a guaranteed NaN pole) live in this tab. No far pointers — the same source passes every way: host == default == +mos-a16 == +mos-xy16 == bsnes-jg, -verify clean.