29.8. Conjugation, order, and principal radicals
Hex.AlgebraicNumber.conj is cheap: a nonreal number shares one
canonical upper-half-plane isolation with its conjugate and stores a tag
selecting the upper or lower value. Conjugation flips the tag. It does not
factor a polynomial, isolate roots, refine a ball, or build an ever-growing
certificate. Real values are unchanged. The companion provides StarRing
and Hex.AlgebraicNumber.conjRingEquiv, with the usual arithmetic laws.
Root enumeration puts real roots first and nonreal conjugate pairs next to
one another, the negative imaginary member first. Pairs use the upper
isolation's dyadic centre (im, re, precision), with the minimal polynomial
breaking remaining ties. This is a cheap deterministic enumeration order;
it is not lexicographic comparison of exact complex coordinates. Root indices
and nearest-root ties involving nonreal values may change when the isolation
algorithm changes. A printed rootNear expression still names its original
mathematical value. The companion proves sorting with
Hex.ZPoly.algebraicRoots_sorted and the absence of intervening values
with Hex.AlgebraicNumber.between_conjugates.
The global < and ≤ operations instead match Mathlib's complex partial
order: imaginary parts must be equal, and real parts are compared. Thus
I < 1 + I, while neither 0 ≤ I nor I ≤ 0. There is no total Ord or
LinearOrder instance on algebraic numbers. Comparing unequal nonreal values
on the same side of the real axis first tests stored coordinate intervals,
then refines by 16 and 64 extra bits if needed. Disjoint imaginary intervals
prove incomparability, and </≤ also reject impossible real inequalities.
Real-real comparisons try stored intervals before computing a product
separation bound and refining geometrically. Inconclusive complex comparisons
compute an exact subtraction, so that fallback can
cost as much as a field operation. Equal imaginary parts pay for inconclusive
refinement before subtraction; the recorded same-imaginary benchmark was about
9% slower than the former comparison on the measured host. Use the real algebraic type for
sorting real values by exact comparison. The companion's
Hex.AlgebraicNumber.toComplexOrder preserves and reflects this order.
open Hex
#guard AlgebraicNumber.I.conj == -AlgebraicNumber.I
#guard AlgebraicNumber.I < 1 + AlgebraicNumber.I
#guard ¬ ((0 : AlgebraicNumber) ≤ AlgebraicNumber.I)
#guard ¬ (AlgebraicNumber.I ≤ (0 : AlgebraicNumber))
example (a : AlgebraicNumber) : a.conj.conj = a := AlgebraicNumber.conj_conj a
example : PartialOrder AlgebraicNumber := inferInstance
example : StarRing AlgebraicNumber := inferInstance
Hex.AlgebraicNumber.sqrt and Hex.AlgebraicNumber.nthRoot
select Mathlib's principal complex branches. For a positive index n, the
result has argument in (-π/n, π/n]. Index zero returns 1, including at
zero. A negative real number's principal odd root is generally complex:
nthRoot (-8) 3 is 1 + √3 I, not the real cube root -2.
The general implementation solves X^n - a with the existing algebraic
coefficient solver. It filters lazy roots by their exact imaginary side,
then selects maximal real part using certified intervals. It first checks
stored intervals and tries two modest refinement rounds before falling back
to exact coordinate comparisons. A successful interval selection exactifies
only the winner. Overlap alone never establishes an ordering or equality.
The general root solver and final canonicalization can still be expensive.
Zero, one, and indices zero and one have direct paths; radicals of -1,
I, and -I use the roots-of-unity constructor below.
#guard (-1 : AlgebraicNumber).sqrt == AlgebraicNumber.I
example (a : AlgebraicNumber) : a.sqrt ^ 2 = a := AlgebraicNumber.sqrt_sq a
example (a : AlgebraicNumber) (n : Nat) (hn : n ≠ 0) :
a.nthRoot n ^ n = a := AlgebraicNumber.nthRoot_pow a hn
example (a : AlgebraicNumber) : a.sqrt.toComplex = a.toComplex.sqrt :=
AlgebraicNumber.sqrt_toComplex a
Conjugation commutes with these branches away from the negative real axis;
Hex.AlgebraicNumber.nthRoot_conj states the necessary argument
hypothesis. The corollary Hex.AlgebraicNumber.nthRoot_conj_of_not_lt
uses the executable condition ¬ a < 0, which holds exactly away from the
negative real axis in the complex partial order. On the cut, both sqrt (-1) and sqrt (conj (-1)) are I,
whereas conj (sqrt (-1)) is -I.