arnaucube
arnaucube/poulpyPublic Self-hosted repository
[prime]: nth_root does not mutate prime anymore
Jean-Philippe Bossuat jeanphilippe.bossuat@gmail.com
Fri, 20 Dec 2024 13:49:37 +0100
commit

ad68ce83cf544cc3fe64a100e0091a8e9fb005b9

parent

5dd371f6b04ed24512f1d11070272f5f954a0eae

M benches/ntt.rs → benches/ntt.rs

@@ -3,8 +3,8 @@ use math::{modulus::prime::Prime,dft::ntt::Table};

use math::dft::DFT; fn forward_inplace(c: &mut Criterion) { - fn runner<T: DFT<u64> + 'static>(prime_instance: &mut Prime<u64>, nth_root: u64) -> Box<dyn FnMut()+ '_> { - let ntt_table: Table<'_, u64> = Table::<u64>::new(prime_instance, nth_root); + fn runner<T: DFT<u64> + 'static>(prime_instance: Prime<u64>, nth_root: u64) -> Box<dyn FnMut()> { + let ntt_table: Table<u64> = Table::<u64>::new(prime_instance, nth_root); let mut a: Vec<u64> = vec![0; (nth_root >> 1) as usize]; for i in 0..a.len(){ a[i] = i as u64;

@@ -21,7 +21,7 @@ let mut prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1);

let runners = [ ("prime", { - runner::<Table<'_, u64>>(&mut prime_instance, 1<<log_nth_root) + runner::<Table<u64>>(prime_instance, 1<<log_nth_root) }), ]; for (name, mut runner) in runners {

@@ -32,8 +32,8 @@ }

} fn forward_inplace_lazy(c: &mut Criterion) { - fn runner<T: DFT<u64> + 'static>(prime_instance: &mut Prime<u64>, nth_root: u64) -> Box<dyn FnMut()+ '_> { - let ntt_table: Table<'_, u64> = Table::<u64>::new(prime_instance, nth_root); + fn runner<T: DFT<u64> + 'static>(prime_instance: Prime<u64>, nth_root: u64) -> Box<dyn FnMut()> { + let ntt_table: Table<u64> = Table::<u64>::new(prime_instance, nth_root); let mut a: Vec<u64> = vec![0; (nth_root >> 1) as usize]; for i in 0..a.len(){ a[i] = i as u64;

@@ -46,11 +46,11 @@

let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = c.benchmark_group("forward_inplace_lazy"); for log_nth_root in 11..17 { - let mut prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); + let prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); let runners = [ ("prime", { - runner::<Table<'_, u64>>(&mut prime_instance, 1<<log_nth_root) + runner::<Table<u64>>(prime_instance, 1<<log_nth_root) }), ]; for (name, mut runner) in runners {

@@ -61,8 +61,8 @@ }

} fn backward_inplace(c: &mut Criterion) { - fn runner<T: DFT<u64> + 'static>(prime_instance: &mut Prime<u64>, nth_root: u64) -> Box<dyn FnMut()+ '_> { - let ntt_table: Table<'_, u64> = Table::<u64>::new(prime_instance, nth_root); + fn runner<T: DFT<u64> + 'static>(prime_instance: Prime<u64>, nth_root: u64) -> Box<dyn FnMut()> { + let ntt_table: Table<u64> = Table::<u64>::new(prime_instance, nth_root); let mut a: Vec<u64> = vec![0; (nth_root >> 1) as usize]; for i in 0..a.len(){ a[i] = i as u64;

@@ -75,11 +75,11 @@

let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = c.benchmark_group("backward_inplace"); for log_nth_root in 11..18 { - let mut prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); + let prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); let runners = [ ("prime", { - runner::<Table<'_, u64>>(&mut prime_instance, 1<<log_nth_root) + runner::<Table<u64>>(prime_instance, 1<<log_nth_root) }), ]; for (name, mut runner) in runners {

@@ -90,8 +90,8 @@ }

} fn backward_inplace_lazy(c: &mut Criterion) { - fn runner<T: DFT<u64> + 'static>(prime_instance: &mut Prime<u64>, nth_root: u64) -> Box<dyn FnMut()+ '_> { - let ntt_table: Table<'_, u64> = Table::<u64>::new(prime_instance, nth_root); + fn runner<T: DFT<u64> + 'static>(prime_instance: Prime<u64>, nth_root: u64) -> Box<dyn FnMut()> { + let ntt_table: Table<u64> = Table::<u64>::new(prime_instance, nth_root); let mut a: Vec<u64> = vec![0; (nth_root >> 1) as usize]; for i in 0..a.len(){ a[i] = i as u64;

@@ -104,11 +104,11 @@

let mut b: criterion::BenchmarkGroup<'_, criterion::measurement::WallTime> = c.benchmark_group("backward_inplace_lazy"); for log_nth_root in 11..17 { - let mut prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); + let prime_instance: Prime<u64> = Prime::<u64>::new(0x1fffffffffe00001, 1); let runners = [ ("prime", { - runner::<Table<'_, u64>>(&mut prime_instance, 1<<log_nth_root) + runner::<Table<u64>>(prime_instance, 1<<log_nth_root) }), ]; for (name, mut runner) in runners {
M examples/main.rs → examples/main.rs

@@ -1,11 +1,12 @@

extern crate math; +use math::ring::Ring; use math::modulus::prime::Prime; use math::dft::ntt::Table; fn main() { // Example usage of `Prime<u64>` let q_base: u64 = 0x1fffffffffe00001; // Example prime base - let q_power: u64 = 1; // Example power + let q_power: usize = 1; // Example power let mut prime_instance: Prime<u64> = Prime::<u64>::new(q_base, q_power); // Display the fields of `Prime` to verify

@@ -17,7 +18,7 @@

let n: u64 = 1024; let nth_root: u64 = n<<1; - let ntt_table: Table<'_, u64> = Table::<u64>::new(&mut prime_instance, nth_root); + let ntt_table: Table<u64> = Table::<u64>::new(prime_instance, nth_root); let mut a: Vec<u64> = vec![0; (nth_root >> 1) as usize];

@@ -34,5 +35,7 @@

ntt_table.backward_inplace(&mut a); println!("{:?}", a); + + let r : Ring<u64> = Ring::<u64>::new(n as usize, q_base, q_power); }
M src/dft/ntt.rs → src/dft/ntt.rs

@@ -6,8 +6,8 @@ use crate::modulus::WordOps;

use crate::dft::DFT; use itertools::izip; -pub struct Table<'a, O>{ - prime:&'a Prime<O>, +pub struct Table<O>{ + prime:Prime<O>, psi_forward_rev:Vec<Shoup<u64>>, psi_backward_rev: Vec<Shoup<u64>>, q:O,

@@ -15,8 +15,8 @@ two_q:O,

four_q:O, } -impl<'a> Table<'a, u64> { - pub fn new(prime: &'a mut Prime<u64>, nth_root: u64)->Self{ +impl Table< u64> { + pub fn new(prime: Prime<u64>, nth_root: u64)->Self{ assert!(nth_root&(nth_root-1) == 0, "invalid argument: nth_root = {} is not a power of two", nth_root);

@@ -46,14 +46,16 @@

psi_forward_rev[i_rev] = prime.shoup.prepare(powers_forward); psi_backward_rev[i_rev] = prime.shoup.prepare(powers_backward); } + + let q: u64 = prime.q(); Self{ prime: prime, psi_forward_rev: psi_forward_rev, psi_backward_rev: psi_backward_rev, - q:prime.q(), - two_q:prime.q()<<1, - four_q:prime.q()<<2, + q:q, + two_q:q<<1, + four_q:q<<2, } }

@@ -64,7 +66,7 @@ }

} -impl<'a> DFT<u64> for Table<'a,u64>{ +impl DFT<u64> for Table<u64>{ fn forward_inplace(&self, a: &mut [u64]){ self.forward_inplace(a) }

@@ -82,7 +84,7 @@ self.backward_inplace_lazy(a)

} } -impl<'a> Table<'a,u64>{ +impl Table<u64>{ pub fn forward_inplace_lazy(&self, a: &mut [u64]){ self.forward_inplace_core::<true>(a);
M src/modulus/impl_u64/prime.rs → src/modulus/impl_u64/prime.rs

@@ -9,7 +9,7 @@

/// Returns a new instance of Prime<u64>. /// Panics if q_base is not a prime > 2 and /// if q_base^q_power would overflow u64. - pub fn new(q_base: u64, q_power: u64) -> Self{ + pub fn new(q_base: u64, q_power: usize) -> Self{ assert!(is_prime(q_base) && q_base > 2); Self::new_unchecked(q_base, q_power) }

@@ -17,7 +17,7 @@

/// Returns a new instance of Prime<u64>. /// Does not check if q_base is a prime > 2. /// Panics if q_base^q_power would overflow u64. - pub fn new_unchecked(q_base: u64, q_power: u64) -> Self { + pub fn new_unchecked(q_base: u64, q_power: usize) -> Self { let mut q = q_base; for _i in 1..q_power{

@@ -31,7 +31,7 @@ for _i in 1..q_power{

phi *= q_base } - Self { + let mut prime: Prime<u64> = Self { q:q, q_base:q_base, q_power:q_power,

@@ -39,7 +39,12 @@ factors: Vec::new(),

montgomery:MontgomeryPrecomp::new(q), shoup:ShoupPrecomp::new(q), phi:phi, - } + }; + + prime.check_factors(); + + prime + } pub fn q(&self) -> u64{

@@ -50,7 +55,7 @@ pub fn q_base(&self) -> u64{

self.q_base } - pub fn q_power(&self) -> u64{ + pub fn q_power(&self) -> usize{ self.q_power }

@@ -84,9 +89,7 @@ }

impl Prime<u64>{ /// Returns the smallest nth primitive root of q_base. - pub fn primitive_root(&mut self) -> u64{ - - self.check_factors(); + pub fn primitive_root(&self) -> u64{ let mut candidate: u64 = 1u64; let mut not_found: bool = true;

@@ -113,7 +116,7 @@ candidate

} /// Returns an nth primitive root of q = q_base^q_power in Montgomery. - pub fn primitive_nth_root(&mut self, nth_root:u64) -> u64{ + pub fn primitive_nth_root(&self, nth_root:u64) -> u64{ assert!(self.q & (nth_root-1) == 1, "invalid prime: q = {} % nth_root = {} = {} != 1", self.q, nth_root, self.q & (nth_root-1));
M src/modulus/prime.rs → src/modulus/prime.rs

@@ -1,11 +1,11 @@

-use crate::modulus::montgomery::{MontgomeryPrecomp, Montgomery}; -use crate::modulus::shoup::{ShoupPrecomp}; - +use crate::modulus::montgomery::MontgomeryPrecomp; +use crate::modulus::shoup::ShoupPrecomp; +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Prime<O> { pub q: O, /// q_base^q_powers pub q_base: O, - pub q_power: O, + pub q_power: usize, pub factors: Vec<O>, /// distinct factors of q-1 pub montgomery: MontgomeryPrecomp<O>, pub shoup:ShoupPrecomp<O>,
M src/modulus/shoup.rs → src/modulus/shoup.rs

@@ -14,6 +14,7 @@ &self.1

} } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ShoupPrecomp<O>{ pub q: O, pub one: Shoup<O>,
M src/ring.rs → src/ring.rs

@@ -7,5 +7,5 @@

pub struct Ring<O>{ pub n:usize, pub modulus:Prime<O>, - pub dft:dyn DFT<O>, + pub dft:Box<dyn DFT<O>>, }
M src/ring/impl_u64/mod.rs → src/ring/impl_u64/mod.rs

@@ -1,1 +1,2 @@

-pub mod automorphism;+pub mod automorphism; +pub mod ring;
A src/ring/impl_u64/ring.rs

@@ -0,0 +1,23 @@

+use crate::ring::Ring; +use crate::dft::ntt::Table; +use crate::modulus::prime::Prime; +use crate::poly::Poly; + +impl Ring<u64>{ + pub fn new(n:usize, q_base:u64, q_power:usize) -> Self{ + let prime: Prime<u64> = Prime::<u64>::new(q_base, q_power); + Self { + n: n, + modulus: prime.clone(), + dft: Box::new(Table::<u64>::new(prime, (2 * n) as u64)), + } + } + + pub fn n(&self) -> usize{ + return self.n + } + + pub fn new_poly(&self) -> Poly<u64>{ + Poly::<u64>::new(self.n()) + } +}