weld.py

Checks: CLOCK: The width theorem; OBSERVATORY: The jump set as the class maxima theorem.

Cited on: CLOCK, OBSERVATORY.

To run it: save weld.py, with clock.py, module_law.py, tame.py, triangle.py, wild.py beside it; standard library only.

"""weld.py -- the second point of a field's jump set, read off the
digits: Pagano's jump set and the landing readouts are one invariant.

QUESTION. Let K/Q_p be totally ramified of degree e, cut out by F =
x^e + sum_{i=1}^{e-1} p b_i x^i - p d with root pi and u = p/pi^e
(triangle.py), and let K contain zeta_p but not zeta_(p^2). Pagano
(Jump sets in local fields, arXiv:1810.09975, Theorem 1.5) attaches to
K an extended jump set (I, beta): the principal units U_1 are, as a
filtered Z_p-module, a free module modulo one relation, and (I, beta)
is that relation's orbit under the filtered automorphisms. Its points
(i, beta(i)) have beta strictly decreasing and WEIGHT rho^beta(i)(i)
strictly increasing, rho(i) = min(p i, i + e). The first point sits at
weight e* = p e/(p - 1). What is the weight W_2 of the second point,
and is it the quantity the landing readouts read (tame.py at an odd
prime, wild.py at 2)?

THE OBJECTS. The bend s = e/(p - 1) is an integer (zeta_p lies in K),
written s = c_0 p^M with p not dividing c_0. The CLASS (c_0, M) is the
units of level exactly c_0, whose p^M-th powers reach level s; a unit
z LANDS at v(z^(p^(M+1)) - 1) (tame.py). The DEPARTURE is l = v(u + 1)
(tame.py) and, at p = 2 with c_0 = 1, the wild departure lam, the least
level where a coefficient digit of F leaves the anchor design's
(wild.py). The CAP X is p^M, except 3e/2 at p = 2 with c_0 = 1.

THE DERIVATION (on paper, before the engine).
  (1) THE INTRINSIC READING (Pagano, Proposition 3.39, read at source).
      For zeta a generator of the p-power roots of unity, of order p^N,
      let g(n) be the weight of zeta in U_1/U_1^(p^n) under the quotient
      filtration: the largest v(zeta h - 1) over h in U_1^(p^n). Then g
      changes value exactly at the n = beta(i) - N, and g(beta(i) - N +
      1) = rho^(beta(i) - N)(i). Here N = 1, so in the presentation the
      lift of zeta carries the coordinates p^(beta(i) - 1) e_i and g(n)
      is the least rho^(beta(i) - 1)(i) over the points with beta(i) <=
      n. Hence g(n) = s for n >= M + 1, the first point is (c_0, M + 1)
      at weight rho^(M+1)(c_0) = e* (c_0 p^M = s is below the bend, and
      c_0 is the one pullback of s in T*), and when M >= 1 the second
      point (i_2, beta_2) has g(M) = rho^(beta_2 - 1)(i_2). Since g(M) >
      s, rho(g(M)) = g(M) + e, so
          W_2 = g(M) + e,   W_2 - e* = g(M) - s =: D.
      D is how far above zeta_p's own level a p^M-th power can push it.
  (2) D IS THE CLASS MAXIMUM. Let y be a unit of level s. Above the bend
      the p-th power carries U_j onto U_(j+e) (j > s: the digit moves by
      ubar, a bijection of F_p, and O_K is complete), and in every field
      of this scope (totally ramified, zeta_p in K) the level-s digit
      of y^p - 1 at e* cancels for every digit (it is a(ubar + 1), and
      zeta_p in K forces ubar = -1). So if v(y^p - 1) = e* + t,
      t >= 1, then y^p = w^p with w in U_(s+t), and y/w is a p-th root
      of unity other than 1: y = zeta_p^a w. Hence
          v(y^p - 1) - e* = v(zeta_p^(-a) y - 1) - s
      for the one a matching y's leading digit. Put y = z^(p^M), z in the
      class (c_0, M). Raising z to a power b prime to p multiplies its
      leading digit by b and leaves v(zeta_p^(-a) y - 1) fixed, and the
      p^M-th powers of units off the class sit at levels other than s.
      So the landings of the class run over e* + v(zeta_p x^(p^M) - 1)
      - s, x over the units whose p^M-th power matches zeta_p^(-1)'s
      leading digit, and their maximum is e* + D = W_2: THE SECOND POINT
      IS THE HIGHEST LANDING OF THE SEAT CLASS.
  (3) THE WELD. The readouts give the LEAST landing of the class, e* +
      min(dep, X), and say every unit lands there when dep < X (tame.py
      for every class at odd p; wild.py at p = 2, for c >= 2 and for the
      top class, dep = lam, X = 3e/2). A rigid class has its maximum at
      its minimum, so dep < X gives D = dep; dep >= X gives D >= X. So
          min(W_2 - e*, X) = min(dep, X).
      At a place with a head (s = p^n, c_0 = 1) the cap is clock.py's, and the second
      point's excess, capped, is clock.py's width: w = min(W_2 - e*, X).
  (4) NO SECOND POINT at M = 0 (the relation is one coordinate); and
      zeta_(p^2) in K makes zeta_p a p-th power, so N >= 2, outside
      this scope (Q_2(zeta_2e) is such a field).

THE ENGINE, independent of the readouts. U_1/U_L carried in O_K mod
p^N, eN > L. H_n = U_1^(p^n) is the image of the p^n-th power map, a
subgroup, generated by the (1 + pi^i)^(p^n): K being totally
ramified, every graded piece is F_p, so the 1 + pi^i generate U_1 over
Z_p. A FILTERED ECHELON holds one element of H_n at each level it
reaches; inserting an element reduces it level by level (the leading
coefficients' ratio fixes the power that cancels) and files the
remainder at its new level, then
inserts that remainder's p-th power. Once every generator and every
filed element's p-th power reduces to 1, the products of filed elements
with digit exponents are closed under multiplication by each filed
element (an exponent reaching p is paid by that element's p-th power,
filed higher), so they are all of H_n, and the filed levels are exactly
the levels H_n reaches. Then the largest v(zeta h - 1) over h in H_n is
the first level at which reducing zeta_p finds nothing filed: that is
g(n). zeta_p itself is lifted digit by digit from 1 + pi^s, each step
cancelling the leading digit of y^p - 1 with a unit of level above s.
The jump set is then rebuilt from g alone by (1): a change of value
between n - 1 and n is the point beta = n, and i is the pullback of
g(n) through rho^(n - 1) into T* = {a < e*, p not dividing a} u {e*}.

TRANSPLANTS. The pairing of W_2 - e* with the departure is the record
this script replaces, which read the second point off a basis of the
module and the digits of -p/pi^e; nothing of it is used. Pagano's
Proposition 3.39 is used as stated; the engine reads g directly and
never builds his presentation.

PREDICTIONS, fixed before the run.
  C  CONTROL. (a) zeta_p lifted: zeta^p = 1 to precision, level s,
     at every field read. (b) The echelon's closure: every filed
     element's p-th power reduces to 1, and a random product of
     generators' powers reduces to 1, at every (field, n). (c) Six
     fields whose second weight the replaced record printed from a
     module basis: x^2 - 2 W_2 = 5; x^4 - 2 W_2 = 10; x^6 + 3x + 3 W_2
     = 10; x^6 + 3x^3 + 3 and x^6 + 6x^3 + 3 W_2 = 13; x^12 - 2 W_2 =
     30. (d) x^2 + 3 (M = 0): the jump set is {(1, 1)} alone.
  J  THE JUMP SET REBUILT FROM g. At every field: g(n) = s for n = M +
     1 and M + 2; every value change pulls back into T*; beta strictly
     decreasing, weights strictly increasing, the first point (c_0, M +
     1) at weight e*, the last point beta = 1 (Pagano, Proposition 3.42:
     the torsion is Z/p^(beta(max I))).
  W  THE WELD. min(W_2 - e*, X) = min(dep, X) at every field with M >= 1:
     odd p over (3, 6), (3, 12), (3, 18), (5, 20), (7, 42) at every
     departure 1..X + 2 and infinity with random digits above, and
     random open polynomials; p = 2 over e = 2, 4, 8, 16 (top class,
     lam from 1 to 3e/2 + 2, the anchor itself, two random) and e = 6,
     10, 12
     (c_0 odd, tame's l). A field with zeta_(p^2) (g(1) at precision)
     is set aside and counted, never read.
  X  THE CLASS MAXIMUM. At p^2 e <= 800, every landing of the class
     (c_0, M) over its units written to two digits is at most W_2, and at the rigid fields
     (dep < X) every one equals W_2.
  H  THE HEAD. At the places with a head among them (c_0 = 1) and
     e <= 16, clock.py's
     width off the tick ladder (tame.py and wild.py's ladder_width)
     equals min(W_2 - e*, X).
KILLS, as printed observables: any C line off (nothing below is read);
one field whose rebuilt set breaks a J line; one field of W whose
capped excess differs from its capped departure; one landing above W_2
or a rigid class with a landing off it; one place with a head whose
ladder width differs.

THE SECOND SLATE, frozen after the first run and before its own. The
first run set aside 28 top-class fields over 2 as holding i, all but
one with lam > e. On paper: at N = 1, g(M) <= g(1), the last point's
i, which lies in T*, so D <= e* - s = e. Directly: D > e puts zeta_p
x^(p^M) in U_(e*+1), where every unit is a p-th power, so zeta_p is a
p-th power (M >= 1) and zeta_(p^2) lies in K. At odd p and at c_0 > 1
the cap is at most s < e, so this reads nothing new; at the top class
over 2 the cap is 3e/2 > e. There lam > e gives D > e by the wild
readout (rigid below 3e/2, at least 3e/2 above), so lam > e FORCES i
into K, and a field without i has lam <= e, its top class rigid and
W_2 - e* = lam exactly, the cap never reached.
  I  (a) At every field read in W, D <= e. (b) A fresh population over
     2 (seed 1427), e = 4, 8, 16, lam from e + 1 to 3e/2 + 2 and six
     more at random lam in (e, 2e + 4], digits above lam random: -1 is
     a square in every one (g(1) at precision). (c) Control: over
     Q_2(sqrt delta), |delta| <= 400 squarefree and 2 ramified, -1 is a
     square exactly at delta = 7 mod 8, where lam = 3 > e = 2.
KILLS: one field in W with D > e; one field of (b) where -1 is not a
square; one delta of (c) on the wrong side.

FINDINGS. Every prediction landed: 16/16 checks PASS, no kill fired.
C(b)'s first half re-reduces p-th powers that insert
already reduced when it filed them, so it guards only the filing; its
random products draw on the first six generators.
  C  zeta_p lifts and the echelon closes at every field; the six
     printed weights are reproduced, with the replaced record's points
     where it printed them: x^6 + 3x^3 + 3 reads (1, 2), (7, 1) and
     x^12 - 2 reads (3, 3), (9, 2), (21, 1).
  J  At 106 fields the set rebuilt from g alone is an extended jump set
     with first point (c_0, M + 1) at e* and last beta = 1, 0 off; the
     last beta = 1 holds by construction (g(0) = L, and a field with
     g(1) at precision is set aside, so g changes value at n = 1).
  W  min(W_2 - e*, X) = min(dep, X) at all 106, 0 off. Below the cap
     the excess IS the departure; above it the excess varies with the
     deeper digits (p = 3, e = 12: dep 5 reads 5, dep infinite reads 8;
     p = 2, e = 10, X = 2: dep 2 reads 7, dep 3 reads 3).
  X  At 94 fields no landing of the seat class exceeds W_2, and at the
     66 rigid ones every landing equals it.
  H  At 45 places with a head clock.py's ladder width is
     min(W_2 - e*, X).
  I  D <= e at all 106, attained (the top class at lam = e, e = 2 to
     16). -1 is a square at all 38 fields with lam > e, and over
     Q_2(sqrt delta) exactly at delta = 7 mod 8 (324 delta).
  Tiers: (1)-(3) a theorem, given Pagano's Proposition 3.39; the bound
  D <= e and the forcing of i a theorem, the bound needing Pagano only
  to name D.

RUN RECORD. 16/16, 18.0 s wall, peak working set 13.0 MB under
a memory guard. The first run (13/13) held the first slate; the second slate
was frozen after it and ran once.
"""

import os
os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
import random

from module_law import check, section, CHECKS, vp
from tame import departure, designed, local, landings, INF
import tame
import wild

SEED = 1426


class Units:
    """U_1/U_L of O_K = Z_p[pi]/(F), F Eisenstein, carried mod p^N."""

    def __init__(self, p, e, b, d, L):
        self.p, self.e, self.L = p, e, L
        self.N = L // e + 2
        self.mod = p ** self.N
        self.loc = local(p, e, b, d)
        self.one = [1] + [0] * (e - 1)

    def mul(self, x, y):
        return self.loc.mul(x, y, self.mod)

    def pw(self, x, k):
        return self.loc.power(x, k, self.mod)

    def lead(self, z):
        """(level, leading coefficient) of z - 1; level L means z = 1."""
        w = [(z[0] - 1) % self.mod] + z[1:]
        best = (self.L, 0)
        for i, c in enumerate(w):
            if c:
                k = vp(c, self.p)
                r = self.e * k + i
                if r < best[0]:
                    best = (r, (c // self.p ** k) % self.p)
        return best

    def gen(self, i):
        z = list(self.one)
        return [(a + x) % self.mod
                for a, x in zip(z, self.loc.pi_pow(i, self.mod))]

    def inv(self, z):
        return self.pw(z, self.p ** (self.N * self.e + 1) - 1)


class Echelon:
    """One element of a subgroup of U_1/U_L at each level it reaches."""

    def __init__(self, U):
        self.U, self.at = U, {}

    def reduce(self, z):
        U = self.U
        while True:
            r, c = U.lead(z)
            if r >= U.L or r not in self.at:
                return z, r
            b, cb, invs = self.at[r]
            k = c * pow(cb, -1, U.p) % U.p
            z = U.mul(z, invs[k])

    def insert(self, z):
        todo = [z]
        while todo:
            z, r = self.reduce(todo.pop())
            if r < self.U.L:
                U = self.U
                bi = U.inv(z)
                invs = [U.one]
                for _ in range(U.p - 1):
                    invs.append(U.mul(invs[-1], bi))
                self.at[r] = (z, U.lead(z)[1], invs)
                todo.append(U.pw(z, U.p))

    def closed(self, rng, gens):
        U = self.U
        ok = all(self.reduce(U.pw(b, U.p))[1] >= U.L
                 for b, _, _ in self.at.values())
        for _ in range(4):
            z = U.one
            for g in gens:
                z = U.mul(z, U.pw(g, rng.randrange(U.p ** 2)))
            ok &= self.reduce(z)[1] >= U.L
        return ok


def power_subgroup(U, n):
    gens = [U.pw(U.gen(i), U.p ** n) for i in range(1, U.L)]
    E = Echelon(U)
    for g in gens:
        E.insert(g)
    return E, gens


def zeta_p(U, s):
    """The p-th root of unity with leading digit 1 at level s."""
    p, e = U.p, U.e
    y = U.gen(s)
    while True:
        r, c = U.lead(U.pw(y, p))
        if r >= U.L:
            return y
        t = r - e
        assert t > s, "the candidate's p-th power did not cancel at e*"
        _, cw = U.lead(U.pw(U.gen(t), p))
        k = (-c * pow(cw, -1, p)) % p
        y = U.mul(y, U.pw(U.gen(t), k))


def rho(p, e, i):
    return min(p * i, i + e)


def pullback(p, e, level, b):
    """The a in T* with rho^b(a) = level, or None."""
    es = p * e // (p - 1)
    for a in list(range(1, es)) + [es]:
        if a < es and a % p == 0:
            continue
        x = a
        for _ in range(b):
            x = rho(p, e, x)
        if x == level:
            return a
    return None


def read_field(p, e, b, d, rng=None):
    """g(0..M+2), the rebuilt jump set, W_2, and the controls' verdicts."""
    s = e // (p - 1)
    M = vp(s, p)
    c0 = s // p ** M
    es = p * s
    X = 3 * e // 2 if (p == 2 and c0 == 1) else p ** M
    L = max(es, s + X) + 3
    # zeta_p is found to precision L + e, so its p-th power is read there
    Z = Units(p, e, b, d, L + e)
    z = zeta_p(Z, s)
    U = Units(p, e, b, d, L)
    z = [c % U.mod for c in z]
    ok_zeta = U.lead(U.pw(z, p))[0] >= L and U.lead(z)[0] == s
    g, closed = {}, True
    for n in range(0, M + 3):
        if n == 0:
            g[0] = L
            continue
        E, gens = power_subgroup(U, n)
        if rng is not None:
            closed &= E.closed(rng, gens[:6])
        g[n] = E.reduce(z)[1]
    return dict(s=s, M=M, c0=c0, es=es, X=X, L=L, g=g,
                ok_zeta=ok_zeta, closed=closed)


def jump_set(p, e, g, top):
    """Points (i, beta) from g: a change of value between n - 1 and n."""
    pts = []
    for n in range(1, top + 1):
        if g[n] != g[n - 1]:
            i = pullback(p, e, g[n], n - 1)
            pts.append((i, n))
    return sorted(pts)


def weight(p, e, i, bt):
    x = i
    for _ in range(bt):
        x = rho(p, e, x)
    return x


def excess(W, p, e):
    return None if W is None else W - p * e // (p - 1)


def second_weight(p, e, rec):
    pts = jump_set(p, e, rec["g"], rec["M"] + 2)
    return pts, (weight(p, e, *pts[1]) if len(pts) > 1 else None)


# ------------------------------------------------------------ populations

ODD = [(3, 6), (3, 12), (3, 18), (5, 20), (7, 42)]
TOP = [2, 4, 8, 16]
EVEN = [6, 10, 12]


def cap(p, e):
    s = e // (p - 1)
    M = vp(s, p)
    return 3 * e // 2 if (p == 2 and s == 2 ** M) else p ** M


def population(rng):
    """(label, p, e, b, d, dep) over the W scopes."""
    out = []
    for (p, e) in ODD:
        s, X = e // (p - 1), cap(p, e)
        top = 2 * e + s
        for l in list(range(1, X + 3)) + [INF]:
            b, d = designed(rng, p, e, l, top)
            out.append((f"l={'inf' if l >= INF else l}", p, e, b, d, l))
        for _ in range(2):
            b = [0] + [rng.randrange(p ** 3) for _ in range(1, e)]
            d = -1 + p * rng.randrange(1, p ** 3)
            out.append(("random", p, e, b, d, departure(p, e, b, d)))
    for e in TOP:
        X = cap(2, e)
        for lam in range(1, X + 3):
            b, d = wild.designed(rng, e, lam, 2 * e + 4)
            out.append((f"lam={lam}", 2, e, b, d, lam))
        b, d = wild.anchor(e)
        out.append(("anchor", 2, e, b, d, INF))
        for _ in range(2):
            b, d = wild.random_poly(rng, e)
            out.append(("random", 2, e, b, d, wild.wild_departure(e, b, d)))
    for e in EVEN:
        X = cap(2, e)
        for l in list(range(1, X + 3)) + [INF]:
            b, d = wild.designed_l(rng, e, l, 2 * e + 4)
            out.append((f"l={'inf' if l >= INF else l}", 2, e, b, d, l))
    return out


def dep_of(p, e, b, d):
    if p == 2 and cap(2, e) == 3 * e // 2:
        return wild.wild_departure(e, b, d)
    return departure(p, e, b, d)


CONTROLS = [("x^2 - 2", 2, 2, [0, 0], 1, 5),
            ("x^4 - 2", 2, 4, [0] * 4, 1, 10),
            ("x^6 + 3x + 3", 3, 6, [0, 1, 0, 0, 0, 0], -1, 10),
            ("x^6 + 3x^3 + 3", 3, 6, [0, 0, 0, 1, 0, 0], -1, 13),
            ("x^6 + 6x^3 + 3", 3, 6, [0, 0, 0, 2, 0, 0], -1, 13),
            ("x^12 - 2", 2, 12, [0] * 12, 1, 30)]


# ------------------------------------------------------------ sections

def section_control(rng):
    section("C  CONTROL: zeta_p, the echelon's closure, printed weights")
    bad_z = bad_c = 0
    for name, p, e, b, d, want in CONTROLS:
        rec = read_field(p, e, b, d, rng)
        pts, W = second_weight(p, e, rec)
        bad_z += not rec["ok_zeta"]
        bad_c += not rec["closed"]
        check(f"Cc {name}: W_2 = {want}", W == want,
              f"g = {[rec['g'][n] for n in sorted(rec['g'])]}, "
              f"points {pts}, W_2 = {W}")
    rec = read_field(3, 2, [0, 0], -1, rng)
    pts, W = second_weight(3, 2, rec)
    bad_z += not rec["ok_zeta"]
    bad_c += not rec["closed"]
    check("Cd x^2 + 3 (M = 0): the jump set is {(1, 1)}", pts == [(1, 1)],
          f"points {pts}")
    check("Ca zeta_p: zeta^p = 1 to precision, level s", bad_z == 0,
          f"{bad_z} off")
    check("Cb the echelon closed under p-th powers and random products",
          bad_c == 0, f"{bad_c} off")


def section_jump_weld(rng, rows):
    section("J, W  THE JUMP SET REBUILT FROM g; THE WELD")
    bad_j = bad_w = aside = 0
    by = {}
    for label, p, e, b, d, dep in population(rng):
        assert dep_of(p, e, b, d) == dep
        rec = read_field(p, e, b, d, rng)
        g, M, s, L, X = rec["g"], rec["M"], rec["s"], rec["L"], rec["X"]
        if g[1] >= L:
            aside += 1
            print(f"    aside: p={p} e={e} {label}: zeta_p a p-th power "
                  f"to precision")
            continue
        pts, W = second_weight(p, e, rec)
        ok_j = (rec["ok_zeta"] and rec["closed"]
                and g[M + 1] == s == g[M + 2]
                and all(i is not None for i, _ in pts)
                and pts[0] == (rec["c0"], M + 1)
                and weight(p, e, *pts[0]) == rec["es"]
                and pts[-1][1] == 1
                and all(pts[k][1] > pts[k + 1][1]
                        and weight(p, e, *pts[k]) < weight(p, e, *pts[k + 1])
                        for k in range(len(pts) - 1)))
        bad_j += not ok_j
        D = excess(W, p, e)
        ok_w = D is not None and min(D, X) == min(dep, X)
        bad_w += not ok_w
        by.setdefault((p, e), []).append((dep, D))
        rows.append((label, p, e, b, d, dep, W, rec))
        if not (ok_j and ok_w):
            print(f"    OFF p={p} e={e} {label} dep={dep} g={g} "
                  f"points={pts} W_2={W}")
    for (p, e), v in by.items():
        X = cap(p, e)
        shown = ", ".join(f"{'inf' if a >= INF else a}:{D}" for a, D in v)
        print(f"  p={p} e={e:2d} X={X:2d}  dep:W_2-e* = {shown}")
    check("J the rebuilt set: g = s past M, first point (c_0, M + 1) at "
          "e*, last beta = 1, beta down, weights up", bad_j == 0,
          f"{len(rows)} fields, {bad_j} off")
    check("W min(W_2 - e*, X) = min(dep, X)", bad_w == 0,
          f"{len(rows)} fields, {bad_w} off, {aside} set aside "
          f"(zeta_p^2 in K)")


def section_class_max(rows):
    section("X  THE CLASS MAXIMUM: every landing of (c_0, M) is at most W_2")
    bad = seen = rigid = 0
    for label, p, e, b, d, dep, W, rec in rows:
        if p ** 2 * e > 800:
            continue
        land = landings(local(p, e, b, d), rec["c0"], rec["M"], 2)[0]
        seen += 1
        ok = all(x <= W for x in land)
        if dep < rec["X"]:
            rigid += 1
            ok &= set(land) == {W}
        bad += not ok
        if not ok:
            print(f"    OFF p={p} e={e} {label}: W_2={W} "
                  f"landings {sorted(set(land))}")
    check("X no landing above W_2, rigid classes all at W_2", bad == 0,
          f"{seen} fields, {rigid} rigid, {bad} off")


def section_head(rows):
    section("H  THE HEAD: clock.py's ladder width = min(W_2 - e*, X)")
    bad = seen = 0
    for label, p, e, b, d, dep, W, rec in rows:
        if rec["c0"] != 1 or e > 16:
            continue
        lw = (wild.ladder_width if p == 2 else tame.ladder_width)(
            local(p, e, b, d))
        want = min(excess(W, p, e), rec["X"])
        seen += 1
        bad += lw != want
        if lw != want:
            print(f"    OFF p={p} e={e} {label}: ladder {lw}, weld {want}")
    check("H the ladder's width is the second point's capped excess",
          bad == 0, f"{seen} heads, {bad} off")


def minus_one_square(e, b, d):
    """-1 in K^(x2): its reduction against the squares mod U_L."""
    U = Units(2, e, b, d, 2 * e + 3)
    E, _ = power_subgroup(U, 1)
    return E.reduce([(-1) % U.mod] + [0] * (e - 1))[1] >= U.L


def section_i(rows):
    section("I  AT N = 1 THE EXCESS IS AT MOST e; lam > e FORCES i INTO K")
    worst = max(excess(W, p, e) - e for _, p, e, _, _, _, W, _ in rows)
    check("Ia D <= e at every field read in W", worst <= 0,
          f"{len(rows)} fields, max D - e = {worst}")
    rng = random.Random(SEED + 1)
    seen = bad = 0
    for e in (4, 8, 16):
        pop = [wild.designed(rng, e, lam, 2 * e + 4)
               for lam in range(e + 1, 3 * e // 2 + 3)]
        pop += [wild.designed(rng, e, rng.randrange(e + 1, 2 * e + 5),
                              2 * e + 4) for _ in range(6)]
        for b, d in pop:
            assert wild.wild_departure(e, b, d) > e
            seen += 1
            bad += not minus_one_square(e, b, d)
    check("Ib lam > e: -1 is a square in K", bad == 0,
          f"{seen} fields over e = 4, 8, 16, {bad} off")
    seen = bad = 0
    for delta in range(-400, 401):
        if delta % 4 in (0, 1) or not wild.squarefree(delta):
            continue
        b, d = wild.quadratic(delta)
        seen += 1
        bad += minus_one_square(2, b, d) != (delta % 8 == 7)
    check("Ic over Q_2(sqrt delta): -1 a square iff delta = 7 mod 8",
          bad == 0, f"{seen} delta, {bad} off")


def main():
    rng = random.Random(SEED)
    section_control(rng)
    if not all(CHECKS):
        print("\ncontrol failed: nothing below is read")
        raise SystemExit(1)
    rows = []
    section_jump_weld(rng, rows)
    section_class_max(rows)
    section_head(rows)
    section_i(rows)
    print()
    print(f"{sum(CHECKS)}/{len(CHECKS)} checks PASS")
    if not all(CHECKS):
        raise SystemExit(1)


if __name__ == "__main__":
    main()