Skip to content

Complex Plot

Domain-colouring of a complex-valued expression over the complex plane, rendered by <notatio-complex-plot> — Wolfram's ComplexPlot — one WebGPU invocation per pixel. Hue is the argument, brightness a compressed magnitude, poles blow out white and zeros go black.

Unlike the other plot elements, which sample a real-valued function, this one carries the whole complex value: the phase is the picture. It works on any expression the complex GPU lowering can emit — the elementary operations, and the analytic special functions from @enumeratio/analytic.

Any expression

A rational function

The three cube roots of unity are the black zeros; the poles at ±i are the points every hue spirals into. Reading the colour wheel around a point gives its order, and the direction of the winding says zero or pole.

source
<ClientOnly>
  <notatio-complex-plot value="(z^3 - 1)/(z^2 + 1)" extent="4" height="380" />
</ClientOnly>

An essential singularity

Every hue, infinitely often, in any neighbourhood of the origin — Picard's theorem as a picture.

source
<ClientOnly>
  <notatio-complex-plot value="Exp(1/z)" extent="1.2" height="380" />
</ClientOnly>

Special functions

The Riemann zeta function

The pole at z = 1, the trivial zeros marching left along the real axis, and the critical strip's zeros stacked up the imaginary axis.

source
<ClientOnly>
  <notatio-complex-plot value="Zeta(z)" extent="40" height="380" />
</ClientOnly>

A disk of convergence

mask dims everything outside that radius — for a series whose disk of convergence is part of the story. The polylogarithm's Lerch series reaches |z| < 1 only, so the lit disk is exactly its domain.

source
<ClientOnly>
  <notatio-complex-plot value="PolyLog(2, z)" mask="1" height="380" />
</ClientOnly>

Every constant an axis

Because the compiled pipeline is keyed on the expression's shape, moving a constant costs one small uniform upload rather than a shader rebuild. So any literal can become a Manipulate axis and still hold frame rate.

The polylogarithm's order

Sweep the order and watch the disk go from the wound-up spirals of a small real part to the near-linear ramp where the first term dominates.

source
<ClientOnly>
  <notatio-manipulate params="{s, 0.25, 6, 0.05}" fps>
    <notatio-complex-plot value="PolyLog(_s, z)" mask="1" height="380" />
  </notatio-manipulate>
</ClientOnly>

Two axes at once

Framing is manipulable too — center takes the notatio list form [_c, 0], and extent a bare wildcard. The polygamma's poles sit at 0, −1, −2, …, of order m+1 — raise the order and the hue winds more times around each.

source
<ClientOnly>
  <notatio-manipulate params="{m, 1, 12, 1}, {c, -4, 1, 0.1}">
    <notatio-complex-plot value="PolyGamma(_m, z)" center="[_c, 0]" extent="6" height="380" />
  </notatio-manipulate>
</ClientOnly>

Notes

  • WebGPU only. Where it is unavailable the element says so rather than falling back — a CPU sampler at this resolution is seconds per frame, not milliseconds.
  • f32 on the GPU. Good for ~5–6 digits. The CPU kernels in @enumeratio/analytic stay the source of truth; a portrait is for seeing shape, not for reading values off.
  • Expressions that do not lower — an unsupported head, or a free symbol other than the plot variable — are reported instead of silently drawn wrong.