Collatz fractal
The Collatz conjecture involves a piecewise integer recurrence:
\[ c(n) = \left\{ \begin{array}{ll} n/2 & n\text{ even} \\ 3n+1 & n\text{ odd} \end{array} \right. \]
The unsolved conjecture is that iterating \(c\) starting with a positive integer will always reach \(1\).
The integer function \(c\) can be extended to real and complex numbers like this:
\[ c(z) = \frac{1}{4}(1 + 4z - (1 + 2z)\cos(\pi z)) \]
and iterating this function for each pixel of an image gives an escape time fractal with escape condition \(|\Im(z)| \to \infty\). I implemented this in Fragmentarium, also calculating the running derivative for distance estimate colouring:
#include "Progressive2D.frag" float pi = 3.141592653; // hyperbolic cosine float cosh(float x) { return (exp(x) + exp(-x))/2.0; } // hyperbolic sine float sinh(float x) { return (exp(x) - exp(-x))/2.0; } // complex multiplication vec2 cmul(vec2 a, vec2 b) { return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } // complex cosine vec2 ccos(vec2 a) { return vec2(cos(a.x) * cosh(a.y), -sin(a.x) * sinh(a.y)); } // complex sine vec2 csin(vec2 a) { return vec2(sin(a.x) * cosh(a.y), cos(a.x) * sinh(a.y)); } vec3 color(vec2 z0) { // initialize vec2 z = z0; vec2 dz = vec2(1.0, 0.0); int n = 0; // iterate for (int i = 1; i < 2048; ++i) { // bail out if z gets too big if (abs(z.y) > 4.0) { n = i; break; } // do one step of generalized Collatz function dz = cmul(dz, (vec2(4.0,0.0) - cmul(vec2(1.0, 0.0) + 2.0 * z, pi * -csin(pi * z)) - 2.0 * ccos(pi * z)) / 4.0); z = (vec2(1.0,0.0) + 4.0 * z - cmul(vec2(1.0,0.0) + 2.0 * z, ccos(pi * z))) / 4.0; } // colour pixel according to distance estimate float de = length(z) * log(length(z)) / length(dz); if (n == 0) { return vec3(1.0, 0.7, 0.0); } return vec3(tanh(clamp(de / length(dFdx(z0)), 0.0, 4.0))); }
You can download the collatz.frag.