Documentation

HexBerlekamp.LinearFactors

The linear factor corresponding to a prime-field residue.

Equations
Instances For

    The listed prime-field linear factors are genuinely degree-one candidates.

    No listed prime-field linear factor is the zero polynomial.

    Each prime-field linear factor has size 2 (it is genuinely degree 1).

    Each prime-field linear factor has degree exactly one.

    Distinct residues give distinct linear factors.

    Distinct prime-field linear factors are coprime: any common divisor is a unit.

    theorem Hex.Berlekamp.foldl_primeFieldLinearFactor_dvd {p : Nat} [ZMod64.Bounds p] [ZMod64.PrimeModulus p] (f : FpPoly p) (xs : List (ZMod64 p)) (acc : FpPoly p) :
    xs.Nodup → acc ∣ f → (∀ (c : ZMod64 p), c ∈ xs → primeFieldLinearFactor c ∣ f) → (∀ (c : ZMod64 p), c ∈ xs → ∀ (e : FpPoly p), e ∣ acc → e ∣ primeFieldLinearFactor c → e ∣ 1) → List.foldl (fun (acc : FpPoly p) (c : ZMod64 p) => acc * (FpPoly.X - FpPoly.C c)) acc xs ∣ f

    Foldl-shape divisibility: if every linear factor in xs divides f, the cumulative (acc * ∏ (X - C cᵢ)) divides f as long as acc is coprime with each new linear factor.

    The constant polynomial 1 over a prime modulus is nonzero.

    The constant polynomial 1 over a prime modulus has size 1.

    The constant polynomial 1 over a prime modulus is monic.

    theorem Hex.Berlekamp.foldl_size_and_monic {p : Nat} [ZMod64.Bounds p] [ZMod64.PrimeModulus p] (xs : List (ZMod64 p)) (acc : FpPoly p) :
    acc ≠ 0 → DensePoly.Monic acc → List.foldl (fun (acc : FpPoly p) (c : ZMod64 p) => acc * (FpPoly.X - FpPoly.C c)) acc xs ≠ 0 ∧ (List.foldl (fun (acc : DensePoly (ZMod64 p)) (c : ZMod64 p) => acc * (FpPoly.X - FpPoly.C c)) acc xs).Monic ∧ DensePoly.size (List.foldl (fun (acc : FpPoly p) (c : ZMod64 p) => acc * (FpPoly.X - FpPoly.C c)) acc xs) = DensePoly.size acc + xs.length

    Foldl induction: size grows by one for each linear factor multiplied in.

    def Hex.Berlekamp.rootsBelow {p : Nat} [ZMod64.Bounds p] (f : FpPoly p) :
    Nat → List (ZMod64 p) → List (ZMod64 p)

    The roots of f among the residues ofNat p k for k < n, listed in increasing k and consed onto acc.

    Counting down and consing keeps the loop tail-recursive and allocates only the roots it keeps, so the scan holds deg f residues rather than the whole of F_p. Filtering ZMod64.values p instead would allocate p residues, and the budget in Hex.Berlekamp.rootScanBudget only bounds the scan against the kernel computation it replaces, not in the absolute.

    Equations
    Instances For

      The roots of f in F_p, listed in canonical residue order.

      One Horner evaluation per residue, so p * f.size modular multiplications. Callers gate the scan on the field size; see Hex.Berlekamp.rootScanBudget.

      Equations
      Instances For

        The scan enumerates exactly the vanishing residues of the canonical residue list: the loop is the filter, without materializing the list.

        Membership in rootsIn is exactly vanishing of the evaluation.

        The root list has no duplicates: it enumerates the duplicate-free residue list.

        Distinct residues give a duplicate-free list of monic linear factors.

        Every listed root contributes its monic linear factor as a divisor of f.

        theorem Hex.Berlekamp.eq_of_dvd_of_monic_of_size_eq {p : Nat} [ZMod64.Bounds p] [ZMod64.PrimeModulus p] {a f : FpPoly p} (hdvd : a ∣ f) (ha : DensePoly.Monic a) (hf : DensePoly.Monic f) (hf_ne : f ≠ 0) (hsize : DensePoly.size a = DensePoly.size f) :
        a = f

        A monic divisor of a monic polynomial of the same size is that polynomial.

        theorem Hex.Berlekamp.eq_foldl_rootsIn_of_length {p : Nat} [ZMod64.Bounds p] [ZMod64.PrimeModulus p] (f : FpPoly p) (hmonic : DensePoly.Monic f) (hlen : (rootsIn f).length + 1 = DensePoly.size f) :
        List.foldl (fun (acc : FpPoly p) (c : ZMod64 p) => acc * primeFieldLinearFactor c) 1 (rootsIn f) = f

        Reconstruction from roots. When the residue scan finds deg f distinct roots of a monic f, the corresponding monic linear factors multiply back to f: their product divides f (pairwise coprime divisors), is monic, and has the same size, so it is f itself.