v0.1.0
This commit is contained in:
parent
f34f931030
commit
610cc4784a
5 changed files with 39 additions and 310 deletions
|
|
@ -8,6 +8,8 @@
|
|||
#![allow(clippy::tabs_in_doc_comments)]
|
||||
|
||||
//! Modular and polynomial arithmetic.
|
||||
//!
|
||||
//! See the examples in the repo.
|
||||
|
||||
pub mod matrix;
|
||||
pub mod ntt;
|
||||
|
|
|
|||
232
src/r7681.rs
232
src/r7681.rs
|
|
@ -1,232 +0,0 @@
|
|||
crate::ring!(Z7681, u16, u32, i32, 7681);
|
||||
|
||||
/// Element of (Z/2Z)[x]/(x^N+1)
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct R7681<const N: usize>(pub [Z7681; N]);
|
||||
|
||||
impl<const N: usize> crate::poly::Poly<u16, N> for R7681<N> {
|
||||
type Element = Z7681;
|
||||
fn modulus() -> u16 {
|
||||
7681
|
||||
}
|
||||
fn new(v: [Z7681; N]) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> R7681<N> {
|
||||
pub const fn one() -> Self {
|
||||
let mut x = Self([Z7681(0); N]);
|
||||
x.0[0].0 = 1;
|
||||
x
|
||||
}
|
||||
pub fn is_one(&self) -> bool {
|
||||
self.0[0].0 == 1 && self.0.iter().skip(1).all(|x| x.0 == 0)
|
||||
}
|
||||
pub const fn zetas() -> [u16; N] {
|
||||
let mut zetas = [0; N];
|
||||
let mut i: usize = 1;
|
||||
let mut z = 62;
|
||||
while i < N {
|
||||
zetas[crate::poly::bitrev(i, N)] = z;
|
||||
z = (z as u32 * 62 % 7681) as u16;
|
||||
i += 1;
|
||||
}
|
||||
zetas
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Add for R7681<N> {
|
||||
type Output = Self;
|
||||
fn add(mut self, rhs: Self) -> Self {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x += *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Add<&Self> for R7681<N> {
|
||||
type Output = Self;
|
||||
fn add(mut self, rhs: &Self) -> Self {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x += *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::AddAssign for R7681<N> {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x += *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::AddAssign<&Self> for R7681<N> {
|
||||
fn add_assign(&mut self, rhs: &Self) {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x += *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Sub for R7681<N> {
|
||||
type Output = Self;
|
||||
fn sub(mut self, rhs: Self) -> Self {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x -= *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Sub<&Self> for R7681<N> {
|
||||
type Output = Self;
|
||||
fn sub(mut self, rhs: &Self) -> Self {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x -= *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::SubAssign for R7681<N> {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x -= *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::SubAssign<&Self> for R7681<N> {
|
||||
fn sub_assign(&mut self, rhs: &Self) {
|
||||
self.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.iter())
|
||||
.for_each(|(x, y)| *x -= *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> num_traits::Zero for R7681<N> {
|
||||
fn zero() -> Self {
|
||||
Self([Z7681(0); N])
|
||||
}
|
||||
fn is_zero(&self) -> bool {
|
||||
self.0.iter().all(num_traits::Zero::is_zero)
|
||||
}
|
||||
}
|
||||
|
||||
/*impl num_traits::One for R7681<N> {
|
||||
fn one() -> Self {
|
||||
let mut x = Self([$Zq(0); $N]);
|
||||
x.0[0].0 = 1;
|
||||
x
|
||||
}
|
||||
fn is_one(&self) -> bool {
|
||||
self.0[0].0 == 1 && self.0.iter().skip(1).all(|x| x.0 == 0)
|
||||
}
|
||||
}*/
|
||||
|
||||
impl<const N: usize> crate::ntt::Ntt for R7681<N> {
|
||||
type Output = crate::ntt::NttDomain<R7681<N>>;
|
||||
fn ntt(mut self) -> crate::ntt::NttDomain<R7681<N>> {
|
||||
let mut m = 0;
|
||||
let mut len = N / 2;
|
||||
while len >= 1 {
|
||||
for start in (0..N).step_by(2 * len) {
|
||||
m += 1;
|
||||
let z = Z7681(R7681::<N>::zetas()[m]);
|
||||
for j in start..start + len {
|
||||
let t = z * self.0[j + len];
|
||||
self.0[j + len] = self.0[j] - t;
|
||||
self.0[j] += t;
|
||||
}
|
||||
}
|
||||
len /= 2;
|
||||
}
|
||||
crate::ntt::NttDomain(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> crate::ntt::NttInv for crate::ntt::NttDomain<R7681<N>> {
|
||||
type Output = R7681<N>;
|
||||
fn ntt_inv(mut self) -> R7681<N> {
|
||||
let mut m = N;
|
||||
let mut len = 1;
|
||||
while len < N {
|
||||
for start in (0..N).step_by(2 * len) {
|
||||
m -= 1;
|
||||
let z = Z7681(7681 - R7681::<N>::zetas()[m]);
|
||||
for j in start..start + len {
|
||||
let t = self.0.0[j];
|
||||
self.0.0[j] += self.0.0[j + len];
|
||||
self.0.0[j + len] = z * (t - self.0.0[j + len]);
|
||||
}
|
||||
}
|
||||
len *= 2;
|
||||
}
|
||||
self.0.0.iter_mut().for_each(|wj| *wj *= Z7681(N as u16).inverse());
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Mul for crate::ntt::NttDomain<R7681<N>> {
|
||||
type Output = Self;
|
||||
fn mul(mut self, rhs: Self) -> Self {
|
||||
self.0
|
||||
.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.0.iter())
|
||||
.for_each(|(x, y)| *x *= *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Mul<&Self> for crate::ntt::NttDomain<R7681<N>> {
|
||||
type Output = Self;
|
||||
fn mul(mut self, rhs: &Self) -> Self {
|
||||
self.0
|
||||
.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.0.iter())
|
||||
.for_each(|(x, y)| *x *= *y);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::MulAssign for crate::ntt::NttDomain<R7681<N>> {
|
||||
fn mul_assign(&mut self, rhs: Self) {
|
||||
self.0
|
||||
.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.0.iter())
|
||||
.for_each(|(x, y)| *x *= *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::MulAssign<&Self> for crate::ntt::NttDomain<R7681<N>> {
|
||||
fn mul_assign(&mut self, rhs: &Self) {
|
||||
self.0
|
||||
.0
|
||||
.iter_mut()
|
||||
.zip(rhs.0.0.iter())
|
||||
.for_each(|(x, y)| *x *= *y);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> num_traits::Inv for crate::ntt::NttDomain<R7681<N>> {
|
||||
type Output = Self;
|
||||
fn inv(mut self) -> Self {
|
||||
self.0.0.iter_mut().for_each(|x| *x = x.inverse());
|
||||
self
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue