mathr / blog / #

Collatz fractal

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.