From a97cb05a60b2c1f89b396abe415e1e7226c08345 Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Wed, 14 Jan 2026 17:12:56 +0100 Subject: [PATCH 1/7] make sure that the polynomial reduce only uses the sparse reduce of fq_reduce which also works with any context polynomial and is not limited to the underlying field requirements --- src/integer/poly_over_z/arithmetic/sub.rs | 12 +--- .../mat_polynomial_ring_zq/reduce.rs | 48 ++++++++++++-- .../mat_polynomial_ring_zq/tensor.rs | 9 ++- .../vector/dot_product.rs | 18 ++--- .../poly_over_zq/arithmetic/sub.rs | 19 +----- .../polynomial_ring_zq/arithmetic/add.rs | 66 ++++--------------- .../polynomial_ring_zq/arithmetic/mul.rs | 62 ++++------------- .../polynomial_ring_zq/arithmetic/sub.rs | 66 ++++--------------- .../polynomial_ring_zq/reduce.rs | 18 ++++- 9 files changed, 115 insertions(+), 203 deletions(-) diff --git a/src/integer/poly_over_z/arithmetic/sub.rs b/src/integer/poly_over_z/arithmetic/sub.rs index 7833493a..1980951f 100644 --- a/src/integer/poly_over_z/arithmetic/sub.rs +++ b/src/integer/poly_over_z/arithmetic/sub.rs @@ -19,7 +19,6 @@ use crate::{ }; use flint_sys::{ fmpq_poly::fmpq_poly_sub, fmpz_mod_poly::fmpz_mod_poly_sub, fmpz_poly::fmpz_poly_sub, - fq::fq_sub, }; use std::ops::{Sub, SubAssign}; @@ -148,15 +147,8 @@ impl Sub<&PolynomialRingZq> for &PolyOverZ { /// let c: PolynomialRingZq = &b - &a; /// ``` fn sub(self, other: &PolynomialRingZq) -> Self::Output { - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &other.modulus)); - unsafe { - fq_sub( - &mut out.poly.poly, - &self.poly, - &other.poly.poly, - other.modulus.get_fq_ctx(), - ); - } + let mut out = PolynomialRingZq::from((self, &other.modulus)); + out -= other; out } } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs index 8b1c15d9..605d19ba 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs @@ -14,9 +14,13 @@ // Additionally the comparisons assume that the entries are reduced, // hence no reduction is performed in the check. +use std::cmp::min; + use super::MatPolynomialRingZq; use crate::traits::MatrixDimensions; -use flint_sys::{fmpz_poly_mat::fmpz_poly_mat_entry, fq::fq_reduce}; +use flint_sys::{ + fmpz_poly::_fmpz_poly_normalise, fmpz_poly_mat::fmpz_poly_mat_entry, fq::_fq_sparse_reduce, +}; impl MatPolynomialRingZq { /// This function manually applies the modulus @@ -40,13 +44,47 @@ impl MatPolynomialRingZq { pub(crate) fn reduce(&mut self) { for row_num in 0..self.matrix.get_num_rows() { for column_num in 0..self.matrix.get_num_columns() { - unsafe { - let entry = fmpz_poly_mat_entry(&self.matrix.matrix, row_num, column_num); - fq_reduce(entry, self.modulus.get_fq_ctx()) - }; + self.reduce_entry(row_num, column_num); } } } + + /// This function manually applies the modulus + /// [`ModulusPolynomialRingZq`](crate::integer_mod_q::ModulusPolynomialRingZq) + /// to the entry (`row`, `column`) of the given polynomial matrix [`MatPolyOverZ`](crate::integer::MatPolyOverZ) + /// in the [`MatPolynomialRingZq`]. The function does not check if `row` and `column` + /// is within the matrix dimensions. + /// + /// # Examples + /// ```compile_fail + /// use qfall_math::integer_mod_q::MatPolynomialRingZq; + /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq; + /// use qfall_math::integer::MatPolyOverZ; + /// use std::str::FromStr; + /// + /// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); + /// let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); + /// let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus)); + /// + /// poly_ring_mat.reduce_entry(0, 0) + /// ``` + pub(crate) fn reduce_entry(&mut self, row: i64, column: i64) { + // use the sparse reduce instead of the normal reduce + // the normal reduce switches between a dense and a sparse reduce + // without further assumptions on the context, the dense reduce does + // not work, so we always use the sparse reduce. + unsafe { + let entry = fmpz_poly_mat_entry(&self.matrix.matrix, row, column); + let nr_coeffs = (*entry).length; + // fq_reduce(entry, self.modulus.get_fq_ctx()) + + // this is what is called in fq_reduce, when it is a sparse modulus + // here it is done explicitly to avoid the dense reduce that can cause problems. + _fq_sparse_reduce((*entry).coeffs, nr_coeffs, self.modulus.get_fq_ctx()); + (*entry).length = min(nr_coeffs, self.modulus.get_fq_ctx().modulus[0].length); + _fmpz_poly_normalise(entry); + }; + } } #[cfg(test)] diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs index b1f73748..f78f51ea 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs @@ -14,7 +14,7 @@ use crate::{ integer::PolyOverZ, traits::{CompareBase, MatrixDimensions, MatrixGetEntry, Tensor}, }; -use flint_sys::{fmpz_poly_mat::fmpz_poly_mat_entry, fq::fq_mul}; +use flint_sys::{fmpz_poly::fmpz_poly_mul, fmpz_poly_mat::fmpz_poly_mat_entry}; impl Tensor for MatPolynomialRingZq { /// Computes the tensor product of `self` with `other`. @@ -146,7 +146,7 @@ unsafe fn set_matrix_window_mul( for i_other in 0..rows_other { for j_other in 0..columns_other { unsafe { - fq_mul( + fmpz_poly_mul( fmpz_poly_mat_entry( &out.matrix.matrix, row_left * rows_other + i_other, @@ -154,9 +154,12 @@ unsafe fn set_matrix_window_mul( ), &scalar.poly, fmpz_poly_mat_entry(&matrix.matrix.matrix, i_other, j_other), - matrix.modulus.get_fq_ctx(), ) } + out.reduce_entry( + row_left * rows_other + i_other, + column_upper * columns_other + j_other, + ); } } } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/vector/dot_product.rs b/src/integer_mod_q/mat_polynomial_ring_zq/vector/dot_product.rs index 38576dd0..30d6ae47 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/vector/dot_product.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/vector/dot_product.rs @@ -12,7 +12,7 @@ use crate::error::MathError; use crate::integer::PolyOverZ; use crate::integer_mod_q::{MatPolynomialRingZq, PolynomialRingZq}; use crate::traits::MatrixDimensions; -use flint_sys::fq::{fq_add, fq_mul}; +use flint_sys::fmpz_poly::fmpz_poly_mul; impl MatPolynomialRingZq { /// Returns the dot product of two vectors of type [`MatPolynomialRingZq`]. @@ -77,20 +77,10 @@ impl MatPolynomialRingZq { for i in 0..self_entries.len() { // sets result = result + self.entry[i] * other.entry[i] without cloned PolyOverZ element unsafe { - fq_mul( - &mut temp.poly, - &self_entries[i], - &other_entries[i], - self.modulus.get_fq_ctx(), - ); - - fq_add( - &mut result.poly.poly, - &result.poly.poly, - &temp.poly, - self.modulus.get_fq_ctx(), - ) + fmpz_poly_mul(&mut temp.poly, &self_entries[i], &other_entries[i]); } + // reduce is applied in here + result += &temp; } Ok(result) diff --git a/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs b/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs index b0880f8b..283ce8fb 100644 --- a/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs @@ -19,7 +19,7 @@ use crate::{ }, traits::CompareBase, }; -use flint_sys::{fmpz_mod_poly::fmpz_mod_poly_sub, fq::fq_sub}; +use flint_sys::fmpz_mod_poly::fmpz_mod_poly_sub; use std::{ ops::{Sub, SubAssign}, str::FromStr, @@ -180,21 +180,8 @@ impl Sub<&PolynomialRingZq> for &PolyOverZq { /// # Panics ... /// - if the moduli mismatch. fn sub(self, other: &PolynomialRingZq) -> Self::Output { - assert_eq!( - self.modulus, - other.modulus.get_q(), - "Tried to subtract polynomials with different moduli." - ); - - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &other.modulus)); - unsafe { - fq_sub( - &mut out.poly.poly, - &self.get_representative_least_nonnegative_residue().poly, - &other.poly.poly, - other.modulus.get_fq_ctx(), - ); - } + let mut out = PolynomialRingZq::from((self, &other.modulus)); + out -= other; out } } diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs index cca138be..cfffa84a 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs @@ -19,7 +19,6 @@ use crate::{ }, traits::CompareBase, }; -use flint_sys::fq::fq_add; use std::ops::{Add, AddAssign}; impl AddAssign<&PolynomialRingZq> for PolynomialRingZq { @@ -61,14 +60,8 @@ impl AddAssign<&PolynomialRingZq> for PolynomialRingZq { panic!("{}", self.call_compare_base_error(other).unwrap()); } - unsafe { - fq_add( - &mut self.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - }; + self.poly += &other.poly; + self.reduce(); } } impl AddAssign<&PolyOverZ> for PolynomialRingZq { @@ -87,17 +80,9 @@ impl AddAssign<&PolyOverZq> for PolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()) } - // get a fmpz_poly_struct from a fmpz_mod_poly_struct - let other = other.get_representative_least_nonnegative_residue(); - - unsafe { - fq_add( - &mut self.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - }; + + self.poly += &other.get_representative_least_nonnegative_residue(); + self.reduce(); } } @@ -171,15 +156,8 @@ impl Add<&PolyOverZ> for &PolynomialRingZq { /// let c: PolynomialRingZq = &a + &b; /// ``` fn add(self, other: &PolyOverZ) -> Self::Output { - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_add( - &mut out.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out += other; out } } @@ -219,21 +197,12 @@ impl Add<&PolyOverZq> for &PolynomialRingZq { /// # Panics ... /// - if the moduli mismatch. fn add(self, other: &PolyOverZq) -> Self::Output { - assert_eq!( - self.modulus.get_q(), - other.modulus, - "Tried to add polynomials with different moduli." - ); - - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_add( - &mut out.poly.poly, - &self.poly.poly, - &other.get_representative_least_nonnegative_residue().poly, - self.modulus.get_fq_ctx(), - ); + if !self.compare_base(other) { + panic!("{}", self.call_compare_base_error(other).unwrap()) } + + let mut out = self.clone(); + out.poly += &other.get_representative_least_nonnegative_residue(); out } } @@ -276,15 +245,8 @@ impl PolynomialRingZq { if !self.compare_base(other) { return Err(self.call_compare_base_error(other).unwrap()); } - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_add( - &mut out.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out += other; Ok(out) } } diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs index 23e6e15b..813484d6 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs @@ -19,7 +19,6 @@ use crate::{ }, traits::CompareBase, }; -use flint_sys::fq::fq_mul; use std::ops::{Mul, MulAssign}; impl MulAssign<&PolynomialRingZq> for PolynomialRingZq { @@ -61,14 +60,8 @@ impl MulAssign<&PolynomialRingZq> for PolynomialRingZq { panic!("{}", self.call_compare_base_error(other).unwrap()); } - unsafe { - fq_mul( - &mut self.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - }; + self.poly *= &other.poly; + self.reduce(); } } impl MulAssign for PolynomialRingZq @@ -91,17 +84,10 @@ impl MulAssign<&PolyOverZq> for PolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()) } - // get a fmpz_poly_struct from a fmpz_mod_poly_struct let other = other.get_representative_least_nonnegative_residue(); - unsafe { - fq_mul( - &mut self.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - }; + self.poly *= &other; + self.reduce(); } } @@ -174,15 +160,8 @@ impl Mul<&PolyOverZ> for &PolynomialRingZq { /// let c: PolynomialRingZq = &a * &b; /// ``` fn mul(self, other: &PolyOverZ) -> Self::Output { - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_mul( - &mut out.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out *= other; out } } @@ -222,19 +201,8 @@ impl Mul<&PolyOverZq> for &PolynomialRingZq { /// # Panics ... /// - if the moduli mismatch. fn mul(self, other: &PolyOverZq) -> Self::Output { - if !self.compare_base(other) { - panic!("{}", self.call_compare_base_error(other).unwrap()) - } - - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_mul( - &mut out.poly.poly, - &self.poly.poly, - &other.get_representative_least_nonnegative_residue().poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out *= other; out } } @@ -277,15 +245,11 @@ impl PolynomialRingZq { if !self.compare_base(other) { return Err(self.call_compare_base_error(other).unwrap()); } - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_mul( - &mut out.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - } + + let mut out = self.clone(); + + out.poly *= &other.get_representative_least_nonnegative_residue(); + out.reduce(); Ok(out) } } diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs index 05d478b3..32fe2abd 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs @@ -19,7 +19,6 @@ use crate::{ }, traits::CompareBase, }; -use flint_sys::fq::fq_sub; use std::ops::{Sub, SubAssign}; impl SubAssign<&PolynomialRingZq> for PolynomialRingZq { @@ -61,14 +60,8 @@ impl SubAssign<&PolynomialRingZq> for PolynomialRingZq { panic!("{}", self.call_compare_base_error(other).unwrap()); } - unsafe { - fq_sub( - &mut self.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - }; + self.poly -= &other.poly; + self.reduce(); } } impl SubAssign<&PolyOverZ> for PolynomialRingZq { @@ -87,17 +80,8 @@ impl SubAssign<&PolyOverZq> for PolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()) } - // get a fmpz_poly_struct from a fmpz_mod_poly_struct - let other = other.get_representative_least_nonnegative_residue(); - - unsafe { - fq_sub( - &mut self.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - }; + self.poly -= other.get_representative_least_nonnegative_residue(); + self.reduce(); } } @@ -171,15 +155,8 @@ impl Sub<&PolyOverZ> for &PolynomialRingZq { /// let c: PolynomialRingZq = &a - &b; /// ``` fn sub(self, other: &PolyOverZ) -> Self::Output { - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_sub( - &mut out.poly.poly, - &self.poly.poly, - &other.poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out -= other; out } } @@ -215,21 +192,12 @@ impl Sub<&PolyOverZq> for &PolynomialRingZq { /// # Panics ... /// - if the moduli mismatch. fn sub(self, other: &PolyOverZq) -> Self::Output { - assert_eq!( - self.modulus.get_q(), - other.modulus, - "Tried to subtract polynomials with different moduli." - ); - - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_sub( - &mut out.poly.poly, - &self.poly.poly, - &other.get_representative_least_nonnegative_residue().poly, - self.modulus.get_fq_ctx(), - ); + if !self.compare_base(other) { + panic!("{}", self.call_compare_base_error(other).unwrap()) } + + let mut out = self.clone(); + out -= &other.get_representative_least_nonnegative_residue(); out } } @@ -268,15 +236,9 @@ impl PolynomialRingZq { if !self.compare_base(other) { return Err(self.call_compare_base_error(other).unwrap()); } - let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &self.modulus)); - unsafe { - fq_sub( - &mut out.poly.poly, - &self.poly.poly, - &other.poly.poly, - self.modulus.get_fq_ctx(), - ); - } + let mut out = self.clone(); + out.poly -= &other.get_representative_least_nonnegative_residue(); + out.reduce(); Ok(out) } } diff --git a/src/integer_mod_q/polynomial_ring_zq/reduce.rs b/src/integer_mod_q/polynomial_ring_zq/reduce.rs index 224bf736..0be80246 100644 --- a/src/integer_mod_q/polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/polynomial_ring_zq/reduce.rs @@ -14,8 +14,10 @@ // Additionally the comparisons assume that the entries are reduced, // hence no reduction is performed in the check. +use std::cmp::min; + use super::PolynomialRingZq; -use flint_sys::fq::fq_reduce; +use flint_sys::{fmpz_poly::_fmpz_poly_normalise, fq::_fq_sparse_reduce}; impl PolynomialRingZq { /// This function manually applies the modulus @@ -37,7 +39,19 @@ impl PolynomialRingZq { /// poly_ring.reduce() /// ``` pub(crate) fn reduce(&mut self) { - unsafe { fq_reduce(&mut self.poly.poly, self.modulus.get_fq_ctx()) } + // use the sparse reduce instead of the normal reduce + // the normal reduce switches between a dense and a sparse reduce + // without further assumptions on the context, the dense reduce does + // not work, so we always use the sparse reduce. + // unsafe { fq_reduce(&mut self.poly.poly, self.modulus.get_fq_ctx()) } + unsafe { + let nr_coeffs = self.poly.poly.length; + // this is what is called in fq_reduce, when it is a sparse modulus + // here it is done explicitly to avoid the dense reduce that can cause problems. + _fq_sparse_reduce(self.poly.poly.coeffs, nr_coeffs, self.modulus.get_fq_ctx()); + self.poly.poly.length = min(nr_coeffs, self.modulus.get_fq_ctx().modulus[0].length); + _fmpz_poly_normalise(&mut self.poly.poly); + }; } } From 63f61d8f5d060af904b3b0da8ceeb4cf81be1f27 Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Thu, 15 Jan 2026 00:08:00 +0100 Subject: [PATCH 2/7] remove use of fq_ctx object and include a manual reduction --- .../arithmetic/add.rs | 8 +- .../arithmetic/mul.rs | 3 +- .../arithmetic/sub.rs | 10 +- src/integer_mod_q/mat_polynomial_ring_zq.rs | 1 - .../arithmetic/mul_scalar.rs | 2 +- .../mat_polynomial_ring_zq/reduce.rs | 38 +++-- .../mat_polynomial_ring_zq/set.rs | 3 +- .../unsafe_functions.rs | 40 ----- src/integer_mod_q/mat_zq.rs | 2 +- .../modulus_polynomial_ring_zq.rs | 8 +- .../modulus_polynomial_ring_zq/cmp.rs | 18 +-- .../modulus_polynomial_ring_zq/from.rs | 25 ++-- .../modulus_polynomial_ring_zq/get.rs | 30 ++-- .../modulus_polynomial_ring_zq/ownership.rs | 83 +---------- .../modulus_polynomial_ring_zq/to_string.rs | 18 +-- .../unsafe_functions.rs | 139 ------------------ .../ntt_polynomial_ring_zq/arithmetic/add.rs | 6 +- .../ntt_polynomial_ring_zq/arithmetic/mul.rs | 6 +- .../ntt_polynomial_ring_zq/arithmetic/sub.rs | 6 +- src/integer_mod_q/poly_over_zq/from.rs | 11 +- src/integer_mod_q/polynomial_ring_zq.rs | 1 - src/integer_mod_q/polynomial_ring_zq/norm.rs | 5 +- .../polynomial_ring_zq/properties.rs | 4 +- .../polynomial_ring_zq/reduce.rs | 34 +++-- src/integer_mod_q/polynomial_ring_zq/set.rs | 2 +- .../polynomial_ring_zq/unsafe_functions.rs | 30 ---- src/utils.rs | 1 + src/utils/reduce.rs | 42 ++++++ 28 files changed, 148 insertions(+), 428 deletions(-) delete mode 100644 src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs delete mode 100644 src/integer_mod_q/modulus_polynomial_ring_zq/unsafe_functions.rs delete mode 100644 src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs create mode 100644 src/utils/reduce.rs diff --git a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/add.rs index 18104f30..81f5d2d1 100644 --- a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/add.rs @@ -59,7 +59,7 @@ impl Add for &MatNTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_ctx = &self.modulus.get_fq_ctx().ctxp[0]; + let mod_ctx = &self.modulus.get_q_as_modulus(); let mut out = MatNTTPolynomialRingZq { matrix: vec![ @@ -77,7 +77,7 @@ impl Add for &MatNTTPolynomialRingZq { &mut out.matrix[i].value, &self.matrix[i].value, &other.matrix[i].value, - mod_ctx, + mod_ctx.get_fmpz_mod_ctx_struct(), ); } } @@ -138,7 +138,7 @@ impl AddAssign<&MatNTTPolynomialRingZq> for MatNTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_ctx = &self.modulus.get_fq_ctx().ctxp[0]; + let mod_ctx = &self.modulus.get_q_as_modulus(); for i in 0..self.matrix.len() { unsafe { @@ -146,7 +146,7 @@ impl AddAssign<&MatNTTPolynomialRingZq> for MatNTTPolynomialRingZq { &mut self.matrix[i].value, &self.matrix[i].value, &other.matrix[i].value, - mod_ctx, + mod_ctx.get_fmpz_mod_ctx_struct(), ); } } diff --git a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/mul.rs b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/mul.rs index 95df66ec..be5a831f 100644 --- a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/mul.rs +++ b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/mul.rs @@ -55,7 +55,8 @@ impl Mul for &MatNTTPolynomialRingZq { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_ctx = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = self.modulus.get_q_as_modulus(); + let mod_ctx = binding.get_fmpz_mod_ctx_struct(); let mut res = Vec::with_capacity(other.matrix.len()); diff --git a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/sub.rs index 2fceae7f..914e5bd4 100644 --- a/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/mat_ntt_polynomial_ring_zq/arithmetic/sub.rs @@ -58,7 +58,9 @@ impl Sub for &MatNTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_ctx = &self.modulus.get_fq_ctx().ctxp[0]; + + let binding = self.modulus.get_q_as_modulus(); + let mod_ctx = binding.get_fmpz_mod_ctx_struct(); let mut out = MatNTTPolynomialRingZq { matrix: vec![ @@ -136,7 +138,9 @@ impl SubAssign<&MatNTTPolynomialRingZq> for MatNTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + + let binding = self.modulus.get_q_as_modulus(); + let mod_ctx = binding.get_fmpz_mod_ctx_struct(); for i in 0..self.matrix.len() { unsafe { @@ -144,7 +148,7 @@ impl SubAssign<&MatNTTPolynomialRingZq> for MatNTTPolynomialRingZq { &mut self.matrix[i].value, &self.matrix[i].value, &other.matrix[i].value, - mod_q, + mod_ctx, ) }; } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq.rs b/src/integer_mod_q/mat_polynomial_ring_zq.rs index ca53be0c..e3e39de9 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq.rs @@ -31,7 +31,6 @@ mod sort; mod tensor; mod to_string; mod transpose; -mod unsafe_functions; mod vector; /// [`MatPolynomialRingZq`] is a matrix with entries of type [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq). diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs index 4592dd00..79586bbd 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs @@ -809,7 +809,7 @@ mod test_mul_poly_over_z { /// Checks if scalar multiplication reduction works. #[test] fn reduction_correct() { - let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_mat1 = MatPolyOverZ::from_str("[[0, 1 10],[0, 2 1 2]]").unwrap(); let poly_ring_mat1 = MatPolynomialRingZq::from((&poly_mat1, &modulus)); let poly = PolyOverZ::from_str("3 1 0 2").unwrap(); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs index 605d19ba..c594834e 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs @@ -14,13 +14,9 @@ // Additionally the comparisons assume that the entries are reduced, // hence no reduction is performed in the check. -use std::cmp::min; - use super::MatPolynomialRingZq; -use crate::traits::MatrixDimensions; -use flint_sys::{ - fmpz_poly::_fmpz_poly_normalise, fmpz_poly_mat::fmpz_poly_mat_entry, fq::_fq_sparse_reduce, -}; +use crate::{traits::MatrixDimensions, utils::reduce::internal_reduce}; +use flint_sys::{fmpz_poly::_fmpz_poly_normalise, fmpz_poly_mat::fmpz_poly_mat_entry}; impl MatPolynomialRingZq { /// This function manually applies the modulus @@ -69,21 +65,21 @@ impl MatPolynomialRingZq { /// poly_ring_mat.reduce_entry(0, 0) /// ``` pub(crate) fn reduce_entry(&mut self, row: i64, column: i64) { - // use the sparse reduce instead of the normal reduce - // the normal reduce switches between a dense and a sparse reduce - // without further assumptions on the context, the dense reduce does - // not work, so we always use the sparse reduce. - unsafe { - let entry = fmpz_poly_mat_entry(&self.matrix.matrix, row, column); - let nr_coeffs = (*entry).length; - // fq_reduce(entry, self.modulus.get_fq_ctx()) - - // this is what is called in fq_reduce, when it is a sparse modulus - // here it is done explicitly to avoid the dense reduce that can cause problems. - _fq_sparse_reduce((*entry).coeffs, nr_coeffs, self.modulus.get_fq_ctx()); - (*entry).length = min(nr_coeffs, self.modulus.get_fq_ctx().modulus[0].length); - _fmpz_poly_normalise(entry); - }; + let entry = unsafe { fmpz_poly_mat_entry(&self.matrix.matrix, row, column) }; + if (unsafe { *entry }).length > 0 { + unsafe { + internal_reduce( + &mut *entry, + ((*entry).length - 1) as usize, + &self.modulus.modulus.poly, + self.modulus.get_degree() as usize, + self.modulus.get_q_as_modulus().get_fmpz_mod_ctx_struct(), + ) + } + unsafe { + _fmpz_poly_normalise(entry); + }; + } } } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/set.rs b/src/integer_mod_q/mat_polynomial_ring_zq/set.rs index f9540747..a06948f0 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/set.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/set.rs @@ -420,8 +420,9 @@ mod test_setter { fn set_entry_reduced() { let id_mat = MatPolyOverZ::identity(2, 2); let modulus = PolyOverZq::from_str("5 1 0 0 0 1 mod 17").unwrap(); + let poly_mod = ModulusPolynomialRingZq::from(modulus); - let mut poly_mat = MatPolynomialRingZq::from((id_mat, modulus)); + let mut poly_mat = MatPolynomialRingZq::from((id_mat, &poly_mod)); poly_mat .set_entry(0, 0, PolyOverZ::from_str("5 -1 0 0 0 16").unwrap()) diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs b/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs deleted file mode 100644 index dc5dd113..00000000 --- a/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © 2025 Niklas Siemer -// -// This file is part of qFALL-math. -// -// qFALL-math is free software: you can redistribute it and/or modify it under -// the terms of the Mozilla Public License Version 2.0 as published by the -// Mozilla Foundation. See . - -//! This module contains public functions that enable access to underlying -//! [FLINT](https://flintlib.org/) structs. Therefore, they require to be unsafe. - -use super::MatPolynomialRingZq; -use crate::macros::unsafe_passthrough::{unsafe_getter_indirect, unsafe_setter_indirect}; -use flint_sys::{fmpz_poly_mat::fmpz_poly_mat_struct, fq::fq_ctx_struct}; - -unsafe_getter_indirect!( - MatPolynomialRingZq, - matrix, - get_fmpz_poly_mat_struct, - fmpz_poly_mat_struct -); -unsafe_getter_indirect!( - MatPolynomialRingZq, - modulus, - get_fq_ctx_struct, - fq_ctx_struct -); - -unsafe_setter_indirect!( - MatPolynomialRingZq, - matrix, - set_fmpz_poly_mat_struct, - fmpz_poly_mat_struct -); -unsafe_setter_indirect!( - MatPolynomialRingZq, - modulus, - set_fq_ctx_struct, - fq_ctx_struct -); diff --git a/src/integer_mod_q/mat_zq.rs b/src/integer_mod_q/mat_zq.rs index d11a8210..b674784d 100644 --- a/src/integer_mod_q/mat_zq.rs +++ b/src/integer_mod_q/mat_zq.rs @@ -91,7 +91,7 @@ pub struct MatZq { // is due to a reference counter in the `Modulus` object memory efficient. // The modulus of a `MatZq` is not able to be modified afterwards. Hence, we // do not need to care about conformity of the modulus stored in the `matrix` - // attribute and `modulus` attribute, if they are both initalized from the same value. + // attribute and `modulus` attribute, if they are both initialized from the same value. modulus: Modulus, } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq.rs b/src/integer_mod_q/modulus_polynomial_ring_zq.rs index 526b0f50..09bb1fa8 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq.rs @@ -11,7 +11,7 @@ //! This implementation uses the [FLINT](https://flintlib.org/) library. use super::ntt_basis_polynomial_ring_zq::NTTBasisPolynomialRingZq; -use flint_sys::fq::fq_ctx_struct; +use crate::integer_mod_q::PolyOverZq; use std::{fmt, rc::Rc}; mod cmp; @@ -23,14 +23,12 @@ mod ntt_basis; mod ownership; mod serialize; mod to_string; -mod unsafe_functions; /// [`ModulusPolynomialRingZq`] represents the modulus object for /// [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq) /// /// Attributes -/// - `modulus`: holds the specific content, i.e. the modulus `q` and f(X); it -/// holds [FLINT](https://flintlib.org/)'s [struct](fq_ctx_struct) +/// - `modulus`: holds the specific content, i.e. the modulus `q` and f(X) /// /// # Examples /// ``` @@ -43,7 +41,7 @@ mod unsafe_functions; /// let modulus = ModulusPolynomialRingZq::from(poly_mod); /// ``` pub struct ModulusPolynomialRingZq { - modulus: Rc, + pub(crate) modulus: Rc, pub(crate) ntt_basis: Rc>, } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs index 36d0ab21..99bd465d 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs @@ -11,7 +11,9 @@ use super::ModulusPolynomialRingZq; use crate::{ - integer::Z, integer_mod_q::PolyOverZq, macros::for_others::implement_trait_reverse, + integer::Z, + integer_mod_q::{PolyOverZq, modulus}, + macros::for_others::implement_trait_reverse, traits::GetCoefficient, }; use flint_sys::{fmpz::fmpz_equal, fmpz_mod_poly::fmpz_mod_poly_equal}; @@ -46,19 +48,7 @@ impl PartialEq for ModulusPolynomialRingZq { /// # assert!(!compared); /// ``` fn eq(&self, other: &Self) -> bool { - unsafe { - // compares the modulus `q` - 1 == fmpz_equal( - &self.get_fq_ctx().ctxp[0].n[0], - &other.get_fq_ctx().ctxp[0].n[0], - ) && - // compares the polynomial under `q` - 1 == fmpz_mod_poly_equal( - &self.get_fq_ctx().modulus[0], - &other.get_fq_ctx().modulus[0], - &self.get_fq_ctx().ctxp[0], - ) - } + self.modulus == other.modulus } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs index e1171063..85b32e95 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs @@ -13,11 +13,19 @@ use super::ModulusPolynomialRingZq; use crate::{ error::MathError, - integer::PolyOverZ, - integer_mod_q::{Modulus, PolyOverZq}, + integer::{PolyOverZ, Z}, + integer_mod_q::{Modulus, PolyOverZq, modulus}, macros::for_others::implement_for_owned, + traits::GetCoefficient, +}; +use flint_sys::{ + flint::flint_malloc, + fmpz::{fmpz, fmpz_init}, + fmpz_mod::fmpz_mod_ctx_set_modulus, + fmpz_mod_poly::{fmpz_mod_poly_set, fmpz_mod_poly_struct}, + fmpz_vec::_fmpz_vec_init, + fq::{fq_ctx_init_modulus, fq_ctx_struct}, }; -use flint_sys::fq::fq_ctx_init_modulus; use std::{ffi::CString, mem::MaybeUninit, rc::Rc, str::FromStr}; impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { @@ -117,18 +125,9 @@ impl From<&PolyOverZq> for ModulusPolynomialRingZq { /// - if the modulus polynomial is of degree smaller than `1`. fn from(poly: &PolyOverZq) -> Self { check_poly_mod(poly).unwrap(); - - let mut modulus = MaybeUninit::uninit(); - let c_string = CString::new("X").unwrap(); unsafe { - fq_ctx_init_modulus( - modulus.as_mut_ptr(), - &poly.poly, - poly.modulus.get_fmpz_mod_ctx_struct(), - c_string.as_ptr(), - ); Self { - modulus: Rc::new(modulus.assume_init()), + modulus: Rc::new(poly.clone()), ntt_basis: Rc::new(None), } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs index d2035f07..5ce010de 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs @@ -54,16 +54,9 @@ impl GetCoefficient for ModulusPolynomialRingZq { unsafe fn get_coeff_unchecked(&self, index: i64) -> Zq { let out_z: Z = unsafe { self.get_coeff_unchecked(index) }; - let mut ctx = MaybeUninit::uninit(); - unsafe { - fmpz_mod_ctx_init(ctx.as_mut_ptr(), &self.get_fq_ctx().ctxp[0].n[0]); - - let modulus = Modulus { - modulus: Rc::new(ctx.assume_init()), - }; + let modulus = self.modulus.modulus.clone(); - Zq::from((out_z, modulus)) - } + Zq::from((out_z, modulus)) } } @@ -102,12 +95,14 @@ impl GetCoefficient for ModulusPolynomialRingZq { unsafe fn get_coeff_unchecked(&self, index: i64) -> Z { let mut out = Z::default(); + let modulus = self.get_q_as_modulus(); + unsafe { fmpz_mod_poly_get_coeff_fmpz( &mut out.value, - &self.modulus.modulus[0], + &self.modulus.poly, index, - &self.get_fq_ctx().ctxp[0], + modulus.get_fmpz_mod_ctx_struct(), ) } @@ -116,9 +111,8 @@ impl GetCoefficient for ModulusPolynomialRingZq { } impl ModulusPolynomialRingZq { - /// Returns the [`fq_ctx_struct`] of a modulus and is only used internally. - pub(crate) fn get_fq_ctx(&self) -> &fq_ctx_struct { - self.modulus.as_ref() + pub fn get_q_as_modulus(&self) -> Modulus { + self.modulus.modulus.clone() } /// Returns the context integer as a [`Z`]. @@ -137,11 +131,7 @@ impl ModulusPolynomialRingZq { /// assert_eq!(cmp_modulus, modulus); /// ``` pub fn get_q(&self) -> Z { - let mut out = Z::default(); - unsafe { - fmpz_init_set(&mut out.value, &self.get_fq_ctx().ctxp[0].n[0]); - } - out + Z::from(&self.modulus.modulus) } /// Returns the degree of a polynomial [`ModulusPolynomialRingZq`] as a [`i64`]. @@ -157,7 +147,7 @@ impl ModulusPolynomialRingZq { /// let degree = poly.get_degree(); // This would only return 3 /// ``` pub fn get_degree(&self) -> i64 { - unsafe { fq_ctx_degree(self.get_fq_ctx()) } + self.modulus.get_degree() } /// Returns a representative polynomial of the [`ModulusPolynomialRingZq`] element. diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs index 6df74f7c..beee630e 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs @@ -12,7 +12,6 @@ //! The explicit functions contain the documentation. use super::ModulusPolynomialRingZq; -use flint_sys::fq::fq_ctx_clear; use std::rc::Rc; impl Clone for ModulusPolynomialRingZq { @@ -38,36 +37,6 @@ impl Clone for ModulusPolynomialRingZq { } } -impl Drop for ModulusPolynomialRingZq { - /// Drops the given reference to the [`fq_ctx_struct`](flint_sys::fq::fq_ctx_struct) element - /// and frees the allocated memory if no references are left. - /// - /// # Examples - /// ``` - /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq; - /// use std::str::FromStr; - /// { - /// let a = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap(); - /// } // as a's scope ends here, it get's dropped - /// ``` - /// - /// ``` - /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq; - /// use std::str::FromStr; - /// - /// let a = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap(); - /// drop(a); // explicitly drops a's value - /// ``` - fn drop(&mut self) { - if Rc::strong_count(&self.modulus) <= 1 { - let mut a = *self.modulus; - unsafe { - fq_ctx_clear(&mut a); - } - } - } -} - /// Test that the [`Clone`] trait is correctly implemented. #[cfg(test)] mod test_clone { @@ -91,37 +60,13 @@ mod test_clone { assert_eq!(Rc::strong_count(&b.modulus), 3); assert_eq!(Rc::strong_count(&c.modulus), 3); } - - /// Check if clone points to same point in memory - #[test] - fn same_reference() { - let a = ModulusPolynomialRingZq::from_str(&format!( - "3 {} 0 -{} mod {}", - u64::MAX, - u64::MAX, - u64::MAX - 58 // closest prime number smaller than u64, but larger than 2^62 - )) - .unwrap(); - - let b = a.clone(); - - assert_eq!( - unsafe { *a.get_fq_ctx().a }.0, - unsafe { *b.get_fq_ctx().a }.0, - ); - assert_eq!(a.get_fq_ctx().ctxp[0].n[0].0, b.get_fq_ctx().ctxp[0].n[0].0,); - assert_eq!( - unsafe { *a.get_fq_ctx().modulus[0].coeffs.offset(0) }.0, - unsafe { *b.get_fq_ctx().modulus[0].coeffs.offset(0) }.0, - ); - } } /// Test that the [`Drop`] trait is correctly implemented. #[cfg(test)] mod test_drop { use super::ModulusPolynomialRingZq; - use std::{collections::HashSet, rc::Rc, str::FromStr}; + use std::{rc::Rc, str::FromStr}; /// Check whether references are decreased when dropping instances #[test] @@ -150,30 +95,4 @@ mod test_drop { drop(a); assert_eq!(Rc::strong_count(&b.modulus), 2); } - - /// Creates and drops a [`ModulusPolynomialRingZq`] object, and outputs - /// the storage point in memory of that [`ModulusPolynomialRingZq`] - fn create_and_drop_modulus() -> (i64, i64, i64) { - let a = ModulusPolynomialRingZq::from_str( - "3 184467440739018 0 -184467440739018 mod 184467440739019", - ) - .unwrap(); - ( - unsafe { *a.get_fq_ctx().a }.0, - a.get_fq_ctx().ctxp[0].n[0].0, - unsafe { *a.get_fq_ctx().modulus[0].coeffs.offset(0) }.0, - ) - } - - /// Check whether freed memory is reused afterwards - #[test] - fn free_memory() { - let mut storage_addresses = HashSet::new(); - - for _i in 0..5 { - storage_addresses.insert(create_and_drop_modulus()); - } - - assert!(storage_addresses.len() < 5); - } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs index b4fdf712..ea23a7ed 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs @@ -12,11 +12,7 @@ //! This includes the [`Display`] trait. use super::ModulusPolynomialRingZq; -use crate::{ - integer::{PolyOverZ, Z}, - macros::for_others::implement_for_owned, -}; -use flint_sys::{fmpz::fmpz_init_set, fmpz_mod_poly::fmpz_mod_poly_get_fmpz_poly}; +use crate::macros::for_others::implement_for_owned; use std::fmt::Display; impl From<&ModulusPolynomialRingZq> for String { @@ -63,18 +59,10 @@ impl Display for ModulusPolynomialRingZq { /// ``` fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // get the value of the modulus - let mut modulus = Z::default(); - unsafe { fmpz_init_set(&mut modulus.value, &self.get_fq_ctx().ctxp[0].n[0]) }; + let modulus = self.get_q_as_modulus(); // get the value of the polynomial - let mut poly = PolyOverZ::default(); - unsafe { - fmpz_mod_poly_get_fmpz_poly( - &mut poly.poly, - &self.get_fq_ctx().modulus[0], - &self.get_fq_ctx().ctxp[0], - ) - }; + let poly = self.modulus.get_representative_least_nonnegative_residue(); write!(f, "{poly} mod {modulus}") } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/unsafe_functions.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/unsafe_functions.rs deleted file mode 100644 index c04dbfe9..00000000 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/unsafe_functions.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright © 2025 Niklas Siemer -// -// This file is part of qFALL-math. -// -// qFALL-math is free software: you can redistribute it and/or modify it under -// the terms of the Mozilla Public License Version 2.0 as published by the -// Mozilla Foundation. See . - -//! This module contains public functions that enable access to underlying -//! [FLINT](https://flintlib.org/) structs. Therefore, they require to be unsafe. - -use super::ModulusPolynomialRingZq; -use crate::macros::unsafe_passthrough::unsafe_getter_mod; -use flint_sys::fq::{fq_ctx_clear, fq_ctx_struct}; - -unsafe_getter_mod!(ModulusPolynomialRingZq, modulus, fq_ctx_struct); - -impl ModulusPolynomialRingZq { - /// Sets a mutable reference to the field `modulus` of type [`ModulusPolynomialRingZq`] to a given `fq_ctx_struct`. - /// - /// Parameters: - /// - `flint_struct`: value to set the attribute to - /// - /// **WARNING:** The returned struct is part of [`flint_sys`]. - /// Any changes to this object are unsafe and may introduce memory leaks. - /// Please be aware that most moduli are shared across multiple instances and all - /// modifications of this struct will affect any other instance with a reference to this object. - /// - /// This function is a passthrough to enable users of this library to use [`flint_sys`] - /// and with that [FLINT](https://flintlib.org/) functions that might not be covered in our library yet. - /// If this is the case, please consider contributing to this open-source project - /// by opening a Pull Request at [qfall_math](https://github.com/qfall/math) - /// to provide this feature in the future. - /// - /// # Safety - /// Ensure that the old `modulus` does not share any memory with any moduli - /// that might be used in the future. The memory of the old `modulus` is freed - /// using this function. - /// - /// Any [`flint_sys`] struct and function is part of a FFI to the C-library `FLINT`. - /// As `FLINT` is a C-library, it does not provide all memory safety features - /// that Rust and our Wrapper provide. - /// Thus, using functions of [`flint_sys`] can introduce memory leaks. - pub unsafe fn set_fq_ctx_struct(&mut self, flint_struct: fq_ctx_struct) { - let modulus = std::rc::Rc::::get_mut(&mut self.modulus).unwrap(); - - // free memory of old modulus before new values of modulus are copied - unsafe { fq_ctx_clear(modulus) }; - - modulus.a = flint_struct.a; - modulus.ctxp = flint_struct.ctxp; - modulus.inv = flint_struct.inv; - modulus.is_conway = flint_struct.is_conway; - modulus.j = flint_struct.j; - modulus.len = flint_struct.len; - modulus.modulus = flint_struct.modulus; - modulus.sparse_modulus = flint_struct.sparse_modulus; - modulus.var = flint_struct.var; - } -} - -#[cfg(test)] -mod test_get_fq_ctx_struct { - use super::ModulusPolynomialRingZq; - use std::str::FromStr; - - /// Checks availability of the getter for [`ModulusPolynomialRingZq::modulus`] - /// and its ability to be modified. - #[test] - #[allow(unused_mut)] - fn availability_and_modification() { - let mut modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 7").unwrap(); - let cmp_mod = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 5").unwrap(); - - let mut fmpz_mod = unsafe { modulus.get_fq_ctx_struct() }; - - fmpz_mod.ctxp[0].n[0].0 = 5; - - assert_eq!(cmp_mod, modulus); - } -} - -#[cfg(test)] -mod test_set_fq_ctx_struct { - use super::ModulusPolynomialRingZq; - use crate::{integer::Z, integer_mod_q::PolyOverZq, traits::GetCoefficient}; - use flint_sys::{ - fmpz::fmpz, - fmpz_mod::fmpz_mod_ctx_init, - fmpz_mod_poly::{fmpz_mod_poly_init, fmpz_mod_poly_set_coeff_fmpz}, - fq::fq_ctx_init_modulus, - }; - use std::{ffi::CString, mem::MaybeUninit, str::FromStr}; - - /// Checks availability of the setter for [`ModulusPolynomialRingZq::modulus`] - /// and its ability to modify [`ModulusPolynomialRingZq`]. - #[test] - #[allow(unused_mut)] - fn availability_and_modification() { - let poly_zq = PolyOverZq::from_str("2 2 3 mod 7").unwrap(); - let mut test_struct = ModulusPolynomialRingZq::from(poly_zq); - // Setup modulus, i.e. mod 11 - let mut modulus = MaybeUninit::uninit(); - let mut modulus = unsafe { - fmpz_mod_ctx_init(modulus.as_mut_ptr(), &fmpz(11)); - modulus.assume_init() - }; - // Setup ModulusPolynomial, i.e. 7 mod 11 - let mut poly = MaybeUninit::uninit(); - let mut poly = unsafe { - fmpz_mod_poly_init(poly.as_mut_ptr(), &modulus); - poly.assume_init() - }; - unsafe { - fmpz_mod_poly_set_coeff_fmpz(&mut poly, 1, &fmpz(7), &modulus); - }; - // Setup ModPolynomialRingZq - let mut mod_poly_ring_zq = MaybeUninit::uninit(); - let c_string = CString::new("X").unwrap(); - let mod_poly_ring_zq = unsafe { - fq_ctx_init_modulus( - mod_poly_ring_zq.as_mut_ptr(), - &poly, - &modulus, - c_string.as_ptr(), - ); - mod_poly_ring_zq.assume_init() - }; - - unsafe { test_struct.set_fq_ctx_struct(mod_poly_ring_zq) }; - - assert_eq!(Z::from(11), test_struct.get_q()); - assert_eq!(1, test_struct.get_degree()); - assert_eq!( - Z::from(7), - GetCoefficient::::get_coeff(&test_struct, 1).unwrap() - ); - } -} diff --git a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/add.rs index ae288f86..312cffe8 100644 --- a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/add.rs @@ -49,7 +49,8 @@ impl Add for &NTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); let mut out = NTTPolynomialRingZq { poly: vec![Z::default(); self.poly.len()], @@ -113,7 +114,8 @@ impl AddAssign<&NTTPolynomialRingZq> for NTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); for i in 0..self.poly.len() { unsafe { diff --git a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/mul.rs b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/mul.rs index 771e6362..65b5947b 100644 --- a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/mul.rs +++ b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/mul.rs @@ -50,7 +50,8 @@ impl Mul for &NTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); let mut res = Vec::with_capacity(self.poly.capacity()); for i in 0..self.poly.len() { @@ -114,7 +115,8 @@ impl MulAssign<&NTTPolynomialRingZq> for NTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); for i in 0..self.poly.len() { unsafe { diff --git a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/sub.rs index b0993524..48830563 100644 --- a/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/ntt_polynomial_ring_zq/arithmetic/sub.rs @@ -50,7 +50,8 @@ impl Sub for &NTTPolynomialRingZq { self.modulus, other.modulus, "The moduli of both polynomials have to be equal for subtraction." ); - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); let mut out = NTTPolynomialRingZq { poly: vec![Z::default(); self.poly.len()], @@ -114,7 +115,8 @@ impl SubAssign<&NTTPolynomialRingZq> for NTTPolynomialRingZq { if !self.compare_base(other) { panic!("{}", self.call_compare_base_error(other).unwrap()); } - let mod_q = &self.modulus.get_fq_ctx().ctxp[0]; + let binding = &self.modulus.get_q_as_modulus(); + let mod_q = binding.get_fmpz_mod_ctx_struct(); for i in 0..self.poly.len() { unsafe { diff --git a/src/integer_mod_q/poly_over_zq/from.rs b/src/integer_mod_q/poly_over_zq/from.rs index 9f9470b0..2ecf49cd 100644 --- a/src/integer_mod_q/poly_over_zq/from.rs +++ b/src/integer_mod_q/poly_over_zq/from.rs @@ -228,16 +228,7 @@ impl From<&ModulusPolynomialRingZq> for PolyOverZq { /// assert_eq!(poly_cmp, poly_zq); /// ``` fn from(modulus: &ModulusPolynomialRingZq) -> Self { - let modulus_q = Modulus::from(&modulus.get_q()); - let mut out = PolyOverZq::from(&modulus_q); - unsafe { - fmpz_mod_poly_set( - &mut out.poly, - &modulus.get_fq_ctx().modulus[0], - out.modulus.get_fmpz_mod_ctx_struct(), - ) - }; - out + (*modulus.modulus).clone() } } diff --git a/src/integer_mod_q/polynomial_ring_zq.rs b/src/integer_mod_q/polynomial_ring_zq.rs index 6286181f..d83cc27e 100644 --- a/src/integer_mod_q/polynomial_ring_zq.rs +++ b/src/integer_mod_q/polynomial_ring_zq.rs @@ -33,7 +33,6 @@ mod reduce; mod sample; mod set; mod to_string; -mod unsafe_functions; /// [`PolynomialRingZq`] represents polynomials over the finite field /// [`PolyOverZq`](crate::integer_mod_q::PolyOverZq)/f(X) where f(X) is a polynomial over [`Zq`](super::Zq). diff --git a/src/integer_mod_q/polynomial_ring_zq/norm.rs b/src/integer_mod_q/polynomial_ring_zq/norm.rs index f731e4e5..6679b892 100644 --- a/src/integer_mod_q/polynomial_ring_zq/norm.rs +++ b/src/integer_mod_q/polynomial_ring_zq/norm.rs @@ -41,7 +41,8 @@ impl PolynomialRingZq { let mut res = Z::ZERO; for i in 0..=self.get_degree() { let coeff: Z = unsafe { self.get_coeff_unchecked(i) }; - res += length(&coeff.value, &self.modulus.get_fq_ctx().ctxp[0].n[0]) + + res += length(&coeff.value, &self.modulus.get_q_as_modulus().modulus.n[0]) .pow(2) .unwrap(); } @@ -73,7 +74,7 @@ impl PolynomialRingZq { for i in 0..=self.get_degree() { let coeff: Z = unsafe { self.get_coeff_unchecked(i) }; - let len = length(&coeff.value, &self.modulus.get_fq_ctx().ctxp[0].n[0]); + let len = length(&coeff.value, &self.modulus.get_q_as_modulus().modulus.n[0]); res = max(res, len); } res diff --git a/src/integer_mod_q/polynomial_ring_zq/properties.rs b/src/integer_mod_q/polynomial_ring_zq/properties.rs index a000db7e..51b50e37 100644 --- a/src/integer_mod_q/polynomial_ring_zq/properties.rs +++ b/src/integer_mod_q/polynomial_ring_zq/properties.rs @@ -129,11 +129,9 @@ mod test_is_one { fn one_detection() { let one = PolynomialRingZq::from_str("1 1 / 4 1 10 12 9 mod 7").unwrap(); let one_2 = PolynomialRingZq::from_str("2 1 14 / 4 1 10 12 9 mod 7").unwrap(); - let one_3 = PolynomialRingZq::from_str("3 11 4 10 / 3 5 2 5 mod 11").unwrap(); assert!(one.is_one()); assert!(one_2.is_one()); - assert!(one_3.is_one()); } /// Ensure that is_one returns `false` for other polynomials. @@ -162,7 +160,7 @@ mod test_is_zero { fn zero_detection() { let zero = PolynomialRingZq::from_str("0 / 2 1 1 mod 7").unwrap(); let zero_2 = PolynomialRingZq::from_str("2 7 14 / 2 1 1 mod 7").unwrap(); - let zero_3 = PolynomialRingZq::from_str("3 3 3 6 / 3 1 1 2 mod 11").unwrap(); + let zero_3 = PolynomialRingZq::from_str("3 3 3 3 / 3 1 1 1 mod 11").unwrap(); assert!(zero.is_zero()); assert!(zero_2.is_zero()); diff --git a/src/integer_mod_q/polynomial_ring_zq/reduce.rs b/src/integer_mod_q/polynomial_ring_zq/reduce.rs index 0be80246..2b6d3fad 100644 --- a/src/integer_mod_q/polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/polynomial_ring_zq/reduce.rs @@ -16,8 +16,10 @@ use std::cmp::min; +use crate::utils::reduce::internal_reduce; + use super::PolynomialRingZq; -use flint_sys::{fmpz_poly::_fmpz_poly_normalise, fq::_fq_sparse_reduce}; +use flint_sys::fmpz_poly::_fmpz_poly_normalise; impl PolynomialRingZq { /// This function manually applies the modulus @@ -39,19 +41,23 @@ impl PolynomialRingZq { /// poly_ring.reduce() /// ``` pub(crate) fn reduce(&mut self) { - // use the sparse reduce instead of the normal reduce - // the normal reduce switches between a dense and a sparse reduce - // without further assumptions on the context, the dense reduce does - // not work, so we always use the sparse reduce. - // unsafe { fq_reduce(&mut self.poly.poly, self.modulus.get_fq_ctx()) } - unsafe { - let nr_coeffs = self.poly.poly.length; - // this is what is called in fq_reduce, when it is a sparse modulus - // here it is done explicitly to avoid the dense reduce that can cause problems. - _fq_sparse_reduce(self.poly.poly.coeffs, nr_coeffs, self.modulus.get_fq_ctx()); - self.poly.poly.length = min(nr_coeffs, self.modulus.get_fq_ctx().modulus[0].length); - _fmpz_poly_normalise(&mut self.poly.poly); - }; + let degree = self.get_degree(); + if degree >= 0 { + unsafe { + internal_reduce( + &mut self.poly.poly, + degree as usize, + &self.modulus.modulus.poly, + self.modulus.get_degree() as usize, + self.modulus.get_q_as_modulus().get_fmpz_mod_ctx_struct(), + ) + }; + unsafe { + // let nr_coeffs = self.poly.poly.length; + // self.poly.poly.length = min(nr_coeffs, self.modulus.get_degree()); + _fmpz_poly_normalise(&mut self.poly.poly); + }; + } } } diff --git a/src/integer_mod_q/polynomial_ring_zq/set.rs b/src/integer_mod_q/polynomial_ring_zq/set.rs index 5d7fb043..b941199c 100644 --- a/src/integer_mod_q/polynomial_ring_zq/set.rs +++ b/src/integer_mod_q/polynomial_ring_zq/set.rs @@ -177,7 +177,7 @@ mod test_set_coeff { /// Ensure that the correct coefficient is set and all others are set to `0`. #[test] fn set_coeff_rest_zero() { - let modulus = ModulusPolynomialRingZq::from_str("7 1 8 0 0 1 0 12 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("7 10 12 0 0 10 0 1 mod 17").unwrap(); let poly = PolyOverZ::from_str("2 0 2").unwrap(); let mut poly_ring = PolynomialRingZq::from((&poly, &modulus)); diff --git a/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs b/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs deleted file mode 100644 index e1ea4c30..00000000 --- a/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright © 2025 Niklas Siemer -// -// This file is part of qFALL-math. -// -// qFALL-math is free software: you can redistribute it and/or modify it under -// the terms of the Mozilla Public License Version 2.0 as published by the -// Mozilla Foundation. See . - -//! This module contains public functions that enable access to underlying -//! [FLINT](https://flintlib.org/) structs. Therefore, they require to be unsafe. - -use super::PolynomialRingZq; -use crate::macros::unsafe_passthrough::{unsafe_getter_indirect, unsafe_setter_indirect}; -use flint_sys::{fmpz_poly::fmpz_poly_struct, fq::fq_ctx_struct}; - -unsafe_getter_indirect!( - PolynomialRingZq, - poly, - get_fmpz_poly_struct, - fmpz_poly_struct -); -unsafe_getter_indirect!(PolynomialRingZq, modulus, get_fq_ctx_struct, fq_ctx_struct); - -unsafe_setter_indirect!( - PolynomialRingZq, - poly, - set_fmpz_poly_struct, - fmpz_poly_struct -); -unsafe_setter_indirect!(PolynomialRingZq, modulus, set_fq_ctx_struct, fq_ctx_struct); diff --git a/src/utils.rs b/src/utils.rs index 738250a1..3f7036f4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,6 +15,7 @@ pub(crate) mod dimensions; mod factorization; pub mod index; pub(crate) mod parse; +pub mod reduce; pub mod sample; pub use factorization::Factorization; diff --git a/src/utils/reduce.rs b/src/utils/reduce.rs new file mode 100644 index 00000000..7e02865b --- /dev/null +++ b/src/utils/reduce.rs @@ -0,0 +1,42 @@ +use std::cmp::min; + +use flint_sys::{ + fmpz::{fmpz_submul, fmpz_zero}, + fmpz_mod::{fmpz_mod_ctx_struct, fmpz_mod_set_fmpz}, + fmpz_mod_poly::fmpz_mod_poly_struct, + fmpz_poly::fmpz_poly_struct, +}; + +pub(crate) unsafe fn internal_reduce( + poly: &mut fmpz_poly_struct, + nr_coeffs_poly: usize, + modulus_polynomial: &fmpz_mod_poly_struct, + nr_coeffs_modulus_poly: usize, + modulus: &fmpz_mod_ctx_struct, +) { + let (poly_len, modulus_polynomial_len) = (nr_coeffs_poly, nr_coeffs_modulus_poly); + + // X**3 + X**2 + 58X + 2 / X**3 + 1 + + // X**a + ... / X**b + ... + if poly_len >= modulus_polynomial_len { + // for i in (b..=a) + for i in (modulus_polynomial_len..=poly_len).rev() { + // for i in 0..b + for k in 0..modulus_polynomial_len { + unsafe { + fmpz_submul( + (poly.coeffs).add((i - modulus_polynomial_len) + k), + poly.coeffs.add(i), + modulus_polynomial.coeffs.add(k), + ) + }; + } + unsafe { fmpz_zero(poly.coeffs.add(i)) }; + } + } + + for i in 0..=min(poly_len, modulus_polynomial_len - 1) { + unsafe { fmpz_mod_set_fmpz(poly.coeffs.add(i), poly.coeffs.add(i), modulus) }; + } +} From 9e1de932928b1d02f680b51bbb8138cbb8cdf66c Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Thu, 15 Jan 2026 02:11:19 +0100 Subject: [PATCH 3/7] make the reduction sparse and fix all subsequent tests after requiring monic polynomials --- .../mat_poly_over_z/arithmetic/mul_scalar.rs | 2 +- src/integer/poly_over_z/arithmetic/sub.rs | 6 +- .../mat_ntt_polynomial_ring_zq.rs | 2 +- .../mat_polynomial_ring_zq/arithmetic/add.rs | 17 ++-- .../mat_polynomial_ring_zq/arithmetic/mul.rs | 6 +- .../arithmetic/mul_scalar.rs | 10 +-- .../mat_polynomial_ring_zq/arithmetic/sub.rs | 4 +- .../mat_polynomial_ring_zq/cmp.rs | 6 +- .../coefficient_embedding.rs | 30 +++---- .../mat_polynomial_ring_zq/from.rs | 10 +-- .../mat_polynomial_ring_zq/get.rs | 28 +++---- .../mat_polynomial_ring_zq/properties.rs | 4 +- .../mat_polynomial_ring_zq/reduce.rs | 1 + .../mat_polynomial_ring_zq/set.rs | 36 ++++----- .../mat_polynomial_ring_zq/sort.rs | 44 +++++----- .../mat_polynomial_ring_zq/tensor.rs | 56 ++++++------- .../mat_polynomial_ring_zq/to_string.rs | 6 +- .../vector/is_vector.rs | 28 ++----- .../mat_polynomial_ring_zq/vector/norm.rs | 38 ++++----- .../modulus_polynomial_ring_zq.rs | 1 + .../modulus_polynomial_ring_zq/cmp.rs | 80 +++++++------------ .../coefficient_embedding.rs | 44 +++------- .../modulus_polynomial_ring_zq/from.rs | 63 +++++++-------- .../modulus_polynomial_ring_zq/get.rs | 35 ++++---- .../modulus_polynomial_ring_zq/norm.rs | 6 +- .../modulus_polynomial_ring_zq/ownership.rs | 1 + .../modulus_polynomial_ring_zq/serialize.rs | 16 ++-- .../modulus_polynomial_ring_zq/to_string.rs | 4 +- .../poly_over_zq/arithmetic/sub.rs | 6 +- src/integer_mod_q/poly_over_zq/from.rs | 3 +- .../polynomial_ring_zq/arithmetic/add.rs | 30 ++++--- .../polynomial_ring_zq/arithmetic/mul.rs | 32 ++++---- .../arithmetic/mul_scalar.rs | 22 ++--- .../polynomial_ring_zq/arithmetic/sub.rs | 32 ++++---- src/integer_mod_q/polynomial_ring_zq/cmp.rs | 6 +- .../coefficient_embedding.rs | 20 ++--- src/integer_mod_q/polynomial_ring_zq/from.rs | 24 +++--- src/integer_mod_q/polynomial_ring_zq/get.rs | 2 +- src/integer_mod_q/polynomial_ring_zq/norm.rs | 24 +++--- .../polynomial_ring_zq/properties.rs | 14 ++-- .../polynomial_ring_zq/reduce.rs | 6 +- .../polynomial_ring_zq/sample/binomial.rs | 4 +- .../sample/discrete_gauss.rs | 2 +- .../polynomial_ring_zq/sample/uniform.rs | 2 +- src/integer_mod_q/polynomial_ring_zq/set.rs | 2 +- .../polynomial_ring_zq/to_string.rs | 12 +-- src/utils/reduce.rs | 56 +++++++++++-- 47 files changed, 425 insertions(+), 458 deletions(-) diff --git a/src/integer/mat_poly_over_z/arithmetic/mul_scalar.rs b/src/integer/mat_poly_over_z/arithmetic/mul_scalar.rs index bf602dd0..a95ce930 100644 --- a/src/integer/mat_poly_over_z/arithmetic/mul_scalar.rs +++ b/src/integer/mat_poly_over_z/arithmetic/mul_scalar.rs @@ -470,7 +470,7 @@ mod test_mul_poly_ring_zq { /// Checks if scalar multiplication reduction works. #[test] fn reduction_correct() { - let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_mat1 = MatPolyOverZ::from_str("[[0, 1 10],[0, 2 1 2]]").unwrap(); let poly = PolyOverZ::from(2); let poly_ring = PolynomialRingZq::from((&poly, &modulus)); diff --git a/src/integer/poly_over_z/arithmetic/sub.rs b/src/integer/poly_over_z/arithmetic/sub.rs index 1980951f..5f005302 100644 --- a/src/integer/poly_over_z/arithmetic/sub.rs +++ b/src/integer/poly_over_z/arithmetic/sub.rs @@ -344,10 +344,10 @@ mod test_sub_poly_ring_zq { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 -1 -{} / 4 1 2 3 4 mod {}", + "2 -1 -{} / 4 1 2 3 1 mod {}", i64::MAX as u64 - 2, u64::MAX )) @@ -362,7 +362,7 @@ mod test_sub_poly_ring_zq { /// Checks if subtraction works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = PolyOverZ::from(2); _ = z.clone() - poly.clone(); diff --git a/src/integer_mod_q/mat_ntt_polynomial_ring_zq.rs b/src/integer_mod_q/mat_ntt_polynomial_ring_zq.rs index 6aeb5cf7..5a7cc4b0 100644 --- a/src/integer_mod_q/mat_ntt_polynomial_ring_zq.rs +++ b/src/integer_mod_q/mat_ntt_polynomial_ring_zq.rs @@ -81,7 +81,7 @@ impl fmt::Debug for MatNTTPolynomialRingZq { pub(crate) fn print_vec_z(vector: &Vec) -> String { let mut out = String::new(); for v in vector { - out.push_str(&format!("{}, ", v)); + out.push_str(&format!("{v}, ")); } // Remove last whitespace and comma out.pop().unwrap(); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs index 2fa4ae4c..0291da1f 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs @@ -468,11 +468,8 @@ mod test_add { /// Testing addition for large [`MatPolynomialRingZq`] #[test] fn add_large_numbers() { - let modulus = ModulusPolynomialRingZq::from_str(&format!( - "5 1 1 0 0 {} mod {LARGE_PRIME}", - i64::MAX - )) - .unwrap(); + let modulus = + ModulusPolynomialRingZq::from_str(&format!("5 1 1 0 0 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str(&format!( "[[4 1 {} 1 1, 1 42],[0, 2 {} 2]]", i64::MAX, @@ -513,7 +510,7 @@ mod test_add { #[test] #[should_panic] fn add_mismatching_modulus_polynomial() { - let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_1 = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let poly_ring_mat_1 = MatPolynomialRingZq::from((&poly_mat_1, &modulus_1)); let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); @@ -527,7 +524,7 @@ mod test_add { #[test] #[should_panic] fn add_mismatching_dim() { - let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[1 42],[2 1 2]]").unwrap(); let poly_ring_mat_1 = MatPolynomialRingZq::from((&poly_mat_1, &modulus_1)); let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); @@ -540,10 +537,10 @@ mod test_add { /// Testing whether add_safe throws an error for mismatching moduli #[test] fn add_safe_is_err_moduli() { - let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let poly_ring_mat_1 = MatPolynomialRingZq::from((&poly_mat_1, &modulus_1)); - let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); + let modulus_2 = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_mat_2 = MatPolyOverZ::from_str("[[3 3 0 1, 1 42],[0, 1 17]]").unwrap(); let poly_ring_mat_2 = MatPolynomialRingZq::from((&poly_mat_2, &modulus_2)); @@ -553,7 +550,7 @@ mod test_add { /// Testing whether add_safe throws an error for different dimensions #[test] fn add_safe_is_err_dim() { - let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[4 -1 0 1 1],[2 1 2]]").unwrap(); let poly_ring_mat_1 = MatPolynomialRingZq::from((&poly_mat_1, &modulus_1)); let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul.rs index b0e4a016..c8856314 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul.rs @@ -86,7 +86,7 @@ impl Mul<&MatPolyOverZ> for &MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1 * &mat_2; @@ -176,7 +176,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1.mul_mat_poly_over_z_safe(&mat_2).unwrap(); @@ -269,7 +269,7 @@ mod test_mul { #[test] fn errors() { let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); - let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let poly_ring_mat_1 = MatPolynomialRingZq::from((&poly_mat_1, &modulus_1)); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs index 79586bbd..983dd9b1 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul_scalar.rs @@ -332,7 +332,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer_mod_q::{MatPolynomialRingZq, Zq}; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[1 42, 1 17],[2 1 8, 1 6]] / 3 1 2 3 mod 61").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[1 42, 1 17],[2 1 8, 1 6]] / 3 1 2 1 mod 61").unwrap(); /// let integer = Zq::from((2, 61)); /// /// let mat_2 = &mat_1.mul_scalar_zq_safe(&integer).unwrap(); @@ -745,7 +745,7 @@ mod test_mul_zq { #[test] #[should_panic] fn different_moduli_error() { - let mat_1 = MatPolynomialRingZq::from_str("[[1 42],[0],[1 2]] / 2 1 2 mod 61").unwrap(); + let mat_1 = MatPolynomialRingZq::from_str("[[1 42],[0],[1 2]] / 2 1 1 mod 61").unwrap(); let integer = Zq::from((2, 3)); _ = &integer * mat_1; @@ -754,7 +754,7 @@ mod test_mul_zq { /// Checks if scalar multiplication returns an error if the moduli mismatch #[test] fn different_moduli_error_safe() { - let mat_1 = MatPolynomialRingZq::from_str("[[1 42],[0],[1 2]] / 2 1 2 mod 61").unwrap(); + let mat_1 = MatPolynomialRingZq::from_str("[[1 42],[0],[1 2]] / 2 1 1 mod 61").unwrap(); let integer = Zq::from((2, 3)); let mat_2 = &mat_1.mul_scalar_zq_safe(&integer); @@ -914,7 +914,7 @@ mod test_mul_poly_over_zq { /// Checks if scalar multiplication reduction works. #[test] fn reduction_correct() { - let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_mat1 = MatPolyOverZ::from_str("[[0, 1 10],[0, 2 1 2]]").unwrap(); let poly_ring_mat1 = MatPolynomialRingZq::from((&poly_mat1, &modulus)); let poly = PolyOverZq::from((2, 17)); @@ -1045,7 +1045,7 @@ mod test_mul_poly_ring_zq { /// Checks if scalar multiplication reduction works. #[test] fn reduction_correct() { - let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_mat1 = MatPolyOverZ::from_str("[[0, 1 10],[0, 2 1 2]]").unwrap(); let poly_ring_mat1 = MatPolynomialRingZq::from((&poly_mat1, &modulus)); let poly = PolyOverZ::from(2); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/sub.rs index 20aba4c1..0cb2c4fe 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/sub.rs @@ -150,7 +150,7 @@ impl Sub<&MatPolyOverZ> for &MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1 - &mat_2; @@ -230,7 +230,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1.sub_mat_poly_over_z_safe(&mat_2).unwrap(); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/cmp.rs b/src/integer_mod_q/mat_polynomial_ring_zq/cmp.rs index 731ced7c..fc07cc04 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/cmp.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/cmp.rs @@ -91,8 +91,8 @@ mod test_compare_base { assert!(!one_1.compare_base(&MatPolynomialRingZq::identity(10, 7, &modulus_other))); assert!(one_1.compare_base(&Zq::from((3, 17)))); assert!(!one_1.compare_base(&Zq::from((3, 18)))); - assert!(one_1.compare_base(&PolyOverZq::from_str("1 3 mod 17").unwrap())); - assert!(!one_1.compare_base(&PolyOverZq::from_str("1 3 mod 18").unwrap())); + assert!(one_1.compare_base(&PolyOverZq::from_str("1 1 mod 17").unwrap())); + assert!(!one_1.compare_base(&PolyOverZq::from_str("1 1 mod 18").unwrap())); assert!(one_1.compare_base(&MatZq::new(1, 1, 17))); assert!(!one_1.compare_base(&MatZq::new(1, 1, 18))); assert!(one_1.compare_base(&PolynomialRingZq::from(&modulus))); @@ -106,7 +106,7 @@ mod test_compare_base { assert!(one_1.call_compare_base_error(&Zq::from((3, 18))).is_some()); assert!( one_1 - .call_compare_base_error(&PolyOverZq::from_str("1 3 mod 18").unwrap()) + .call_compare_base_error(&PolyOverZq::from_str("1 1 mod 18").unwrap()) .is_some() ); assert!( diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/coefficient_embedding.rs b/src/integer_mod_q/mat_polynomial_ring_zq/coefficient_embedding.rs index 00a0ddfc..7923fbba 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/coefficient_embedding.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/coefficient_embedding.rs @@ -44,7 +44,7 @@ impl IntoCoefficientEmbedding<(MatZq, ModulusPolynomialRingZq)> for &MatPolynomi /// traits::IntoCoefficientEmbedding, /// }; /// - /// let poly = MatPolynomialRingZq::from_str("[[1 1, 2 1 2],[1 -1, 2 -1 -2]] / 3 1 2 3 mod 17").unwrap(); + /// let poly = MatPolynomialRingZq::from_str("[[1 1, 2 1 2],[1 -1, 2 -1 -2]] / 3 1 2 1 mod 17").unwrap(); /// let embedding = poly.into_coefficient_embedding(2); /// let cmp_mat = MatZq::from_str("[[1, 1],[0, 2],[-1, -1],[0, -2]] mod 17").unwrap(); /// assert_eq!((cmp_mat, poly.get_mod()), embedding); @@ -105,9 +105,9 @@ impl FromCoefficientEmbedding<(&MatZq, &ModulusPolynomialRingZq, i64)> for MatPo /// }; /// /// let matrix = MatZq::from_str("[[17, 1],[3, 2],[-5, 3],[1, 2]] mod 19").unwrap(); - /// let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 4 mod 19").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 1 mod 19").unwrap(); /// let mat = MatPolynomialRingZq::from_coefficient_embedding((&matrix, &modulus, 1)); - /// let cmp_mat = MatPolynomialRingZq::from_str("[[2 17 3, 2 1 2],[2 -5 1, 2 3 2]] / 4 1 2 3 4 mod 19").unwrap(); + /// let cmp_mat = MatPolynomialRingZq::from_str("[[2 17 3, 2 1 2],[2 -5 1, 2 3 2]] / 4 1 2 3 1 mod 19").unwrap(); /// assert_eq!(cmp_mat, mat); /// ``` /// @@ -164,7 +164,7 @@ mod test_into_coefficient_embedding { #[test] fn standard_basis() { let standard_basis = MatPolynomialRingZq::from_str( - "[[1 1, 2 0 1, 3 0 0 1],[1 1, 2 0 1, 3 0 0 1]] / 4 1 2 3 4 mod 17", + "[[1 1, 2 0 1, 3 0 0 1],[1 1, 2 0 1, 3 0 0 1]] / 4 1 2 3 1 mod 17", ) .unwrap(); @@ -184,7 +184,7 @@ mod test_into_coefficient_embedding { #[test] fn standard_basis_vector() { let standard_basis = - MatPolynomialRingZq::from_str("[[1 1, 2 0 1]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[1 1, 2 0 1]] / 3 1 2 1 mod 17").unwrap(); let basis = standard_basis.into_coefficient_embedding(3); @@ -195,7 +195,7 @@ mod test_into_coefficient_embedding { #[test] fn large_entries() { let poly = MatPolynomialRingZq::from_str(&format!( - "[[3 17 {} {}, 1 1],[1 1, 2 0 1]] / 4 1 2 3 4 mod {}", + "[[3 17 {} {}, 1 1],[1 1, 2 0 1]] / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -220,7 +220,7 @@ mod test_into_coefficient_embedding { #[test] fn large_entries_vector() { let poly = MatPolynomialRingZq::from_str(&format!( - "[[3 17 {} {}, 1 1]] / 4 1 2 3 4 mod {}", + "[[3 17 {} {}, 1 1]] / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -244,7 +244,7 @@ mod test_into_coefficient_embedding { #[should_panic] fn size_too_small() { let poly = - MatPolynomialRingZq::from_str("[[3 17 5 7, 2 0 1],[1 1, 1 1]] / 4 1 2 3 4 mod 19") + MatPolynomialRingZq::from_str("[[3 17 5 7, 2 0 1],[1 1, 1 1]] / 4 1 2 3 1 mod 19") .unwrap(); let _ = poly.into_coefficient_embedding(2); @@ -255,7 +255,7 @@ mod test_into_coefficient_embedding { #[should_panic] fn size_too_small_vector() { let poly = - MatPolynomialRingZq::from_str("[[3 17 5 7, 2 0 1]] / 4 1 2 3 4 mod 19").unwrap(); + MatPolynomialRingZq::from_str("[[3 17 5 7, 2 0 1]] / 4 1 2 3 1 mod 19").unwrap(); let _ = poly.into_coefficient_embedding(2); } @@ -278,12 +278,12 @@ mod test_from_coefficient_embedding { )) .unwrap(); let modulus = - ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 4 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 1 mod {}", u64::MAX)).unwrap(); let poly = MatPolynomialRingZq::from_coefficient_embedding((&matrix, &modulus, 0)); let cmp_poly = MatPolynomialRingZq::from_str(&format!( - "[[1 17, 0],[1 {}, 1 -1],[1 {}, 0]] / 4 1 2 3 4 mod {}", + "[[1 17, 0],[1 {}, 1 -1],[1 {}, 0]] / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -303,12 +303,12 @@ mod test_from_coefficient_embedding { )) .unwrap(); let modulus = - ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 4 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 1 mod {}", u64::MAX)).unwrap(); let poly = MatPolynomialRingZq::from_coefficient_embedding((&matrix, &modulus, 2)); let cmp_poly = MatPolynomialRingZq::from_str(&format!( - "[[3 17 {} {}, 2 0 -1]] / 4 1 2 3 4 mod {}", + "[[3 17 {} {}, 2 0 -1]] / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -330,7 +330,7 @@ mod test_from_coefficient_embedding { )) .unwrap(); let modulus = - ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 4 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 1 mod {}", u64::MAX)).unwrap(); let _ = MatPolynomialRingZq::from_coefficient_embedding((&matrix, &modulus, 1)); } @@ -346,7 +346,7 @@ mod test_from_coefficient_embedding { )) .unwrap(); let modulus = - ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 4 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 1 mod {}", u64::MAX)).unwrap(); let _ = MatPolynomialRingZq::from_coefficient_embedding((&matrix, &modulus, 3)); } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/from.rs b/src/integer_mod_q/mat_polynomial_ring_zq/from.rs index 931f207a..d8b87a9e 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/from.rs @@ -57,7 +57,7 @@ impl FromStr for MatPolynomialRingZq { /// string `"4 0 1 2 3"` is the same as `"4 0 1 2 3 4 5 6 7"`. /// /// Parameters: - /// - `string`: the matrix of form: `"[[poly_1, poly_2, poly_3],[poly_4, poly_5, poly_6]] / poly_7 mod 11"` + /// - `string`: the matrix of form: `"[[poly_1, poly_2, poly_3],[poly_4, poly_5, poly_6]] / poly_1 mod 11"` /// for a 2x3 matrix where the first three polynomials are in the first row, /// the second three are in the second row, and the seventh polynomial and 11 form the modulus. /// @@ -73,14 +73,14 @@ impl FromStr for MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let matrix = MatPolynomialRingZq::from_str("[[2 2 2, 1 2],[0, 1 3]] / 2 3 3 mod 24").unwrap(); + /// let matrix = MatPolynomialRingZq::from_str("[[2 2 2, 1 2],[0, 1 3]] / 2 3 1 mod 24").unwrap(); /// ``` /// /// ``` /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let str_1 = "[[2 2 2, 1 2],[0, 1 3]] / 2 3 3 mod 24"; + /// let str_1 = "[[2 2 2, 1 2],[0, 1 3]] / 2 3 1 mod 24"; /// let matrix = MatPolynomialRingZq::from_str(str_1).unwrap(); /// ``` /// @@ -88,7 +88,7 @@ impl FromStr for MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let string = String::from("[[2 2 2, 1 2],[0, 1 3]] / 2 3 3 mod 24"); + /// let string = String::from("[[2 2 2, 1 2],[0, 1 3]] / 2 3 1 mod 24"); /// let matrix = MatPolynomialRingZq::from_str(&string).unwrap(); /// ``` /// @@ -336,7 +336,7 @@ mod test_from { #[test] fn different_dimensions() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("3 1 9 12 mod {LARGE_PRIME}")).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("3 1 9 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[2 1 8],[2 1 2]]").unwrap(); let poly_mat_2 = MatPolyOverZ::from_str("[[2 1 8, 1 42, 0],[0, 2 1 2, 1 17]]").unwrap(); let poly_mat_3 = MatPolyOverZ::from_str("[[2 1 8]]").unwrap(); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/get.rs b/src/integer_mod_q/mat_polynomial_ring_zq/get.rs index 3fa21585..a6709cc1 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/get.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/get.rs @@ -287,7 +287,7 @@ mod test_get_entry { /// Ensure that getting entries works on the edge. #[test] fn get_edges() { - let modulus = ModulusPolynomialRingZq::from_str("2 42 17 mod 89").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("2 42 1 mod 89").unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); let entry_1: PolyOverZ = matrix.get_entry(0, 0).unwrap(); @@ -301,7 +301,7 @@ mod test_get_entry { #[test] fn large_positive() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 3 mod {LARGE_PRIME}")) + ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 1 mod {LARGE_PRIME}")) .unwrap(); let poly_mat = MatPolyOverZ::from_str(&format!("[[4 1 0 {} 1, 1 42],[0, 2 1 2]]", i64::MAX)) @@ -320,7 +320,7 @@ mod test_get_entry { #[test] fn error_wrong_row() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 3 mod {LARGE_PRIME}")) + ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 1 mod {LARGE_PRIME}")) .unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); @@ -334,7 +334,7 @@ mod test_get_entry { #[test] fn error_wrong_column() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 3 mod {LARGE_PRIME}")) + ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 1 mod {LARGE_PRIME}")) .unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); @@ -348,7 +348,7 @@ mod test_get_entry { #[test] fn diff_types() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 3 mod {LARGE_PRIME}")) + ModulusPolynomialRingZq::from_str(&format!("5 42 17 1 2 1 mod {LARGE_PRIME}")) .unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); @@ -368,7 +368,7 @@ mod test_get_num { /// Ensure that the getter for number of rows works correctly. #[test] fn num_rows() { - let modulus = ModulusPolynomialRingZq::from_str("2 42 17 mod 89").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("2 42 1 mod 89").unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); assert_eq!(matrix.get_num_rows(), 5); @@ -377,7 +377,7 @@ mod test_get_num { /// Ensure that the getter for number of columns works correctly. #[test] fn num_columns() { - let modulus = ModulusPolynomialRingZq::from_str("2 42 17 mod 89").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("2 42 1 mod 89").unwrap(); let matrix = MatPolynomialRingZq::new(5, 10, &modulus); assert_eq!(matrix.get_num_columns(), 10); @@ -397,13 +397,13 @@ mod test_mod { /// Ensure that the getter for modulus works correctly. #[test] fn get_mod() { - let modulus = ModulusPolynomialRingZq::from_str("2 42 17 mod 89").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("2 42 1 mod 89").unwrap(); let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let matrix = MatPolynomialRingZq::from((&poly_mat, &modulus)); assert_eq!( matrix.get_mod(), - ModulusPolynomialRingZq::from_str("2 42 17 mod 89").unwrap() + ModulusPolynomialRingZq::from_str("2 42 1 mod 89").unwrap() ); } @@ -411,13 +411,13 @@ mod test_mod { #[test] fn get_mod_large() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("2 42 17 mod {LARGE_PRIME}")).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("2 42 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let matrix = MatPolynomialRingZq::from((&poly_mat, &modulus)); assert_eq!( matrix.get_mod(), - ModulusPolynomialRingZq::from_str(&format!("2 42 17 mod {LARGE_PRIME}")).unwrap() + ModulusPolynomialRingZq::from_str(&format!("2 42 1 mod {LARGE_PRIME}")).unwrap() ); } @@ -425,17 +425,17 @@ mod test_mod { #[test] fn get_mod_memory() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("2 42 17 mod {LARGE_PRIME}")).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("2 42 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let matrix = MatPolynomialRingZq::from((&poly_mat, &modulus)); let _ = matrix.get_mod(); - let _ = ModulusPolynomialRingZq::from_str(&format!("2 42 17 mod {LARGE_PRIME}")).unwrap(); + let _ = ModulusPolynomialRingZq::from_str(&format!("2 42 1 mod {LARGE_PRIME}")).unwrap(); let modulus = matrix.get_mod(); assert_eq!( modulus, - ModulusPolynomialRingZq::from_str(&format!("2 42 17 mod {LARGE_PRIME}")).unwrap() + ModulusPolynomialRingZq::from_str(&format!("2 42 1 mod {LARGE_PRIME}")).unwrap() ); } } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/properties.rs b/src/integer_mod_q/mat_polynomial_ring_zq/properties.rs index d95b9171..afec152b 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/properties.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/properties.rs @@ -273,7 +273,7 @@ mod test_is_symmetric { #[test] fn symmetric_rejection() { let mat_2x3 = - MatPolynomialRingZq::from_str("[[0, 1 6, 2 1 4],[1 2, 0, 2 1 1]] / 2 1 2 mod 17") + MatPolynomialRingZq::from_str("[[0, 1 6, 2 1 4],[1 2, 0, 2 1 1]] / 2 1 1 mod 17") .unwrap(); let mat_2x2 = MatPolynomialRingZq::from_str("[[1 9, 0],[2 1 71, 0]] / 3 1 2 1 mod 17").unwrap(); @@ -286,7 +286,7 @@ mod test_is_symmetric { #[test] fn symmetric_detection() { let mat_2x2 = MatPolynomialRingZq::from_str(&format!( - "[[2 1 {}, 2 3 {}],[2 3 {}, 3 1 {} 8]] / 2 1 2 mod {}", + "[[2 1 {}, 2 3 {}],[2 3 {}, 3 1 {} 8]] / 2 1 1 mod {}", u64::MIN, i64::MAX, i64::MAX, diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs index c594834e..8db3ff8a 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs @@ -74,6 +74,7 @@ impl MatPolynomialRingZq { &self.modulus.modulus.poly, self.modulus.get_degree() as usize, self.modulus.get_q_as_modulus().get_fmpz_mod_ctx_struct(), + &self.modulus.non_zero, ) } unsafe { diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/set.rs b/src/integer_mod_q/mat_polynomial_ring_zq/set.rs index a06948f0..20f7b8d3 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/set.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/set.rs @@ -542,7 +542,7 @@ mod test_setter { #[test] fn modulus_error() { let modulus_1 = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); - let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus_2 = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap(); let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus_1)); let value = PolynomialRingZq::from((&PolyOverZ::default(), &modulus_2)); @@ -771,11 +771,11 @@ mod test_swaps { #[test] fn entries_swapping() { let mut matrix = MatPolynomialRingZq::from_str( - "[[1 1, 1 2, 1 3],[1 4, 2 5 6, 0]] / 3 1 2 3 mod 17", + "[[1 1, 1 2, 1 3],[1 4, 2 5 6, 0]] / 3 1 2 1 mod 17", ) .unwrap(); let cmp = MatPolynomialRingZq::from_str( - "[[1 1, 2 5 6, 1 3],[1 4, 1 2, 0]] / 3 1 2 3 mod 17", + "[[1 1, 2 5 6, 1 3],[1 4, 1 2, 0]] / 3 1 2 1 mod 17", ) .unwrap(); @@ -813,12 +813,12 @@ mod test_swaps { #[test] fn columns_swapping() { let mut matrix = MatPolynomialRingZq::from_str( - "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 3 1 2 3 mod 17", + "[[1 1, 1 2, 1 3],[1 4, 1 5, 1 6]] / 3 1 2 1 mod 17", ) .unwrap(); - let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[1 4]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 3],[1 6]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_2 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 3 mod 17").unwrap(); + let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[1 4]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 3],[1 6]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_2 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap(); let _ = matrix.swap_columns(1, 2); @@ -843,11 +843,11 @@ mod test_swaps { #[test] fn rows_swapping() { let mut matrix = - MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 2 4 5]] / 3 1 2 3 mod 17") + MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 2 4 5]] / 3 1 2 1 mod 17") .unwrap(); let cmp_vec_0 = - MatPolynomialRingZq::from_str("[[1 3, 2 4 5]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[1 3, 2 4 5]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap(); let _ = matrix.swap_rows(1, 0); @@ -881,13 +881,13 @@ mod test_reverses { #[test] fn columns_reversing() { let mut matrix = MatPolynomialRingZq::from_str( - "[[1 1, 1 2, 2 3 4],[0, 1 5, 1 6]] / 3 1 2 3 mod 17", + "[[1 1, 1 2, 2 3 4],[0, 1 5, 1 6]] / 3 1 2 1 mod 17", ) .unwrap(); - let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[0]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 3 mod 17").unwrap(); + let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1],[0]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_1 = MatPolynomialRingZq::from_str("[[1 2],[1 5]] / 3 1 2 1 mod 17").unwrap(); let cmp_vec_2 = - MatPolynomialRingZq::from_str("[[2 3 4],[1 6]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[2 3 4],[1 6]] / 3 1 2 1 mod 17").unwrap(); matrix.reverse_columns(); @@ -900,9 +900,9 @@ mod test_reverses { #[test] fn rows_reversing() { let mut matrix = - MatPolynomialRingZq::from_str("[[1 1, 1 2],[2 3 4, 0]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 3 mod 17").unwrap(); - let cmp_vec_1 = MatPolynomialRingZq::from_str("[[2 3 4, 0]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[1 1, 1 2],[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_0 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap(); + let cmp_vec_1 = MatPolynomialRingZq::from_str("[[2 3 4, 0]] / 3 1 2 1 mod 17").unwrap(); matrix.reverse_rows(); @@ -1023,7 +1023,7 @@ mod test_set_submatrix { let mut mat1 = MatPolynomialRingZq::identity(10, 10, &modulus1); let modulus2 = - ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 2 mod {}", u64::MAX - 1)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 2 0 0 1 mod {}", u64::MAX - 1)).unwrap(); let mat2 = MatPolynomialRingZq::identity(10, 10, &modulus2); assert!(mat1.set_submatrix(0, 0, &mat2.clone(), 0, 9, 0, 9).is_err()); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/sort.rs b/src/integer_mod_q/mat_polynomial_ring_zq/sort.rs index c58367e4..5e5960b4 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/sort.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/sort.rs @@ -31,8 +31,8 @@ impl MatPolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; - /// let mat = MatPolynomialRingZq::from_str("[[2 3 4, 1 2, 1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let cmp = MatPolynomialRingZq::from_str("[[1 1, 1 2, 2 3 4]] / 3 1 2 3 mod 17").unwrap(); + /// let mat = MatPolynomialRingZq::from_str("[[2 3 4, 1 2, 1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let cmp = MatPolynomialRingZq::from_str("[[1 1, 1 2, 2 3 4]] / 3 1 2 1 mod 17").unwrap(); /// /// let sorted = mat.sort_by_column(MatPolynomialRingZq::norm_eucl_sqrd).unwrap(); /// @@ -44,8 +44,8 @@ impl MatPolynomialRingZq { /// use qfall_math::{integer_mod_q::MatPolynomialRingZq, integer::{PolyOverZ, Z}, error::MathError, traits::{MatrixDimensions, MatrixGetEntry}}; /// use crate::qfall_math::traits::GetCoefficient; /// use std::str::FromStr; - /// let mat = MatPolynomialRingZq::from_str("[[2 0 4, 1 2, 1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let cmp = MatPolynomialRingZq::from_str("[[2 0 4, 1 1, 1 2]] / 3 1 2 3 mod 17").unwrap(); + /// let mat = MatPolynomialRingZq::from_str("[[2 0 4, 1 2, 1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let cmp = MatPolynomialRingZq::from_str("[[2 0 4, 1 1, 1 2]] / 3 1 2 1 mod 17").unwrap(); /// /// fn custom_cond_func(matrix: &MatPolynomialRingZq) -> Result { /// let mut sum = Z::ZERO; @@ -99,8 +99,8 @@ impl MatPolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; - /// let mat = MatPolynomialRingZq::from_str("[[2 3 4],[1 2],[1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let cmp = MatPolynomialRingZq::from_str("[[1 1],[1 2],[2 3 4]] / 3 1 2 3 mod 17").unwrap(); + /// let mat = MatPolynomialRingZq::from_str("[[2 3 4],[1 2],[1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let cmp = MatPolynomialRingZq::from_str("[[1 1],[1 2],[2 3 4]] / 3 1 2 1 mod 17").unwrap(); /// /// let sorted = mat.sort_by_row(MatPolynomialRingZq::norm_infty).unwrap(); /// @@ -112,8 +112,8 @@ impl MatPolynomialRingZq { /// use qfall_math::{integer_mod_q::MatPolynomialRingZq, integer::{PolyOverZ, Z}, error::MathError, traits::{MatrixDimensions, MatrixGetEntry}}; /// use crate::qfall_math::traits::GetCoefficient; /// use std::str::FromStr; - /// let mat = MatPolynomialRingZq::from_str("[[2 0 4],[1 2],[1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let cmp = MatPolynomialRingZq::from_str("[[2 0 4],[1 1],[1 2]] / 3 1 2 3 mod 17").unwrap(); + /// let mat = MatPolynomialRingZq::from_str("[[2 0 4],[1 2],[1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let cmp = MatPolynomialRingZq::from_str("[[2 0 4],[1 1],[1 2]] / 3 1 2 1 mod 17").unwrap(); /// /// fn custom_cond_func(matrix: &MatPolynomialRingZq) -> Result { /// let mut sum = Z::ZERO; @@ -174,11 +174,11 @@ mod test_sort_by_length { #[test] fn column_norm_eucl_sqrd_small_entries() { let mat = MatPolynomialRingZq::from_str( - "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 3 mod 17", + "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 1 mod 17", ) .unwrap(); let cmp = MatPolynomialRingZq::from_str( - "[[0, 1 -1, 1 2, 1 3],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 3 mod 17", + "[[0, 1 -1, 1 2, 1 3],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 1 mod 17", ) .unwrap(); @@ -193,13 +193,13 @@ mod test_sort_by_length { #[test] fn column_norm_eucl_sqrd_large_entries() { let mat = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 5],[1 1, 1 2, 1 5],[0, 0, 0]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 5],[1 1, 1 2, 1 5],[0, 0, 0]] / 3 1 2 1 mod {}", i64::MAX, u64::MAX )) .unwrap(); let cmp = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 5, 1 {}],[1 1, 1 5, 1 2],[0, 0, 0]] / 3 1 2 3 mod {}", + "[[1 1, 1 5, 1 {}],[1 1, 1 5, 1 2],[0, 0, 0]] / 3 1 2 1 mod {}", i64::MAX, u64::MAX )) @@ -217,11 +217,11 @@ mod test_sort_by_length { #[test] fn many_columns() { let mat = MatPolynomialRingZq::from_str( - "[[1 3, 1 4, 1 1, 1 7, 1 2, 0, 1 9, 1 -8, 1 6, 1 5]] / 3 1 2 3 mod 17", + "[[1 3, 1 4, 1 1, 1 7, 1 2, 0, 1 9, 1 -8, 1 6, 1 5]] / 3 1 2 1 mod 17", ) .unwrap(); let cmp = MatPolynomialRingZq::from_str( - "[[0, 1 1, 1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 -8, 1 9]] / 3 1 2 3 mod 17", + "[[0, 1 1, 1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 -8, 1 9]] / 3 1 2 1 mod 17", ) .unwrap(); @@ -236,7 +236,7 @@ mod test_sort_by_length { #[test] fn column_error_cond_func() { let mat = - MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 1 4]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 1 4]] / 3 1 2 1 mod 17").unwrap(); let res = mat.sort_by_column(failing_func); @@ -247,11 +247,11 @@ mod test_sort_by_length { #[test] fn row_norm_eucl_sqrd_small_entries() { let mat = MatPolynomialRingZq::from_str( - "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 3 mod 17", + "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 1 mod 17", ) .unwrap(); let cmp = MatPolynomialRingZq::from_str( - "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 3 mod 17", + "[[1 3, 0, 1 2, 1 -1],[1 2, 1 2, 1 2, 1 2]] / 3 1 2 1 mod 17", ) .unwrap(); @@ -266,13 +266,13 @@ mod test_sort_by_length { #[test] fn row_norm_eucl_sqrd_large_entries() { let mat = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 0, 1 5],[1 {}, 1 2, 1 5],[0, 0, 0]] / 3 1 2 3 mod {}", + "[[1 1, 0, 1 5],[1 {}, 1 2, 1 5],[0, 0, 0]] / 3 1 2 1 mod {}", i64::MAX, u64::MAX )) .unwrap(); let cmp = MatPolynomialRingZq::from_str(&format!( - "[[0, 0, 0],[1 1, 0, 1 5],[1 {}, 1 2, 1 5]] / 3 1 2 3 mod {}", + "[[0, 0, 0],[1 1, 0, 1 5],[1 {}, 1 2, 1 5]] / 3 1 2 1 mod {}", i64::MAX, u64::MAX )) @@ -290,9 +290,9 @@ mod test_sort_by_length { #[test] fn many_rows() { let mat = - MatPolynomialRingZq::from_str("[[1 3],[0],[1 -1],[1 -7],[1 2],[1 9],[1 4],[1 8],[1 6],[1 5]] / 3 1 2 3 mod 82").unwrap(); + MatPolynomialRingZq::from_str("[[1 3],[0],[1 -1],[1 -7],[1 2],[1 9],[1 4],[1 8],[1 6],[1 5]] / 3 1 2 1 mod 82").unwrap(); let cmp = - MatPolynomialRingZq::from_str("[[0],[1 -1],[1 2],[1 3],[1 4],[1 5],[1 6],[1 -7],[1 8],[1 9]] / 3 1 2 3 mod 82").unwrap(); + MatPolynomialRingZq::from_str("[[0],[1 -1],[1 2],[1 3],[1 4],[1 5],[1 6],[1 -7],[1 8],[1 9]] / 3 1 2 1 mod 82").unwrap(); let res = mat .sort_by_row(MatPolynomialRingZq::norm_eucl_sqrd) @@ -305,7 +305,7 @@ mod test_sort_by_length { #[test] fn row_error_cond_func() { let mat = - MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 1 4]] / 3 1 2 3 mod 17").unwrap(); + MatPolynomialRingZq::from_str("[[1 1, 1 2],[1 3, 1 4]] / 3 1 2 1 mod 17").unwrap(); let res = mat.sort_by_row(failing_func); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs index f78f51ea..b76ffda9 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs @@ -30,14 +30,14 @@ impl Tensor for MatPolynomialRingZq { /// use qfall_math::traits::Tensor; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[1 1, 2 1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[1 1, 2 1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_ab = mat_1.tensor_product(&mat_2); /// let mat_ba = mat_2.tensor_product(&mat_1); /// - /// let res_ab = "[[1 1, 1 2, 2 1 1, 2 2 2]] / 3 1 2 3 mod 17"; - /// let res_ba = "[[1 1, 2 1 1, 1 2, 2 2 2]] / 3 1 2 3 mod 17"; + /// let res_ab = "[[1 1, 1 2, 2 1 1, 2 2 2]] / 3 1 2 1 mod 17"; + /// let res_ba = "[[1 1, 2 1 1, 1 2, 2 2 2]] / 3 1 2 1 mod 17"; /// assert_eq!(mat_ab, MatPolynomialRingZq::from_str(res_ab).unwrap()); /// assert_eq!(mat_ba, MatPolynomialRingZq::from_str(res_ba).unwrap()); /// ``` @@ -64,14 +64,14 @@ impl MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[1 1, 2 1 1]] / 3 1 2 3 mod 17").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[1 1, 2 1 1]] / 3 1 2 1 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[1 1, 1 2]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_ab = mat_1.tensor_product_safe(&mat_2).unwrap(); /// let mat_ba = mat_2.tensor_product_safe(&mat_1).unwrap(); /// - /// let res_ab = "[[1 1, 1 2, 2 1 1, 2 2 2]] / 3 1 2 3 mod 17"; - /// let res_ba = "[[1 1, 2 1 1, 1 2, 2 2 2]] / 3 1 2 3 mod 17"; + /// let res_ab = "[[1 1, 1 2, 2 1 1, 2 2 2]] / 3 1 2 1 mod 17"; + /// let res_ba = "[[1 1, 2 1 1, 1 2, 2 2 2]] / 3 1 2 1 mod 17"; /// assert_eq!(mat_ab, MatPolynomialRingZq::from_str(res_ab).unwrap()); /// assert_eq!(mat_ba, MatPolynomialRingZq::from_str(res_ba).unwrap()); /// ``` @@ -175,7 +175,7 @@ mod test_tensor { /// Ensure that the dimensions of the tensor product are taken over correctly. #[test] fn dimensions_fit() { - let mod_poly = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); + let mod_poly = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); let mat_1 = MatPolynomialRingZq::new(17, 13, &mod_poly); let mat_2 = MatPolynomialRingZq::new(3, 4, &mod_poly); @@ -189,10 +189,10 @@ mod test_tensor { #[test] fn identity() { let mod_poly = - ModulusPolynomialRingZq::from_str(&format!("3 1 2 3 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("3 1 2 1 mod {}", u64::MAX)).unwrap(); let identity = MatPolynomialRingZq::identity(2, 2, &mod_poly); let mat_1 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -203,7 +203,7 @@ mod test_tensor { let mat_3 = mat_1.tensor_product(&identity); let cmp_mat_2 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 1, 0, 0, 0],[0, 1 {}, 1 -1, 0, 0, 0],[0, 0, 0, 1 1, 1 {}, 1 1],[0, 0, 0, 0, 1 {}, 1 -1]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 1, 0, 0, 0],[0, 1 {}, 1 -1, 0, 0, 0],[0, 0, 0, 1 1, 1 {}, 1 1],[0, 0, 0, 0, 1 {}, 1 -1]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, i64::MAX, @@ -212,7 +212,7 @@ mod test_tensor { )) .unwrap(); let cmp_mat_3 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 0, 1 {}, 0, 1 1, 0],[0, 1 1, 0, 1 {}, 0, 1 1],[0, 0, 1 {}, 0, 1 -1, 0],[0, 0, 0, 1 {}, 0, 1 -1]] / 3 1 2 3 mod {}", + "[[1 1, 0, 1 {}, 0, 1 1, 0],[0, 1 1, 0, 1 {}, 0, 1 1],[0, 0, 1 {}, 0, 1 -1, 0],[0, 0, 0, 1 {}, 0, 1 -1]] / 3 1 2 1 mod {}", i64::MAX, i64::MAX, i64::MIN, @@ -229,10 +229,10 @@ mod test_tensor { #[test] fn vector_matrix() { let vector = - MatPolynomialRingZq::from_str(&format!("[[1 1],[1 -1]] / 3 1 2 3 mod {}", u64::MAX)) + MatPolynomialRingZq::from_str(&format!("[[1 1],[1 -1]] / 3 1 2 1 mod {}", u64::MAX)) .unwrap(); let mat_1 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1]] / 3 1 2 1 mod {}", i64::MAX, i64::MAX, u64::MAX @@ -243,7 +243,7 @@ mod test_tensor { let mat_3 = mat_1.tensor_product(&vector); let cmp_mat_2 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1],[1 -1, 1 -{}, 1 -1],[0, 1 -{}, 1 1]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 1],[0, 1 {}, 1 -1],[1 -1, 1 -{}, 1 -1],[0, 1 -{}, 1 1]] / 3 1 2 1 mod {}", i64::MAX, i64::MAX, i64::MAX, @@ -252,7 +252,7 @@ mod test_tensor { )) .unwrap(); let cmp_mat_3 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 1 1],[1 -1, 1 -{}, 1 -1],[0, 1 {}, 1 -1],[0, 1 -{}, 1 1]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 1 1],[1 -1, 1 -{}, 1 -1],[0, 1 {}, 1 -1],[0, 1 -{}, 1 1]] / 3 1 2 1 mod {}", i64::MAX, i64::MAX, i64::MAX, @@ -269,10 +269,10 @@ mod test_tensor { #[test] fn vector_vector() { let vec_1 = - MatPolynomialRingZq::from_str(&format!("[[1 2],[1 1]] / 3 1 2 3 mod {}", u64::MAX)) + MatPolynomialRingZq::from_str(&format!("[[1 2],[1 1]] / 3 1 2 1 mod {}", u64::MAX)) .unwrap(); let vec_2 = MatPolynomialRingZq::from_str(&format!( - "[[1 {}],[1 {}]] / 3 1 2 3 mod {}", + "[[1 {}],[1 {}]] / 3 1 2 1 mod {}", (u64::MAX - 1) / 2, i64::MIN / 2, u64::MAX @@ -283,7 +283,7 @@ mod test_tensor { let vec_4 = vec_2.tensor_product(&vec_1); let cmp_vec_3 = MatPolynomialRingZq::from_str(&format!( - "[[1 {}],[1 {}],[1 {}],[1 {}]] / 3 1 2 3 mod {}", + "[[1 {}],[1 {}],[1 {}],[1 {}]] / 3 1 2 1 mod {}", u64::MAX - 1, i64::MIN, (u64::MAX - 1) / 2, @@ -292,7 +292,7 @@ mod test_tensor { )) .unwrap(); let cmp_vec_4 = MatPolynomialRingZq::from_str(&format!( - "[[1 {}],[1 {}],[1 {}],[1 {}]] / 3 1 2 3 mod {}", + "[[1 {}],[1 {}],[1 {}],[1 {}]] / 3 1 2 1 mod {}", u64::MAX - 1, (u64::MAX - 1) / 2, i64::MIN, @@ -309,12 +309,12 @@ mod test_tensor { #[test] fn higher_degree() { let higher_degree = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 2 0 1, 2 1 1]] / 3 1 2 3 mod {}", + "[[1 1, 2 0 1, 2 1 1]] / 3 1 2 1 mod {}", u64::MAX )) .unwrap(); let mat_1 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 2 1 {}]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 2 1 {}]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -324,7 +324,7 @@ mod test_tensor { let mat_2 = higher_degree.tensor_product(&mat_1); let cmp_mat_2 = MatPolynomialRingZq::from_str(&format!( - "[[1 1, 1 {}, 2 1 {}, 2 0 1, 2 0 {}, 3 0 1 {}, 2 1 1, 2 {} {}, 3 1 {} {}]] / 3 1 2 3 mod {}", + "[[1 1, 1 {}, 2 1 {}, 2 0 1, 2 0 {}, 3 0 1 {}, 2 1 1, 2 {} {}, 3 1 {} {}]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, i64::MAX, @@ -344,8 +344,8 @@ mod test_tensor { #[test] #[should_panic] fn moduli_mismatch_panic() { - let mod_poly_1 = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); - let mod_poly_2 = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 16").unwrap(); + let mod_poly_1 = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); + let mod_poly_2 = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 16").unwrap(); let mat_1 = MatPolynomialRingZq::new(17, 13, &mod_poly_1); let mat_2 = MatPolynomialRingZq::new(3, 4, &mod_poly_2); @@ -355,8 +355,8 @@ mod test_tensor { /// Ensure that the safe version of the tensor product returns an error, if the moduli mismatch. #[test] fn moduli_mismatch_error() { - let mod_poly_1 = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); - let mod_poly_2 = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 16").unwrap(); + let mod_poly_1 = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); + let mod_poly_2 = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 16").unwrap(); let mat_1 = MatPolynomialRingZq::new(17, 13, &mod_poly_1); let mat_2 = MatPolynomialRingZq::new(3, 4, &mod_poly_2); diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/to_string.rs b/src/integer_mod_q/mat_polynomial_ring_zq/to_string.rs index dc1b7054..6b00e8dc 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/to_string.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/to_string.rs @@ -18,13 +18,13 @@ impl From<&MatPolynomialRingZq> for String { /// Parameters: /// - `value`: specifies the matrix that will be represented as a [`String`] /// - /// Returns a [`String`] of the form `"[[poly_1, poly_2, poly_3],[poly_4, poly_5, poly_6]] / poly_7 mod q"`. + /// Returns a [`String`] of the form `"[[poly_1, poly_2, poly_3],[poly_4, poly_5, poly_6]] / poly_1 mod q"`. /// /// # Examples /// ``` /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; - /// let matrix = MatPolynomialRingZq::from_str("[[2 2 2, 1 2],[0, 1 3]] / 2 4 4 mod 3").unwrap(); + /// let matrix = MatPolynomialRingZq::from_str("[[2 2 2, 1 2],[0, 1 3]] / 2 4 1 mod 3").unwrap(); /// /// let string: String = matrix.into(); /// ``` @@ -95,7 +95,7 @@ mod test_to_string { #[test] fn reduced() { let cmp = - MatPolynomialRingZq::from_str("[[2 2 2, 1 1, 0],[1 5, 1 6, 1 7]] / 2 4 4 mod 3") + MatPolynomialRingZq::from_str("[[2 2 2, 1 1, 0],[1 5, 1 6, 1 7]] / 2 4 1 mod 3") .unwrap(); assert_eq!( diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/vector/is_vector.rs b/src/integer_mod_q/mat_polynomial_ring_zq/vector/is_vector.rs index 7a360270..c583a68f 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/vector/is_vector.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/vector/is_vector.rs @@ -119,11 +119,8 @@ mod test_is_vector { /// get recognized as (row or column) vectors #[test] fn vectors_detected() { - let modulus = ModulusPolynomialRingZq::from_str(&format!( - "5 1 1 0 0 {} mod {LARGE_PRIME}", - i64::MAX - )) - .unwrap(); + let modulus = + ModulusPolynomialRingZq::from_str(&format!("5 1 1 0 0 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str(&format!("[[4 1 {} 1 1, 1 42]]", i64::MAX)).unwrap(); let poly_mat_2 = MatPolyOverZ::from_str(&format!( @@ -149,11 +146,8 @@ mod test_is_vector { /// don't get recognized as (row or column) vector #[test] fn non_vectors_detected() { - let modulus = ModulusPolynomialRingZq::from_str(&format!( - "5 1 1 0 0 {} mod {LARGE_PRIME}", - i64::MAX - )) - .unwrap(); + let modulus = + ModulusPolynomialRingZq::from_str(&format!("5 1 1 0 0 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str(&format!( "[[4 1 {} 1 1, 1 42],[3 1 1 1, 1 17]]", i64::MAX @@ -180,11 +174,8 @@ mod test_is_vector { /// Check whether matrices with only one entry get recognized as single entry matrices #[test] fn single_entry_detected() { - let modulus = ModulusPolynomialRingZq::from_str(&format!( - "5 1 1 0 0 {} mod {LARGE_PRIME}", - i64::MAX - )) - .unwrap(); + let modulus = + ModulusPolynomialRingZq::from_str(&format!("5 1 1 0 0 1 mod {LARGE_PRIME}",)).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str("[[1 42]]").unwrap(); let poly_mat_2 = MatPolyOverZ::from_str(&format!("[[3 1 {} 1]]", i64::MAX)).unwrap(); @@ -209,11 +200,8 @@ mod test_is_vector { /// don't get recognized as single entry matrices #[test] fn non_single_entry_detected() { - let modulus = ModulusPolynomialRingZq::from_str(&format!( - "5 1 1 0 0 {} mod {LARGE_PRIME}", - i64::MAX - )) - .unwrap(); + let modulus = + ModulusPolynomialRingZq::from_str(&format!("5 1 1 0 0 1 mod {LARGE_PRIME}")).unwrap(); let poly_mat_1 = MatPolyOverZ::from_str(&format!("[[4 1 {} 1 1, 1 42]]", i64::MAX)).unwrap(); let poly_mat_2 = MatPolyOverZ::from_str(&format!( diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/vector/norm.rs b/src/integer_mod_q/mat_polynomial_ring_zq/vector/norm.rs index 07ff3675..833b1e70 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/vector/norm.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/vector/norm.rs @@ -35,7 +35,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let vec = MatPolynomialRingZq::from_str("[[1 1],[2 2 2],[1 3]] / 3 1 2 3 mod 11").unwrap(); + /// let vec = MatPolynomialRingZq::from_str("[[1 1],[2 2 2],[1 3]] / 3 1 2 1 mod 11").unwrap(); /// /// let sqrd_2_norm = vec.norm_eucl_sqrd().unwrap(); /// @@ -74,7 +74,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let vec = MatPolynomialRingZq::from_str("[[1 2],[2 2 2],[1 2]] / 3 1 2 3 mod 11").unwrap(); + /// let vec = MatPolynomialRingZq::from_str("[[1 2],[2 2 2],[1 2]] / 3 1 2 1 mod 11").unwrap(); /// /// let sqrd_2_norm = vec.norm_eucl().unwrap(); /// @@ -104,7 +104,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer_mod_q::MatPolynomialRingZq; /// use std::str::FromStr; /// - /// let vec = MatPolynomialRingZq::from_str("[[1 1],[2 2 4],[1 3]] / 3 1 2 3 mod 11").unwrap(); + /// let vec = MatPolynomialRingZq::from_str("[[1 1],[2 2 4],[1 3]] / 3 1 2 1 mod 11").unwrap(); /// /// let infty_norm = vec.norm_infty().unwrap(); /// @@ -148,12 +148,12 @@ mod test_norm_eucl_sqrd { /// with small entries is calculated correctly #[test] fn row_vector_small_entries() { - let vec_1 = MatPolynomialRingZq::from_str("[[1 1]] / 2 1 2 mod 11").unwrap(); + let vec_1 = MatPolynomialRingZq::from_str("[[1 1]] / 2 1 1 mod 11").unwrap(); let vec_2 = - MatPolynomialRingZq::from_str("[[1 1, 2 10 3, 3 1 2 100]] / 4 1 2 3 4 mod 150") + MatPolynomialRingZq::from_str("[[1 1, 2 10 3, 3 1 2 100]] / 4 1 2 3 1 mod 150") .unwrap(); let vec_3 = MatPolynomialRingZq::from_str( - "[[2 1 3, 1 10, 3 1 2 100, 1 1000]] / 4 1 2 3 4 mod 1500", + "[[2 1 3, 1 10, 3 1 2 100, 1 1000]] / 4 1 2 3 1 mod 1500", ) .unwrap(); @@ -167,7 +167,7 @@ mod test_norm_eucl_sqrd { #[test] fn row_vector_large_entries() { let vec = MatPolynomialRingZq::from_str(&format!( - "[[1 {}, 2 {} 2, 2 2 1]] / 3 1 2 3 mod {}", + "[[1 {}, 2 {} 2, 2 2 1]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -186,10 +186,10 @@ mod test_norm_eucl_sqrd { #[test] fn column_vector_small_entries() { let vec_1 = - MatPolynomialRingZq::from_str("[[1 1],[2 10 3],[3 1 2 100]] / 4 1 2 3 4 mod 150") + MatPolynomialRingZq::from_str("[[1 1],[2 10 3],[3 1 2 100]] / 4 1 2 3 1 mod 150") .unwrap(); let vec_2 = MatPolynomialRingZq::from_str( - "[[2 1 3],[1 10],[3 1 2 100],[1 1000]] / 4 1 2 3 4 mod 1500", + "[[2 1 3],[1 10],[3 1 2 100],[1 1000]] / 4 1 2 3 1 mod 1500", ) .unwrap(); @@ -202,7 +202,7 @@ mod test_norm_eucl_sqrd { #[test] fn column_vector_large_entries() { let vec = MatPolynomialRingZq::from_str(&format!( - "[[2 2 {}],[1 {}],[1 2]] / 3 1 2 3 mod {}", + "[[2 2 {}],[1 {}],[1 2]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -220,7 +220,7 @@ mod test_norm_eucl_sqrd { #[test] fn non_vector_yield_error() { let mat = - MatPolynomialRingZq::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]] / 3 1 2 3 mod 11") + MatPolynomialRingZq::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]] / 3 1 2 1 mod 11") .unwrap(); assert!(mat.norm_eucl_sqrd().is_err()); @@ -236,12 +236,12 @@ mod test_norm_infty { /// with small entries is calculated correctly #[test] fn row_vector_small_entries() { - let vec_1 = MatPolynomialRingZq::from_str("[[1 1]] / 2 1 2 mod 11").unwrap(); + let vec_1 = MatPolynomialRingZq::from_str("[[1 1]] / 2 1 1 mod 1000").unwrap(); let vec_2 = - MatPolynomialRingZq::from_str("[[1 1, 2 10 3, 3 1 2 100]] / 4 1 2 3 4 mod 150") + MatPolynomialRingZq::from_str("[[1 1, 2 10 3, 3 1 2 100]] / 4 1 2 3 1 mod 150") .unwrap(); let vec_3 = MatPolynomialRingZq::from_str( - "[[2 1 3, 1 10, 3 1 2 100, 1 1000]] / 4 1 2 3 4 mod 1500", + "[[2 1 3, 1 10, 3 1 2 100, 1 1000]] / 4 1 2 3 1 mod 1500", ) .unwrap(); @@ -255,7 +255,7 @@ mod test_norm_infty { #[test] fn row_vector_large_entries() { let vec = MatPolynomialRingZq::from_str(&format!( - "[[1 {}, 2 {} 2, 2 2 1]] / 3 1 2 3 mod {}", + "[[1 {}, 2 {} 2, 2 2 1]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -270,10 +270,10 @@ mod test_norm_infty { #[test] fn column_vector_small_entries() { let vec_1 = - MatPolynomialRingZq::from_str("[[1 1],[2 10 3],[3 1 2 100]] / 4 1 2 3 4 mod 150") + MatPolynomialRingZq::from_str("[[1 1],[2 10 3],[3 1 2 100]] / 4 1 2 3 1 mod 150") .unwrap(); let vec_2 = MatPolynomialRingZq::from_str( - "[[2 1 3],[1 10],[3 1 2 100],[1 1000]] / 4 1 2 3 4 mod 1500", + "[[2 1 3],[1 10],[3 1 2 100],[1 1000]] / 4 1 2 3 1 mod 1500", ) .unwrap(); @@ -286,7 +286,7 @@ mod test_norm_infty { #[test] fn column_vector_large_entries() { let vec = MatPolynomialRingZq::from_str(&format!( - "[[2 2 {}],[1 {}],[1 2]] / 3 1 2 3 mod {}", + "[[2 2 {}],[1 {}],[1 2]] / 3 1 2 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -300,7 +300,7 @@ mod test_norm_infty { #[test] fn non_vector_yield_error() { let mat = - MatPolynomialRingZq::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]] / 3 1 2 3 mod 11") + MatPolynomialRingZq::from_str("[[2 1 20, 1 1],[1 10, 2 1 2]] / 3 1 2 1 mod 11") .unwrap(); assert!(mat.norm_infty().is_err()); diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq.rs b/src/integer_mod_q/modulus_polynomial_ring_zq.rs index 09bb1fa8..71fe2e02 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq.rs @@ -43,6 +43,7 @@ mod to_string; pub struct ModulusPolynomialRingZq { pub(crate) modulus: Rc, pub(crate) ntt_basis: Rc>, + pub(crate) non_zero: Vec, } impl fmt::Debug for ModulusPolynomialRingZq { diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs index 99bd465d..06c848c4 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/cmp.rs @@ -11,12 +11,9 @@ use super::ModulusPolynomialRingZq; use crate::{ - integer::Z, - integer_mod_q::{PolyOverZq, modulus}, - macros::for_others::implement_trait_reverse, + integer::Z, integer_mod_q::PolyOverZq, macros::for_others::implement_trait_reverse, traits::GetCoefficient, }; -use flint_sys::{fmpz::fmpz_equal, fmpz_mod_poly::fmpz_mod_poly_equal}; impl PartialEq for ModulusPolynomialRingZq { /// Checks if two modulus objects of type over [`ModulusPolynomialRingZq`] are equal. @@ -69,8 +66,8 @@ impl PartialEq for ModulusPolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::{PolyOverZq, ModulusPolynomialRingZq}; /// use std::str::FromStr; - /// let a: ModulusPolynomialRingZq = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); - /// let b: PolyOverZq = PolyOverZq::from_str("3 1 2 3 mod 17").unwrap(); + /// let a: ModulusPolynomialRingZq = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); + /// let b: PolyOverZq = PolyOverZq::from_str("3 1 2 1 mod 17").unwrap(); /// /// // These are all equivalent and return true. /// let compared: bool = (a == b); @@ -135,8 +132,8 @@ mod test_partial_eq { #[test] #[allow(clippy::op_ref)] fn equal_call_methods() { - let one_1 = ModulusPolynomialRingZq::from_str("2 42 -1 mod 17").unwrap(); - let one_2 = ModulusPolynomialRingZq::from_str("2 42 -1 mod 17").unwrap(); + let one_1 = ModulusPolynomialRingZq::from_str("2 42 1 mod 17").unwrap(); + let one_2 = ModulusPolynomialRingZq::from_str("2 42 1 mod 17").unwrap(); assert!(one_1 == one_2); assert!(&one_1 == &one_2); @@ -150,7 +147,7 @@ mod test_partial_eq { #[test] #[allow(clippy::op_ref)] fn not_equal_call_methods_different_num_coeffs() { - let one = ModulusPolynomialRingZq::from_str("2 42 -1 mod 17").unwrap(); + let one = ModulusPolynomialRingZq::from_str("2 42 1 mod 17").unwrap(); let two = ModulusPolynomialRingZq::from_str("3 42 -1 1 mod 17").unwrap(); assert!(one != two); @@ -160,40 +157,23 @@ mod test_partial_eq { assert_ne!(one, two); } - /// Test equal with small positive and negative constant polynomials. + /// Test equal with small positive constant polynomials. #[test] fn equal_small() { - let small_1 = ModulusPolynomialRingZq::from_str("2 1 10 mod 17").unwrap(); - let small_2 = ModulusPolynomialRingZq::from_str("2 1 10 mod 17").unwrap(); - let negative = ModulusPolynomialRingZq::from_str("2 1 -2 mod 17").unwrap(); + let small_1 = ModulusPolynomialRingZq::from_str("2 1 1 mod 17").unwrap(); + let small_2 = ModulusPolynomialRingZq::from_str("2 1 1 mod 17").unwrap(); assert!(small_1 == small_2); assert!(small_2 == small_1); assert!(small_1 == small_1); - assert!(!(small_1 == negative)); - assert!(!(negative == small_1)); - } - - /// Test not equal with small positive and negative constant polynomials. - #[test] - fn not_equal_small() { - let small_1 = ModulusPolynomialRingZq::from_str("2 1 10 mod 17").unwrap(); - let small_2 = ModulusPolynomialRingZq::from_str("2 1 10 mod 17").unwrap(); - let negative = ModulusPolynomialRingZq::from_str("2 1 -1 mod 17").unwrap(); - - assert!(!(small_1 != small_2)); - assert!(!(small_2 != small_1)); - assert!(!(small_1 != small_1)); - assert!(small_1 != negative); - assert!(negative != small_1); } /// Test equal with a large [`ModulusPolynomialRingZq`] /// (uses FLINT's pointer representation) #[test] fn equal_large() { - let max_str = format!("2 1 {} mod {LARGE_PRIME}", u64::MAX); - let min_str = format!("2 1 {} mod {LARGE_PRIME}", i64::MIN); + let max_str = format!("2 {} 1 mod {LARGE_PRIME}", u64::MAX); + let min_str = format!("2 {} 1 mod {LARGE_PRIME}", i64::MIN); let max_1 = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); let max_2 = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); @@ -211,8 +191,8 @@ mod test_partial_eq { /// (uses FLINT's pointer representation) #[test] fn not_equal_large() { - let max_str = format!("2 1 {} mod {LARGE_PRIME}", u64::MAX); - let min_str = format!("2 1 {} mod {LARGE_PRIME}", i64::MIN); + let max_str = format!("2 {} 1 mod {LARGE_PRIME}", u64::MAX); + let min_str = format!("2 {} 1 mod {LARGE_PRIME}", i64::MIN); let max_1 = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); let max_2 = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); @@ -230,14 +210,14 @@ mod test_partial_eq { /// and small polynomial with a small [`ModulusPolynomialRingZq`] (no pointer representation). #[test] fn equal_large_small() { - let max_str = format!("2 1 {} mod {LARGE_PRIME}", u64::MAX); - let min_str = format!("2 1 {} mod {LARGE_PRIME}", i64::MIN); + let max_str = format!("2 {} 1 mod {LARGE_PRIME}", u64::MAX); + let min_str = format!("2 {} 1 mod {LARGE_PRIME}", i64::MIN); let max = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); let min = ModulusPolynomialRingZq::from_str(&min_str).unwrap(); - let small_positive = ModulusPolynomialRingZq::from_str("2 1 2 mod 17").unwrap(); - let small_negative = ModulusPolynomialRingZq::from_str("2 1 -2 mod 17").unwrap(); + let small_positive = ModulusPolynomialRingZq::from_str("2 1 1 mod 17").unwrap(); + let small_negative = ModulusPolynomialRingZq::from_str("2 -1 1 mod 17").unwrap(); assert!(!(max == small_negative)); assert!(!(small_negative == max)); @@ -254,14 +234,14 @@ mod test_partial_eq { /// and small [`ModulusPolynomialRingZq`] (no pointer representation). #[test] fn not_equal_large_small() { - let max_str = format!("2 1 {} mod {LARGE_PRIME}", u64::MAX); - let min_str = format!("2 1 {} mod {LARGE_PRIME}", i64::MIN); + let max_str = format!("2 {} 1 mod {LARGE_PRIME}", u64::MAX); + let min_str = format!("2 {} 1 mod {LARGE_PRIME}", i64::MIN); let max = ModulusPolynomialRingZq::from_str(&max_str).unwrap(); let min = ModulusPolynomialRingZq::from_str(&min_str).unwrap(); - let small_positive = ModulusPolynomialRingZq::from_str("2 1 2 mod 17").unwrap(); - let small_negative = ModulusPolynomialRingZq::from_str("2 1 -2 mod 17").unwrap(); + let small_positive = ModulusPolynomialRingZq::from_str("2 1 1 mod 17").unwrap(); + let small_negative = ModulusPolynomialRingZq::from_str("2 -1 1 mod 17").unwrap(); assert!(max != small_negative); assert!(small_negative != max); @@ -277,8 +257,8 @@ mod test_partial_eq { /// Test not equal for the same polynomial but with a different modulus #[test] fn different_modulus() { - let first_str = "2 1 2 mod 17"; - let second_str = "2 1 2 mod 19"; + let first_str = "2 1 1 mod 17"; + let second_str = "2 1 1 mod 19"; let first = ModulusPolynomialRingZq::from_str(first_str).unwrap(); let second = ModulusPolynomialRingZq::from_str(second_str).unwrap(); @@ -297,8 +277,8 @@ mod test_partial_eq_q_other { #[test] #[allow(clippy::op_ref)] fn availability() { - let q = ModulusPolynomialRingZq::from_str("4 1 2 3 4 mod 17").unwrap(); - let z = PolyOverZq::from_str("4 1 2 3 4 mod 17").unwrap(); + let q = ModulusPolynomialRingZq::from_str("4 1 2 3 1 mod 17").unwrap(); + let z = PolyOverZq::from_str("4 1 2 3 1 mod 17").unwrap(); assert!(q == z); assert!(z == q); @@ -309,10 +289,9 @@ mod test_partial_eq_q_other { /// Ensure that equal values are compared correctly. #[test] fn equal() { - let q = ModulusPolynomialRingZq::from_str(&format!("3 1 2 {} mod {}", i64::MAX, u64::MAX)) - .unwrap(); - let z_1 = PolyOverZq::from_str(&format!("3 1 2 {} mod {}", i64::MAX, u64::MAX)).unwrap(); - let z_2 = PolyOverZq::from_str(&format!("4 1 2 {} 0 mod {}", i64::MAX, u64::MAX)).unwrap(); + let q = ModulusPolynomialRingZq::from_str(&format!("3 1 2 1 mod {}", u64::MAX)).unwrap(); + let z_1 = PolyOverZq::from_str(&format!("3 1 2 1 mod {}", u64::MAX)).unwrap(); + let z_2 = PolyOverZq::from_str(&format!("4 1 2 1 0 mod {}", u64::MAX)).unwrap(); assert!(q == z_1); assert!(q == z_2); @@ -321,8 +300,7 @@ mod test_partial_eq_q_other { /// Ensure that unequal values are compared correctly. #[test] fn unequal() { - let q = ModulusPolynomialRingZq::from_str(&format!("3 1 2 {} mod {}", i64::MAX, u64::MAX)) - .unwrap(); + let q = ModulusPolynomialRingZq::from_str(&format!("3 1 2 1 mod {}", u64::MAX)).unwrap(); let z_1 = PolyOverZq::from_str(&format!("3 1 3 {} mod {}", i64::MAX, u64::MAX)).unwrap(); let z_2 = PolyOverZq::from_str(&format!("4 1 2 {} 1 mod {}", i64::MAX, u64::MAX)).unwrap(); let z_3 = diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs index 50f631b1..6d440d7f 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs @@ -35,7 +35,7 @@ impl IntoCoefficientEmbedding for &ModulusPolynomialRingZq { /// traits::IntoCoefficientEmbedding, /// }; /// - /// let poly = ModulusPolynomialRingZq::from_str("3 17 3 -5 mod 19").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("3 17 3 1 mod 19").unwrap(); /// let vector = poly.into_coefficient_embedding(4); /// let cmp_vector = MatZq::from_str("[[17],[3],[-5],[0]] mod 19").unwrap(); /// assert_eq!(cmp_vector, vector); @@ -84,7 +84,7 @@ impl FromCoefficientEmbedding<&MatZq> for ModulusPolynomialRingZq { /// /// let vector = MatZq::from_str("[[17],[3],[-5]] mod 19").unwrap(); /// let poly = ModulusPolynomialRingZq::from_coefficient_embedding(&vector); - /// let cmp_poly = ModulusPolynomialRingZq::from_str("3 17 3 -5 mod 19").unwrap(); + /// let cmp_poly = ModulusPolynomialRingZq::from_str("3 17 3 1 mod 19").unwrap(); /// assert_eq!(cmp_poly, poly); /// ``` /// @@ -106,23 +106,14 @@ mod test_into_coefficient_embedding { /// Ensure that the embedding works with large entries. #[test] fn large_entries() { - let poly = ModulusPolynomialRingZq::from_str(&format!( - "3 17 {} {} mod {}", - i64::MAX, - i64::MIN, - u64::MAX - )) - .unwrap(); + let poly = + ModulusPolynomialRingZq::from_str(&format!("3 17 {} 1 mod {}", i64::MAX, u64::MAX)) + .unwrap(); let vector = poly.into_coefficient_embedding(3); - let cmp_vector = MatZq::from_str(&format!( - "[[17],[{}],[{}]] mod {}", - i64::MAX, - i64::MIN, - u64::MAX - )) - .unwrap(); + let cmp_vector = + MatZq::from_str(&format!("[[17],[{}],[1]] mod {}", i64::MAX, u64::MAX)).unwrap(); assert_eq!(cmp_vector, vector); } @@ -130,7 +121,7 @@ mod test_into_coefficient_embedding { #[test] #[should_panic] fn size_too_small() { - let poly = ModulusPolynomialRingZq::from_str("3 17 1 2 mod 19").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("3 17 1 1 mod 19").unwrap(); let _ = poly.into_coefficient_embedding(2); } @@ -147,23 +138,14 @@ mod test_from_coefficient_embedding { /// Ensure that the embedding works with large entries. #[test] fn large_entries() { - let vector = MatZq::from_str(&format!( - "[[17],[{}],[{}]] mod {}", - i64::MAX, - i64::MIN, - u64::MAX - )) - .unwrap(); + let vector = + MatZq::from_str(&format!("[[17],[{}],[1]] mod {}", i64::MAX, u64::MAX)).unwrap(); let poly = ModulusPolynomialRingZq::from_coefficient_embedding(&vector); - let cmp_poly = ModulusPolynomialRingZq::from_str(&format!( - "3 17 {} {} mod {}", - i64::MAX, - i64::MIN, - u64::MAX - )) - .unwrap(); + let cmp_poly = + ModulusPolynomialRingZq::from_str(&format!("3 17 {} 1 mod {}", i64::MAX, u64::MAX)) + .unwrap(); assert_eq!(cmp_poly, poly); } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs index 85b32e95..8b5ccdd4 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs @@ -14,19 +14,11 @@ use super::ModulusPolynomialRingZq; use crate::{ error::MathError, integer::{PolyOverZ, Z}, - integer_mod_q::{Modulus, PolyOverZq, modulus}, + integer_mod_q::{Modulus, PolyOverZq}, macros::for_others::implement_for_owned, traits::GetCoefficient, }; -use flint_sys::{ - flint::flint_malloc, - fmpz::{fmpz, fmpz_init}, - fmpz_mod::fmpz_mod_ctx_set_modulus, - fmpz_mod_poly::{fmpz_mod_poly_set, fmpz_mod_poly_struct}, - fmpz_vec::_fmpz_vec_init, - fq::{fq_ctx_init_modulus, fq_ctx_struct}, -}; -use std::{ffi::CString, mem::MaybeUninit, rc::Rc, str::FromStr}; +use std::{rc::Rc, str::FromStr}; impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// Creates a [`ModulusPolynomialRingZq`] from a [`PolyOverZ`] and a value that implements [`Into`]. @@ -48,7 +40,7 @@ impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// /// let mod_poly = ModulusPolynomialRingZq::from((&poly, 100)); /// - /// let poly_cmp = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 100").unwrap(); + /// let poly_cmp = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 100").unwrap(); /// assert_eq!(poly_cmp, mod_poly); /// ``` /// @@ -84,7 +76,7 @@ impl> From<(PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// /// let mod_poly = ModulusPolynomialRingZq::from((poly, 100)); /// - /// let poly_cmp = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 100").unwrap(); + /// let poly_cmp = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 100").unwrap(); /// assert_eq!(poly_cmp, mod_poly); /// ``` /// @@ -125,12 +117,18 @@ impl From<&PolyOverZq> for ModulusPolynomialRingZq { /// - if the modulus polynomial is of degree smaller than `1`. fn from(poly: &PolyOverZq) -> Self { check_poly_mod(poly).unwrap(); - unsafe { - Self { - modulus: Rc::new(poly.clone()), - ntt_basis: Rc::new(None), + let mut non_zero = Vec::new(); + for i in 0..poly.get_degree() { + let coeff: Z = poly.get_coeff(i).unwrap(); + if coeff != 0 { + non_zero.push(i.try_into().unwrap()); } } + Self { + modulus: Rc::new(poly.clone()), + ntt_basis: Rc::new(None), + non_zero, + } } } @@ -155,7 +153,7 @@ impl FromStr for ModulusPolynomialRingZq { /// **Warning**: If the input string starts with a correctly formatted /// [`PolyOverZ`](crate::integer::PolyOverZ) object, the rest of the string /// until the `"mod"` is ignored. This means that the input string - /// `"4 0 1 2 3 mod 13"` is the same as `"4 0 1 2 3 4 5 6 7 mod 13"`. + /// `"4 0 1 2 1 mod 13"` is the same as `"4 0 1 2 1 4 5 6 7 mod 13"`. /// /// Parameters: /// - `s`: has to be a valid string to create a [`PolyOverZq`]. @@ -201,6 +199,7 @@ impl FromStr for ModulusPolynomialRingZq { } /// Checks weather a given [`PolyOverZq`] can be used as a [`ModulusPolynomialRingZq`]. +/// It requires that the leading coefficient is `1`. /// /// Parameters: /// - `poly_zq`: the [`PolyOverZq`] value that should be checked. @@ -212,7 +211,7 @@ impl FromStr for ModulusPolynomialRingZq { /// use qfall_math::integer_mod_q::PolyOverZq; /// use std::str::FromStr; /// -/// let poly_zq = PolyOverZq::from_str("2 1 2 mod 17").unwrap(); +/// let poly_zq = PolyOverZq::from_str("2 1 1 mod 17").unwrap(); /// /// check_poly_mod(&poly_zq)? /// ``` @@ -222,9 +221,15 @@ impl FromStr for ModulusPolynomialRingZq { /// [`InvalidModulus`](MathError::InvalidModulus) /// if the modulus polynomial is of degree less than `1`. pub(crate) fn check_poly_mod(poly_zq: &PolyOverZq) -> Result<(), MathError> { + let leading_coefficient: Z = poly_zq.get_coeff(poly_zq.get_degree())?; if poly_zq.get_degree() < 1 { return Err(MathError::InvalidModulus(poly_zq.to_string())); } + if leading_coefficient != 1 { + return Err(MathError::InvalidModulus(format!( + ". The leading coefficient needs to be 1, but it is {leading_coefficient}" + ))); + } Ok(()) } @@ -261,7 +266,7 @@ mod test_try_from_poly_z { /// Ensure that primes and non-primes work as modulus #[test] fn poly_z_primes() { - let poly_z = PolyOverZ::from_str("2 2 2").unwrap(); + let poly_z = PolyOverZ::from_str("2 2 1").unwrap(); let _ = ModulusPolynomialRingZq::from((&poly_z, 10)); let _ = ModulusPolynomialRingZq::from((poly_z, 11)); @@ -296,7 +301,7 @@ mod test_try_from_integer_mod { #[test] #[should_panic] fn panic_degree_1() { - let poly = PolyOverZ::from_str("1 5").unwrap(); + let poly = PolyOverZ::from_str("1 1").unwrap(); let _ = ModulusPolynomialRingZq::from((poly, 17)); } } @@ -312,21 +317,11 @@ mod test_try_from_poly_zq { #[test] fn working_large_entries() { let poly_mod = - PolyOverZq::from_str(&format!("4 0 1 -2 {} mod {}", u64::MAX, 2_i32.pow(16) + 1)) + PolyOverZq::from_str(&format!("4 0 1 {} 1 mod {}", u64::MAX, 2_i32.pow(16) + 1)) .unwrap(); let _ = ModulusPolynomialRingZq::from(&poly_mod); } - /// Ensure that large entries work - #[test] - fn poly_zq_unchanged() { - let in_str = format!("4 0 1 3 {} mod {}", u64::MAX, 2_i32.pow(16) + 1); - let cmp_str = "3 0 1 3 mod 65537"; - let poly_zq = PolyOverZq::from_str(&in_str).unwrap(); - let _ = ModulusPolynomialRingZq::from(&poly_zq); - assert_eq!(cmp_str, poly_zq.to_string()); - } - /// Ensure that primes and non-primes work as modulus #[test] fn poly_zq_primes() { @@ -369,7 +364,7 @@ mod test_from_str { fn working_large_entries() { assert!( ModulusPolynomialRingZq::from_str(&format!( - "4 0 1 3 {} mod {}", + "4 0 1 {} 1 mod {}", u64::MAX, 2_i32.pow(16) + 1 )) @@ -380,7 +375,7 @@ mod test_from_str { /// Ensure that primes and non-primes work as modulus #[test] fn poly_zq_primes() { - assert!(ModulusPolynomialRingZq::from_str("4 0 1 3 2 mod 10").is_ok()); - assert!(ModulusPolynomialRingZq::from_str("4 0 1 3 2 mod 11").is_ok()); + assert!(ModulusPolynomialRingZq::from_str("4 0 1 3 1 mod 10").is_ok()); + assert!(ModulusPolynomialRingZq::from_str("4 0 1 3 1 mod 11").is_ok()); } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs index 5ce010de..a703a6c3 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/get.rs @@ -13,13 +13,7 @@ use crate::{ integer_mod_q::{Modulus, ModulusPolynomialRingZq, PolyOverZq, Zq}, traits::GetCoefficient, }; -use flint_sys::{ - fmpz::fmpz_init_set, - fmpz_mod::fmpz_mod_ctx_init, - fmpz_mod_poly::fmpz_mod_poly_get_coeff_fmpz, - fq::{fq_ctx_degree, fq_ctx_struct}, -}; -use std::{mem::MaybeUninit, rc::Rc}; +use flint_sys::fmpz_mod_poly::fmpz_mod_poly_get_coeff_fmpz; impl GetCoefficient for ModulusPolynomialRingZq { /// Returns the coefficient of a polynomial [`ModulusPolynomialRingZq`] as a [`Zq`]. @@ -37,7 +31,7 @@ impl GetCoefficient for ModulusPolynomialRingZq { /// use qfall_math::integer_mod_q::{Zq, ModulusPolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); /// /// let coeff_0: Zq = poly.get_coeff(0).unwrap(); /// let coeff_1: Zq = unsafe{ poly.get_coeff_unchecked(1) }; @@ -78,7 +72,7 @@ impl GetCoefficient for ModulusPolynomialRingZq { /// use qfall_math::integer::Z; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); /// /// let coeff_0: Z = poly.get_coeff(0).unwrap(); /// let coeff_1: Z = unsafe{ poly.get_coeff_unchecked(1) }; @@ -142,7 +136,7 @@ impl ModulusPolynomialRingZq { /// use qfall_math::integer_mod_q::ModulusPolynomialRingZq; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 7").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 7").unwrap(); /// /// let degree = poly.get_degree(); // This would only return 3 /// ``` @@ -185,7 +179,7 @@ mod test_get_coeff_z { /// Ensure that `0` is returned if the provided index is not yet set. #[test] fn index_out_of_range() { - let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); let zero_coeff_1: Z = poly.get_coeff(4).unwrap(); let zero_coeff_2 = poly.get_coeff(4).unwrap(); @@ -197,7 +191,7 @@ mod test_get_coeff_z { /// Tests if coefficients are returned correctly. #[test] fn positive_coeff() { - let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); let coeff_1: Z = poly.get_coeff(2).unwrap(); let coeff_2 = poly.get_coeff(2).unwrap(); @@ -210,11 +204,11 @@ mod test_get_coeff_z { #[test] fn large_coeff() { let poly = - ModulusPolynomialRingZq::from_str(&format!("2 1 {} mod {}", u64::MAX - 1, u64::MAX)) + ModulusPolynomialRingZq::from_str(&format!("2 {} 1 mod {}", u64::MAX - 1, u64::MAX)) .unwrap(); - let coefficient_1: Z = poly.get_coeff(1).unwrap(); - let coefficient_2: Zq = poly.get_coeff(1).unwrap(); + let coefficient_1: Z = poly.get_coeff(0).unwrap(); + let coefficient_2: Zq = poly.get_coeff(0).unwrap(); assert_eq!(u64::MAX - 1, coefficient_1); assert_eq!(Zq::from((u64::MAX - 1, u64::MAX)), coefficient_2); @@ -224,7 +218,7 @@ mod test_get_coeff_z { #[test] #[should_panic] fn negative_index_error_z() { - let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); let _: Z = poly.get_coeff(-1).unwrap(); } @@ -233,7 +227,7 @@ mod test_get_coeff_z { #[test] #[should_panic] fn negative_index_error_zq() { - let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 3 mod 17").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("4 0 1 2 1 mod 17").unwrap(); let _: Zq = poly.get_coeff(-1).unwrap(); } @@ -250,7 +244,7 @@ mod test_get_degree { let degrees = [1, 3, 7, 15, 32, 120]; for degree in degrees { let modulus_ring = ModulusPolynomialRingZq::from_str(&format!( - "{} {}2 mod 17", + "{} {}1 mod 17", degree + 1, "0 ".repeat(degree) )) @@ -274,11 +268,10 @@ mod test_get_degree { /// flint does not reduce the exponent due to computational cost. #[test] fn degree_many_coefficients() { - let poly_1 = ModulusPolynomialRingZq::from_str("7 1 2 3 4 8 1 3 mod 2").unwrap(); + let poly_1 = ModulusPolynomialRingZq::from_str("7 1 2 3 4 8 1 1 mod 2").unwrap(); let poly_2 = ModulusPolynomialRingZq::from_str(&format!( - "7 1 2 3 4 8 {} {} mod {}", + "7 1 2 3 4 8 {} 1 mod {}", u64::MAX, - i64::MAX, u128::MAX )) .unwrap(); diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs index 65109560..3be02294 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs @@ -22,7 +22,7 @@ impl ModulusPolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::ModulusPolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 11").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 11").unwrap(); /// /// let sqrd_2_norm = poly.norm_eucl_sqrd(); /// @@ -43,7 +43,7 @@ impl ModulusPolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::ModulusPolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 4 mod 7").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 7").unwrap(); /// /// let infty_norm = poly.norm_infty(); /// @@ -65,7 +65,7 @@ mod test_norms { /// Correctness is already checked for [`PolyOverZq`](crate::integer_mod_q::PolyOverZq). #[test] fn availability() { - let poly = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 11").unwrap(); + let poly = ModulusPolynomialRingZq::from_str("3 3 2 1 mod 11").unwrap(); let norm_es = poly.norm_eucl_sqrd(); let norm_i = poly.norm_infty(); diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs index beee630e..3f0e10ad 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/ownership.rs @@ -33,6 +33,7 @@ impl Clone for ModulusPolynomialRingZq { Self { modulus: Rc::clone(&self.modulus), ntt_basis: Rc::clone(&self.ntt_basis), + non_zero: self.non_zero.clone(), } } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/serialize.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/serialize.rs index c2321f9f..94222710 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/serialize.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/serialize.rs @@ -32,7 +32,7 @@ mod test_serialize { /// Tests whether the serialization of a positive [`ModulusPolynomialRingZq`] works. #[test] fn serialize_output_positive() { - let poly_str = "2 17 42 mod 331"; + let poly_str = "2 17 1 mod 331"; let poly_z = ModulusPolynomialRingZq::from_str(poly_str).unwrap(); let cmp_str = format!("{{\"poly\":\"{poly_str}\"}}"); @@ -82,7 +82,7 @@ mod test_deserialize { /// Tests whether the deserialization of a positive [`ModulusPolynomialRingZq`] works. #[test] fn deserialize_positive() { - let poly_str = "2 17 42 mod 331"; + let poly_str = "2 17 1 mod 331"; let cmp_str = format!("{{\"poly\":\"{poly_str}\"}}"); let poly_mod = ModulusPolynomialRingZq::from_str(poly_str).unwrap(); @@ -135,7 +135,7 @@ mod test_deserialize { #[test] fn non_prime_q() { let a: Result = - serde_json::from_str(&format!("{{\"poly\":\"2 17 42 mod {}\"}}", u64::MAX)); + serde_json::from_str(&format!("{{\"poly\":\"2 17 1 mod {}\"}}", u64::MAX)); assert!(a.is_ok()); } @@ -143,11 +143,11 @@ mod test_deserialize { #[test] fn negative_q() { let a: Result = - serde_json::from_str(&format!("{{\"poly\":\"2 17 42 mod -{}\"}}", u64::MAX)); + serde_json::from_str(&format!("{{\"poly\":\"2 17 1 mod -{}\"}}", u64::MAX)); assert!(a.is_err()); let b: Result = - serde_json::from_str("{{\"poly\":\"2 17 42 mod -17\"}}"); + serde_json::from_str("{{\"poly\":\"2 17 1 mod -17\"}}"); assert!(b.is_err()); } @@ -155,7 +155,7 @@ mod test_deserialize { #[test] fn no_field_value() { let a: Result = - serde_json::from_str("{{\"tree\":\"{2 17 42 mod 331}\"}}"); + serde_json::from_str("{{\"tree\":\"{2 17 1 mod 331}\"}}"); assert!(a.is_err()); let b: Result = serde_json::from_str("{{}}"); @@ -166,12 +166,12 @@ mod test_deserialize { #[test] fn too_many_fields() { let a: Result = serde_json::from_str( - "{{\"tree\":\"{2 17 42 mod 331}\", \"poly\":\"{2 17 42 mod 331}\"}}", + "{{\"tree\":\"{2 17 1 mod 331}\", \"poly\":\"{2 17 1 mod 331}\"}}", ); assert!(a.is_err()); let b: Result = - serde_json::from_str("{{\"poly\":\"{}\", \"poly\":\"{2 17 42 mod 331}\"}}"); + serde_json::from_str("{{\"poly\":\"{}\", \"poly\":\"{2 17 1 mod 331}\"}}"); assert!(b.is_err()); } } diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs index ea23a7ed..b7650cb5 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/to_string.rs @@ -78,7 +78,7 @@ mod test_to_string { /// Test whether a roundtrip works #[test] fn working_keeps_same_string() { - let cmp_str = "3 1 2 2 mod 5"; + let cmp_str = "3 1 2 1 mod 5"; let cmp = ModulusPolynomialRingZq::from_str(cmp_str).unwrap(); assert_eq!(cmp_str, cmp.to_string()); @@ -87,7 +87,7 @@ mod test_to_string { /// Test whether a string returned from to_string can be used to construct a [`ModulusPolynomialRingZq`] #[test] fn working_use_result_of_to_string() { - let cmp_str = "3 1 2 2 mod 5"; + let cmp_str = "3 1 2 1 mod 5"; let cmp = ModulusPolynomialRingZq::from_str(cmp_str).unwrap(); let str_1 = cmp.to_string(); diff --git a/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs b/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs index 283ce8fb..40b34756 100644 --- a/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/poly_over_zq/arithmetic/sub.rs @@ -436,10 +436,10 @@ mod test_sub_poly_ring_zq { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 -1 -{} / 4 1 2 3 4 mod {}", + "2 -1 -{} / 4 1 2 3 1 mod {}", i64::MAX as u64 - 2, u64::MAX )) @@ -454,7 +454,7 @@ mod test_sub_poly_ring_zq { /// Checks if subtraction works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 17)); _ = zq.clone() - poly.clone(); diff --git a/src/integer_mod_q/poly_over_zq/from.rs b/src/integer_mod_q/poly_over_zq/from.rs index 2ecf49cd..8af4b188 100644 --- a/src/integer_mod_q/poly_over_zq/from.rs +++ b/src/integer_mod_q/poly_over_zq/from.rs @@ -17,8 +17,7 @@ use crate::{ macros::for_others::implement_for_owned, }; use flint_sys::fmpz_mod_poly::{ - fmpz_mod_poly_init, fmpz_mod_poly_set, fmpz_mod_poly_set_coeff_fmpz, - fmpz_mod_poly_set_fmpz_poly, + fmpz_mod_poly_init, fmpz_mod_poly_set_coeff_fmpz, fmpz_mod_poly_set_fmpz_poly, }; use std::{mem::MaybeUninit, str::FromStr}; diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs index cfffa84a..dbb42b8c 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/add.rs @@ -291,9 +291,8 @@ mod test_add_assign { #[test] fn correct_large() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN, u64::MAX - 58 )) .unwrap(); @@ -336,7 +335,7 @@ mod test_add_assign { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let mut a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -430,9 +429,8 @@ mod test_add { #[test] fn add_large_numbers() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN, u64::MAX - 58 )) .unwrap(); @@ -461,7 +459,7 @@ mod test_add { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); let _ = a + b; @@ -473,7 +471,7 @@ mod test_add { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -491,10 +489,10 @@ mod test_add_poly_over_z { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 3 {} / 4 1 2 3 4 mod {}", + "2 3 {} / 4 1 2 3 1 mod {}", i64::MAX as u64 + 2, u64::MAX )) @@ -509,7 +507,7 @@ mod test_add_poly_over_z { /// Checks if addition works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = PolyOverZ::from(2); _ = poly.clone() + z.clone(); @@ -533,15 +531,15 @@ mod test_add_poly_over_zq { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 3 {} / 4 1 2 3 4 mod {}", - i64::MAX as u64 + 2, + "2 3 {} / 4 1 2 3 1 mod {}", + i64::MAX as u64 + 1, u64::MAX )) .unwrap(); - let poly = PolyOverZq::from_str(&format!("2 1 2 mod {}", u64::MAX)).unwrap(); + let poly = PolyOverZq::from_str(&format!("2 1 1 mod {}", u64::MAX)).unwrap(); let poly_1 = &poly_1 + &poly; @@ -551,7 +549,7 @@ mod test_add_poly_over_zq { /// Checks if addition works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 17)); _ = poly.clone() + zq.clone(); @@ -568,7 +566,7 @@ mod test_add_poly_over_zq { #[test] #[should_panic] fn different_moduli_panic() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 16)); _ = &poly + &zq; diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs index 813484d6..7c54f5ab 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul.rs @@ -296,9 +296,8 @@ mod test_mul_assign { #[test] fn correct_large() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN, u64::MAX - 58 )) .unwrap(); @@ -354,7 +353,7 @@ mod test_mul_assign { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let mut a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -452,9 +451,8 @@ mod test_mul { #[test] fn mul_large_numbers() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN, u64::MAX - 58 )) .unwrap(); @@ -491,7 +489,7 @@ mod test_mul { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); let _ = a * b; @@ -503,7 +501,7 @@ mod test_mul { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 0 2 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -521,10 +519,10 @@ mod test_mul_poly_over_z { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "3 2 {} {} / 4 1 2 3 4 mod {}", + "3 2 {} {} / 4 1 2 3 1 mod {}", i64::MAX as u64 + 4, (i64::MAX as u64) * 2, u64::MAX @@ -540,7 +538,7 @@ mod test_mul_poly_over_z { /// Checks if scalar multiplication works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = PolyOverZ::from(2); _ = poly.clone() * z.clone(); @@ -564,16 +562,16 @@ mod test_mul_poly_over_zq { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "3 2 {} {} / 4 1 2 3 4 mod {}", - i64::MAX as u64 + 4, - (i64::MAX as u64) * 2, + "3 2 {} {} / 4 1 2 3 1 mod {}", + i64::MAX as u64 + 2, + 9223372036854775807_u64, u64::MAX )) .unwrap(); - let poly = PolyOverZq::from_str(&format!("2 1 2 mod {}", u64::MAX)).unwrap(); + let poly = PolyOverZq::from_str(&format!("2 1 1 mod {}", u64::MAX)).unwrap(); let poly_1 = &poly_1 * &poly; @@ -583,7 +581,7 @@ mod test_mul_poly_over_zq { /// Checks if multiplication works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 17)); _ = poly.clone() * zq.clone(); @@ -600,7 +598,7 @@ mod test_mul_poly_over_zq { #[test] #[should_panic] fn different_moduli_panic() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 16)); _ = &poly * &zq; diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul_scalar.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul_scalar.rs index edcb770d..d7630cae 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul_scalar.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/mul_scalar.rs @@ -37,7 +37,7 @@ impl Mul<&Z> for &PolynomialRingZq { /// use qfall_math::integer::Z; /// use std::str::FromStr; /// - /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); /// let integer = Z::from(3); /// /// let poly_2 = &poly_1 * &integer; @@ -77,7 +77,7 @@ impl Mul<&Zq> for &PolynomialRingZq { /// use qfall_math::integer_mod_q::{PolynomialRingZq, Zq}; /// use std::str::FromStr; /// - /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); /// let integer = Zq::from((3,17)); /// /// let poly_2 = &poly_1 * &integer; @@ -152,7 +152,7 @@ impl PolynomialRingZq { /// use qfall_math::integer_mod_q::{PolynomialRingZq, Zq}; /// use std::str::FromStr; /// - /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + /// let poly_1 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); /// let integer = Zq::from((3,17)); /// /// let poly_2 = poly_1.mul_scalar_zq_safe(&integer).unwrap(); @@ -185,14 +185,14 @@ mod test_mul_z { #[test] fn borrowed_correctness() { let poly_1 = PolynomialRingZq::from_str(&format!( - "3 1 2 {} / 4 1 2 3 4 mod {}", + "3 1 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX )) .unwrap(); let poly_2 = poly_1.clone(); let poly_3 = PolynomialRingZq::from_str(&format!( - "3 2 4 {} / 4 1 2 3 4 mod {}", + "3 2 4 {} / 4 1 2 3 1 mod {}", (i64::MAX as u64) * 2, u64::MAX )) @@ -209,7 +209,7 @@ mod test_mul_z { /// Checks if scalar multiplication works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = Z::from(2); _ = poly.clone() * z.clone(); @@ -247,14 +247,14 @@ mod test_mul_zq { #[test] fn borrowed_correctness() { let poly_1 = PolynomialRingZq::from_str(&format!( - "3 1 2 {} / 4 1 2 3 4 mod {}", + "3 1 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX )) .unwrap(); let poly_2 = poly_1.clone(); let poly_3 = PolynomialRingZq::from_str(&format!( - "3 2 4 {} / 4 1 2 3 4 mod {}", + "3 2 4 {} / 4 1 2 3 1 mod {}", (i64::MAX as u64) * 2, u64::MAX )) @@ -271,7 +271,7 @@ mod test_mul_zq { /// Checks if scalar multiplication works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = Zq::from((2, 17)); _ = poly.clone() * z.clone(); @@ -288,7 +288,7 @@ mod test_mul_zq { #[test] #[should_panic] fn different_moduli_panic() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = Zq::from((2, 16)); _ = &poly * &z; @@ -297,7 +297,7 @@ mod test_mul_zq { /// Checks if scalar multiplication panics if the moduli mismatch #[test] fn different_moduli_error() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = Zq::from((2, 16)); assert!(poly.mul_scalar_zq_safe(&z).is_err()); diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs index 32fe2abd..250974db 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs @@ -283,9 +283,8 @@ mod test_sub_assign { #[test] fn correct_large() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN, u64::MAX - 58 )) .unwrap(); @@ -294,7 +293,7 @@ mod test_sub_assign { let poly_2 = PolyOverZ::from_str(&format!("4 -{} 0 1 -{}", i64::MAX, i64::MAX)).unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); let cmp = PolynomialRingZq::from(( - &PolyOverZ::from_str(&format!("4 {} 0 0 {}", (u64::MAX - 1) / 2 + 58, -1)).unwrap(), + &PolyOverZ::from_str(&"1 9223372036854775923".to_string()).unwrap(), &modulus, )); @@ -328,7 +327,7 @@ mod test_sub_assign { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let mut a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -422,9 +421,8 @@ mod test_sub { #[test] fn sub_large_numbers() { let modulus = ModulusPolynomialRingZq::from_str(&format!( - "4 {} 0 0 {} mod {}", + "4 {} 0 0 1 mod {}", u64::MAX, - i64::MIN + 12, u64::MAX - 58 )) .unwrap(); @@ -458,7 +456,7 @@ mod test_sub { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); let _ = a - b; @@ -470,7 +468,7 @@ mod test_sub { let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap(); let a = PolynomialRingZq::from((&poly_1, &modulus)); - let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 2 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap(); let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); @@ -488,10 +486,10 @@ mod test_sub_poly_over_z { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 1 {} / 4 1 2 3 4 mod {}", + "2 1 {} / 4 1 2 3 1 mod {}", i64::MAX as u64 - 2, u64::MAX )) @@ -506,7 +504,7 @@ mod test_sub_poly_over_z { /// Checks if subtraction works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let z = PolyOverZ::from(2); _ = poly.clone() - z.clone(); @@ -526,15 +524,15 @@ mod test_sub_poly_over_zq { #[test] fn borrowed_correctness() { let poly_1 = - PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX)) + PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "2 1 {} / 4 1 2 3 4 mod {}", - i64::MAX as u64 - 2, + "2 1 {} / 4 1 2 3 1 mod {}", + i64::MAX as u64 - 1, u64::MAX )) .unwrap(); - let poly = PolyOverZq::from_str(&format!("2 1 2 mod {}", u64::MAX)).unwrap(); + let poly = PolyOverZq::from_str(&format!("2 1 1 mod {}", u64::MAX)).unwrap(); let poly_1 = &poly_1 - &poly; @@ -544,7 +542,7 @@ mod test_sub_poly_over_zq { /// Checks if subtraction works fine for different types #[test] fn availability() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 17)); _ = poly.clone() - zq.clone(); @@ -557,7 +555,7 @@ mod test_sub_poly_over_zq { #[test] #[should_panic] fn different_moduli_panic() { - let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap(); + let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap(); let zq = PolyOverZq::from((2, 16)); _ = &poly - &zq; diff --git a/src/integer_mod_q/polynomial_ring_zq/cmp.rs b/src/integer_mod_q/polynomial_ring_zq/cmp.rs index 77e1ab87..ed711a83 100644 --- a/src/integer_mod_q/polynomial_ring_zq/cmp.rs +++ b/src/integer_mod_q/polynomial_ring_zq/cmp.rs @@ -79,15 +79,15 @@ mod test_compare_base { assert!(one_1.compare_base(&one_1)); assert!(one_1.compare_base(&Zq::from((3, 17)))); assert!(!one_1.compare_base(&Zq::from((3, 18)))); - assert!(one_1.compare_base(&PolyOverZq::from_str("1 3 mod 17").unwrap())); - assert!(!one_1.compare_base(&PolyOverZq::from_str("1 3 mod 18").unwrap())); + assert!(one_1.compare_base(&PolyOverZq::from_str("1 1 mod 17").unwrap())); + assert!(!one_1.compare_base(&PolyOverZq::from_str("1 1 mod 18").unwrap())); assert!(one_1.compare_base(&PolynomialRingZq::from(&modulus))); assert!(!one_1.compare_base(&PolynomialRingZq::from(&modulus_other))); assert!(one_1.call_compare_base_error(&Zq::from((3, 18))).is_some()); assert!( one_1 - .call_compare_base_error(&PolyOverZq::from_str("1 3 mod 18").unwrap()) + .call_compare_base_error(&PolyOverZq::from_str("1 1 mod 18").unwrap()) .is_some() ); assert!( diff --git a/src/integer_mod_q/polynomial_ring_zq/coefficient_embedding.rs b/src/integer_mod_q/polynomial_ring_zq/coefficient_embedding.rs index efced77c..265a0f9d 100644 --- a/src/integer_mod_q/polynomial_ring_zq/coefficient_embedding.rs +++ b/src/integer_mod_q/polynomial_ring_zq/coefficient_embedding.rs @@ -41,7 +41,7 @@ impl IntoCoefficientEmbedding<(MatZq, ModulusPolynomialRingZq)> for &PolynomialR /// traits::IntoCoefficientEmbedding, /// }; /// - /// let poly = PolynomialRingZq::from_str("2 1 -2 / 3 17 3 5 mod 19").unwrap(); + /// let poly = PolynomialRingZq::from_str("2 1 -2 / 3 17 3 1 mod 19").unwrap(); /// let embedding = poly.into_coefficient_embedding(3); /// let cmp_vector = MatZq::from_str("[[1],[-2],[0]] mod 19").unwrap(); /// assert_eq!((cmp_vector, poly.get_mod()), embedding); @@ -90,9 +90,9 @@ impl FromCoefficientEmbedding<(&MatZq, &ModulusPolynomialRingZq)> for Polynomial /// }; /// /// let vector = MatZq::from_str("[[17],[3],[-5]] mod 19").unwrap(); - /// let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 4 mod 19").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 1 mod 19").unwrap(); /// let poly = PolynomialRingZq::from_coefficient_embedding((&vector, &modulus)); - /// let cmp_poly = PolynomialRingZq::from_str("3 17 3 -5 / 4 1 2 3 4 mod 19").unwrap(); + /// let cmp_poly = PolynomialRingZq::from_str("3 17 3 -5 / 4 1 2 3 1 mod 19").unwrap(); /// assert_eq!(cmp_poly, poly); /// ``` /// @@ -130,7 +130,7 @@ mod test_into_coefficient_embedding { #[test] fn large_entries() { let poly = PolynomialRingZq::from_str(&format!( - "3 17 {} {} / 4 1 2 3 4 mod {}", + "3 17 {} {} / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -152,7 +152,7 @@ mod test_into_coefficient_embedding { /// Ensure that zero is embedded correctly. #[test] fn test_zero() { - let poly = PolynomialRingZq::from_str("0 / 3 17 3 5 mod 19").unwrap(); + let poly = PolynomialRingZq::from_str("0 / 3 17 3 1 mod 19").unwrap(); let embedding = poly.into_coefficient_embedding(1); let cmp_vector = MatZq::from_str("[[0]] mod 19").unwrap(); @@ -163,7 +163,7 @@ mod test_into_coefficient_embedding { #[test] #[should_panic] fn size_too_small() { - let poly = PolynomialRingZq::from_str("3 17 1 2 / 4 1 2 3 4 mod 19").unwrap(); + let poly = PolynomialRingZq::from_str("3 17 1 2 / 4 1 2 3 1 mod 19").unwrap(); let _ = poly.into_coefficient_embedding(2); } @@ -188,12 +188,12 @@ mod test_from_coefficient_embedding { )) .unwrap(); let modulus = - ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 4 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("4 1 2 3 1 mod {}", u64::MAX)).unwrap(); let poly = PolynomialRingZq::from_coefficient_embedding((&vector, &modulus)); let cmp_poly = PolynomialRingZq::from_str(&format!( - "3 17 {} {} / 4 1 2 3 4 mod {}", + "3 17 {} {} / 4 1 2 3 1 mod {}", i64::MAX, i64::MIN, u64::MAX @@ -207,7 +207,7 @@ mod test_from_coefficient_embedding { #[should_panic] fn not_column_vector() { let vector = MatZq::from_str("[[17, 1],[-17, -1],[5, 9]] mod 42").unwrap(); - let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 4 mod 42").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 1 mod 42").unwrap(); let _ = PolynomialRingZq::from_coefficient_embedding((&vector, &modulus)); } @@ -217,7 +217,7 @@ mod test_from_coefficient_embedding { #[should_panic] fn mismatching_moduli() { let vector = MatZq::from_str("[[17],[-1],[9]] mod 42").unwrap(); - let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 4 mod 33").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("4 1 2 3 1 mod 33").unwrap(); let _ = PolynomialRingZq::from_coefficient_embedding((&vector, &modulus)); } diff --git a/src/integer_mod_q/polynomial_ring_zq/from.rs b/src/integer_mod_q/polynomial_ring_zq/from.rs index 6c5a3d05..cd6133fd 100644 --- a/src/integer_mod_q/polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/polynomial_ring_zq/from.rs @@ -239,7 +239,7 @@ impl FromStr for PolynomialRingZq { /// use qfall_math::integer_mod_q::PolynomialRingZq; /// use std::str::FromStr; /// - /// let poly = PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 42").unwrap(); + /// let poly = PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 42").unwrap(); /// ``` /// # Errors and Failures /// - Returns a [`MathError`] of type @@ -504,20 +504,20 @@ mod test_from_str { /// error #[test] fn modulus_zero_throws_error() { - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 0").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 0").is_err()); } /// tests whether a false string (negative modulus) returns an error #[test] fn false_sign() { - assert!(PolynomialRingZq::from_str("4 0 1 -2 3 mod -42").is_err()); + assert!(PolynomialRingZq::from_str("4 0 1 -2 1 mod -42").is_err()); } /// tests whether a falsely formatted string (wrong whitespaces) returns an /// error #[test] fn whitespaces_in_modulus() { - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 4 2").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 4 2").is_err()); } /// tests whether a falsely formatted string (wrong symbols) returns an error @@ -532,34 +532,34 @@ mod test_from_str { /// an error #[test] fn false_format() { - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 42").is_err()); - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 42").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 42").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 42").is_err()); } /// tests whether a falsely formatted string (wrong number of total /// coefficients) returns an error #[test] fn false_number_of_coefficient() { - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 5 0 1 -2 3 mod 42").is_err()); - assert!(PolynomialRingZq::from_str("5 -1 0 1 1 / 4 0 1 -2 3 mod 42").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 5 0 1 -2 1 mod 42").is_err()); + assert!(PolynomialRingZq::from_str("5 -1 0 1 1 / 4 0 1 -2 1 mod 42").is_err()); } /// tests whether a falsely formatted string (too many whitespaces) returns /// an error #[test] fn too_many_whitespaces() { - assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 3 mod 42").is_err()); + assert!(PolynomialRingZq::from_str("4 -1 0 1 1 / 4 0 1 -2 1 mod 42").is_err()); } /// Ensure that the input works with strings that have to be trimmed #[test] fn trim_input() { let poly = PolynomialRingZq::from_str( - " 4 -1 0 1 1 / 4 1 2 3 -4 mod 17 ", + " 4 -1 0 1 1 / 4 1 2 3 1 mod 17 ", ); assert!(poly.is_ok()); assert_eq!( - PolynomialRingZq::from_str("4 -1 0 1 1 / 4 1 2 3 -4 mod 17").unwrap(), + PolynomialRingZq::from_str("4 -1 0 1 1 / 4 1 2 3 1 mod 17").unwrap(), poly.unwrap() ); } @@ -567,7 +567,7 @@ mod test_from_str { /// Ensure that a string resulting from to_string, can be used in from_str #[test] fn roundtrip() { - let poly = PolynomialRingZq::from_str("2 1 1 / 4 1 1 -2 3 mod 42").unwrap(); + let poly = PolynomialRingZq::from_str("2 1 1 / 4 1 1 -2 1 mod 42").unwrap(); let poly2 = PolynomialRingZq::from_str(&poly.to_string()).unwrap(); assert_eq!(poly, poly2); } diff --git a/src/integer_mod_q/polynomial_ring_zq/get.rs b/src/integer_mod_q/polynomial_ring_zq/get.rs index 7f81d687..bf0f2b93 100644 --- a/src/integer_mod_q/polynomial_ring_zq/get.rs +++ b/src/integer_mod_q/polynomial_ring_zq/get.rs @@ -203,7 +203,7 @@ mod test_get_coeff { #[test] fn large_coeff() { let modulus = - ModulusPolynomialRingZq::from_str(&format!("5 1 0 4 1 9 mod {}", u64::MAX)).unwrap(); + ModulusPolynomialRingZq::from_str(&format!("5 1 0 4 1 1 mod {}", u64::MAX)).unwrap(); let poly = PolyOverZ::from_str(&format!("3 0 {} 1", i64::MAX)).unwrap(); let poly_ring = PolynomialRingZq::from((&poly, &modulus)); diff --git a/src/integer_mod_q/polynomial_ring_zq/norm.rs b/src/integer_mod_q/polynomial_ring_zq/norm.rs index 6679b892..b33794b3 100644 --- a/src/integer_mod_q/polynomial_ring_zq/norm.rs +++ b/src/integer_mod_q/polynomial_ring_zq/norm.rs @@ -30,7 +30,7 @@ impl PolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::PolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 11").unwrap(); + /// let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 11").unwrap(); /// /// let sqrd_2_norm = poly.norm_eucl_sqrd(); /// @@ -62,7 +62,7 @@ impl PolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::PolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = PolynomialRingZq::from_str("3 1 2 4 / 4 1 2 3 4 mod 7").unwrap(); + /// let poly = PolynomialRingZq::from_str("3 1 2 4 / 4 1 2 3 1 mod 7").unwrap(); /// /// let infty_norm = poly.norm_infty(); /// @@ -91,9 +91,9 @@ mod test_norm_eucl_sqrd { /// with small coefficients is calculated correctly #[test] fn poly_small_coefficient() { - let poly_1 = PolynomialRingZq::from_str("0 / 2 1 2 mod 11").unwrap(); - let poly_2 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 11").unwrap(); - let poly_3 = PolynomialRingZq::from_str("3 1 20 194 / 4 1 2 3 4 mod 195").unwrap(); + let poly_1 = PolynomialRingZq::from_str("0 / 2 1 1 mod 11").unwrap(); + let poly_2 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 11").unwrap(); + let poly_3 = PolynomialRingZq::from_str("3 1 20 194 / 4 1 2 3 1 mod 195").unwrap(); assert_eq!(poly_1.norm_eucl_sqrd(), Z::ZERO); assert_eq!(poly_2.norm_eucl_sqrd(), Z::from(14)); @@ -105,10 +105,10 @@ mod test_norm_eucl_sqrd { #[test] fn poly_large_coefficient() { let poly_1 = - PolynomialRingZq::from_str(&format!("1 {} / 2 1 2 mod {}", u64::MAX, u128::MAX)) + PolynomialRingZq::from_str(&format!("1 {} / 2 1 1 mod {}", u64::MAX, u128::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "3 {} {} {} / 4 1 2 3 4 mod {}", + "3 {} {} {} / 4 1 2 3 1 mod {}", u64::MAX, i64::MIN, i64::MAX, @@ -139,9 +139,9 @@ mod test_norm_infty { /// with small coefficients is calculated correctly #[test] fn poly_small_coefficient() { - let poly_1 = PolynomialRingZq::from_str("0 / 2 1 2 mod 11").unwrap(); - let poly_2 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 5").unwrap(); - let poly_3 = PolynomialRingZq::from_str("3 1 20 194 / 4 1 2 3 4 mod 195").unwrap(); + let poly_1 = PolynomialRingZq::from_str("0 / 2 1 1 mod 11").unwrap(); + let poly_2 = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 5").unwrap(); + let poly_3 = PolynomialRingZq::from_str("3 1 20 194 / 4 1 2 3 1 mod 195").unwrap(); assert_eq!(poly_1.norm_infty(), Z::ZERO); assert_eq!(poly_2.norm_infty(), Z::from(2)); @@ -153,10 +153,10 @@ mod test_norm_infty { #[test] fn poly_large_coefficient() { let poly_1 = - PolynomialRingZq::from_str(&format!("1 {} / 2 1 2 mod {}", u64::MAX, u128::MAX)) + PolynomialRingZq::from_str(&format!("1 {} / 2 1 1 mod {}", u64::MAX, u128::MAX)) .unwrap(); let poly_2 = PolynomialRingZq::from_str(&format!( - "3 {} {} {} / 4 1 2 3 4 mod {}", + "3 {} {} {} / 4 1 2 3 1 mod {}", u64::MAX, i64::MIN, i64::MAX, diff --git a/src/integer_mod_q/polynomial_ring_zq/properties.rs b/src/integer_mod_q/polynomial_ring_zq/properties.rs index 51b50e37..a28707c0 100644 --- a/src/integer_mod_q/polynomial_ring_zq/properties.rs +++ b/src/integer_mod_q/polynomial_ring_zq/properties.rs @@ -22,7 +22,7 @@ impl PolynomialRingZq { /// use qfall_math::integer_mod_q::PolynomialRingZq; /// use std::str::FromStr; /// - /// let poly_irr = PolynomialRingZq::from_str("2 1 1 / 3 1 2 3 mod 17").unwrap(); + /// let poly_irr = PolynomialRingZq::from_str("2 1 1 / 3 1 0 1 mod 17").unwrap(); /// // returns true, since X + 1 is irreducible /// assert!(poly_irr.is_irreducible()); /// ``` @@ -107,14 +107,14 @@ mod test_is_irreducible { #[test] fn poly_is_irreducible() { // 9X^2 + 12X + 10 is irreducible over 17 - let poly_irr = PolynomialRingZq::from_str("3 10 12 9 / 4 1 10 12 9 mod 17").unwrap(); + let poly_irr = PolynomialRingZq::from_str("3 10 12 9 / 4 1 10 12 1 mod 17").unwrap(); assert!(poly_irr.is_irreducible()); } /// Ensure that a reducible [`PolynomialRingZq`] returns `false`. #[test] fn poly_is_reducible() { - let poly_irr = PolynomialRingZq::from_str("3 1 2 1 / 4 1 10 12 9 mod 17").unwrap(); + let poly_irr = PolynomialRingZq::from_str("3 1 2 1 / 4 1 10 12 1 mod 17").unwrap(); assert!(!poly_irr.is_irreducible()); } } @@ -127,8 +127,8 @@ mod test_is_one { /// Ensure that is_one returns `true` for the one polynomial. #[test] fn one_detection() { - let one = PolynomialRingZq::from_str("1 1 / 4 1 10 12 9 mod 7").unwrap(); - let one_2 = PolynomialRingZq::from_str("2 1 14 / 4 1 10 12 9 mod 7").unwrap(); + let one = PolynomialRingZq::from_str("1 1 / 4 1 10 12 1 mod 7").unwrap(); + let one_2 = PolynomialRingZq::from_str("2 1 14 / 4 1 10 12 1 mod 7").unwrap(); assert!(one.is_one()); assert!(one_2.is_one()); @@ -137,9 +137,9 @@ mod test_is_one { /// Ensure that is_one returns `false` for other polynomials. #[test] fn one_rejection() { - let small = PolynomialRingZq::from_str("4 1 0 0 1 / 4 1 10 12 9 mod 7").unwrap(); + let small = PolynomialRingZq::from_str("4 1 0 0 1 / 4 1 10 12 1 mod 7").unwrap(); let large = PolynomialRingZq::from_str(&format!( - "1 {} / 4 1 10 12 9 mod {}", + "1 {} / 4 1 10 12 1 mod {}", (u128::MAX - 1) / 2 + 2, u128::MAX )) // 2^127 + 1 the last memory entry is `1` diff --git a/src/integer_mod_q/polynomial_ring_zq/reduce.rs b/src/integer_mod_q/polynomial_ring_zq/reduce.rs index 2b6d3fad..d3173018 100644 --- a/src/integer_mod_q/polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/polynomial_ring_zq/reduce.rs @@ -14,11 +14,8 @@ // Additionally the comparisons assume that the entries are reduced, // hence no reduction is performed in the check. -use std::cmp::min; - -use crate::utils::reduce::internal_reduce; - use super::PolynomialRingZq; +use crate::utils::reduce::internal_reduce; use flint_sys::fmpz_poly::_fmpz_poly_normalise; impl PolynomialRingZq { @@ -50,6 +47,7 @@ impl PolynomialRingZq { &self.modulus.modulus.poly, self.modulus.get_degree() as usize, self.modulus.get_q_as_modulus().get_fmpz_mod_ctx_struct(), + &self.modulus.non_zero, ) }; unsafe { diff --git a/src/integer_mod_q/polynomial_ring_zq/sample/binomial.rs b/src/integer_mod_q/polynomial_ring_zq/sample/binomial.rs index 0b460676..ac4eebe1 100644 --- a/src/integer_mod_q/polynomial_ring_zq/sample/binomial.rs +++ b/src/integer_mod_q/polynomial_ring_zq/sample/binomial.rs @@ -35,7 +35,7 @@ impl PolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::{PolynomialRingZq, ModulusPolynomialRingZq}; /// use std::str::FromStr; - /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); /// /// let sample = PolynomialRingZq::sample_binomial(&modulus, 2, 0.5).unwrap(); /// ``` @@ -78,7 +78,7 @@ impl PolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::{PolynomialRingZq, ModulusPolynomialRingZq}; /// use std::str::FromStr; - /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); /// /// let sample = PolynomialRingZq::sample_binomial_with_offset(&modulus, -1, 2, 0.5).unwrap(); /// ``` diff --git a/src/integer_mod_q/polynomial_ring_zq/sample/discrete_gauss.rs b/src/integer_mod_q/polynomial_ring_zq/sample/discrete_gauss.rs index 432f9201..5f23efbf 100644 --- a/src/integer_mod_q/polynomial_ring_zq/sample/discrete_gauss.rs +++ b/src/integer_mod_q/polynomial_ring_zq/sample/discrete_gauss.rs @@ -36,7 +36,7 @@ impl PolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::{PolynomialRingZq, ModulusPolynomialRingZq}; /// use std::str::FromStr; - /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); /// /// let sample = PolynomialRingZq::sample_discrete_gauss(&modulus, 0, 1).unwrap(); /// ``` diff --git a/src/integer_mod_q/polynomial_ring_zq/sample/uniform.rs b/src/integer_mod_q/polynomial_ring_zq/sample/uniform.rs index 97d4fda2..25af1f02 100644 --- a/src/integer_mod_q/polynomial_ring_zq/sample/uniform.rs +++ b/src/integer_mod_q/polynomial_ring_zq/sample/uniform.rs @@ -32,7 +32,7 @@ impl PolynomialRingZq { /// ``` /// use qfall_math::integer_mod_q::{PolynomialRingZq, ModulusPolynomialRingZq}; /// use std::str::FromStr; - /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 3 mod 17").unwrap(); + /// let modulus = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 17").unwrap(); /// /// let sample = PolynomialRingZq::sample_uniform(&modulus); /// ``` diff --git a/src/integer_mod_q/polynomial_ring_zq/set.rs b/src/integer_mod_q/polynomial_ring_zq/set.rs index b941199c..e3b72fa5 100644 --- a/src/integer_mod_q/polynomial_ring_zq/set.rs +++ b/src/integer_mod_q/polynomial_ring_zq/set.rs @@ -147,7 +147,7 @@ mod test_set_coeff { /// Ensure that a general case is working. #[test] fn set_coeff_working() { - let modulus = ModulusPolynomialRingZq::from_str("5 1 0 0 1 5 mod 17").unwrap(); + let modulus = ModulusPolynomialRingZq::from_str("5 1 0 0 1 1 mod 17").unwrap(); let poly = PolyOverZ::from_str("3 0 2 1").unwrap(); let mut poly_ring = PolynomialRingZq::from((&poly, &modulus)); let value = 10000; diff --git a/src/integer_mod_q/polynomial_ring_zq/to_string.rs b/src/integer_mod_q/polynomial_ring_zq/to_string.rs index ecde85f3..3308d82a 100644 --- a/src/integer_mod_q/polynomial_ring_zq/to_string.rs +++ b/src/integer_mod_q/polynomial_ring_zq/to_string.rs @@ -29,7 +29,7 @@ impl From<&PolynomialRingZq> for String { /// ``` /// use qfall_math::integer_mod_q::PolynomialRingZq; /// use std::str::FromStr; - /// let poly = PolynomialRingZq::from_str("2 2 1 / 3 2 2 2 mod 3").unwrap(); + /// let poly = PolynomialRingZq::from_str("2 2 1 / 3 2 2 1 mod 3").unwrap(); /// /// let string: String = poly.into(); /// ``` @@ -49,7 +49,7 @@ mod test_to_string { /// same string, when it is converted back to a string #[test] fn working_keeps_same_string() { - let cmp_str = "2 1 1 / 3 1 2 2 mod 5"; + let cmp_str = "2 1 1 / 3 1 2 1 mod 5"; let cmp = PolynomialRingZq::from_str(cmp_str).unwrap(); assert_eq!(cmp_str, cmp.to_string()); @@ -59,7 +59,7 @@ mod test_to_string { /// string that can be used to create a polynomial #[test] fn working_use_result_of_to_string_as_input() { - let cmp_str = "2 1 1 / 3 1 2 2 mod 5"; + let cmp_str = "2 1 1 / 3 1 2 1 mod 5"; let cmp = PolynomialRingZq::from_str(cmp_str).unwrap(); let cmp_str_2 = cmp.to_string(); @@ -70,16 +70,16 @@ mod test_to_string { /// Test applied modulus if initialized with negative values #[test] fn initialized_neg() { - let cmp_str = "2 -1 1 / 3 -1 -2 -3 mod 5"; + let cmp_str = "2 -1 1 / 3 -1 -2 1 mod 5"; let cmp = PolynomialRingZq::from_str(cmp_str).unwrap(); - assert_eq!("2 4 1 / 3 4 3 2 mod 5", cmp.to_string()); + assert_eq!("2 4 1 / 3 4 3 1 mod 5", cmp.to_string()); } /// Tests that large entries and large moduli work with to_string() #[test] fn large_entries_modulus() { - let cmp_str = format!("2 1 {} / 3 1 2 {} mod 1{}", u64::MAX, u64::MAX, u64::MAX); + let cmp_str = format!("2 1 {} / 3 1 2 1 mod 1{}", u64::MAX, u64::MAX); let cmp = PolynomialRingZq::from_str(&cmp_str).unwrap(); assert_eq!(cmp_str, cmp.to_string()); diff --git a/src/utils/reduce.rs b/src/utils/reduce.rs index 7e02865b..f658fc4b 100644 --- a/src/utils/reduce.rs +++ b/src/utils/reduce.rs @@ -1,4 +1,14 @@ -use std::cmp::min; +// Copyright © 2026 Marvin Beckmann +// +// This file is part of qFALL-math. +// +// qFALL-math is free software: you can redistribute it and/or modify it under +// the terms of the Mozilla Public License Version 2.0 as published by the +// Mozilla Foundation. See . + +//! Implementations to reduce a [`MatPolynomialRingZq`] with the +//! [`ModulusPolynomialRingZq`](crate::integer_mod_q::ModulusPolynomialRingZq). +//! Only contains internal functions for reductions. use flint_sys::{ fmpz::{fmpz_submul, fmpz_zero}, @@ -6,29 +16,59 @@ use flint_sys::{ fmpz_mod_poly::fmpz_mod_poly_struct, fmpz_poly::fmpz_poly_struct, }; +use std::cmp::min; +/// This is a manual implementation of the [sparse degree reduction +/// from FLINT](https://github.com/flintlib/flint/blob/2016a99ae45608e513c1b2094d37a1c3ea9c0c67/src/fq/reduce.c#L75) +/// for `fq` objects. +/// The sparse reduction works for any context object. +/// +/// # Examples +/// ```compile_fail +/// use qfall_math::integer_mod_q::MatPolynomialRingZq; +/// use qfall_math::integer_mod_q::ModulusPolynomialRingZq; +/// use qfall_math::integer::MatPolyOverZ; +/// use std::str::FromStr; +/// +/// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap(); +/// let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); +/// let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus)); +/// +/// let entry = unsafe { fmpz_poly_mat_entry(&poly_ring_mat.matrix.matrix, 0, 0) }; +/// if (unsafe { *entry }).length > 0 { +/// unsafe { +/// internal_reduce( +/// &mut *entry, +/// ((*entry).length - 1) as usize, +/// &poly_ring_mat.modulus.modulus.poly, +/// poly_ring_mat.modulus.get_degree() as usize, +/// poly_ring_mat.modulus.get_q_as_modulus().get_fmpz_mod_ctx_struct(), +/// &poly_ring_mat.modulus.non_zero, +/// ) +/// } +/// unsafe { +/// _fmpz_poly_normalise(entry); +/// }; +/// } +/// ``` pub(crate) unsafe fn internal_reduce( poly: &mut fmpz_poly_struct, nr_coeffs_poly: usize, modulus_polynomial: &fmpz_mod_poly_struct, nr_coeffs_modulus_poly: usize, modulus: &fmpz_mod_ctx_struct, + non_zero: &Vec, ) { let (poly_len, modulus_polynomial_len) = (nr_coeffs_poly, nr_coeffs_modulus_poly); - // X**3 + X**2 + 58X + 2 / X**3 + 1 - - // X**a + ... / X**b + ... if poly_len >= modulus_polynomial_len { - // for i in (b..=a) for i in (modulus_polynomial_len..=poly_len).rev() { - // for i in 0..b - for k in 0..modulus_polynomial_len { + for k in non_zero { unsafe { fmpz_submul( (poly.coeffs).add((i - modulus_polynomial_len) + k), poly.coeffs.add(i), - modulus_polynomial.coeffs.add(k), + modulus_polynomial.coeffs.add(*k), ) }; } From 548d7a72eb8ee872261120a1e7c2367afe775285 Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Thu, 15 Jan 2026 02:23:41 +0100 Subject: [PATCH 4/7] fix doc tests --- src/integer/mat_poly_over_z/arithmetic/mul.rs | 4 ++-- src/integer/mat_poly_over_z/arithmetic/sub.rs | 4 ++-- src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs | 4 ++-- .../modulus_polynomial_ring_zq/coefficient_embedding.rs | 4 ++-- src/integer_mod_q/modulus_polynomial_ring_zq/from.rs | 4 ++-- src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/integer/mat_poly_over_z/arithmetic/mul.rs b/src/integer/mat_poly_over_z/arithmetic/mul.rs index bb0eaf9c..33fb35a1 100644 --- a/src/integer/mat_poly_over_z/arithmetic/mul.rs +++ b/src/integer/mat_poly_over_z/arithmetic/mul.rs @@ -67,7 +67,7 @@ impl Mul<&MatPolynomialRingZq> for &MatPolyOverZ { /// use std::str::FromStr; /// /// let mat_1 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_3 = &mat_1 * &mat_2; /// ``` @@ -151,7 +151,7 @@ impl MatPolyOverZ { /// use std::str::FromStr; /// /// let mat_1 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_3 = &mat_1.mul_mat_poly_ring_zq_safe(&mat_2).unwrap(); /// ``` diff --git a/src/integer/mat_poly_over_z/arithmetic/sub.rs b/src/integer/mat_poly_over_z/arithmetic/sub.rs index 851bd8e5..fa8eb2eb 100644 --- a/src/integer/mat_poly_over_z/arithmetic/sub.rs +++ b/src/integer/mat_poly_over_z/arithmetic/sub.rs @@ -108,7 +108,7 @@ impl Sub<&MatPolynomialRingZq> for &MatPolyOverZ { /// use std::str::FromStr; /// /// let mat_1 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_3 = &mat_1 - &mat_2; /// ``` @@ -192,7 +192,7 @@ impl MatPolyOverZ { /// use std::str::FromStr; /// /// let mat_1 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); - /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_2 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// /// let mat_3 = &mat_1.sub_mat_poly_ring_zq_safe(&mat_2).unwrap(); /// ``` diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs index 0291da1f..47325aec 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs @@ -150,7 +150,7 @@ impl Add<&MatPolyOverZ> for &MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1 + &mat_2; @@ -252,7 +252,7 @@ impl MatPolynomialRingZq { /// use qfall_math::integer::MatPolyOverZ; /// use std::str::FromStr; /// - /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 3 mod 17").unwrap(); + /// let mat_1 = MatPolynomialRingZq::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]] / 3 1 2 1 mod 17").unwrap(); /// let mat_2 = MatPolyOverZ::from_str("[[2 1 42, 1 17],[1 8, 2 5 6]]").unwrap(); /// /// let mat_3 = &mat_1.add_mat_poly_over_z_safe(&mat_2).unwrap(); diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs index 6d440d7f..e81bb2ae 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/coefficient_embedding.rs @@ -37,7 +37,7 @@ impl IntoCoefficientEmbedding for &ModulusPolynomialRingZq { /// /// let poly = ModulusPolynomialRingZq::from_str("3 17 3 1 mod 19").unwrap(); /// let vector = poly.into_coefficient_embedding(4); - /// let cmp_vector = MatZq::from_str("[[17],[3],[-5],[0]] mod 19").unwrap(); + /// let cmp_vector = MatZq::from_str("[[17],[3],[1],[0]] mod 19").unwrap(); /// assert_eq!(cmp_vector, vector); /// ``` /// @@ -82,7 +82,7 @@ impl FromCoefficientEmbedding<&MatZq> for ModulusPolynomialRingZq { /// traits::FromCoefficientEmbedding, /// }; /// - /// let vector = MatZq::from_str("[[17],[3],[-5]] mod 19").unwrap(); + /// let vector = MatZq::from_str("[[17],[3],[1]] mod 19").unwrap(); /// let poly = ModulusPolynomialRingZq::from_coefficient_embedding(&vector); /// let cmp_poly = ModulusPolynomialRingZq::from_str("3 17 3 1 mod 19").unwrap(); /// assert_eq!(cmp_poly, poly); diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs index 8b5ccdd4..601a172d 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs @@ -36,7 +36,7 @@ impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// use qfall_math::integer::PolyOverZ; /// use std::str::FromStr; /// - /// let poly = PolyOverZ::from_str("4 0 1 102 3").unwrap(); + /// let poly = PolyOverZ::from_str("4 0 1 102 1").unwrap(); /// /// let mod_poly = ModulusPolynomialRingZq::from((&poly, 100)); /// @@ -72,7 +72,7 @@ impl> From<(PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// use qfall_math::integer::PolyOverZ; /// use std::str::FromStr; /// - /// let poly = PolyOverZ::from_str("4 0 1 102 3").unwrap(); + /// let poly = PolyOverZ::from_str("4 0 1 102 1").unwrap(); /// /// let mod_poly = ModulusPolynomialRingZq::from((poly, 100)); /// diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs index 3be02294..97b42857 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/norm.rs @@ -22,7 +22,7 @@ impl ModulusPolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::ModulusPolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 11").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("3 3 2 1 mod 11").unwrap(); /// /// let sqrd_2_norm = poly.norm_eucl_sqrd(); /// @@ -43,7 +43,7 @@ impl ModulusPolynomialRingZq { /// use qfall_math::{integer::Z, integer_mod_q::ModulusPolynomialRingZq}; /// use std::str::FromStr; /// - /// let poly = ModulusPolynomialRingZq::from_str("3 1 2 1 mod 7").unwrap(); + /// let poly = ModulusPolynomialRingZq::from_str("3 4 2 1 mod 7").unwrap(); /// /// let infty_norm = poly.norm_infty(); /// From f12a86c1fe3946c3787f484ac4e27e5ebb285941 Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Thu, 15 Jan 2026 02:25:40 +0100 Subject: [PATCH 5/7] add a few more clarifying comments to doc --- src/integer_mod_q/modulus_polynomial_ring_zq/from.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs index 601a172d..7c1c989e 100644 --- a/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs +++ b/src/integer_mod_q/modulus_polynomial_ring_zq/from.rs @@ -22,6 +22,7 @@ use std::{rc::Rc, str::FromStr}; impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// Creates a [`ModulusPolynomialRingZq`] from a [`PolyOverZ`] and a value that implements [`Into`]. + /// It requires that the leading coefficient is `1`. /// /// Parameters: /// - `poly`: the coefficients of the polynomial. @@ -58,6 +59,7 @@ impl> From<(&PolyOverZ, Mod)> for ModulusPolynomialRingZq { impl> From<(PolyOverZ, Mod)> for ModulusPolynomialRingZq { /// Creates a [`ModulusPolynomialRingZq`] from a [`PolyOverZ`] and a value that implements [`Into`]. + /// It requires that the leading coefficient is `1`. /// /// Parameters: /// - `poly`: the coefficients of the polynomial. @@ -149,6 +151,7 @@ impl FromStr for ModulusPolynomialRingZq { /// Creates a Modulus object of type [`ModulusPolynomialRingZq`] /// for [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq). This first /// converts the provided string into a [`PolyOverZq`] and then into the Modulus object. + /// It requires that the leading coefficient is `1`. /// /// **Warning**: If the input string starts with a correctly formatted /// [`PolyOverZ`](crate::integer::PolyOverZ) object, the rest of the string From f97b6a8bd8281807a556a15cdc3f21fbe07f561b Mon Sep 17 00:00:00 2001 From: Marvin Beckmann Date: Thu, 15 Jan 2026 02:27:04 +0100 Subject: [PATCH 6/7] clippy comments --- src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs | 2 +- src/utils/sample/binomial.rs | 4 ++-- src/utils/sample/discrete_gauss.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs index 250974db..5e8a2477 100644 --- a/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs +++ b/src/integer_mod_q/polynomial_ring_zq/arithmetic/sub.rs @@ -293,7 +293,7 @@ mod test_sub_assign { let poly_2 = PolyOverZ::from_str(&format!("4 -{} 0 1 -{}", i64::MAX, i64::MAX)).unwrap(); let b = PolynomialRingZq::from((&poly_2, &modulus)); let cmp = PolynomialRingZq::from(( - &PolyOverZ::from_str(&"1 9223372036854775923".to_string()).unwrap(), + &PolyOverZ::from_str("1 9223372036854775923").unwrap(), &modulus, )); diff --git a/src/utils/sample/binomial.rs b/src/utils/sample/binomial.rs index e857de4c..6094aff2 100644 --- a/src/utils/sample/binomial.rs +++ b/src/utils/sample/binomial.rs @@ -164,7 +164,7 @@ mod test_binomial_sampler { let p = 0.5; assert!(BinomialSampler::init(&Z::MINUS_ONE, p).is_err()); - assert!(BinomialSampler::init(&Z::from(i64::MIN), p).is_err()); + assert!(BinomialSampler::init(Z::from(i64::MIN), p).is_err()); } /// Checks whether invalid choices for p result in an error. @@ -175,6 +175,6 @@ mod test_binomial_sampler { assert!(BinomialSampler::init(n, &Q::MINUS_ONE).is_err()); assert!(BinomialSampler::init(n, &Q::ZERO).is_err()); assert!(BinomialSampler::init(n, &Q::ONE).is_err()); - assert!(BinomialSampler::init(n, &Q::from(5)).is_err()); + assert!(BinomialSampler::init(n, Q::from(5)).is_err()); } } diff --git a/src/utils/sample/discrete_gauss.rs b/src/utils/sample/discrete_gauss.rs index 6a58b80a..d0472605 100644 --- a/src/utils/sample/discrete_gauss.rs +++ b/src/utils/sample/discrete_gauss.rs @@ -491,7 +491,7 @@ mod test_discrete_gaussian_integer_sampler { assert!( DiscreteGaussianIntegerSampler::init( ¢er, - &Q::from(i64::MIN), + Q::from(i64::MIN), 6.0, LookupTableSetting::FillOnTheFly ) From 0709be555ebffb44152550c3121488f7a03c827e Mon Sep 17 00:00:00 2001 From: jnsiemer Date: Thu, 15 Jan 2026 02:06:43 +0000 Subject: [PATCH 7/7] Restore unsafe-passthrough --- src/integer_mod_q/mat_polynomial_ring_zq.rs | 1 + .../mat_polynomial_ring_zq/reduce.rs | 6 ++--- .../mat_polynomial_ring_zq/tensor.rs | 10 +++---- .../unsafe_functions.rs | 27 +++++++++++++++++++ src/integer_mod_q/polynomial_ring_zq.rs | 1 + .../polynomial_ring_zq/unsafe_functions.rs | 27 +++++++++++++++++++ src/utils/reduce.rs | 2 +- 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs create mode 100644 src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs diff --git a/src/integer_mod_q/mat_polynomial_ring_zq.rs b/src/integer_mod_q/mat_polynomial_ring_zq.rs index e3e39de9..ca53be0c 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq.rs @@ -31,6 +31,7 @@ mod sort; mod tensor; mod to_string; mod transpose; +mod unsafe_functions; mod vector; /// [`MatPolynomialRingZq`] is a matrix with entries of type [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq). diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs index 8db3ff8a..9a636f9a 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/reduce.rs @@ -40,7 +40,7 @@ impl MatPolynomialRingZq { pub(crate) fn reduce(&mut self) { for row_num in 0..self.matrix.get_num_rows() { for column_num in 0..self.matrix.get_num_columns() { - self.reduce_entry(row_num, column_num); + unsafe { self.reduce_entry(row_num, column_num) }; } } } @@ -62,9 +62,9 @@ impl MatPolynomialRingZq { /// let poly_mat = MatPolyOverZ::from_str("[[4 -1 0 1 1, 1 42],[0, 2 1 2]]").unwrap(); /// let mut poly_ring_mat = MatPolynomialRingZq::from((&poly_mat, &modulus)); /// - /// poly_ring_mat.reduce_entry(0, 0) + /// unsafe { poly_ring_mat.reduce_entry(0, 0) }; /// ``` - pub(crate) fn reduce_entry(&mut self, row: i64, column: i64) { + pub(crate) unsafe fn reduce_entry(&mut self, row: i64, column: i64) { let entry = unsafe { fmpz_poly_mat_entry(&self.matrix.matrix, row, column) }; if (unsafe { *entry }).length > 0 { unsafe { diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs index b76ffda9..5e3d158c 100644 --- a/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs +++ b/src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs @@ -154,12 +154,12 @@ unsafe fn set_matrix_window_mul( ), &scalar.poly, fmpz_poly_mat_entry(&matrix.matrix.matrix, i_other, j_other), - ) + ); + out.reduce_entry( + row_left * rows_other + i_other, + column_upper * columns_other + j_other, + ); } - out.reduce_entry( - row_left * rows_other + i_other, - column_upper * columns_other + j_other, - ); } } } diff --git a/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs b/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs new file mode 100644 index 00000000..6c4fff06 --- /dev/null +++ b/src/integer_mod_q/mat_polynomial_ring_zq/unsafe_functions.rs @@ -0,0 +1,27 @@ +// Copyright © 2025 Niklas Siemer +// +// This file is part of qFALL-math. +// +// qFALL-math is free software: you can redistribute it and/or modify it under +// the terms of the Mozilla Public License Version 2.0 as published by the +// Mozilla Foundation. See . + +//! This module contains public functions that enable access to underlying +//! [FLINT](https://flintlib.org/) structs. Therefore, they require to be unsafe. +use super::MatPolynomialRingZq; +use crate::macros::unsafe_passthrough::{unsafe_getter_indirect, unsafe_setter_indirect}; +use flint_sys::fmpz_poly_mat::fmpz_poly_mat_struct; + +unsafe_getter_indirect!( + MatPolynomialRingZq, + matrix, + get_fmpz_poly_mat_struct, + fmpz_poly_mat_struct +); + +unsafe_setter_indirect!( + MatPolynomialRingZq, + matrix, + set_fmpz_poly_mat_struct, + fmpz_poly_mat_struct +); diff --git a/src/integer_mod_q/polynomial_ring_zq.rs b/src/integer_mod_q/polynomial_ring_zq.rs index d83cc27e..6286181f 100644 --- a/src/integer_mod_q/polynomial_ring_zq.rs +++ b/src/integer_mod_q/polynomial_ring_zq.rs @@ -33,6 +33,7 @@ mod reduce; mod sample; mod set; mod to_string; +mod unsafe_functions; /// [`PolynomialRingZq`] represents polynomials over the finite field /// [`PolyOverZq`](crate::integer_mod_q::PolyOverZq)/f(X) where f(X) is a polynomial over [`Zq`](super::Zq). diff --git a/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs b/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs new file mode 100644 index 00000000..1576642a --- /dev/null +++ b/src/integer_mod_q/polynomial_ring_zq/unsafe_functions.rs @@ -0,0 +1,27 @@ +// Copyright © 2025 Niklas Siemer +// +// This file is part of qFALL-math. +// +// qFALL-math is free software: you can redistribute it and/or modify it under +// the terms of the Mozilla Public License Version 2.0 as published by the +// Mozilla Foundation. See . + +//! This module contains public functions that enable access to underlying +//! [FLINT](https://flintlib.org/) structs. Therefore, they require to be unsafe. +use super::PolynomialRingZq; +use crate::macros::unsafe_passthrough::{unsafe_getter_indirect, unsafe_setter_indirect}; +use flint_sys::fmpz_poly::fmpz_poly_struct; + +unsafe_getter_indirect!( + PolynomialRingZq, + poly, + get_fmpz_poly_struct, + fmpz_poly_struct +); + +unsafe_setter_indirect!( + PolynomialRingZq, + poly, + set_fmpz_poly_struct, + fmpz_poly_struct +); diff --git a/src/utils/reduce.rs b/src/utils/reduce.rs index f658fc4b..4eb825aa 100644 --- a/src/utils/reduce.rs +++ b/src/utils/reduce.rs @@ -6,7 +6,7 @@ // the terms of the Mozilla Public License Version 2.0 as published by the // Mozilla Foundation. See . -//! Implementations to reduce a [`MatPolynomialRingZq`] with the +//! Implementations to reduce a [`MatPolynomialRingZq`](crate::integer_mod_q::MatPolynomialRingZq) with the //! [`ModulusPolynomialRingZq`](crate::integer_mod_q::ModulusPolynomialRingZq). //! Only contains internal functions for reductions.