Skip to content

feat(NumberTheory): the number-theoretic transform#41924

Open
junjihashimoto wants to merge 3 commits into
leanprover-community:masterfrom
junjihashimoto:ntt
Open

feat(NumberTheory): the number-theoretic transform#41924
junjihashimoto wants to merge 3 commits into
leanprover-community:masterfrom
junjihashimoto:ntt

Conversation

@junjihashimoto

Copy link
Copy Markdown

The number-theoretic transform is the discrete Fourier transform of functions ZMod N → M, where M is a module over a commutative domain R containing a primitive N-th root of unity ζ (e.g. R = ZMod p with N ∣ p - 1):

ntt hζ f k = ∑ j, ζ ^ (j * k) • f j.

We prove the character orthogonality relation (sum_zmodChar_mul, from AddChar.sum_eq_ite), the Fourier inversion formula nttInv_ntt / ntt_nttInv (so the transform is bijective whenever N is invertible in R), and the bilinear Parseval identity sum_bilin_ntt_ntt_neg — over a general coefficient ring there is no norm or conjugation, and this is the correct finite-field replacement for Plancherel's theorem.

The module M is arbitrary; taking M to be a hypercomplex algebra over R (e.g. the octonions or sedenions over ZMod p from #41919, whence the dependency) yields hypercomplex number-theoretic transforms, recorded as an example. This is the finite-field counterpart of the archimedean theory in #41921/#41922.

The NTT is the transform underlying polynomial multiplication in lattice-based cryptography (e.g. ML-KEM/Kyber), so this also provides groundwork for formalizing those schemes.

Define the Cayley-Dickson double of a (possibly non-associative) star
ring, and show that it preserves NonAssocRing and StarRing, so the
construction iterates: quaternions -> octonions -> sedenions -> ...

The doubling unit l = (0, 1) satisfies l * (l * x) = -x at every level
of the tower, by a computation using only that star is an involution
(no alternativity is developed). Left multiplication by l is therefore
a complex structure on every Cayley-Dickson algebra.
The discrete Fourier transform of functions ZMod N -> M for M a module
over a commutative domain containing a primitive N-th root of unity:
orthogonality, the Fourier inversion formula, and the bilinear Parseval
identity (the finite-field replacement for Plancherel's theorem). The
module can be a hypercomplex algebra, giving hypercomplex NTTs.
@github-actions github-actions Bot added the new-contributor This PR was made by a contributor with at most 5 merged PRs. Welcome to the community! label Jul 19, 2026
@github-actions

Copy link
Copy Markdown

Welcome new contributor!

Thank you for contributing to Mathlib! If you haven't done so already, please review our contribution guidelines, as well as the style guide and naming conventions. In particular, we kindly remind contributors that we have guidelines regarding the use of AI when making pull requests.

We use a review queue to manage reviews. If your PR does not appear there, it is probably because it is not successfully building (i.e., it doesn't have a green checkmark), has the awaiting-author tag, or another reason described in the Lifecycle of a PR. The review dashboard has a dedicated webpage which shows whether your PR is on the review queue, and (if not), why.

If you haven't already done so, please come to https://leanprover.zulipchat.com/, introduce yourself, and mention your new PR.

Thank you again for joining our community.

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

PR summary 93b9e11055

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference
Mathlib.Algebra.CayleyDickson (new file) 1335
Mathlib.Algebra.Octonion (new file) 1336
Mathlib.NumberTheory.NumberTheoreticTransform (new file) 2661

Declarations diff (regex)

+ CayleyDickson
+ Octonion
+ Quaternion.instStarModule
+ Sedenion
+ Trigintaduonion
+ add_fst
+ add_snd
+ instModule
+ instance : Add (CayleyDickson A) := ⟨fun x y => ⟨x.fst + y.fst, x.snd + y.snd⟩⟩
+ instance : AddCommGroup (CayleyDickson A)
+ instance : IntCast (CayleyDickson A) := ⟨fun n => ⟨n, 0⟩⟩
+ instance : Mul (CayleyDickson A)
+ instance : NatCast (CayleyDickson A) := ⟨fun n => ⟨n, 0⟩⟩
+ instance : Neg (CayleyDickson A) := ⟨fun x => ⟨-x.fst, -x.snd⟩⟩
+ instance : NonAssocRing (CayleyDickson A)
+ instance : NonUnitalNonAssocRing (CayleyDickson A)
+ instance : One (CayleyDickson A) := ⟨⟨1, 0⟩⟩
+ instance : Star (CayleyDickson A) := ⟨fun x => ⟨star x.fst, -x.snd⟩⟩
+ instance : StarRing (CayleyDickson A)
+ instance : Sub (CayleyDickson A) := ⟨fun x y => ⟨x.fst - y.fst, x.snd - y.snd⟩⟩
+ instance : Zero (CayleyDickson A) := ⟨⟨0, 0⟩⟩
+ instance [Monoid S] [DistribMulAction S A]
+ instance [Monoid S] [DistribMulAction S A] [Star S] [TrivialStar S] [StarModule S A] :
+ instance [Monoid S] [Star S] [TrivialStar S] [DistribMulAction S A] [StarModule S A]
+ instance [SMul S A] : SMul S (CayleyDickson A)
+ instance [Semiring S] [Module S A] [Module.Finite S A] :
+ intCast_fst
+ intCast_snd
+ mul_def
+ mul_fst
+ mul_smul_comm'
+ mul_snd
+ natCast_fst
+ natCast_snd
+ neg_fst
+ neg_snd
+ ntt
+ nttInv
+ nttInv_ntt
+ ntt_nttInv
+ one_fst
+ one_snd
+ smul_fst
+ smul_mul_assoc'
+ smul_snd
+ star_fst
+ star_snd
+ sub_fst
+ sub_snd
+ sum_bilin_ntt_ntt_neg
+ sum_zmodChar_mul
+ sum_zmodChar_smul_ntt_neg
+ toProd
+ toProdHom
+ toProdLinearEquiv
+ toProd_injective
+ unit
+ unit_fst
+ unit_mul
+ unit_mul_unit
+ unit_mul_unit_mul
+ unit_snd
+ zero_fst
+ zero_snd

You can run this locally as follows
## from your `mathlib4` directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci

## summary with just the declaration names:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh in the mathlib-ci repository contains some details about this script.

Declarations diff (Lean)

Lean-aware diff — post-build, computed from the Lean environment (commit 93b9e11).

  • +82 new declarations
  • −0 removed declarations
+AddChar.zmodChar.congr_simp
+CayleyDickson
+CayleyDickson.add_fst
+CayleyDickson.add_snd
+CayleyDickson.casesOn
+CayleyDickson.ctorIdx
+CayleyDickson.ext
+CayleyDickson.ext_iff
+CayleyDickson.fst
+CayleyDickson.instAdd
+CayleyDickson.instAddCommGroup
+CayleyDickson.instFinite
+CayleyDickson.instIntCast
+CayleyDickson.instIsScalarTowerOfSMulCommClass
+CayleyDickson.instModule
+CayleyDickson.instMul
+CayleyDickson.instNatCast
+CayleyDickson.instNeg
+CayleyDickson.instNonAssocRing
+CayleyDickson.instNonUnitalNonAssocRing
+CayleyDickson.instOne
+CayleyDickson.instSMul
+CayleyDickson.instSMulCommClassOfTrivialStarOfStarModuleOfIsScalarTower
+CayleyDickson.instStar
+CayleyDickson.instStarModuleOfTrivialStar
+CayleyDickson.instStarRing
+CayleyDickson.instSub
+CayleyDickson.instZero
+CayleyDickson.intCast_fst
+CayleyDickson.intCast_snd
+CayleyDickson.mk
+CayleyDickson.mk.inj
+CayleyDickson.mk.injEq
+CayleyDickson.mk.noConfusion
+CayleyDickson.mk.sizeOf_spec
+CayleyDickson.mul_def
+CayleyDickson.mul_fst
+CayleyDickson.mul_smul_comm'
+CayleyDickson.mul_snd
+CayleyDickson.natCast_fst
+CayleyDickson.natCast_snd
+CayleyDickson.neg_fst
+CayleyDickson.neg_snd
+CayleyDickson.noConfusion
+CayleyDickson.noConfusionType
+CayleyDickson.one_fst
+CayleyDickson.one_snd
+CayleyDickson.rec
+CayleyDickson.recOn
+CayleyDickson.smul_fst
+CayleyDickson.smul_mul_assoc'
+CayleyDickson.smul_snd
+CayleyDickson.snd
+CayleyDickson.star_fst
+CayleyDickson.star_snd
+CayleyDickson.sub_fst
+CayleyDickson.sub_snd
+CayleyDickson.toProd
+CayleyDickson.toProdHom
+CayleyDickson.toProdLinearEquiv
+CayleyDickson.toProdLinearEquiv_apply
+CayleyDickson.toProd_injective
+CayleyDickson.unit
+CayleyDickson.unit_fst
+CayleyDickson.unit_mul
+CayleyDickson.unit_mul_unit
+CayleyDickson.unit_mul_unit_mul
+CayleyDickson.unit_snd
+CayleyDickson.zero_fst
+CayleyDickson.zero_snd
+Octonion
+Quaternion.instStarModule
+Sedenion
+Trigintaduonion
+ZMod.ntt
+ZMod.ntt.congr_simp
+ZMod.nttInv
+ZMod.nttInv_ntt
+ZMod.ntt_nttInv
+ZMod.sum_bilin_ntt_ntt_neg
+ZMod.sum_zmodChar_mul
+ZMod.sum_zmodChar_smul_ntt_neg

No changes to strong technical debt.

Increase in weak tech debt: (relative, absolute) = (3.00, 0.00)
Current number Change Type (weak)
5017 3 exposed public sections

Current commit 93b9e11055
Reference commit 8c79cb4f54

This script lives in the mathlib-ci repository. To run it locally, from your mathlib4 directory:

git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
../mathlib-ci/scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@mathlib-dependent-issues

Copy link
Copy Markdown

This PR/issue depends on:

@mathlib-dependent-issues mathlib-dependent-issues Bot added the blocked-by-other-PR This PR depends on another PR (this label is automatically managed by a bot) label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked-by-other-PR This PR depends on another PR (this label is automatically managed by a bot) new-contributor This PR was made by a contributor with at most 5 merged PRs. Welcome to the community!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant