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
20 changes: 20 additions & 0 deletions src/integer/mat_poly_over_z/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//! This uses the traits from [`std::cmp`].

use super::MatPolyOverZ;
use crate::traits::CompareBase;
use flint_sys::fmpz_poly_mat::fmpz_poly_mat_equal;

impl PartialEq for MatPolyOverZ {
Expand Down Expand Up @@ -48,6 +49,8 @@ impl PartialEq for MatPolyOverZ {
// This is not guaranteed by the [`PartialEq`] trait.
impl Eq for MatPolyOverZ {}

impl CompareBase for MatPolyOverZ {}

/// Test that the [`PartialEq`] trait is correctly implemented.
#[cfg(test)]
mod test_partial_eq {
Expand Down Expand Up @@ -218,3 +221,20 @@ mod test_partial_eq {
assert!(small_positive != min);
}
}

/// Test that the [`CompareBase`] trait uses the default implementation.
#[cfg(test)]
mod test_compare_base {
use crate::{integer::MatPolyOverZ, traits::CompareBase};
use std::str::FromStr;

/// Ensures that the [`CompareBase`] trait uses the default implementation.
#[test]
fn uses_default_implementation() {
let one_1 = MatPolyOverZ::from_str("[[2 24 47],[2 24 42]]").unwrap();
let one_2 = MatPolyOverZ::from_str("[[2 24 42]]").unwrap();

assert!(one_1.compare_base(&one_2));
assert!(one_1.call_compare_base_error(&one_2).is_none());
}
}
20 changes: 20 additions & 0 deletions src/integer/mat_z/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! This module contains implementations for comparison of [`MatZ`].

use super::MatZ;
use crate::traits::CompareBase;
use flint_sys::fmpz_mat::fmpz_mat_equal;

impl PartialEq for MatZ {
Expand Down Expand Up @@ -42,6 +43,8 @@ impl PartialEq for MatZ {
}
}

impl CompareBase for MatZ {}

// With the [`Eq`] trait, `a == a` is always true.
// This is not guaranteed by the [`PartialEq`] trait.
impl Eq for MatZ {}
Expand Down Expand Up @@ -104,3 +107,20 @@ mod test_partial_eq {
assert_ne!(&d, &e);
}
}

/// Test that the [`CompareBase`] trait uses the default implementation.
#[cfg(test)]
mod test_compare_base {
use crate::{integer::MatZ, traits::CompareBase};
use std::str::FromStr;

/// Ensures that the [`CompareBase`] trait uses the default implementation.
#[test]
fn different_base() {
let one_1 = MatZ::from_str("[[2, 24, 47],[2, 24, 42]]").unwrap();
let one_2 = MatZ::from_str("[[2, 4, 42]]").unwrap();

assert!(one_1.compare_base(&one_2));
assert!(one_1.call_compare_base_error(&one_2).is_none());
}
}
1 change: 1 addition & 0 deletions src/integer_mod_q/mat_polynomial_ring_zq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use derive_more::Display;
use serde::{Deserialize, Serialize};

mod arithmetic;
mod cmp;
mod coefficient_embedding;
mod concat;
mod default;
Expand Down
8 changes: 3 additions & 5 deletions src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
arithmetic_trait_mixed_borrowed_owned,
},
traits::CompareBase,
};
use std::ops::{Add, AddAssign};

Expand Down Expand Up @@ -132,11 +133,8 @@ impl MatPolynomialRingZq {
/// - Returns a [`MathError`] of type [`MathError::MismatchingMatrixDimension`]
/// if the dimensions of both [`MatPolynomialRingZq`] mismatch.
pub fn add_safe(&self, other: &Self) -> Result<MatPolynomialRingZq, MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to add polynomial with modulus '{}' and polynomial with modulus '{}'.",
self.modulus, other.modulus
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}
let matrix = self.matrix.add_safe(&other.matrix)?;

Expand Down
9 changes: 3 additions & 6 deletions src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::error::MathError;
use crate::macros::arithmetics::{
arithmetic_trait_borrowed_to_owned, arithmetic_trait_mixed_borrowed_owned,
};
use crate::traits::CompareBase;
use std::ops::Mul;

impl Mul for &MatPolynomialRingZq {
Expand Down Expand Up @@ -101,12 +102,8 @@ impl MatPolynomialRingZq {
/// - Returns a [`MathError`] of type
/// [`MathError::MismatchingModulus`] if the moduli mismatch.
pub fn mul_safe(&self, other: &Self) -> Result<Self, MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to multiply matrices with moduli '{}' and '{}'.",
self.get_mod(),
other.get_mod()
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

let mut new =
Expand Down
8 changes: 3 additions & 5 deletions src/integer_mod_q/mat_polynomial_ring_zq/arithmetic/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::integer_mod_q::MatPolynomialRingZq;
use crate::macros::arithmetics::{
arithmetic_trait_borrowed_to_owned, arithmetic_trait_mixed_borrowed_owned,
};
use crate::traits::CompareBase;
use std::ops::Sub;

impl Sub for &MatPolynomialRingZq {
Expand Down Expand Up @@ -84,11 +85,8 @@ impl MatPolynomialRingZq {
/// - Returns a [`MathError`] of type [`MathError::MismatchingMatrixDimension`]
/// if the dimensions of both [`MatPolynomialRingZq`] mismatch.
pub fn sub_safe(&self, other: &Self) -> Result<MatPolynomialRingZq, MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to subtract polynomial with modulus '{}' and polynomial with modulus '{}'.",
self.modulus, other.modulus
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}
let matrix = self.matrix.sub_safe(&other.matrix)?;

Expand Down
103 changes: 103 additions & 0 deletions src/integer_mod_q/mat_polynomial_ring_zq/cmp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright © 2025 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 <https://mozilla.org/en-US/MPL/2.0/>.

//! This module contains implementations for comparison of [`MatPolynomialRingZq`].

use super::MatPolynomialRingZq;
use crate::{error::MathError, traits::CompareBase};

impl CompareBase for MatPolynomialRingZq {
/// Compares the moduli of the two elements.
///
/// Parameters:
/// - `other`: The other object whose base is compared to `self`
///
/// Returns true if the moduli match and false otherwise.
///
/// # Example
/// ```
/// use qfall_math::{
/// integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
/// traits::CompareBase,
/// };
/// use std::str::FromStr;
///
/// let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
/// let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
/// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 23").unwrap();
/// let one_2 = MatPolynomialRingZq::identity(10, 7, &modulus);
///
/// assert!(!one_1.compare_base(&one_2));
/// ```
fn compare_base(&self, other: &Self) -> bool {
self.get_mod() == other.get_mod()
}

/// Returns an error that gives small explanation how the moduli differ.
///
/// Parameters:
/// - `other`: The other object whose base is compared to `self`
///
/// Returns a MathError of type [MathError::MismatchingModulus].
///
/// # Example
/// ```
/// use qfall_math::{
/// integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
/// traits::CompareBase,
/// };
/// use std::str::FromStr;
///
/// let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
/// let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
/// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 23").unwrap();
/// let one_2 = MatPolynomialRingZq::identity(10, 7, &modulus);
///
/// assert!(one_1.call_compare_base_error(&one_2).is_some());
/// ```
fn call_compare_base_error(&self, other: &Self) -> Option<MathError> {
Some(MathError::MismatchingModulus(format!(
"The moduli of the matrices mismatch. One of them is {} and the other is {}.
The desired operation is not defined and an error is returned.",
self.get_mod(),
other.get_mod()
)))
}
}

/// Test that the [`CompareBase`] trait uses an actual implementation.
#[cfg(test)]
mod test_compare_base {
use crate::{
integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
traits::CompareBase,
};
use std::str::FromStr;

/// Ensures that the [`CompareBase`] trait uses an actual implementation.
#[test]
fn different_base() {
let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 23").unwrap();
let one_2 = MatPolynomialRingZq::identity(10, 7, &modulus);

assert!(!one_1.compare_base(&one_2));
assert!(one_1.call_compare_base_error(&one_2).is_some())
}

/// Ensures that the same base return `true`.
#[test]
fn same_base() {
let modulus = ModulusPolynomialRingZq::from_str("3 1 0 1 mod 17").unwrap();
let one_1 = MatPolynomialRingZq::identity(10, 7, &modulus);
let one_2 = MatPolynomialRingZq::identity(29, 3, &modulus);

assert!(one_1.compare_base(&one_2));
}
}
18 changes: 5 additions & 13 deletions src/integer_mod_q/mat_polynomial_ring_zq/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::MatPolynomialRingZq;
use crate::{
error::MathError,
integer::MatPolyOverZ,
traits::{Concatenate, MatrixDimensions},
traits::{CompareBase, Concatenate, MatrixDimensions},
};
use flint_sys::fmpz_poly_mat::{fmpz_poly_mat_concat_horizontal, fmpz_poly_mat_concat_vertical};

Expand Down Expand Up @@ -60,12 +60,8 @@ impl Concatenate for &MatPolynomialRingZq {
)));
}

if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to concatenate matrices with different moduli {} and {}.",
self.get_mod(),
other.get_mod(),
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

let mut matrix = MatPolyOverZ::new(
Expand Down Expand Up @@ -126,12 +122,8 @@ impl Concatenate for &MatPolynomialRingZq {
)));
}

if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to concatenate matrices with different moduli {} and {}.",
self.get_mod(),
other.get_mod(),
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

let mut matrix = MatPolyOverZ::new(
Expand Down
18 changes: 5 additions & 13 deletions src/integer_mod_q/mat_polynomial_ring_zq/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use super::MatPolynomialRingZq;
use crate::integer_mod_q::PolynomialRingZq;
use crate::macros::for_others::implement_for_owned;
use crate::traits::{MatrixSetSubmatrix, MatrixSwaps};
use crate::traits::{CompareBase, MatrixSetSubmatrix, MatrixSwaps};
use crate::utils::index::evaluate_indices_for_matrix;
use crate::{error::MathError, integer::PolyOverZ, traits::MatrixSetEntry};
use flint_sys::{fmpz_poly::fmpz_poly_set, fmpz_poly_mat::fmpz_poly_mat_entry};
Expand Down Expand Up @@ -250,12 +250,8 @@ impl MatrixSetSubmatrix for MatPolynomialRingZq {
other: &Self,
col_1: impl TryInto<i64> + Display,
) -> Result<(), MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"set_column requires the moduli to be equal, but {} differs from {}",
self.get_mod(),
other.get_mod()
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

self.matrix.set_column(col_0, &other.matrix, col_1)
Expand Down Expand Up @@ -299,12 +295,8 @@ impl MatrixSetSubmatrix for MatPolynomialRingZq {
other: &Self,
row_1: impl TryInto<i64> + Display,
) -> Result<(), MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"set_row requires the moduli to be equal, but {} differs from {}",
self.get_mod(),
other.get_mod()
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

self.matrix.set_row(row_0, &other.matrix, row_1)
Expand Down
10 changes: 3 additions & 7 deletions src/integer_mod_q/mat_polynomial_ring_zq/tensor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::MatPolynomialRingZq;
use crate::{
error::MathError,
integer::PolyOverZ,
traits::{MatrixDimensions, MatrixGetEntry, Tensor},
traits::{CompareBase, MatrixDimensions, MatrixGetEntry, Tensor},
};
use flint_sys::{fmpz_poly_mat::fmpz_poly_mat_entry, fq::fq_mul};

Expand Down Expand Up @@ -81,12 +81,8 @@ impl MatPolynomialRingZq {
/// [`MismatchingModulus`](MathError::MismatchingModulus) if the
/// moduli of the provided matrices mismatch.
pub fn tensor_product_safe(&self, other: &Self) -> Result<Self, MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to compute tensor product of matrices with moduli '{}' and '{}'.",
self.get_mod(),
other.get_mod()
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}

let mut out = MatPolynomialRingZq::new(
Expand Down
10 changes: 3 additions & 7 deletions src/integer_mod_q/mat_zq/arithmetic/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::macros::arithmetics::{
arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
};
use crate::traits::MatrixDimensions;
use crate::traits::{CompareBase, MatrixDimensions};
use flint_sys::fmpz_mat::fmpz_mat_add;
use flint_sys::fmpz_mod_mat::{_fmpz_mod_mat_reduce, fmpz_mod_mat_add};
use std::ops::{Add, AddAssign};
Expand Down Expand Up @@ -204,12 +204,8 @@ impl MatZq {
/// - Returns a [`MathError`] of type
/// [`MathError::MismatchingModulus`] if the moduli mismatch.
pub fn add_safe(&self, other: &Self) -> Result<MatZq, MathError> {
if self.modulus != other.modulus {
return Err(MathError::MismatchingModulus(format!(
"Tried to add matrices with moduli '{}' and '{}'.",
self.get_mod(),
other.get_mod()
)));
if !self.compare_base(other) {
return Err(self.call_compare_base_error(other).unwrap());
}
if self.get_num_rows() != other.get_num_rows()
|| self.get_num_columns() != other.get_num_columns()
Expand Down
Loading
Loading