Computing the recurrence by a single exponentiation #
Sendov.rev_qrow says that qrow computes the coefficients of (g₀ + g₁t + g₂t²) ^ k.
Evaluating that identity at integer points turns it into a statement about packed values,
and the packing is nothing but the same Horner evaluation read in ℤ instead of ℝ. So the
forward direction needs no new theory at all: Sendov.pevZ_rowZ_qrow follows from
rev_qrow by casting.
Two bases are involved:
βpacks a coefficient polynomial inαinto one integer (Sendov.pevZ);τpacks the resulting row, a polynomial int, into one integer.
Together they are the two-dimensional Kronecker substitution, and the whole recurrence
becomes G ^ k for the single integer G = pevZ g₀ β + pevZ g₁ β * τ + pevZ g₂ β * τ².
Sendov.unpackZ_pevZ then reads the row back off, given the overflow bounds — which is where
the numerical parameters β and τ have to be chosen, one per degree.
Main statements #
Sendov.pev_intCast,Sendov.rev_intCast: evaluation overℝat an integer point agrees with the packed evaluation overℤ;Sendov.pevZ_rowZ_qrow: the recurrence as one integer exponentiation.
The row with each coefficient polynomial packed at the base β.
Equations
- Sendov.rowZ r β = List.map (fun (p : List ℤ) => Sendov.pevZ p β) r
Instances For
The recurrence as one exponentiation. The two-dimensionally packed row is the k-th
power of a single integer. In the kernel this replaces Θ(k³) interpreted list steps by one
GMP-backed exponentiation; measured at k = 46, hours become about half a second.
Reading the packed row back, given the overflow bound on the packed coefficients. The bound is a hypothesis: it is discharged per degree from explicit numerical parameters.
The moment as a single integer polynomial #
Sendov.irow has rational weights 1/(j+4). Scaling by a common multiple L of the
denominators clears them, turning the moment into one ℤ-polynomial in α.
Coefficient bounds #
Injectivity of packing needs a bound on the coefficients of both lists compared — including
the true row, which is precisely the object we must not compute. So the bound has to be
proved rather than checked. The L¹ norm does it: it is submultiplicative, so a coefficient
of the k-th power is at most (l1 g₀ + l1 g₁ + l1 g₂) ^ k.
The L¹ norm of a row: the total of its coefficients' absolute values.
Equations
- Sendov.l1row [] = 0
- Sendov.l1row (p :: r) = Sendov.l1 p + Sendov.l1row r
Instances For
Lengths, and the magnitude of a packed value #
The verification step #
The generator supplies the moment numerator; Lean checks it with one integer comparison. Lengths need not match exactly: a shorter list is compared against its zero-padding, which has the same value as a polynomial.
The weighted sum computed directly on the α-packed row.
Equations
- Sendov.wsumZ L x✝ [] = 0
- Sendov.wsumZ L x✝ (a :: s) = L / (↑x✝ + 4) * a + Sendov.wsumZ L (x✝ + 1) s
Instances For
Verification of a supplied moment numerator. Given the overflow bounds, checking a
generator-supplied Nmom is one integer comparison against the packed computation — which is
a single exponentiation and 2k+1 digit extractions.
Entry lengths #
qrow_length counts the entries of a row; bounding the α-packed values also needs each
entry's length. Multiplying by a g of length at most G lengthens an entry by at most
G, so after k steps an entry has length at most 1 + G*k. This is what lets the
hypotheses of wsum_eq_of_packed be discharged by arithmetic instead of by computing
qrow.
The bounds in usable form #
Each hypothesis of Sendov.wsum_eq_of_packed reduces to an inequality between explicit
numbers, so a degree file never computes qrow.
The τ bound: the α-packed row entries are bounded by the L¹ norm times a power of
β, the exponent coming from Sendov.qrow_entry_length_le.
Pad-tolerant verification. Concludes equality of the polynomial functions, which is all the moment needs, and so requires only length bounds rather than an exact match.
The moment from a verified numerator. Combining Sendov.integral_moment_of with
Sendov.pev_wsum, the integral is an explicit integer polynomial over an explicit
denominator. Everything on the right is either supplied by the generator or a kernel
computation on integers.