Documentation

HexModArith.Ntt.Transform

theorem Hex.ZMod64.NttPlan.length_pos {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
0 < n

A transform plan always has positive length.

theorem Hex.ZMod64.NttPlan.length_eq_pow_log2 {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
n = 2 ^ n.log2

Recover the executable power-of-two exponent used by the transform loop.

theorem Hex.ZMod64.NttPlan.length_lt_modulus {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
n < p

A valid transform length is strictly smaller than its prime modulus.

theorem Hex.ZMod64.NttPlan.length_ne_zero {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
↑n ≠ 0

The transform length is nonzero as a prime-field residue.

theorem Hex.ZMod64.NttPlan.invLength_mul_length {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
plan.invLength * ↑n = 1

The stored inverse-length scale cancels the transform length.

Read a forward twiddle, wrapping the requested exponent into the plan.

Equations
Instances For

    Read an inverse twiddle, wrapping the requested exponent into the plan.

    Equations
    Instances For
      theorem Hex.ZMod64.NttPlan.forwardTwiddle_value {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (i : Nat) :
      (plan.forwardTwiddle i).value = plan.root ^ (i % n)

      A forward twiddle is the corresponding wrapped root power.

      theorem Hex.ZMod64.NttPlan.inverseTwiddle_value {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (i : Nat) :
      (plan.inverseTwiddle i).value = plan.invRoot ^ (i % n)

      An inverse twiddle is the corresponding wrapped inverse-root power.

      theorem Hex.ZMod64.NttPlan.root_ne_zero {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) :
      plan.root ≠ 0

      An exact-order transform root is nonzero.

      theorem Hex.ZMod64.NttPlan.invRoot_pow_mul_root_pow {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (e : Nat) :
      plan.invRoot ^ e * plan.root ^ e = 1

      Matching inverse and forward root powers cancel.

      theorem Hex.ZMod64.NttPlan.root_half_eq_neg_one {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (hn : 1 < n) :
      plan.root ^ (n / 2) = 0 - 1

      For a nontrivial power-of-two plan, the half-order root power is -1.

      theorem Hex.ZMod64.NttPlan.root_stride_half {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (hscale : n = stride * 2 ^ (fuel + 1)) :
      (plan.root ^ stride) ^ 2 ^ fuel = 0 - 1

      At every recursive radix depth, the effective root raised to half the current transform length is minus one.

      def Hex.ZMod64.Ntt.interleave {α : Type u} :
      List α → List α → List α

      Interleave two frequency classes. Equal-length inputs produce the usual even/odd merge; the trailing clauses make the helper total.

      Equations
      Instances For
        def Hex.ZMod64.Ntt.deinterleave {α : Type u} :
        List α → List α × List α

        Split a list into its even- and odd-indexed entries.

        Equations
        Instances For
          theorem Hex.ZMod64.Ntt.deinterleave_interleave {α : Type u} (left right : List α) (hlength : left.length = right.length) :
          deinterleave (interleave left right) = (left, right)

          Deinterleaving reverses an equal-length interleave.

          def Hex.ZMod64.Ntt.forwardStage {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
          Nat → List (NttRaw2 p) → List (NttRaw2 p) → List (NttRaw2 p) × List (NttRaw2 p)

          One forward DIF stage over two equal-sized halves.

          Equations
          Instances For
            def Hex.ZMod64.Ntt.inverseStage {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
            Nat → List (NttRaw4 p) → List (NttRaw4 p) → List (NttRaw4 p) × List (NttRaw4 p)

            One inverse DIT stage over two equal-sized recursive results.

            Equations
            Instances For
              def Hex.ZMod64.Ntt.forwardStageSpec {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
              Nat → List (ZMod64 p) → List (ZMod64 p) → List (ZMod64 p) × List (ZMod64 p)

              Canonical-residue specification of one forward DIF stage.

              Equations
              Instances For
                def Hex.ZMod64.Ntt.inverseStageSpec {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
                Nat → List (ZMod64 p) → List (ZMod64 p) → List (ZMod64 p) × List (ZMod64 p)

                Canonical-residue specification of one inverse DIT stage.

                Equations
                Instances For
                  theorem Hex.ZMod64.Ntt.eval_forwardStageSpec_fst {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (point : ZMod64 p) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  evalCoeffs point (forwardStageSpec plan stride i left right).fst = evalCoeffs point left + evalCoeffs point right

                  Evaluating the sum half of a forward DIF stage adds the evaluations of the two input halves.

                  theorem Hex.ZMod64.Ntt.eval_forwardStageSpec_snd {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (point : ZMod64 p) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  evalCoeffs point (forwardStageSpec plan stride i left right).snd = plan.root ^ (i * stride) * (evalCoeffs (plan.root ^ stride * point) left - evalCoeffs (plan.root ^ stride * point) right)

                  Evaluating the difference half of a forward DIF stage absorbs its coefficient twiddles into the evaluation point.

                  theorem Hex.ZMod64.Ntt.normalize_forwardStage {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (NttRaw2 p)) :

                  Normalizing a raw forward stage gives its residue-level specification.

                  theorem Hex.ZMod64.Ntt.normalize_inverseStage {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (NttRaw4 p)) :

                  Normalizing a raw inverse stage gives its residue-level specification.

                  theorem Hex.ZMod64.Ntt.inverse_forwardStageSpec {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  have forward := forwardStageSpec plan stride i left right; inverseStageSpec plan stride i forward.fst forward.snd = (List.map (fun (value : ZMod64 p) => value + value) left, List.map (fun (value : ZMod64 p) => value + value) right)

                  Applying the inverse stage to one forward stage doubles both original halves.

                  theorem Hex.ZMod64.Ntt.inverseStageSpec_scale {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (c : ZMod64 p) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  inverseStageSpec plan stride i (List.map (fun (value : ZMod64 p) => c * value) left) (List.map (fun (value : ZMod64 p) => c * value) right) = have output := inverseStageSpec plan stride i left right; (List.map (fun (value : ZMod64 p) => c * value) output.fst, List.map (fun (value : ZMod64 p) => c * value) output.snd)

                  Inverse stages commute with a common scalar on both halves.

                  theorem Hex.ZMod64.Ntt.forwardStageSpec_lengths {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  have output := forwardStageSpec plan stride i left right; output.fst.length = left.length ∧ output.snd.length = right.length

                  A residue-level forward stage preserves both equal half lengths.

                  theorem Hex.ZMod64.Ntt.inverseStageSpec_lengths {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (ZMod64 p)) (hlength : left.length = right.length) :
                  have output := inverseStageSpec plan stride i left right; output.fst.length = left.length ∧ output.snd.length = right.length

                  A residue-level inverse stage preserves both equal half lengths.

                  def Hex.ZMod64.Ntt.forwardGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
                  Nat → List (NttRaw2 p) → List (NttRaw2 p)

                  Recursive DIF forward transform. fuel is the remaining radix-two depth and stride is the root-power stride at this level.

                  Equations
                  Instances For
                    def Hex.ZMod64.Ntt.inverseGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
                    Nat → List (NttRaw4 p) → List (NttRaw4 p)

                    Recursive DIT inverse transform. Its input is in ordinary DFT order, so the even and odd frequency classes are separated before recursion.

                    Equations
                    Instances For
                      def Hex.ZMod64.Ntt.forwardRadix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
                      Nat → List (ZMod64 p) → List (ZMod64 p)

                      Residue-level recursive specification of the forward radix-two loop.

                      Equations
                      Instances For
                        def Hex.ZMod64.Ntt.inverseRadix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride : Nat) :
                        Nat → List (ZMod64 p) → List (ZMod64 p)

                        Residue-level recursive specification of the inverse radix-two loop.

                        Equations
                        Instances For
                          theorem Hex.ZMod64.Ntt.length_interleave {α : Type u} (left right : List α) :
                          (interleave left right).length = left.length + right.length

                          Interleaving preserves the combined input length.

                          theorem Hex.ZMod64.Ntt.getElem_interleave_even {α : Type u} (left right : List α) (hlength : left.length = right.length) (k : Nat) (hk : k < left.length) :
                          (interleave left right)[2 * k] = left[k]

                          An even position of an equal-length interleave comes from the left list.

                          theorem Hex.ZMod64.Ntt.getElem_interleave_odd {α : Type u} (left right : List α) (hlength : left.length = right.length) (k : Nat) (hk : k < right.length) :
                          (interleave left right)[2 * k + 1] = right[k]

                          An odd position of an equal-length interleave comes from the right list.

                          theorem Hex.ZMod64.Ntt.forwardStage_lengths {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (NttRaw2 p)) (hlength : left.length = right.length) :
                          have output := forwardStage plan stride i left right; output.fst.length = left.length ∧ output.snd.length = right.length

                          A forward stage preserves both equal half lengths.

                          theorem Hex.ZMod64.Ntt.inverseStage_lengths {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride i : Nat) (left right : List (NttRaw4 p)) (hlength : left.length = right.length) :
                          have output := inverseStage plan stride i left right; output.fst.length = left.length ∧ output.snd.length = right.length

                          An inverse stage preserves both equal half lengths.

                          theorem Hex.ZMod64.Ntt.deinterleave_lengths {α : Type u} (values : List α) (m : Nat) (hlength : values.length = 2 * m) :
                          have halves := deinterleave values; halves.fst.length = m ∧ halves.snd.length = m

                          Deinterleaving an even list produces two equal halves.

                          theorem Hex.ZMod64.Ntt.length_forwardGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (NttRaw2 p)) (hlength : values.length = 2 ^ fuel) :
                          (forwardGo plan stride fuel values).length = 2 ^ fuel

                          The raw forward loop preserves a power-of-two input length.

                          theorem Hex.ZMod64.Ntt.length_inverseGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (NttRaw4 p)) (hlength : values.length = 2 ^ fuel) :
                          (inverseGo plan stride fuel values).length = 2 ^ fuel

                          The raw inverse loop preserves a power-of-two input length.

                          theorem Hex.ZMod64.Ntt.normalize_forwardGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (NttRaw2 p)) :
                          List.map NttRaw2.normalize (forwardGo plan stride fuel values) = forwardRadix plan stride fuel (List.map NttRaw2.normalize values)

                          The raw forward loop represents its residue-level radix specification at every recursive depth.

                          theorem Hex.ZMod64.Ntt.normalize_inverseGo {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (NttRaw4 p)) :
                          List.map NttRaw4.normalize (inverseGo plan stride fuel values) = inverseRadix plan stride fuel (List.map NttRaw4.normalize values)

                          The raw inverse loop represents its residue-level radix specification at every recursive depth.

                          theorem Hex.ZMod64.Ntt.length_forwardRadix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (ZMod64 p)) (hlength : values.length = 2 ^ fuel) :
                          (forwardRadix plan stride fuel values).length = 2 ^ fuel

                          The residue-level forward radix recurrence preserves a power-of-two length.

                          theorem Hex.ZMod64.Ntt.length_inverseRadix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (ZMod64 p)) (hlength : values.length = 2 ^ fuel) :
                          (inverseRadix plan stride fuel values).length = 2 ^ fuel

                          The residue-level inverse radix recurrence preserves a power-of-two length.

                          theorem Hex.ZMod64.Ntt.forwardRadix_eq_dft {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (ZMod64 p)) (hlength : values.length = 2 ^ fuel) (hscale : n = stride * 2 ^ fuel) :
                          forwardRadix plan stride fuel values = dft (plan.root ^ stride) (2 ^ fuel) values

                          At every recursive depth, the residue-level forward recurrence is the coefficientwise DFT for the effective root at that depth.

                          theorem Hex.ZMod64.Ntt.inverse_forwardRadix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (stride fuel : Nat) (values : List (ZMod64 p)) (hlength : values.length = 2 ^ fuel) :
                          inverseRadix plan stride fuel (forwardRadix plan stride fuel values) = List.map (fun (value : ZMod64 p) => ↑(2 ^ fuel) * value) values

                          The unscaled inverse radix recurrence cancels the forward recurrence and multiplies every coefficient by the transform length.

                          def Hex.ZMod64.Ntt.forwardRadixArray {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :

                          Residue-level forward result computed by the radix specification.

                          Equations
                          Instances For
                            def Hex.ZMod64.Ntt.inverseRadixArray {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :

                            Residue-level inverse result, including the final n⁻¹ scaling.

                            Equations
                            Instances For
                              theorem Hex.ZMod64.Ntt.forwardArray_eq_dft {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                              forwardRadixArray plan values = dftArray plan.root n values

                              The residue-level forward array is exactly the coefficientwise DFT.

                              theorem Hex.ZMod64.Ntt.inverse_forwardArray {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                              inverseRadixArray plan (forwardRadixArray plan values) = values

                              The scaled residue-level inverse exactly cancels the forward transform on an array of the plan length.

                              def Hex.ZMod64.Ntt.forward? {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :

                              Forward radix-two transform. A length mismatch is normal checked failure; successful execution reuses every root power from plan.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                def Hex.ZMod64.Ntt.inverse? {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :

                                Inverse radix-two transform, including multiplication by n⁻¹ after the raw inverse loop.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  theorem Hex.ZMod64.Ntt.forward?_eq_radix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                                  forward? plan values = some (forwardRadixArray plan values)

                                  Successful forward execution is exactly its residue-level radix specification.

                                  theorem Hex.ZMod64.Ntt.forward?_eq_dft {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                                  forward? plan values = some (dftArray plan.root n values)

                                  Successful public forward execution is the coefficientwise DFT.

                                  theorem Hex.ZMod64.Ntt.inverse?_eq_radix {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                                  inverse? plan values = some (inverseRadixArray plan values)

                                  Successful inverse execution is exactly its residue-level radix specification.

                                  theorem Hex.ZMod64.Ntt.forward?_eq_none_iff {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :
                                  forward? plan values = none ↔ values.size ≠ n

                                  Forward execution rejects exactly a length mismatch.

                                  theorem Hex.ZMod64.Ntt.inverse?_eq_none_iff {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) :
                                  inverse? plan values = none ↔ values.size ≠ n

                                  Inverse execution rejects exactly a length mismatch.

                                  theorem Hex.ZMod64.Ntt.forward?_size {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values result : Array (ZMod64 p)) (hrun : forward? plan values = some result) :
                                  result.size = n

                                  Every successful forward transform has the plan length.

                                  theorem Hex.ZMod64.Ntt.inverse?_size {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values result : Array (ZMod64 p)) (hrun : inverse? plan values = some result) :
                                  result.size = n

                                  Every successful inverse transform has the plan length.

                                  theorem Hex.ZMod64.Ntt.inverse?_forward? {p n : Nat} [Bounds p] [PrimeModulus p] (plan : NttPlan p n) (values : Array (ZMod64 p)) (hsize : values.size = n) :
                                  (forward? plan values).bind (inverse? plan) = some values

                                  On an array of the plan length, public forward execution followed by public inverse execution returns the original array.