From 74bfb52ada7532936176cf68ff8897ec47d5fa67 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bossuat Date: Fri, 10 Jan 2025 21:52:40 +0100 Subject: [PATCH] more additions to automorphisms --- math/examples/main.rs | 2 +- math/src/ring/impl_u64/automorphism.rs | 102 ++++++++++++++++++++++-- math/src/ring/impl_u64/mod.rs | 2 + math/src/ring/impl_u64/packing.rs | 50 ++---------- math/src/ring/impl_u64/trace.rs | 32 ++++++++ math/src/ring/impl_u64/utils.rs | 38 +++++++++ math/tests/automorphism.rs | 2 +- rustc-ice-2025-01-10T11_02_18-37328.txt | 63 --------------- 8 files changed, 177 insertions(+), 114 deletions(-) create mode 100644 math/src/ring/impl_u64/trace.rs create mode 100644 math/src/ring/impl_u64/utils.rs delete mode 100644 rustc-ice-2025-01-10T11_02_18-37328.txt diff --git a/math/examples/main.rs b/math/examples/main.rs index 96242bd..8039886 100644 --- a/math/examples/main.rs +++ b/math/examples/main.rs @@ -44,7 +44,7 @@ fn main() { p0.0[i] = i as u64 } - r.automorphism::(&p0, 2 * r.n - 1, nth_root, &mut p1); + r.a_apply_automorphism_into_b::(&p0, 2 * r.n - 1, nth_root, &mut p1); println!("{:?}", p1); } diff --git a/math/src/ring/impl_u64/automorphism.rs b/math/src/ring/impl_u64/automorphism.rs index a366d00..bbb93c9 100644 --- a/math/src/ring/impl_u64/automorphism.rs +++ b/math/src/ring/impl_u64/automorphism.rs @@ -1,6 +1,7 @@ -use crate::modulus::WordOps; +use crate::modulus::{REDUCEMOD, WordOps}; use crate::poly::Poly; use crate::ring::Ring; +use crate::modulus::{ONCE, ScalarOperations}; /// Returns a lookup table for the automorphism X^{i} -> X^{i * k mod nth_root}. /// Method will panic if n or nth_root are not power-of-two. @@ -44,7 +45,41 @@ pub fn automorphism_index(n: usize, nth_root: usize, gal_el: us } impl Ring { - pub fn automorphism( + + // b <- auto(a) + pub fn a_apply_automorphism_into_b( + &self, + a: &Poly, + gal_el: usize, + nth_root: usize, + b: &mut Poly, + ){ + self.apply_automorphism_core::<0, ONCE, NTT>(a, gal_el, nth_root, b) + } + + // b <- REDUCEMOD(b + auto(a)) + pub fn a_apply_automorphism_add_b_into_b( + &self, + a: &Poly, + gal_el: usize, + nth_root: usize, + b: &mut Poly, + ){ + self.apply_automorphism_core::<1, REDUCE, NTT>(a, gal_el, nth_root, b) + } + + // b <- REDUCEMOD(b - auto(a)) + pub fn a_apply_automorphism_sub_b_into_b( + &self, + a: &Poly, + gal_el: usize, + nth_root: usize, + b: &mut Poly, + ){ + self.apply_automorphism_core::<2, REDUCE, NTT>(a, gal_el, nth_root, b) + } + + fn apply_automorphism_core( &self, a: &Poly, gal_el: usize, @@ -81,7 +116,12 @@ impl Ring { let i_rev: usize = 2 * i.reverse_bits_msb(log_nth_root_half) + 1; let gal_el_i: usize = (((gal_el * i_rev) & mask) - 1) >> 1; let idx: usize = gal_el_i.reverse_bits_msb(log_nth_root_half); - b_vec[idx] = *ai; + match MOD{ + 0 =>{b_vec[idx] = *ai} + 1=>{self.modulus.sa_add_sb_into_sb::(ai, &mut b_vec[idx])} + 2=>{self.modulus.sa_sub_sb_into_sa::<1, REDUCE>(ai, &mut b_vec[idx])} + _=>{panic!("invalid const MOD should be 0, 1, or 2 but is {}", MOD)} + } }); } else { let n: usize = a.n(); @@ -92,12 +132,49 @@ impl Ring { let gal_el_i: usize = i * gal_el; let sign: u64 = ((gal_el_i >> log_n) & 1) as u64; let i_out: usize = gal_el_i & mask; - b_vec[i_out] = ai * (sign ^ 1) | (q - ai) * sign + let v: u64 = ai * (sign ^ 1) | (q - ai) * sign; + match MOD{ + 0 =>{b_vec[i_out] = v} + 1=>{self.modulus.sa_add_sb_into_sb::(&v, &mut b_vec[i_out])} + 2=>{self.modulus.sa_sub_sb_into_sa::<1, REDUCE>(&v, &mut b_vec[i_out])} + _=>{panic!("invalid const MOD should be 0, 1, or 2 but is {}", MOD)} + } }); } } - pub fn automorphism_from_index( + // b <- auto(a) + pub fn a_apply_automorphism_from_index_into_b( + &self, + a: &Poly, + idx: &[usize], + b: &mut Poly, + ){ + self.automorphism_from_index_core::<0, ONCE, NTT>(a, idx, b) + } + + // b <- REDUCEMOD(b + auto(a)) + pub fn a_apply_automorphism_from_index_add_b_into_b( + &self, + a: &Poly, + idx: &[usize], + b: &mut Poly, + ){ + self.automorphism_from_index_core::<1, REDUCE, NTT>(a, idx, b) + } + + // b <- REDUCEMOD(b - auto(a)) + pub fn a_apply_automorphism_from_index_sub_b_into_b( + &self, + a: &Poly, + idx: &[usize], + b: &mut Poly, + ){ + self.automorphism_from_index_core::<2, REDUCE, NTT>(a, idx, b) + } + + // b <- auto(a) if OVERWRITE else b <- REDUCEMOD(b + auto(a)) + fn automorphism_from_index_core( &self, a: &Poly, idx: &[usize], @@ -115,7 +192,12 @@ impl Ring { if NTT { a_vec.iter().enumerate().for_each(|(i, ai)| { - b_vec[idx[i]] = *ai; + match MOD{ + 0 =>{ b_vec[idx[i]] = *ai} + 1 =>{self.modulus.sa_add_sb_into_sb::(ai, &mut b_vec[idx[i]])} + 2=>{self.modulus.sa_sub_sb_into_sa::<1, REDUCE>(ai, &mut b_vec[idx[i]])} + _=>{panic!("invalid const MOD should be 0, 1, or 2 but is {}", MOD)} + } }); } else { let n: usize = a.n(); @@ -123,7 +205,13 @@ impl Ring { let q: u64 = self.modulus.q(); a_vec.iter().enumerate().for_each(|(i, ai)| { let sign: u64 = (idx[i] >> usize::BITS - 1) as u64; - b_vec[idx[i] & mask] = ai * (sign ^ 1) | (q - ai) * sign; + let v: u64 = ai * (sign ^ 1) | (q - ai) * sign; + match MOD{ + 0 =>{b_vec[idx[i] & mask] = v} + 1 =>{self.modulus.sa_add_sb_into_sb::(&v, &mut b_vec[idx[i] & mask])} + 2=>{self.modulus.sa_sub_sb_into_sa::<1, REDUCE>(&v, &mut b_vec[idx[i] & mask])} + _=>{panic!("invalid const MOD should be 0, 1, or 2 but is {}", MOD)} + } }); } } diff --git a/math/src/ring/impl_u64/mod.rs b/math/src/ring/impl_u64/mod.rs index 456fb78..00b6dfa 100644 --- a/math/src/ring/impl_u64/mod.rs +++ b/math/src/ring/impl_u64/mod.rs @@ -1,6 +1,8 @@ pub mod automorphism; pub mod packing; +pub mod trace; pub mod rescaling_rns; pub mod ring; pub mod ring_rns; pub mod sampling; +pub mod utils; \ No newline at end of file diff --git a/math/src/ring/impl_u64/packing.rs b/math/src/ring/impl_u64/packing.rs index 45c00aa..f485112 100644 --- a/math/src/ring/impl_u64/packing.rs +++ b/math/src/ring/impl_u64/packing.rs @@ -3,41 +3,8 @@ use crate::modulus::ONCE; use crate::poly::Poly; use crate::ring::Ring; use std::cmp::min; -use std::collections::HashSet; impl Ring { - // Generates a vector storing {X^{2^0}, X^{2^1}, .., X^{2^log_n}}. - pub fn gen_x_pow_2(&self, log_n: usize) -> Vec> { - let mut x_pow: Vec> = Vec::>::with_capacity(log_n); - - (0..log_n).for_each(|i| { - let mut idx: usize = 1 << i; - - if INV { - idx = self.n() - idx; - } - - x_pow.push(self.new_poly()); - - if i == 0 { - x_pow[i].0[idx] = self.modulus.montgomery.one(); - self.ntt_inplace::(&mut x_pow[i]); - } else { - let (left, right) = x_pow.split_at_mut(i); - self.a_mul_b_montgomery_into_c::(&left[i - 1], &left[i - 1], &mut right[0]); - } - }); - - if INV { - self.a_neg_into_a::<1, ONCE>(&mut x_pow[0]); - } - - if !NTT { - x_pow.iter_mut().for_each(|x| self.intt_inplace::(x)); - } - - x_pow - } pub fn pack( &self, @@ -61,8 +28,6 @@ impl Ring { let gap: usize = max_gap(&indices); - let set: HashSet<_> = indices.into_iter().collect(); - if !ZEROGARBAGE { if gap > 0 { log_end -= gap.trailing_zeros() as usize; @@ -79,7 +44,7 @@ impl Ring { .barrett .prepare(self.modulus.inv(1 << (log_end - log_start))); - set.iter().for_each(|i| { + indices.iter().for_each(|i| { if let Some(poly) = polys[*i].as_mut() { if !NTT { self.ntt_inplace::(poly); @@ -111,15 +76,14 @@ impl Ring { let gal_el: usize = self.galois_element((1 << i) >> 1, i == 0, log_nth_root); if !polys_hi[j].is_none() { - self.automorphism::(&tmpa, gal_el, 2 << self.log_n(), &mut tmpb); - self.a_add_b_into_b::(&tmpb, poly_lo); + self.a_apply_automorphism_add_b_into_b::(&tmpa, gal_el, 2 << self.log_n(), poly_lo); } else { - self.automorphism::(poly_lo, gal_el, nth_root, &mut tmpa); + self.a_apply_automorphism_into_b::(poly_lo, gal_el, nth_root, &mut tmpa); self.a_add_b_into_b::(&tmpa, poly_lo); } } else if let Some(poly_hi) = polys_hi[j].as_mut() { let gal_el: usize = self.galois_element((1 << i) >> 1, i == 0, log_nth_root); - self.automorphism::(poly_hi, gal_el, nth_root, &mut tmpa); + self.a_apply_automorphism_into_b::(poly_hi, gal_el, nth_root, &mut tmpa); self.a_sub_b_into_a::<1, ONCE>(&tmpa, poly_hi); std::mem::swap(&mut polys_lo[j], &mut polys_hi[j]); } @@ -136,12 +100,14 @@ impl Ring { } } -// Returns the largest gap. + +// Returns the largest gap between two values in an ordered array of distinct values. +// Panics if the array is not ordered or values are not distincts. fn max_gap(vec: &[usize]) -> usize { let mut gap: usize = usize::MAX; for i in 1..vec.len() { let (l, r) = (vec[i - 1], vec[i]); - assert!(r > l, "invalid input vec: not sorted"); + assert!(r > l, "invalid input vec: not sorted or collision between indices"); gap = min(gap, r - l); if gap == 1 { break; diff --git a/math/src/ring/impl_u64/trace.rs b/math/src/ring/impl_u64/trace.rs new file mode 100644 index 0000000..6402841 --- /dev/null +++ b/math/src/ring/impl_u64/trace.rs @@ -0,0 +1,32 @@ +use crate::ring::Ring; +use crate::poly::Poly; +use crate::modulus::barrett::Barrett; +use crate::modulus::ONCE; + +impl Ring{ + pub fn trace_inplace(&self, log_start: usize, log_end: usize, a: &mut Poly){ + assert!(log_end <= self.log_n(), "invalid argument log_end: log_end={} > self.log_n()={}", log_end, self.log_n()); + assert!(log_end > log_start, "invalid argument log_start: log_start={} > log_end={}", log_start, log_end); + + let log_steps = log_end - log_start; + + if log_steps > 0 { + let n_inv: Barrett = self.modulus.barrett.prepare(self.modulus.inv(1<(&n_inv, a); + + if !NTT{ + self.ntt_inplace::(a); + } + + let mut tmp: Poly = self.new_poly(); + + (log_start..log_end).for_each(|i|{ + + }); + } + + + + + } +} \ No newline at end of file diff --git a/math/src/ring/impl_u64/utils.rs b/math/src/ring/impl_u64/utils.rs new file mode 100644 index 0000000..9a5bde2 --- /dev/null +++ b/math/src/ring/impl_u64/utils.rs @@ -0,0 +1,38 @@ +use crate::ring::Ring; +use crate::poly::Poly; +use crate::modulus::ONCE; + +impl Ring{ + // Generates a vector storing {X^{2^0}, X^{2^1}, .., X^{2^log_n}}. + pub fn gen_x_pow_2(&self, log_n: usize) -> Vec> { + let mut x_pow: Vec> = Vec::>::with_capacity(log_n); + + (0..log_n).for_each(|i| { + let mut idx: usize = 1 << i; + + if INV { + idx = self.n() - idx; + } + + x_pow.push(self.new_poly()); + + if i == 0 { + x_pow[i].0[idx] = self.modulus.montgomery.one(); + self.ntt_inplace::(&mut x_pow[i]); + } else { + let (left, right) = x_pow.split_at_mut(i); + self.a_mul_b_montgomery_into_c::(&left[i - 1], &left[i - 1], &mut right[0]); + } + }); + + if INV { + self.a_neg_into_a::<1, ONCE>(&mut x_pow[0]); + } + + if !NTT { + x_pow.iter_mut().for_each(|x| self.intt_inplace::(x)); + } + + x_pow + } +} \ No newline at end of file diff --git a/math/tests/automorphism.rs b/math/tests/automorphism.rs index 421e9a5..3e88be4 100644 --- a/math/tests/automorphism.rs +++ b/math/tests/automorphism.rs @@ -39,7 +39,7 @@ fn test_automorphism_u64(ring: &Ring, nth_root: usize) { ring.ntt_inplace::(&mut p0); } - ring.automorphism::(&p0, 2 * n - 1, nth_root, &mut p1); + ring.a_apply_automorphism_into_b::(&p0, 2 * n - 1, nth_root, &mut p1); if NTT { ring.intt_inplace::(&mut p1); diff --git a/rustc-ice-2025-01-10T11_02_18-37328.txt b/rustc-ice-2025-01-10T11_02_18-37328.txt deleted file mode 100644 index 28ed942..0000000 --- a/rustc-ice-2025-01-10T11_02_18-37328.txt +++ /dev/null @@ -1,63 +0,0 @@ -thread 'rustc' panicked at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\compiler\rustc_query_system\src\query\plumbing.rs:729:9: -Found unstable fingerprints for thir_abstract_const(math[de55]::dft::ntt::{impl#2}::forward_inplace_core::{closure#2}): Ok(None) -stack backtrace: - 0: 0x7ff8de431d43 - std::backtrace_rs::backtrace::dbghelp64::trace - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\..\..\backtrace\src\backtrace\dbghelp64.rs:91 - 1: 0x7ff8de431d43 - std::backtrace_rs::backtrace::trace_unsynchronized - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\..\..\backtrace\src\backtrace\mod.rs:66 - 2: 0x7ff8de431d43 - std::backtrace::Backtrace::create - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\backtrace.rs:331 - 3: 0x7ff8de431c8a - std::backtrace::Backtrace::force_capture - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\backtrace.rs:312 - 4: 0x7ff8dfa55e22 - strncpy - 5: 0x7ff8de44cb82 - alloc::boxed::impl$30::call - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/alloc\src\boxed.rs:1982 - 6: 0x7ff8de44cb82 - std::panicking::rust_panic_with_hook - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\panicking.rs:809 - 7: 0x7ff8de44c9c9 - std::panicking::begin_panic_handler::closure$0 - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\panicking.rs:674 - 8: 0x7ff8de44a1cf - std::sys::backtrace::__rust_end_short_backtrace - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\sys\backtrace.rs:170 - 9: 0x7ff8de44c5ce - std::panicking::begin_panic_handler - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\panicking.rs:665 - 10: 0x7ff8e1457e31 - core::panicking::panic_fmt - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/core\src\panicking.rs:76 - 11: 0x7ff8e087eb42 - >::visit_ty - 12: 0x7ff8df148500 - rustc_ty_utils[611601a2e2e4762f]::ty::self_ty_of_trait_impl_enabling_order_dep_trait_object_hack - 13: 0x7ff8df0b6a5f - rustc_ty_utils[611601a2e2e4762f]::ty::self_ty_of_trait_impl_enabling_order_dep_trait_object_hack - 14: 0x7ff8de046cf9 - rustc_query_impl[5b7e8b0772f52dfc]::query_system - 15: 0x7ff8de9b3ab6 - rustc_mir_build[c21120f9a6e0100a]::build::mir_build - 16: 0x7ff8de899beb - rustc_mir_transform[79b20237fda78f87]::mir_built - 17: 0x7ff8df1f5b8b - rustc_query_impl[5b7e8b0772f52dfc]::plumbing::query_key_hash_verify_all - 18: 0x7ff8df13db6e - rustc_ty_utils[611601a2e2e4762f]::ty::self_ty_of_trait_impl_enabling_order_dep_trait_object_hack - 19: 0x7ff8de038988 - rustc_ty_utils[611601a2e2e4762f]::ty::adt_sized_constraint - 20: 0x7ff8e08f6c2f - >::visit_ty - 21: 0x7ff8df0ac364 - rustc_ty_utils[611601a2e2e4762f]::ty::self_ty_of_trait_impl_enabling_order_dep_trait_object_hack - 22: 0x7ff8df0b3406 - rustc_ty_utils[611601a2e2e4762f]::ty::self_ty_of_trait_impl_enabling_order_dep_trait_object_hack - 23: 0x7ff8df1fd6c7 - rustc_query_impl[5b7e8b0772f52dfc]::plumbing::query_key_hash_verify_all - 24: 0x7ff8de4bf29e - rustc_interface[8d61ccc26bf4800c]::passes::resolver_for_lowering_raw - 25: 0x7ff8db4854be - rustc_interface[8d61ccc26bf4800c]::passes::analysis - 26: 0x7ff8de03dc5b - rustc_ty_utils[611601a2e2e4762f]::ty::adt_sized_constraint - 27: 0x7ff8ddf512b7 - rustc_ty_utils[611601a2e2e4762f]::ty::adt_sized_constraint - 28: 0x7ff8de043603 - rustc_query_impl[5b7e8b0772f52dfc]::query_system - 29: 0x7ff8db443ce7 - _rust_alloc_error_handler - 30: 0x7ff8db43f9bf - _rust_alloc_error_handler - 31: 0x7ff8db4498d7 - _rust_alloc_error_handler - 32: 0x7ff8de45e7cd - alloc::boxed::impl$28::call_once - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/alloc\src\boxed.rs:1968 - 33: 0x7ff8de45e7cd - alloc::boxed::impl$28::call_once - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/alloc\src\boxed.rs:1968 - 34: 0x7ff8de45e7cd - std::sys::pal::windows::thread::impl$0::new::thread_start - at /rustc/5ec7d6eee7e0f5236ec1559499070eaf836bc608\library/std\src\sys\pal\windows\thread.rs:55 - 35: 0x7ff9be46e8d7 - BaseThreadInitThunk - 36: 0x7ff9bec7fbcc - RtlUserThreadStart - - -rustc version: 1.84.0-nightly (5ec7d6eee 2024-11-17) -platform: x86_64-pc-windows-msvc - -query stack during panic: -#0 [thir_abstract_const] building an abstract representation for `dft::ntt::::forward_inplace_core::{closure#2}` -#1 [mir_built] building MIR for `dft::ntt::::forward_inplace_core::{closure#2}` -#2 [analysis] running analysis passes on this crate -end of query stack