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
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "qfall-math"
version = "0.1.1"
version = "0.1.2"
edition = "2024"
rust-version = "1.87" # due to wit_bindgen dependency
description = "Mathematical foundations for rapid prototyping of lattice-based cryptography"
Expand All @@ -15,7 +15,7 @@ autobenches = false
[dependencies]
criterion = { version = "0.8", features = ["html_reports"] }
flint-sys = "0.7"
libc = "0"
libc = "0.2"
paste = "1"
rand = "0.10"
rand_distr = "0.6"
Expand All @@ -26,7 +26,7 @@ string-builder = "0.2"
thiserror = "2"
lazy_static = "1"
probability = "0.20"
derive_more = { version = "2.1", features = ["display"] }
derive_more = { version = "2", features = ["display"] }

[profile.bench]
debug = true
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ let vec_t = &mat_a * &vec_e;
let vec_b = vec_s.transpose() * mat_a + vec_e.transpose();
```

## SemVer and Backward Compatibility
While this library is not stable yet, i.e. pre-version 1.0.0, we may introduce API-breaking changes in MINOR version updates.
Therefore, we recommend to fix the used version `version = "0.y"` in your `Cargo.toml`.

## Bugs
Please report bugs through the [GitHub issue tracker](https://github.com/qfall/math/issues).

Expand Down
46 changes: 45 additions & 1 deletion src/integer/mat_poly_over_z/norm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::MatPolyOverZ;
use crate::{
integer::Z,
rational::Q,
traits::{MatrixDimensions, MatrixGetSubmatrix},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
};

impl MatPolyOverZ {
Expand Down Expand Up @@ -89,6 +89,31 @@ impl MatPolyOverZ {
}
max_norm
}

/// Outputs the hamming weight of `self`, i.e. it computes the number of non-zero
/// coefficients across all polynomials in the matrix.
///
/// # Examples
/// ```
/// use qfall_math::integer::MatPolyOverZ;
/// use std::str::FromStr;
///
/// let mat = MatPolyOverZ::from_str("[[2 2 1, 2 3 0],[1 2, 0]]").unwrap();
///
/// let hamming_weight = mat.hamming_weight();
///
/// assert_eq!(4, hamming_weight);
/// ```
pub fn hamming_weight(&self) -> i64 {
let mut hamming_weight = 0;
for row in 0..self.get_num_rows() {
for col in 0..self.get_num_columns() {
let entry = unsafe { self.get_entry_unchecked(row, col) };
hamming_weight += entry.hamming_weight();
}
}
hamming_weight
}
}

#[cfg(test)]
Expand Down Expand Up @@ -131,3 +156,22 @@ mod test_matrix_norms {
assert_eq!(Z::from(5), infty_norm);
}
}

#[cfg(test)]
mod test_hamming_weight {
use super::MatPolyOverZ;
use std::str::FromStr;

/// Ensures that the hamming weight is computed correctly.
#[test]
fn hamming_weight() {
let mat0 = MatPolyOverZ::new(3, 4);
let mat1 = MatPolyOverZ::from_str("[[1 -2, 2 3 2],[2 2 0, 1 -5],[1 -2, 0]]").unwrap();

let hw0 = mat0.hamming_weight();
let hw1 = mat1.hamming_weight();

assert_eq!(0, hw0);
assert_eq!(6, hw1);
}
}
48 changes: 47 additions & 1 deletion src/integer/mat_z/norm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::MatZ;
use crate::{
integer::Z,
rational::Q,
traits::{MatrixDimensions, MatrixGetSubmatrix},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
};

impl MatZ {
Expand Down Expand Up @@ -89,6 +89,33 @@ impl MatZ {
}
max_norm
}

/// Outputs the hamming weight of `self`, i.e. it returns the number of
/// non-zero entries in the matrix.
///
/// # Examples
/// ```
/// use qfall_math::integer::MatZ;
/// use std::str::FromStr;
///
/// let mat = MatZ::from_str("[[2, 3],[2, 0]]").unwrap();
///
/// let hamming_weight = mat.hamming_weight();
///
/// assert_eq!(3, hamming_weight);
/// ```
pub fn hamming_weight(&self) -> i64 {
let mut hamming_weight = 0;
for row in 0..self.get_num_rows() {
for col in 0..self.get_num_columns() {
let entry = unsafe { self.get_entry_unchecked(row, col) };
if !entry.is_zero() {
hamming_weight += 1;
}
}
}
hamming_weight
}
}

#[cfg(test)]
Expand Down Expand Up @@ -126,3 +153,22 @@ mod test_matrix_norms {
assert_eq!(Z::from(5), infty_norm);
}
}

#[cfg(test)]
mod test_hamming_weight {
use super::MatZ;
use std::str::FromStr;

/// Ensures that the hamming weight is computed correctly.
#[test]
fn hamming_weight() {
let mat0 = MatZ::new(10, 8);
let mat1 = MatZ::from_str("[[-2, 3],[2, -5],[-2, 0]]").unwrap();

let hw0 = mat0.hamming_weight();
let hw1 = mat1.hamming_weight();

assert_eq!(0, hw0);
assert_eq!(5, hw1);
}
}
65 changes: 65 additions & 0 deletions src/integer/poly_over_z/norm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use crate::{
integer::{PolyOverZ, Z},
rational::Q,
traits::{GetCoefficient, Pow},
};
use std::cmp::max;
Expand Down Expand Up @@ -42,6 +43,26 @@ impl PolyOverZ {
res
}

/// Returns the Euclidean norm or 2-norm of the given polynomial.
/// The Euclidean norm for a polynomial is obtained by treating the coefficients
/// of the polynomial as a vector and then applying the standard Euclidean norm.
///
/// # Examples
/// ```
/// use qfall_math::{integer::PolyOverZ, rational::Q};
/// use std::str::FromStr;
///
/// let poly = PolyOverZ::from_str("1 3").unwrap();
///
/// let norm = poly.norm_eucl();
///
/// // sqrt(3^2) = 3
/// assert_eq!(Q::from(3), norm);
/// ```
pub fn norm_eucl(&self) -> Q {
self.norm_eucl_sqrd().sqrt()
}

/// Returns the infinity norm or the maximal absolute value of a
/// coefficient of the given polynomial.
/// The infinity norm for a polynomial is obtained by treating the coefficients
Expand All @@ -68,6 +89,31 @@ impl PolyOverZ {
}
res
}

/// Outputs the hamming weight of `self`, i.e. it returns the number of
/// non-zero coefficients in the polynomial.
///
/// # Examples
/// ```
/// use qfall_math::integer::PolyOverZ;
/// use std::str::FromStr;
///
/// let poly = PolyOverZ::from_str("5 1 2 3 0 4").unwrap();
///
/// let hamming_weight = poly.hamming_weight();
///
/// assert_eq!(4, hamming_weight);
/// ```
pub fn hamming_weight(&self) -> i64 {
let mut hamming_weight = 0;
for i in 0..=self.get_degree() {
let coeff = unsafe { self.get_coeff_unchecked(i) };
if !coeff.is_zero() {
hamming_weight += 1;
}
}
hamming_weight
}
}

#[cfg(test)]
Expand Down Expand Up @@ -139,3 +185,22 @@ mod test_norm_infty {
assert_eq!(poly_2.norm_infty(), Z::from(u64::MAX));
}
}

#[cfg(test)]
mod test_hamming_weight {
use super::PolyOverZ;
use std::str::FromStr;

/// Ensures that the hamming weight is computed correctly.
#[test]
fn hamming_weight() {
let poly0 = PolyOverZ::default();
let poly1 = PolyOverZ::from_str("6 0 0 2 3 4 5").unwrap();

let hw0 = poly0.hamming_weight();
let hw1 = poly1.hamming_weight();

assert_eq!(0, hw0);
assert_eq!(4, hw1);
}
}
54 changes: 52 additions & 2 deletions src/integer_mod_q/mat_polynomial_ring_zq/norm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

use super::MatPolynomialRingZq;
use crate::{
integer::Z,
integer::{PolyOverZ, Z},
rational::Q,
traits::{MatrixDimensions, MatrixGetSubmatrix},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
};

impl MatPolynomialRingZq {
Expand Down Expand Up @@ -96,6 +96,33 @@ impl MatPolynomialRingZq {
}
max_norm
}

/// Outputs the hamming weight of `self`, i.e. it computes the number of non-zero
/// coefficients across all polynomials in the matrix.
///
/// # Examples
/// ```
/// use qfall_math::{integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq}, integer::{Z, MatPolyOverZ}};
/// use std::str::FromStr;
///
/// let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 7").unwrap();
/// let mat = MatPolyOverZ::from_str("[[2 2 1, 2 3 0],[1 2, 0]]").unwrap();
/// let mat = MatPolynomialRingZq::from((&mat, &modulus));
///
/// let hamming_weight = mat.hamming_weight();
///
/// assert_eq!(4, hamming_weight);
/// ```
pub fn hamming_weight(&self) -> i64 {
let mut hamming_weight = 0;
for row in 0..self.get_num_rows() {
for col in 0..self.get_num_columns() {
let entry: PolyOverZ = unsafe { self.get_entry_unchecked(row, col) };
hamming_weight += entry.hamming_weight();
}
}
hamming_weight
}
}

#[cfg(test)]
Expand Down Expand Up @@ -145,3 +172,26 @@ mod test_matrix_norms {
assert_eq!(Z::from(3), infty_norm);
}
}

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

/// Ensures that the hamming weight is computed correctly.
#[test]
fn hamming_weight() {
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 8").unwrap();
let mat0 = MatPolyOverZ::new(3, 4);
let mat0 = MatPolynomialRingZq::from((&mat0, &modulus));
let mat1 = MatPolyOverZ::from_str("[[1 -2, 2 3 2],[2 2 0, 1 -5],[1 -2, 0]]").unwrap();
let mat1 = MatPolynomialRingZq::from((&mat1, &modulus));

let hw0 = mat0.hamming_weight();
let hw1 = mat1.hamming_weight();

assert_eq!(0, hw0);
assert_eq!(6, hw1);
}
}
49 changes: 48 additions & 1 deletion src/integer_mod_q/mat_zq/norm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
use super::MatZq;
use crate::{
integer::Z,
integer_mod_q::Zq,
rational::Q,
traits::{MatrixDimensions, MatrixGetSubmatrix},
traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
};

impl MatZq {
Expand Down Expand Up @@ -89,6 +90,33 @@ impl MatZq {
}
max_norm
}

/// Outputs the hamming weight of `self`, i.e. it returns the number of
/// non-zero entries in the matrix.
Comment thread
Marvin-Beckmann marked this conversation as resolved.
///
/// # Examples
/// ```
/// use qfall_math::integer_mod_q::MatZq;
/// use std::str::FromStr;
///
/// let mat = MatZq::from_str("[[2, 3],[2, 0]] mod 3").unwrap();
///
/// let hamming_weight = mat.hamming_weight();
///
/// assert_eq!(2, hamming_weight);
/// ```
pub fn hamming_weight(&self) -> i64 {
let mut hamming_weight = 0;
for row in 0..self.get_num_rows() {
for col in 0..self.get_num_columns() {
let entry: Zq = unsafe { self.get_entry_unchecked(row, col) };
if !entry.is_zero() {
hamming_weight += 1;
}
}
}
hamming_weight
}
}

#[cfg(test)]
Expand Down Expand Up @@ -126,3 +154,22 @@ mod test_matrix_norms {
assert_eq!(Z::from(3), infty_norm);
}
}

#[cfg(test)]
mod test_hamming_weight {
use super::MatZq;
use std::str::FromStr;

/// Ensures that the hamming weight is computed correctly.
#[test]
fn hamming_weight() {
let mat0 = MatZq::new(10, 8, 7);
let mat1 = MatZq::from_str("[[-2, 3],[2, -4],[-2, 0]] mod 4").unwrap();

let hw0 = mat0.hamming_weight();
let hw1 = mat1.hamming_weight();

assert_eq!(0, hw0);
assert_eq!(4, hw1);
}
}
Loading
Loading