Documentation

HexHensel.ModularPolynomial

def Hex.ZPoly.intModNat (z : Int) (m : Nat) :

Canonical nonnegative representative of z modulo m.

Computes Int.toNat (z % m); for 0 < m this is the unique value in [0, m) congruent to z. Used coefficientwise by modP and reduceModPow to land integer coefficients in the standard representative window before transport to FpPoly or back into ZPoly.

Equations
Instances For

    Windowed implementation of intModNat.

    Modular addition of canonical operands lands in [0, 2m) and modular subtraction in (-m, m), so on the modular hot path almost every coefficient is within one modulus of its canonical representative. Testing for that costs a bignum comparison and at most one bignum addition, where Int.emod costs a full division; a value already in [0, m) is returned without allocating at all. Only genuinely wide values -- products, and the descent from a doubled precision -- pay for the division.

    Proved equal to intModNat in intModNat_eq_impl.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      @[csimp]

      Proof-backed compiled implementation of the canonical representative.

      def Hex.ZPoly.intEmod (z : Int) (m : Nat) :

      Canonical nonnegative representative of z modulo m, as an Int.

      The Int-valued sibling of intModNat, for the coefficient arrays that are Int-valued on both sides of a reduction.

      Equations
      Instances For
        def Hex.ZPoly.intEmodImpl (z : Int) (m : Nat) :

        Windowed implementation of intEmod.

        Routing through intModNat would cost a multi-limb copy on every coefficient, in both directions: Int.toNat copies a big nonnegative Int into a Nat, and the value is then immediately coerced back. Since Int.emod is already nonnegative at a nonzero modulus, that round trip is pure allocation, and allocation -- not division width -- is what the modular hot path is made of.

        The two near-canonical windows are kept: modular addition of canonical operands lands in [0, 2m) and modular subtraction in (-m, m), so a coefficient already canonical is returned as itself, allocating nothing at all, and one within a modulus below costs a single addition. A genuinely wide value -- the long division's window, or the descent from a doubled precision -- pays for one Int.emod and nothing else.

        Proved equal to intEmod in intEmod_eq_impl.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          @[csimp]

          Proof-backed compiled implementation of the Int-valued canonical representative.

          theorem Hex.ZPoly.intEmod_eq_emod (z : Int) {m : Nat} (hm : 0 < m) :
          intEmod z m = z % m

          At a positive modulus intEmod is the ordinary integer remainder.

          theorem Hex.ZPoly.intEmod_mem (z : Int) {m : Nat} (hm : 0 < m) :
          0 intEmod z m intEmod z m < m

          intEmod lands in the canonical window.

          theorem Hex.ZPoly.intEmod_eq_self {z : Int} {m : Nat} (h0 : 0 z) (h1 : z < m) :
          intEmod z m = z

          A value already in the canonical window is returned unchanged.

          theorem Hex.ZPoly.intEmod_congr {a b : Int} {m : Nat} (h : a % m = b % m) :
          intEmod a m = intEmod b m

          Congruent integers have the same canonical representative.

          theorem Hex.ZPoly.intEmod_sub_intEmod (a b : Int) {m : Nat} (hm : 0 < m) :
          intEmod (a - intEmod b m) m = intEmod (a - b) m

          Reducing one summand first does not change the canonical representative of a difference: the windowed elimination may subtract the raw product where the specification subtracts its reduction.

          Reduce the coefficients of an integer polynomial modulo p.

          Equations
          Instances For

            Array-map implementation of coefficient reduction modulo p.

            Equations
            Instances For

              The direct array map computes the reference modular image.

              Exact direct-array implementation of reduction modulo p.

              This equality is intentionally not a csimp rule: on the large reduction ladder the compiler's implementation of the list/range specification is materially faster than Array.map.

              Reduce each coefficient to its canonical representative modulo p^k.

              Equations
              Instances For

                Array-map implementation of coefficient reduction modulo p^k.

                Equations
                Instances For

                  The direct array map computes the reference prime-power reduction.

                  @[csimp]

                  Proof-backed compiled implementation of prime-power coefficient reduction.

                  @[simp]

                  Coefficientwise characterisation of modP: the i-th coefficient of the reduction is the ZMod64 image of the canonical representative of the original coefficient.

                  @[simp]
                  theorem Hex.ZPoly.modP_zero (p : Nat) [ZMod64.Bounds p] :
                  modP p 0 = 0

                  Reducing the zero polynomial modulo p preserves zero.

                  @[simp]

                  Coefficientwise characterisation of reduceModPow: each coefficient is replaced by its canonical nonnegative representative in [0, p^k).

                  @[simp]

                  Reducing the zero polynomial modulo p^k preserves zero.

                  @[simp]
                  theorem Hex.ZPoly.reduceModPow_one_of_nontrivial (p k : Nat) (hpk : 1 < p ^ k) :
                  reduceModPow 1 p k = 1

                  Reducing the integer one polynomial modulo a nontrivial power preserves one.

                  If a coefficient is already divisible by p^k, its reduceModPow image vanishes.

                  For positive modulus p^k, the reduced coefficient equals the integer remainder f.coeff i % p^k. Identifies the Nat-valued executable representative with Int.emod.

                  theorem Hex.ZPoly.congr_reduceModPow (f : ZPoly) (p k : Nat) (hpk : 0 < p ^ k) :
                  (f.reduceModPow p k).congr f (p ^ k)

                  Coefficientwise reduction modulo p^k is congruent to the original polynomial.

                  theorem Hex.ZPoly.congr_reduceModPow_of_congr (f g : ZPoly) (p k : Nat) (hfg : f.congr g (p ^ k)) :

                  Congruence is preserved by coefficientwise canonical reduction modulo p^k.

                  theorem Hex.ZPoly.congr_of_dvd_modulus (f g : ZPoly) {m n : Nat} (hmn : m n) (hfg : f.congr g n) :
                  f.congr g m

                  Congruence modulo a larger modulus descends along divisibility of moduli.

                  theorem Hex.ZPoly.congr_pow_of_le (p a b : Nat) (f g : ZPoly) (hab : a b) (hfg : f.congr g (p ^ b)) :
                  f.congr g (p ^ a)

                  Congruence modulo p^b descends to congruence modulo p^a for a ≤ b.

                  theorem Hex.ZPoly.reduceModPow_eq_of_congr (f g : ZPoly) (p k : Nat) (hfg : f.congr g (p ^ k)) :

                  Alias oriented toward canonical reduction: congruent inputs have the same reduction.

                  theorem Hex.ZPoly.reduceModPow_idempotent (f : ZPoly) (p k : Nat) (hpk : 0 < p ^ k) :

                  Reducing twice to the same positive modulus is idempotent.

                  @[simp]

                  Canonical reduction modulo a positive power is idempotent.

                  The coefficient-range invariant of the modular kernels: every coefficient of f is the canonical residue in [0, m).

                  This is the invariant a lift must carry in order to drop a canonicalisation: reduceModPow_eq_self_of_canonical says it is exactly the hypothesis under which reduceModPow is the identity.

                  Equations
                  Instances For
                    theorem Hex.ZPoly.canonical_reduceModPow (f : ZPoly) (p k : Nat) (hpk : 0 < p ^ k) :
                    (f.reduceModPow p k).Canonical (p ^ k)

                    Canonical reduction at a positive modulus produces canonical coefficients.

                    theorem Hex.ZPoly.reduceModPow_eq_self_of_canonical (f : ZPoly) (p k : Nat) (hpk : 0 < p ^ k) (hf : f.Canonical (p ^ k)) :
                    f.reduceModPow p k = f

                    Canonical coefficients are fixed by reduceModPow.

                    This is the theorem that licenses deleting a redundant canonicalisation: a reduction applied to data already reduced to [0, p ^ k) returns its input unchanged, so removing it cannot change any result.

                    theorem Hex.ZPoly.modP_eq_of_congr (p : Nat) [ZMod64.Bounds p] (f g : ZPoly) (hfg : f.congr g p) :
                    modP p f = modP p g

                    Congruent integer polynomials have the same reduction modulo p.

                    @[simp]
                    theorem Hex.ZPoly.modP_reduceModPow (p k : Nat) [ZMod64.Bounds p] (f : ZPoly) :
                    modP p (f.reduceModPow p (k + 1)) = modP p f

                    Reducing modulo p^(k+1) does not change the reduction modulo p.

                    @[simp]
                    theorem Hex.ZPoly.modP_reduceModPow_of_pos (p k : Nat) [ZMod64.Bounds p] (f : ZPoly) (hk : 0 < k) :
                    modP p (f.reduceModPow p k) = modP p f

                    Reducing modulo any positive power of p does not change the reduction modulo p.

                    Lift F_p coefficients to their standard nonnegative integer representatives.

                    Equations
                    Instances For
                      @[simp]

                      Coefficientwise characterisation of liftToZ: each coefficient is the standard nonnegative Nat representative of the corresponding ZMod64 element.

                      @[simp]

                      The canonical integer lift of the zero polynomial is zero.

                      Reducing the canonical lift back modulo p recovers the original coefficient data.

                      @[simp]

                      Reducing a canonical lift back modulo p recovers the original polynomial.

                      The canonical integer lift of a monic polynomial over F_p is monic, provided the modulus is nontrivial. The 1 < p hypothesis is necessary because 1 : ZMod64 1 has representative zero.

                      A polynomial is congruent modulo p to the canonical integer lift of its reduction.

                      @[simp]
                      theorem Hex.ZPoly.modP_one (p : Nat) [ZMod64.Bounds p] :
                      modP p 1 = 1

                      Reducing the integer 1 polynomial modulo p yields the FpPoly p identity. Bottom-of-recursion case for the modP p rewrites used by Hensel lifting modules.