FLINT3.7.0-dev
Algorithm

Gaussian integers

Cost
Euclidean GCD of nn-bit inputs: O(n)O(n) division steps, O(n2)O(n^2) bit operations; lattice GCD: dominated by a continued fraction expansion, quasi-linear with a half-GCD for large inputs; primality: one primality test of the norm or of a rational prime.

The ring Z[i]\mathbb{Z}[i] of Gaussian integers is a Euclidean domain with respect to the norm N(a+bi)=a2+b2N(a + bi) = a^2 + b^2, and hence a unique factorisation domain. Its units are ±1,±i\pm 1, \pm i, and 1+i1 + i is the unique prime above 2, with 2=−i(1+i)22 = -i(1 + i)^2. Standard references are [Coh1996, §1.2] for Euclidean rings and [Wei2000] for the binary algorithm.

Division with remainder#

Proposition 1. For x,y∈Z[i]x, y \in \mathbb{Z}[i] with y≠0y \ne 0, let q=⌊re⁡(x/y)+1/2⌋+i⌊im⁡(x/y)+1/2⌋q = \lfloor \operatorname{re} (x/y) + 1/2 \rfloor + i \lfloor \operatorname{im}(x/y) + 1/2 \rfloor and r=x−qyr = x - qy. Then N(r)≤N(y)/2N(r) \le N(y)/2.

Proof. Each of the real and imaginary parts of x/y−qx/y - q lies in (−1/2,1/2](-1/2, 1/2], so ∣x/y−q∣2≤1/2|x/y - q|^2 \le 1/2, and N(r)=N(y) ∣x/y−q∣2N(r) = N(y)\,|x/y - q|^2.

fmpzi_divrem computes this quotient exactly: with t=2xyˉ+N(y)(1+i)t = 2x\bar y + N(y)(1 + i), it takes the floor quotients of the real and imaginary parts of tt by 2N(y)2N(y), which costs one complex multiplication and two divisions. Ties are rounded upwards in each coordinate, which makes the remainder unique. When xx has at least three bits fewer than yy (in the larger of its parts), ∣x/y∣<1/2|x/y| < 1/2 and the quotient is zero without computation.

fmpzi_divrem_approx only guarantees N(r)<N(y)N(r) < N(y), which is all the Euclidean algorithm needs. When the bit sizes of xx and yy differ by less than 45, it computes the quotient from double-precision approximations of xx and yy (scaled by a common power of 2 if they are large). Each coordinate of the computed quotient then differs from the corresponding coordinate of x/yx/y by at most 1/2+ε1/2 + \varepsilon with a tiny ε\varepsilon, so ∣x/y−q∣2≤2(1/2+ε)2<1|x/y - q|^2 \le 2(1/2 + \varepsilon)^2 < 1. Otherwise it calls fmpzi_divrem.

Canonical associates#

Every nonzero xx has exactly one associate ikxi^k x with real part positive and imaginary part in (−re⁡,re⁡](-\operatorname{re}, \operatorname{re}]: the four associates are the rotations of xx by multiples of 90°90°, and exactly one of them lies in the sector −π/4<arg⁡z≤π/4-\pi/4 < \arg z \le \pi/4. fmpzi_canonical_unit_i_pow returns the exponent k∈{0,1,2,3}k \in \{0, 1, 2, 3\} from two comparisons, and fmpzi_canonicalise_unit applies it. The GCD functions return the canonical associate, so that the GCD is unique; for example gcd⁡(2,1+i)=1+i\gcd(2, 1 + i) = 1 + i, while 1−i1 - i, −1+i-1 + i and −1−i-1 - i are its other associates.

Greatest common divisors#

Euclidean algorithm#

By Proposition 1 each step of (x,y)←(y,x mod y)(x, y) \gets (y, x \bmod y) at least halves the norm, so for inputs of nn bits there are at most about 2n2n steps, and the total cost is O(n2)O(n^2) bit operations as for integers. fmpzi_gcd_euclidean uses fmpzi_divrem. fmpzi_gcd_euclidean_improved uses fmpzi_divrem_approx, and as soon as all four parts are below 2502^{50} in absolute value it finishes in double-precision arithmetic: the approximate quotient may differ from the rounded one, but the remainder x−qyx - qy is computed exactly in doubles because all intermediate values stay below 2532^{53}, and any quotient with N(r)<N(y)N(r) < N(y) gives a correct Euclidean sequence.

The (1+i)-ary algorithm#

Weilert's analogue of the binary GCD [Wei2000] replaces divisions by additions and divisions by 1+i1 + i. Since Z[i]/(1+i)≅F2\mathbb{Z}[i]/(1 + i) \cong \mathbf{F}_2, any two elements x,yx, y not divisible by 1+i1 + i satisfy x≡y≡1x \equiv y \equiv 1, so all four of x±yx \pm y and x±iyx \pm iy are divisible by 1+i1 + i. fmpzi_gcd_binary first removes the factors 1+i1 + i from both inputs, remembering the smaller multiplicity, and then repeatedly replaces the larger of x,yx, y (by norm) by the one of x±yx \pm y, x±iyx \pm iy of smallest norm, divided by the largest power of 1+i1 + i. The four norms sum to 4(N(x)+N(y))4(N(x) + N(y)), so the smallest is at most N(x)+N(y)≤2N(x)N(x) + N(y) \le 2N(x), and the division by 1+i1 + i at least halves it; Weilert shows that the algorithm has quadratic bit complexity, like the binary GCD for integers [Wei2000]. The implementation estimates the norms in double precision and falls back to fmpzi_gcd_euclidean when an input has more than 500 bits.

The lattice algorithm#

The ideal (x,y)=gZ[i](x, y) = g\mathbb{Z}[i] generated by xx and yy is a lattice in Z2\mathbb{Z}^2, generated over Z\mathbb{Z} by x,ix,y,iyx, ix, y, iy (as vectors of real and imaginary parts). Its Hermite normal form is (cb0a)\begin{pmatrix} c & b \\ 0 & a \end{pmatrix} with ac=N(g)ac = N(g), and gg is, up to a unit, a shortest nonzero vector of the lattice: every element is gwgw with N(w)≥1N(w) \ge 1. fmpzi_gcd_shortest, due to D. Schultz, computes the Hermite form by integer GCDs of the coordinates and then the shortest vector of the two-dimensional lattice in the ℓ∞\ell^\infty norm from the continued fraction expansion of an interval around a/ba/b, computed by the quasi-linear ball continued fraction routine _fmpq_ball_get_cfrac of fmpq. A special case handles purely real or purely imaginary gg, where a vector g(1+i)g(1 + i) has the same ℓ∞\ell^\infty norm as gg.

Choice of algorithm#

fmpzi_gcd returns the canonical associate of the other input if one is zero. If all parts are below 2502^{50} in absolute value it uses the double-precision Euclidean algorithm directly. If either input has both parts of one word, or either input has at most 30000 bits, it uses fmpzi_gcd_euclidean_improved. Otherwise it uses fmpzi_gcd_shortest, first reducing the larger input modulo the smaller with one approximate division if their sizes differ by more than a factor 1.5.

The prime 1 + i#

For x=a+bi≠0x = a + bi \ne 0, let s=min⁡(ord⁡2a,ord⁡2b)s = \min(\operatorname{ord}_2 a, \operatorname{ord}_2 b) (with ord⁡20=∞\operatorname{ord}_2 0 = \infty). Then x=2sx′x = 2^s x' with x′x' not divisible by 2, and x′x' is divisible by 1+i1 + i, exactly once, if and only if both parts of x′x' are odd. Since 2s=(1+i)2si−s2^s = (1 + i)^{2s} i^{-s}, the multiplicity of 1+i1 + i in xx is 2s2s or 2s+12s + 1. fmpzi_remove_one_plus_i computes it from the 2-adic valuations of the parts, divides by 2s2^s with shifts, multiplies by isi^{s}, and divides by 1+i1 + i once more using (a+bi)/(1+i)=((a+b)+(b−a)i)/2(a + bi)/(1 + i) = ((a + b) + (b - a)i)/2 if needed.

Primality#

The Gaussian primes are, up to units, 1+i1 + i, the rational primes p≡3(mod4)p \equiv 3 \pmod 4, and the elements π\pi with N(π)=pN(\pi) = p a rational prime p≡1(mod4)p \equiv 1 \pmod 4 [Coh1996, §1.2]. Hence a+bia + bi is prime if and only if either ab=0ab = 0 and the nonzero part is ±p\pm p with pp prime and p≡3(mod4)p \equiv 3 \pmod 4, or ab≠0ab \ne 0 and a2+b2a^2 + b^2 is prime. fmpzi_is_prime applies this criterion with fmpz_is_prime, which proves primality, and fmpzi_is_probabprime with fmpz_is_probabprime. FLINT does not provide factorisation in Z[i]\mathbb{Z}[i], which reduces to factoring the norm and, for each prime p≡1(mod4)p \equiv 1 \pmod 4 dividing it, finding π=gcd⁡(p,t+i)\pi = \gcd(p, t + i) with t2≡−1(modp)t^2 \equiv -1 \pmod p.

Use in FLINT#

Referenced from#

References#

  • [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
  • [Wei2000] A. Weilert, "(1+i)-ary GCD computation in Z[i] as an analogue to the binary GCD algorithm", Journal of Symbolic Computation 30.5 (2000): 605-617, https://doi.org/10.1006/jsco.2000.0422
Cite this page

The FLINT team, “Gaussian integers,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/number-theory/gaussian-integers.html (generated 2026-11-02).