Number theory in the complex plane

Gaussian Integers

Whole numbers, extended into the complex plane. They form a lattice you can see, an arithmetic you can do, and — remarkably — a world with its own primes and its own unique factorization.

The ring of Gaussian integers
\[ \mathbb{Z}[i]=\{\,a+bi \;:\; a,b\in\mathbb{Z}\,\},\qquad i^2=-1. \]

Introduced by Carl Friedrich Gauss in 1832 while studying biquadratic reciprocity, \(\mathbb{Z}[i]\) turns hard questions about ordinary integers — like "which numbers are a sum of two squares?" — into easy questions about factorization. Below: the full theory with proofs, verified GNU Octave code, and four things to play with.

01What the Gaussian Integers Are

A Gaussian integer is a complex number whose real and imaginary parts are both ordinary integers: \(a+bi\) with \(a,b\in\mathbb{Z}\). Plotted in the complex plane, they are exactly the corners of the unit grid — a perfect square lattice.

They are closed under addition, subtraction, and multiplication, so they form a commutative ring with identity \(1\), written \(\mathbb{Z}[i]\). Addition is componentwise; multiplication uses \(i^2=-1\):

\[ (a+bi)+(c+di)=(a+c)+(b+d)i, \] \[ (a+bi)(c+di)=(ac-bd)+(ad+bc)i. \]

There are no zero divisors (a product is zero only if a factor is), so \(\mathbb{Z}[i]\) is an integral domain. Geometrically, multiplication is the complex-plane move you may know: lengths multiply and angles add. The widget below lets you feel that — drag the two points and switch between sum and product.

Lattice arithmetic · drag z and w
z
w
z + w
norm check

In product mode, notice the result's angle is the sum of the two angles and its norm is the product of the norms.

02The Norm — the Master Tool

Almost everything about \(\mathbb{Z}[i]\) is controlled by a single function, the norm, which sends a Gaussian integer to an ordinary non-negative integer:

\[ N(a+bi)=a^2+b^2=|a+bi|^2=(a+bi)\overline{(a+bi)}. \]

It is the squared distance from the origin. Its superpower is that it is multiplicative — it turns multiplication in \(\mathbb{Z}[i]\) into multiplication in \(\mathbb{Z}\), letting us drag hard problems down to familiar integer arithmetic.

Proof — the norm is multiplicative

Via conjugates The conjugate satisfies \(\overline{zw}=\bar z\,\bar w\). So

\[ N(zw)=zw\,\overline{zw}=z\bar z\cdot w\bar w=N(z)\,N(w). \]

Spelled out with \(z=a+bi,\ w=c+di\), this is the Brahmagupta–Fibonacci identity:

\[ (a^2+b^2)(c^2+d^2)=(ac-bd)^2+(ad+bc)^2. \]

The right side is exactly \(N\big((ac-bd)+(ad+bc)i\big)=N(zw)\).

Why this matters

If \(z\) divides \(w\) in \(\mathbb{Z}[i]\), then \(N(z)\) divides \(N(w)\) in \(\mathbb{Z}\). A divisibility question about complex lattice points becomes a divisibility question about ordinary integers — which we know how to answer.

03Conjugates, Units & Associates

The conjugate \(\overline{a+bi}=a-bi\) is the mirror image across the real axis, and \(z\bar z=N(z)\). A unit is a Gaussian integer with a multiplicative inverse inside \(\mathbb{Z}[i]\). In the ordinary integers the only units are \(\pm1\); here there are exactly four.

Proof — the units are exactly \(1,\,-1,\,i,\,-i\)

Necessity If \(u\) is a unit, then \(uv=1\) for some \(v\). Taking norms, \(N(u)N(v)=N(1)=1\). Since norms are positive integers, \(N(u)=1\).

Solve \(N(a+bi)=a^2+b^2=1\) over the integers. The only solutions are \((a,b)\in\{(\pm1,0),(0,\pm1)\}\), i.e. \(u\in\{1,-1,i,-i\}\).

Sufficiency Each of these is invertible: \(1\cdot1=1,\ (-1)(-1)=1,\ i\cdot(-i)=1\). So all four are units, and there are no others.

Two Gaussian integers are associates if they differ by a unit — i.e. \(z\) and \(uz\) for \(u\in\{1,-1,i,-i\}\). Multiplying by \(i\) is a \(90^\circ\) rotation, so every Gaussian integer has four associates arranged as a little pinwheel around the origin. Factorization is only ever unique "up to units and order," exactly as \(6=2\cdot3=(-2)(-3)\) in \(\mathbb{Z}\).

04Divisibility & the Division Algorithm

We say \(\beta\) divides \(\alpha\) if \(\alpha=\beta\gamma\) for some Gaussian integer \(\gamma\). The decisive fact — the engine behind unique factorization — is that \(\mathbb{Z}[i]\) supports division with a small remainder, just like \(\mathbb{Z}\). This makes it a Euclidean domain, with the norm as its size function.

Proof — the division algorithm in \(\mathbb{Z}[i]\)

Claim For any \(\alpha,\beta\in\mathbb{Z}[i]\) with \(\beta\neq0\), there exist \(q,r\in\mathbb{Z}[i]\) with

\[ \alpha=\beta q+r\qquad\text{and}\qquad N(r)Take the exact quotient in the field \(\mathbb{Q}(i)\): write \(\dfrac{\alpha}{\beta}=x+yi\) with \(x,y\in\mathbb{Q}\).

Round to the nearest lattice point. Choose integers \(m,n\) closest to \(x,y\), so \(|x-m|\le\tfrac12\) and \(|y-n|\le\tfrac12\). Set \(q=m+ni\) and \(r=\alpha-\beta q\). Both lie in \(\mathbb{Z}[i]\).

Estimate the remainder. Since \(\dfrac{r}{\beta}=\dfrac{\alpha}{\beta}-q=(x-m)+(y-n)i\),

\[ N\!\left(\tfrac{r}{\beta}\right)=(x-m)^2+(y-n)^2\le\tfrac14+\tfrac14=\tfrac12. \]

Multiply back by the multiplicativity of the norm:

\[ N(r)=N(\beta)\,N\!\left(\tfrac{r}{\beta}\right)\le\tfrac12\,N(\beta)So a valid \((q,r)\) always exists. (It need not be unique — a point can have two nearest lattice points — but existence is all the Euclidean algorithm needs.)

The geometry is the whole proof: the multiples of \(\beta\) form a scaled, rotated copy of the lattice, and every point of the plane lies within distance \(|\beta|/\sqrt2\) of some multiple \(\beta q\) — within the circle drawn below. That bound is exactly \(N(r)\le N(\beta)/2\).

Division geometry · why a small remainder always exists
quotient q
remainder r
N(r) ≤ N(β)/2 ?

Purple dots are multiples βq′. The amber vector is the remainder r from the nearest multiple to α; it always fits inside the circle.

05Why Factorization Is Unique

The division algorithm sets off a chain of consequences, each a standard theorem of ring theory:

\[ \textbf{Euclidean domain}\;\Longrightarrow\;\textbf{PID}\;\Longrightarrow\;\textbf{UFD}. \]

That is: because we can divide with remainder, the Euclidean algorithm computes greatest common divisors; every ideal is generated by a single element (a principal ideal domain); and from there, every nonzero non-unit factors into primes uniquely, up to order and unit multiples (a unique factorization domain).

Sketch — Euclidean ⟹ principal ideal domain

Let \(I\neq\{0\}\) be an ideal. Among its nonzero elements pick one, \(\beta\), of smallest norm (possible because norms are positive integers and every nonempty set of positive integers has a least element).

Take any \(\alpha\in I\). Divide: \(\alpha=\beta q+r\) with \(N(r)

Hence \(\alpha=\beta q\): every element of \(I\) is a multiple of \(\beta\), i.e. \(I=(\beta)\). Every ideal is principal. Combined with the standard result that every PID is a UFD, \(\mathbb{Z}[i]\) has unique factorization.

So we may speak of Gaussian primes — the irreducible building blocks — and know that every Gaussian integer is a product of them in essentially one way. The next section says exactly what those primes are.

06Gaussian Primes, Classified

A Gaussian integer \(\pi\) (not \(0\), not a unit) is a Gaussian prime if its only divisors are units and associates of itself. The complete list comes in three flavours, and the norm tells them apart.

TypeWhoNorm
Ramified1+i and its associates (the prime "above 2")N = 2
Splita+bi with \(a^2+b^2=p\), for a rational prime \(p\equiv1\pmod4\)N = p
Inertrational primes p with \(p\equiv3\pmod4\) (still prime here)N = p²
Proof — the classification

Norm‑prime test If \(N(\pi)\) is a rational prime \(p\), then \(\pi\) is a Gaussian prime: a factorization \(\pi=\alpha\beta\) gives \(p=N(\alpha)N(\beta)\), forcing one factor to have norm \(1\) — a unit. This covers \(1+i\ (N=2)\) and the split primes \(\ (N=p\equiv1)\).

Primes \(p\equiv3\pmod4\) stay prime. If such a \(p\) factored as \(\alpha\beta\) with both non-units, then \(N(\alpha)=N(\beta)=p\), i.e. \(p=a^2+b^2\). But modulo \(4\) a sum of two squares is \(0,1,\) or \(2\) — never \(3\). Contradiction, so \(p\) is inert, with \(N(p)=p^2\).

Primes \(p\equiv1\pmod4\) split. Here \(-1\) is a square mod \(p\) (the group \(\mathbb{Z}_p^\times\) is cyclic of order \(p-1\), divisible by \(4\), so it has an element of order \(4\) whose square is \(-1\)). Pick \(x\) with \(p\mid x^2+1=(x+i)(x-i)\). If \(p\) were a Gaussian prime it would divide one factor — impossible, since \(\tfrac{x}{p}\pm\tfrac1p i\notin\mathbb{Z}[i]\). So \(p\) is reducible: \(p=\pi\bar\pi\) with \(N(\pi)=p\).

Nothing else. Any Gaussian prime \(\pi\) divides \(N(\pi)=\pi\bar\pi\in\mathbb{Z}\), hence divides some rational prime \(p\); analysing \(p\) by its class mod \(4\) lands \(\pi\) in one of the three families above.

Plotted in the plane, the Gaussian primes form a famously beautiful pattern with full 8-fold symmetry (reflections plus the \(90^\circ\) rotations from multiplying by \(i\)). Explore it — click any dot for its norm and type.

The Gaussian prime constellation
ramified (1+i) split, N=p inert, N=p²
clicked point
click a dot →
primes shown

07Fermat's Two-Square Theorem

Here is the payoff — a 350-year-old gem about ordinary integers that falls out almost for free once you have Gaussian primes.

Fermat (1640), proved by Euler (1749)
\[ \text{An odd prime }p\text{ is a sum of two squares}\iff p\equiv1\pmod4. \]
Proof via Gaussian integers

(⇐) If \(p\equiv1\pmod4\), the splitting argument above gives \(p=\pi\bar\pi\). Writing \(\pi=a+bi\), this reads \(p=N(\pi)=a^2+b^2\). Done — the factorization is the representation.

(⇒) If \(p=a^2+b^2\), look mod \(4\): squares are \(0\) or \(1\), so \(a^2+b^2\in\{0,1,2\}\bmod4\). An odd prime can't be \(0\) or \(2\) mod \(4\), so \(p\equiv1\). (And \(2=1^2+1^2\) is the lone even case.)

How to actually find \(a,b\): solve \(x^2\equiv-1\pmod p\), then compute the Gaussian \(\gcd(p,\,x+i)\) with the Euclidean algorithm — its components are your \(a\) and \(b\). The widget and the Octave code both do exactly this.

The full sum-of-two-squares theorem extends this to every positive integer: \(n\) is a sum of two squares iff every prime \(\equiv3\pmod4\) in its factorization appears to an even power. (Reason: such primes are inert, so they can only enter a Gaussian factorization in conjugate-free pairs.) Try numbers below and watch the rule decide.

Sum of two squares · the rule in action

Try 325, 50, 100, 21, 1000, 2025. A red prime ≡3 (mod 4) to an odd power blocks any representation.

08GNU Octave — Verified Code

Octave handles complex numbers natively (use 1i for the imaginary unit so it can't be shadowed by a variable). Every snippet ran in GNU Octave 8.4; the output is the real result.

The norm, and its multiplicativity

norm_demo.m
N = @(z) round(real(z)).^2 + round(imag(z)).^2;   % Gaussian norm

z = 3 + 2i;   w = 1 + 4i;
printf("N(z)=%d  N(w)=%d  N(z)*N(w)=%d\n", N(z), N(w), N(z)*N(w));
printf("z*w = %s   N(z*w) = %d\n", num2str(z*w), N(z*w));
outputN(z)=13 N(w)=17 N(z)*N(w)=221 z*w = -5+14i N(z*w) = 221

Units are the four norm-1 elements

units.m
N = @(z) round(real(z)).^2 + round(imag(z)).^2;
for u = [1, -1, 1i, -1i, 2, 1+1i]
  printf("  %-5s  N=%d  unit? %d\n", num2str(u), N(u), N(u)==1);
end
output 1 N=1 unit? 1 -1 N=1 unit? 1 0+1i N=1 unit? 1 -0-1i N=1 unit? 1 2 N=4 unit? 0 1+1i N=2 unit? 0

Division algorithm & Euclidean gcd

gdiv.m & ggcd.m
function [q, r] = gdiv(a, b)
  q = round(real(a/b)) + 1i*round(imag(a/b));   % nearest Gaussian integer
  r = a - b*q;                                   % guaranteed N(r) < N(b)
end

function g = ggcd(a, b)
  while round(real(b))^2 + round(imag(b))^2 ~= 0    % while b is nonzero
    [~, r] = gdiv(a, b);
    a = b;  b = r;
  end
  g = a;                                          % gcd, defined up to a unit
end
Octave session>> [q,r] = gdiv(11+10i, 3+1i) q = 4 + 2i r = 1 >> ggcd(5, 2+1i) % 5 = (2+i)(2-i), so they share 2+i ans = 2 + 1i >> ggcd(32+9i, 4+11i) % coprime: gcd is a unit ans = 0 - 1i

Classifying Gaussian primes

gisprime.m
function tf = gisprime(z)
  a = abs(round(real(z)));  b = abs(round(imag(z)));
  n = a^2 + b^2;
  if n <= 1
    tf = false;                       % 0 and the units are not primes
  elseif a == 0 || b == 0
    p = max(a, b);                    % a real/imaginary integer
    tf = isprime(p) && mod(p,4) == 3; % inert primes p = 3 (mod 4)
  else
    tf = isprime(n);                  % norm is a rational prime
  end
end
tested on a range of values 1+1i N=2 prime? 1 (ramified) 2 N=4 prime? 0 (= -i(1+i)^2) 3 N=9 prime? 1 (inert) 5 N=25 prime? 0 (splits: 5=(2+i)(2-i)) 2+1i N=5 prime? 1 (split) 4+1i N=17 prime? 1 (split) 2+2i N=8 prime? 0 (= 2(1+i))

An ASCII map of the prime constellation

prime_map.m
R = 8;                          % print '#' at every Gaussian prime
for b = R:-1:-R
  line = "";
  for a = -R:R
    if a==0 && b==0,            line = [line "+"];
    elseif gisprime(a + b*1i),  line = [line "#"];
    else                        line = [line "."];
    end
  end
  printf("%s\n", line);
end
output — note the 8-fold symmetry.#.#.#.....#.#.#. #.....#.#.#.....# ...#...#.#...#... #.#.#.#...#.#.#.# ...#...#.#...#... #.....#.#.#.....# .#.#.#.#.#.#.#.#. ..#.#.##.##.#.#.. .#...#..+..#...#. ..#.#.##.##.#.#.. .#.#.#.#.#.#.#.#. #.....#.#.#.....# ...#...#.#...#... #.#.#.#...#.#.#.# ...#...#.#...#... #.....#.#.#.....# .#.#.#.....#.#.#.

Fermat: write a prime as a sum of two squares

twosq.m
function [a, b] = twosq(p)
  x = [];                              % find x with x^2 = -1 (mod p)
  for t = 2:p-1
    if mod(t*t + 1, p) == 0, x = t; break; end
  end
  g = ggcd(p, x + 1i);                 % gcd(p, x+i): a Gaussian prime of norm p
  a = abs(round(real(g)));  b = abs(round(imag(g)));
end

for p = [5 13 17 29 97 101]
  [a,b] = twosq(p);
  printf("  %3d = %d^2 + %d^2\n", p, a, b);
end
output 5 = 2^2 + 1^2 13 = 3^2 + 2^2 17 = 4^2 + 1^2 29 = 5^2 + 2^2 97 = 9^2 + 4^2 101 = 10^2 + 1^2

Bonus — Pythagorean triples from \((m+ni)^2\)

triples.m
% Squaring a Gaussian integer manufactures a Pythagorean triple,
% because N((m+ni)^2) = (m^2+n^2)^2 is a perfect square.
for mn = [2 1; 3 2; 4 1]'
  m = mn(1);  n = mn(2);
  z = (m + n*1i)^2;
  A = abs(round(real(z)));  B = abs(round(imag(z)));  C = m^2 + n^2;
  printf("  (%d+%di)^2 -> (%d, %d, %d)\n", m, n, A, B, C);
end
output (2+1i)^2 -> (3, 4, 5) (3+2i)^2 -> (5, 12, 13) (4+1i)^2 -> (15, 8, 17)

09Applications & Wonders

Every primitive Pythagorean triple comes from one Gaussian integer

If \(m>n>0\) are coprime of opposite parity, then \((m+ni)^2=(m^2-n^2)+2mn\,i\) has norm \((m^2+n^2)^2\), so \((m^2-n^2,\,2mn,\,m^2+n^2)\) is a Pythagorean triple — and every primitive triple arises this way exactly once. Pythagoras, hiding inside complex multiplication.

The Gaussian moat problem

Can you walk from the origin to infinity stepping only on Gaussian primes, with bounded step size? Unlike the rational primes (where arbitrarily long prime gaps are known), this is open: nobody knows whether the primes thin out enough to leave an uncrossable "moat." It is a rare elementary-sounding question still unsolved.

Beyond \(i\): other rings of integers

\(\mathbb{Z}[i]\) is the first of the rings of integers of number fields. Its cousin \(\mathbb{Z}[\omega]\) (Eisenstein integers, \(\omega=e^{2\pi i/3}\)) tiles the plane with triangles and governs sums of the form \(a^2+ab+b^2\). Not all such rings enjoy unique factorization — the failure of it in \(\mathbb{Z}[\sqrt{-5}]\) (where \(6=2\cdot3=(1+\sqrt{-5})(1-\sqrt{-5})\)) is what launched the modern theory of ideals.

· i · −1 · −i · 1 ·