Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion src/integer_mod_q/mat_polynomial_ring_zq/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::MatPolynomialRingZq;
use crate::{
integer::{MatPolyOverZ, PolyOverZ},
integer_mod_q::{ModulusPolynomialRingZq, PolynomialRingZq},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix, MatrixSetEntry},
};
use flint_sys::{fmpz_poly::fmpz_poly_struct, fmpz_poly_mat::fmpz_poly_mat_entry};

Expand All @@ -37,11 +37,46 @@ impl MatPolynomialRingZq {
}

impl MatPolynomialRingZq {
/// Creates a [`MatPolyOverZ`] where each entry is a representative of the
/// equivalence class of each entry from a [`MatPolynomialRingZq`] with coefficients centered around `0`.
///
/// The representation of the coefficients is in the range `[-modulus/2, modulus/2]` and
/// the representation of the polynomials is in the range `[0, modulus_polynomial)`.
/// Use [`MatPolynomialRingZq::get_representative_least_nonnegative_residue`] if they should be
/// in the range `[0, modulus)`.
///
/// # Examples
/// ```
/// use qfall_math::integer_mod_q::MatPolynomialRingZq;
/// use qfall_math::integer::MatPolyOverZ;
/// use std::str::FromStr;
///
/// let poly_ring_mat = MatPolynomialRingZq::from_str("[[1 10, 1 11]] / 4 1 0 0 1 mod 21").unwrap();
///
/// let matrix = poly_ring_mat.get_representative_least_absolute_residue();
///
/// let cmp_poly_mat = MatPolyOverZ::from_str("[[1 10, 1 -10]]").unwrap();
/// assert_eq!(cmp_poly_mat, matrix);
/// ```
pub fn get_representative_least_absolute_residue(&self) -> MatPolyOverZ {
let mut out = MatPolyOverZ::new(self.get_num_rows(), self.get_num_columns());
for row in 0..self.get_num_rows() {
for col in 0..self.get_num_columns() {
let poly: PolynomialRingZq = unsafe { self.get_entry_unchecked(row, col) };
let lar_poly = poly.get_representative_least_absolute_residue();
unsafe { out.set_entry_unchecked(row, col, lar_poly) };
}
}
out
}

/// Creates a [`MatPolyOverZ`] where each entry is a representative of the
/// equivalence class of each entry from a [`MatPolynomialRingZq`].
///
/// The representation of the coefficients is in the range `[0, modulus)` and
/// the representation of the polynomials is in the range `[0, modulus_polynomial)`.
/// Use [`MatPolynomialRingZq::get_representative_least_absolute_residue`] if they should be
/// in the range `[-modulus/2, modulus/2]`.
///
/// # Examples
/// ```
Expand Down Expand Up @@ -440,6 +475,40 @@ mod test_mod {
}
}

#[cfg(test)]
mod test_get_representative_least_absolute_residue {
use crate::{integer::MatPolyOverZ, integer_mod_q::MatPolynomialRingZq};
use std::str::FromStr;

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
#[test]
fn large_numbers() {
let poly_ring = MatPolynomialRingZq::from_str(&format!(
"[[2 {} {}]] / 4 1 0 0 1 mod {}",
i64::MAX,
u64::MAX - 1,
u64::MAX
))
.unwrap();

let lar_mat = poly_ring.get_representative_least_absolute_residue();

let cmp_mat = MatPolyOverZ::from_str(&format!("[[2 {} -1]]", i64::MAX)).unwrap();
assert_eq!(cmp_mat, lar_mat);
}

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
#[test]
fn special_numbers() {
let mat = MatPolynomialRingZq::from_str("[[3 10 0 11]] / 4 1 0 0 1 mod 21").unwrap();

let lar_mat = mat.get_representative_least_absolute_residue();

let cmp_mat = MatPolyOverZ::from_str("[[3 10 0 -10]]").unwrap();
assert_eq!(cmp_mat, lar_mat);
}
}

#[cfg(test)]
mod test_get_representative_least_nonnegative_residue {
use crate::{
Expand Down
67 changes: 66 additions & 1 deletion src/integer_mod_q/poly_over_zq/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::PolyOverZq;
use crate::{
integer::{PolyOverZ, Z},
integer_mod_q::{Modulus, Zq},
traits::GetCoefficient,
traits::{GetCoefficient, SetCoefficient},
};
use flint_sys::fmpz_mod_poly::{
fmpz_mod_poly_degree, fmpz_mod_poly_get_coeff_fmpz, fmpz_mod_poly_get_fmpz_poly,
Expand Down Expand Up @@ -133,9 +133,40 @@ impl PolyOverZq {
self.modulus.clone()
}

/// Returns a representative polynomial of the [`PolyOverZq`] element with coefficients centered around `0`.
///
/// The output [`PolyOverZ`] has coefficients in the range of `[-modulus/2, modulus/2]`.
/// For even moduli, the positive representative is chosen for the element `modulus / 2`.
/// Use [`PolyOverZq::get_representative_least_nonnegative_residue`] if they should be
/// in the range `[0, modulus)`.
///
/// # Examples
/// ```
/// use qfall_math::integer_mod_q::PolyOverZq;
/// use qfall_math::integer::PolyOverZ;
/// use std::str::FromStr;
///
/// let value = PolyOverZq::from_str("2 10 11 mod 21").unwrap();
///
/// let least_abs_residue = value.get_representative_least_absolute_residue();
///
/// assert_eq!(PolyOverZ::from_str("2 10 -10").unwrap(), least_abs_residue);
/// ```
pub fn get_representative_least_absolute_residue(&self) -> PolyOverZ {
let mut out = PolyOverZ::default();
for i in 0..=self.get_degree() {
let coeff: Zq = unsafe { self.get_coeff_unchecked(i) };
let lar_coeff = coeff.get_representative_least_absolute_residue();
unsafe { out.set_coeff_unchecked(i, lar_coeff) };
}
out
}

/// Returns a representative polynomial of the [`PolyOverZq`] element.
///
/// The representation of the coefficients is in the range `[0, modulus)`.
/// Use [`PolyOverZq::get_representative_least_absolute_residue`] if they should be
/// in the range `[-modulus/2, modulus/2]`.
///
/// # Examples
/// ```
Expand Down Expand Up @@ -339,6 +370,40 @@ mod test_mod {
}
}

#[cfg(test)]
mod test_get_representative_least_absolute_residue {
use crate::{integer::PolyOverZ, integer_mod_q::PolyOverZq};
use std::str::FromStr;

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
#[test]
fn large_numbers() {
let poly_zq = PolyOverZq::from_str(&format!(
"2 {} {} mod {}",
i64::MAX,
u64::MAX - 1,
u64::MAX
))
.unwrap();

let poly_z = poly_zq.get_representative_least_absolute_residue();

let cmp_poly = PolyOverZ::from_str(&format!("2 {} -1", i64::MAX)).unwrap();
assert_eq!(cmp_poly, poly_z);
}

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
#[test]
fn special_numbers() {
let poly_zq = PolyOverZq::from_str("3 10 0 11 mod 21").unwrap();

let poly_z = poly_zq.get_representative_least_absolute_residue();

let cmp_poly = PolyOverZ::from_str("3 10 0 -10").unwrap();
assert_eq!(cmp_poly, poly_z);
}
}

#[cfg(test)]
mod test_get_representative_least_nonnegative_residue {
use crate::{integer::PolyOverZ, integer_mod_q::PolyOverZq};
Expand Down
67 changes: 66 additions & 1 deletion src/integer_mod_q/polynomial_ring_zq/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::PolynomialRingZq;
use crate::{
integer::{PolyOverZ, Z},
integer_mod_q::{ModulusPolynomialRingZq, Zq},
traits::GetCoefficient,
traits::{GetCoefficient, SetCoefficient},
};
use flint_sys::fmpz_poly::{fmpz_poly_degree, fmpz_poly_get_coeff_fmpz};

Expand Down Expand Up @@ -116,10 +116,41 @@ impl PolynomialRingZq {
self.modulus.clone()
}

/// Returns a representative polynomial of the [`PolynomialRingZq`] element with coefficients centered around `0`.
///
/// The output [`PolyOverZ`] has coefficients in the range of `[-modulus/2, modulus/2]`.
/// For even moduli, the positive representative is chosen for the element `modulus / 2`.
/// Use [`PolynomialRingZq::get_representative_least_nonnegative_residue`] if they should be
/// in the range `[0, modulus)`.
///
/// # Examples
/// ```
/// use qfall_math::integer_mod_q::PolynomialRingZq;
/// use qfall_math::integer::PolyOverZ;
/// use std::str::FromStr;
///
/// let value = PolynomialRingZq::from_str("2 10 11 / 4 1 0 0 1 mod 21").unwrap();
///
/// let least_abs_residue = value.get_representative_least_absolute_residue();
///
/// assert_eq!(PolyOverZ::from_str("2 10 -10").unwrap(), least_abs_residue);
/// ```
pub fn get_representative_least_absolute_residue(&self) -> PolyOverZ {
let mut out = PolyOverZ::default();
for i in 0..=self.get_degree() {
let coeff: Zq = unsafe { self.get_coeff_unchecked(i) };
let lar_coeff = coeff.get_representative_least_absolute_residue();
unsafe { out.set_coeff_unchecked(i, lar_coeff) };
}
out
}

/// Returns a representative polynomial of the [`PolynomialRingZq`] element.
///
/// The representation of the coefficients is in the range `[0, modulus)` and
/// the representation of the polynomial is in the range `[0, modulus_polynomial)`.
/// Use [`PolynomialRingZq::get_representative_least_absolute_residue`] if they should be
/// in the range `[-modulus/2, modulus/2]`.
///
/// # Examples
/// ```
Expand Down Expand Up @@ -258,6 +289,40 @@ mod test_get_mod {
}
}

#[cfg(test)]
mod test_get_representative_least_absolute_residue {
use crate::{integer::PolyOverZ, integer_mod_q::PolynomialRingZq};
use std::str::FromStr;

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
#[test]
fn large_numbers() {
let poly_ring = PolynomialRingZq::from_str(&format!(
"2 {} {} / 4 1 0 0 1 mod {}",
i64::MAX,
u64::MAX - 1,
u64::MAX
))
.unwrap();

let poly_z = poly_ring.get_representative_least_absolute_residue();

let cmp_poly = PolyOverZ::from_str(&format!("2 {} -1", i64::MAX)).unwrap();
assert_eq!(cmp_poly, poly_z);
}

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
#[test]
fn special_numbers() {
let poly_ring = PolynomialRingZq::from_str("3 10 0 11 / 4 1 0 0 1 mod 21").unwrap();

let poly_z = poly_ring.get_representative_least_absolute_residue();

let cmp_poly = PolyOverZ::from_str("3 10 0 -10").unwrap();
assert_eq!(cmp_poly, poly_z);
}
}

#[cfg(test)]
mod test_get_representative_least_nonnegative_residue {
use crate::{
Expand Down
16 changes: 10 additions & 6 deletions src/integer_mod_q/z_q/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ impl Zq {
///
/// let z_value = zq_value.get_representative_least_absolute_residue();
///
/// assert_eq!(Z::from(2), z_value);
/// assert_eq!(Z::from(-2), z_value);
/// ```
pub fn get_representative_least_absolute_residue(&self) -> Z {
let mod_z = Z::from(&self.modulus);
if self.value < mod_z.div_ceil(2) {
self.value.clone()
let mod_half = mod_z.div_floor(2);
if self.value > mod_half {
&self.value - mod_z
} else {
Z::from(self.modulus.clone()) - self.value.clone()
self.value.clone()
}
}

Expand Down Expand Up @@ -123,7 +124,7 @@ mod test_get_representative_least_absolute_residue {
let res_1 = value_1.get_representative_least_absolute_residue();

assert_eq!(res_0, Z::from(2));
assert_eq!(res_1, Z::from(2));
assert_eq!(res_1, Z::from(-2));
}

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for large values
Expand All @@ -136,20 +137,23 @@ mod test_get_representative_least_absolute_residue {
let res_1 = value_1.get_representative_least_absolute_residue();

assert_eq!(res_0, Z::from(i64::MAX));
assert_eq!(res_1, Z::from(1));
assert_eq!(res_1, Z::from(-1));
}

/// Check whether `get_representative_least_absolute_residue` outputs the correct value for special cases
#[test]
fn get_special() {
let value_0 = Zq::from((10, 20));
let value_1 = Zq::from((0, 20));
let value_2 = Zq::from((11, 21));

let res_0 = value_0.get_representative_least_absolute_residue();
let res_1 = value_1.get_representative_least_absolute_residue();
let res_2 = value_2.get_representative_least_absolute_residue();

assert_eq!(res_0, Z::from(10));
assert_eq!(res_1, Z::from(0));
assert_eq!(res_2, Z::from(-10));
}
}

Expand Down
Loading