mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
wip
This commit is contained in:
22
Cargo.toml
22
Cargo.toml
@@ -1,20 +1,2 @@
|
|||||||
[package]
|
[workspace]
|
||||||
name = "math"
|
members = ["math"]
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
primality-test = "0.3.0"
|
|
||||||
num-bigint = "0.4.6"
|
|
||||||
num-traits = "0.2.19"
|
|
||||||
prime_factorization = "1.0.5"
|
|
||||||
itertools = "0.13.0"
|
|
||||||
criterion = "0.5.1"
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "ntt"
|
|
||||||
harness = false
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "operations"
|
|
||||||
harness = false
|
|
||||||
20
math/Cargo.toml
Normal file
20
math/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "math"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
primality-test = "0.3.0"
|
||||||
|
num-bigint = "0.4.6"
|
||||||
|
num-traits = "0.2.19"
|
||||||
|
prime_factorization = "1.0.5"
|
||||||
|
itertools = "0.13.0"
|
||||||
|
criterion = "0.5.1"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "ntt"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "operations"
|
||||||
|
harness = false
|
||||||
@@ -2,9 +2,8 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
|||||||
use math::ring::Ring;
|
use math::ring::Ring;
|
||||||
use math::modulus::VecOperations;
|
use math::modulus::VecOperations;
|
||||||
use math::modulus::montgomery::Montgomery;
|
use math::modulus::montgomery::Montgomery;
|
||||||
use math::modulus::{BARRETT, ONCE};
|
use math::modulus::ONCE;
|
||||||
|
use math::CHUNK;
|
||||||
const CHUNK: usize= 8;
|
|
||||||
|
|
||||||
fn vec_add_unary(c: &mut Criterion) {
|
fn vec_add_unary(c: &mut Criterion) {
|
||||||
fn runner(r: Ring<u64>) -> Box<dyn FnMut()> {
|
fn runner(r: Ring<u64>) -> Box<dyn FnMut()> {
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
extern crate math;
|
|
||||||
use math::ring::Ring;
|
use math::ring::Ring;
|
||||||
use math::modulus::prime::Prime;
|
use math::modulus::prime::Prime;
|
||||||
use math::dft::ntt::Table;
|
use math::dft::ntt::Table;
|
||||||
@@ -7,6 +7,7 @@ use crate::modulus::ONCE;
|
|||||||
use crate::dft::DFT;
|
use crate::dft::DFT;
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct Table<O>{
|
pub struct Table<O>{
|
||||||
prime:Prime<O>,
|
prime:Prime<O>,
|
||||||
psi: O,
|
psi: O,
|
||||||
@@ -6,6 +6,8 @@ pub mod dft;
|
|||||||
pub mod ring;
|
pub mod ring;
|
||||||
pub mod poly;
|
pub mod poly;
|
||||||
|
|
||||||
|
pub const CHUNK: usize= 8;
|
||||||
|
|
||||||
pub mod macros{
|
pub mod macros{
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@@ -72,7 +72,10 @@ pub trait WordOperations<O>{
|
|||||||
fn word_sub_unary_assign<const REDUCE:REDUCEMOD>(&self, a: &O, b: &mut O);
|
fn word_sub_unary_assign<const REDUCE:REDUCEMOD>(&self, a: &O, b: &mut O);
|
||||||
|
|
||||||
// Assigns -a to a.
|
// Assigns -a to a.
|
||||||
fn word_neg_assign<const REDUCE:REDUCEMOD>(&self, a:&mut O);
|
fn word_neg_unary_assign<const REDUCE:REDUCEMOD>(&self, a:&mut O);
|
||||||
|
|
||||||
|
// Assigns -a to b.
|
||||||
|
fn word_neg_binary_assign<const REDUCE:REDUCEMOD>(&self, a: &O, b:&mut O);
|
||||||
|
|
||||||
// Assigns a * 2^64 to b.
|
// Assigns a * 2^64 to b.
|
||||||
fn word_prepare_montgomery_assign<const REDUCE:REDUCEMOD>(&self, a: &O, b: &mut montgomery::Montgomery<O>);
|
fn word_prepare_montgomery_assign<const REDUCE:REDUCEMOD>(&self, a: &O, b: &mut montgomery::Montgomery<O>);
|
||||||
@@ -102,7 +105,10 @@ pub trait VecOperations<O>{
|
|||||||
fn vec_sub_unary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[O], b: &mut [O]);
|
fn vec_sub_unary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[O], b: &mut [O]);
|
||||||
|
|
||||||
// Assigns -a[i] to a[i].
|
// Assigns -a[i] to a[i].
|
||||||
fn vec_neg_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &mut [O]);
|
fn vec_neg_unary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &mut [O]);
|
||||||
|
|
||||||
|
// Assigns -a[i] to a[i].
|
||||||
|
fn vec_neg_binary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[O], b: &mut [O]);
|
||||||
|
|
||||||
// Assigns a * 2^64 to b.
|
// Assigns a * 2^64 to b.
|
||||||
fn vec_prepare_montgomery_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[O], b: &mut [montgomery::Montgomery<O>]);
|
fn vec_prepare_montgomery_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[O], b: &mut [montgomery::Montgomery<O>]);
|
||||||
@@ -44,11 +44,17 @@ impl WordOperations<u64> for Prime<u64>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn word_neg_assign<const REDUCE:REDUCEMOD>(&self, a: &mut u64){
|
fn word_neg_unary_assign<const REDUCE:REDUCEMOD>(&self, a: &mut u64){
|
||||||
*a = self.q.wrapping_sub(*a);
|
*a = self.q.wrapping_sub(*a);
|
||||||
self.word_reduce_assign::<REDUCE>(a)
|
self.word_reduce_assign::<REDUCE>(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn word_neg_binary_assign<const REDUCE:REDUCEMOD>(&self, a: &u64, b: &mut u64){
|
||||||
|
*b = self.q.wrapping_sub(*a);
|
||||||
|
self.word_reduce_assign::<REDUCE>(b)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn word_prepare_montgomery_assign<const REDUCE:REDUCEMOD>(&self, a: &u64, b: &mut Montgomery<u64>){
|
fn word_prepare_montgomery_assign<const REDUCE:REDUCEMOD>(&self, a: &u64, b: &mut Montgomery<u64>){
|
||||||
self.montgomery.prepare_assign::<REDUCE>(*a, b);
|
self.montgomery.prepare_assign::<REDUCE>(*a, b);
|
||||||
@@ -100,8 +106,13 @@ impl VecOperations<u64> for Prime<u64>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn vec_neg_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &mut [u64]){
|
fn vec_neg_unary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &mut [u64]){
|
||||||
apply_unary!(self, Self::word_neg_assign::<REDUCE>, a, CHUNK);
|
apply_unary!(self, Self::word_neg_unary_assign::<REDUCE>, a, CHUNK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn vec_neg_binary_assign<const CHUNK:usize, const REDUCE:REDUCEMOD>(&self, a: &[u64], b: &mut [u64]){
|
||||||
|
apply_binary!(self, Self::word_neg_binary_assign::<REDUCE>, a, b, CHUNK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
58
math/src/poly.rs
Normal file
58
math/src/poly.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
pub mod poly;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Poly<O>(pub Vec<O>);
|
||||||
|
|
||||||
|
impl<O> Poly<O>where
|
||||||
|
O: Default + Clone,
|
||||||
|
{
|
||||||
|
pub fn new(n: usize) -> Self{
|
||||||
|
Self(vec![O::default();n])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer_size(&self) -> usize{
|
||||||
|
return self.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_buffer(&mut self, n: usize, buf: &mut [O]){
|
||||||
|
assert!(buf.len() >= n, "invalid buffer: buf.len()={} < n={}", buf.len(), n);
|
||||||
|
self.0 = Vec::from(&buf[..n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn n(&self) -> usize{
|
||||||
|
return self.0.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct PolyRNS<O>(pub Vec<Poly<O>>);
|
||||||
|
|
||||||
|
impl<O> PolyRNS<O>where
|
||||||
|
O: Default + Clone,
|
||||||
|
{
|
||||||
|
pub fn new(n: usize) -> Self{
|
||||||
|
Self(vec![Poly::<O>::new(n);n])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn n(&self) -> usize{
|
||||||
|
self.0[0].n()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn level(&self) -> usize{
|
||||||
|
self.0.len()-1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer_size(&self) -> usize{
|
||||||
|
self.n() * (self.level()+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_buffer(&mut self, n: usize, level: usize, buf: &mut [O]){
|
||||||
|
assert!(buf.len() >= n * (level+1), "invalid buffer: buf.len()={} < n * (level+1)={}", buf.len(), level+1);
|
||||||
|
self.0.clear();
|
||||||
|
for chunk in buf.chunks_mut(n).take(level+1) {
|
||||||
|
let mut poly: Poly<O> = Poly(Vec::new());
|
||||||
|
poly.from_buffer(n, chunk);
|
||||||
|
self.0.push(poly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,4 +8,7 @@ pub struct Ring<O>{
|
|||||||
pub n:usize,
|
pub n:usize,
|
||||||
pub modulus:Prime<O>,
|
pub modulus:Prime<O>,
|
||||||
pub dft:Box<dyn DFT<O>>,
|
pub dft:Box<dyn DFT<O>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct RingRNS<O>(pub Vec<Ring<O>>);
|
||||||
3
math/src/ring/impl_u64/mod.rs
Normal file
3
math/src/ring/impl_u64/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod automorphism;
|
||||||
|
pub mod ring;
|
||||||
|
pub mod ring_rns;
|
||||||
102
math/src/ring/impl_u64/ring.rs
Normal file
102
math/src/ring/impl_u64/ring.rs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
use crate::ring::Ring;
|
||||||
|
use crate::dft::ntt::Table;
|
||||||
|
use crate::modulus::prime::Prime;
|
||||||
|
use crate::modulus::montgomery::Montgomery;
|
||||||
|
use crate::poly::Poly;
|
||||||
|
use crate::modulus::REDUCEMOD;
|
||||||
|
use crate::modulus::VecOperations;
|
||||||
|
use crate::CHUNK;
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ring<u64>{
|
||||||
|
pub fn ntt_inplace<const LAZY:bool>(&self, poly: &mut Poly<u64>){
|
||||||
|
match LAZY{
|
||||||
|
true => self.dft.forward_inplace_lazy(&mut poly.0),
|
||||||
|
false => self.dft.forward_inplace(&mut poly.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intt_inplace<const LAZY:bool>(&self, poly: &mut Poly<u64>){
|
||||||
|
match LAZY{
|
||||||
|
true => self.dft.forward_inplace_lazy(&mut poly.0),
|
||||||
|
false => self.dft.forward_inplace(&mut poly.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ntt<const LAZY:bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>){
|
||||||
|
poly_out.0.copy_from_slice(&poly_in.0);
|
||||||
|
match LAZY{
|
||||||
|
true => self.dft.backward_inplace_lazy(&mut poly_out.0),
|
||||||
|
false => self.dft.backward_inplace(&mut poly_out.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intt<const LAZY:bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>){
|
||||||
|
poly_out.0.copy_from_slice(&poly_in.0);
|
||||||
|
match LAZY{
|
||||||
|
true => self.dft.backward_inplace_lazy(&mut poly_out.0),
|
||||||
|
false => self.dft.backward_inplace(&mut poly_out.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ring<u64>{
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn add_inplace<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_add_unary_assign::<CHUNK, REDUCE>(&a.0, &mut b.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn add<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &Poly<u64>, c: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_add_binary_assign::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sub_inplace<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_sub_unary_assign::<CHUNK, REDUCE>(&a.0, &mut b.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sub<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &Poly<u64>, c: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_sub_binary_assign::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn neg<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_neg_binary_assign::<CHUNK, REDUCE>(&a.0, &mut b.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn neg_inplace<const REDUCE: REDUCEMOD>(&self, a: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_neg_unary_assign::<CHUNK, REDUCE>(&mut a.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mul_montgomery_external<const REDUCE:REDUCEMOD>(&self, a:&Poly<Montgomery<u64>>, b:&Poly<u64>, c: &mut Poly<u64>){
|
||||||
|
self.modulus.vec_mul_montgomery_external_binary_assign::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mul_montgomery_external_inplace<const REDUCE:REDUCEMOD>(&self, a:&Poly<Montgomery<u64>>, b:&mut Poly<u64>){
|
||||||
|
self.modulus.vec_mul_montgomery_external_unary_assign::<CHUNK, REDUCE>(&a.0, &mut b.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
114
math/src/ring/impl_u64/ring_rns.rs
Normal file
114
math/src/ring/impl_u64/ring_rns.rs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
use crate::ring::{Ring, RingRNS};
|
||||||
|
use crate::poly::PolyRNS;
|
||||||
|
use crate::modulus::montgomery::Montgomery;
|
||||||
|
use crate::modulus::REDUCEMOD;
|
||||||
|
|
||||||
|
impl RingRNS<u64>{
|
||||||
|
pub fn new(n:usize, moduli: Vec<u64>) -> Self{
|
||||||
|
assert!(!moduli.is_empty(), "moduli cannot be empty");
|
||||||
|
let rings: Vec<Ring<u64>> = moduli
|
||||||
|
.into_iter()
|
||||||
|
.map(|prime: u64| Ring::new(n, prime, 1))
|
||||||
|
.collect();
|
||||||
|
RingRNS(rings)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn n(&self) -> usize{
|
||||||
|
self.0[0].n()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_level(&self) -> usize{
|
||||||
|
self.0.len()-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RingRNS<u64>{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RingRNS<u64>{
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn add<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &PolyRNS<u64>, c: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(c.n() >= self.n(), "c.n()={} < n={}", c.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
debug_assert!(c.level() >= LEVEL, "c.level()={} < LEVEL={}", c.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.add::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn add_inplace<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.add_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sub<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &PolyRNS<u64>, c: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(c.n() >= self.n(), "c.n()={} < n={}", c.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
debug_assert!(c.level() >= LEVEL, "c.level()={} < LEVEL={}", c.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.sub::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sub_inplace<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.sub_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn neg<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.neg::<REDUCE>(&a.0[i], &mut b.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn neg_inplace<const LEVEL:usize, const REDUCE: REDUCEMOD>(&self, a: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.neg_inplace::<REDUCE>(&mut a.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mul_montgomery_external<const LEVEL:usize, const REDUCE:REDUCEMOD>(&self, a:&PolyRNS<Montgomery<u64>>, b:&PolyRNS<u64>, c: &mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(c.n() >= self.n(), "c.n()={} < n={}", c.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
debug_assert!(c.level() >= LEVEL, "c.level()={} < LEVEL={}", c.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.mul_montgomery_external::<REDUCE>(&a.0[i], &b.0[i], &mut c.0[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mul_montgomery_external_inplace<const LEVEL:usize, const REDUCE:REDUCEMOD>(&self, a:&PolyRNS<Montgomery<u64>>, b:&mut PolyRNS<u64>){
|
||||||
|
debug_assert!(self.max_level() <= LEVEL, "max_level={} < LEVEL={}", self.max_level(), LEVEL);
|
||||||
|
debug_assert!(a.n() >= self.n(), "a.n()={} < n={}", a.n(), self.n());
|
||||||
|
debug_assert!(b.n() >= self.n(), "b.n()={} < n={}", b.n(), self.n());
|
||||||
|
debug_assert!(a.level() >= LEVEL, "a.level()={} < LEVEL={}", a.level(), LEVEL);
|
||||||
|
debug_assert!(b.level() >= LEVEL, "b.level()={} < LEVEL={}", b.level(), LEVEL);
|
||||||
|
self.0.iter().take(LEVEL + 1).enumerate().for_each(|(i, ring)| ring.mul_montgomery_external_inplace::<REDUCE>(&a.0[i], &mut b.0[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/poly.rs
29
src/poly.rs
@@ -1,29 +0,0 @@
|
|||||||
pub mod poly;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Poly<O>(pub Vec<O>);
|
|
||||||
|
|
||||||
impl<O> Poly<O>where
|
|
||||||
O: Default + Clone,
|
|
||||||
{
|
|
||||||
pub fn new(n: usize) -> Self{
|
|
||||||
Self(vec![O::default();n])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_montgomery(n: usize) -> Self{
|
|
||||||
Self(vec![O::default();n])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn buffer_size(&self) -> usize{
|
|
||||||
return self.0.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_buffer(&mut self, n: usize, buf: &mut [O]){
|
|
||||||
assert!(buf.len() >= n, "invalid buffer: buf.len()={} < n={}", buf.len(), n);
|
|
||||||
self.0 = Vec::from(&buf[..n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn n(&self) -> usize{
|
|
||||||
return self.0.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
pub mod automorphism;
|
|
||||||
pub mod ring;
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ntt_inplace<const LAZY:bool>(&self, poly: &mut Poly<u64>){
|
|
||||||
match LAZY{
|
|
||||||
true => self.dft.forward_inplace_lazy(&mut poly.0),
|
|
||||||
false => self.dft.forward_inplace(&mut poly.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intt_inplace<const LAZY:bool>(&self, poly: &mut Poly<u64>){
|
|
||||||
match LAZY{
|
|
||||||
true => self.dft.forward_inplace_lazy(&mut poly.0),
|
|
||||||
false => self.dft.forward_inplace(&mut poly.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ntt<const LAZY:bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>){
|
|
||||||
poly_out.0.copy_from_slice(&poly_in.0);
|
|
||||||
match LAZY{
|
|
||||||
true => self.dft.backward_inplace_lazy(&mut poly_out.0),
|
|
||||||
false => self.dft.backward_inplace(&mut poly_out.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intt<const LAZY:bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>){
|
|
||||||
poly_out.0.copy_from_slice(&poly_in.0);
|
|
||||||
match LAZY{
|
|
||||||
true => self.dft.backward_inplace_lazy(&mut poly_out.0),
|
|
||||||
false => self.dft.backward_inplace(&mut poly_out.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user