qfall_math/integer_mod_q/mat_ntt_polynomial_ring_zq.rs
1// Copyright © 2025 Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! [`MatNTTPolynomialRingZq`] containts the NTT representations of matrices over polynomials.
10
11use crate::{integer::Z, integer_mod_q::ModulusPolynomialRingZq};
12use derive_more::Display;
13use serde::{Deserialize, Serialize};
14use std::fmt;
15
16mod arithmetic;
17mod cmp;
18mod from;
19mod get;
20mod sample;
21
22/// [`MatNTTPolynomialRingZq`] contains the NTT representation of a matrix over polynomials with respect to
23/// a [`NTTBasisPolynomialRingZq`](super::NTTBasisPolynomialRingZq) that itself isn't aware of.
24///
25/// Any polynomial in NTT representation in row `i` and column `j` can be accessed via `matrix[j * nr_columns + i]`.
26///
27/// Attributes
28/// - `matrix`: holds the matrix entries with its coefficients
29/// - `nr_rows`: the number of rows of the matrix
30/// - `nr_columns`: the number of columns of the matrix
31/// - `modulus`: the [`ModulusPolynomialRingZq`] defining the modulus `q`, the ring `Z_q[X]/f(X)`, and
32/// the NTT transform [`NTTBasisPolynomialRingZq`](crate::integer_mod_q::NTTBasisPolynomialRingZq)
33///
34/// # Examples
35/// ```
36/// use qfall_math::integer_mod_q::{Modulus, MatPolynomialRingZq, MatNTTPolynomialRingZq, ModulusPolynomialRingZq};
37/// use std::str::FromStr;
38///
39/// // setup modulus with ability to transform to NTT
40/// let mut modulus = ModulusPolynomialRingZq::from_str("5 1 0 0 0 1 mod 257").unwrap();
41/// modulus.set_ntt_unchecked(64);
42///
43/// // sample random matrix
44/// let mat_rnd = MatNTTPolynomialRingZq::sample_uniform(2, 2, &modulus);
45/// // or instantiate matrix from MatPolynomialRingZq
46/// let mat_poly_ring = MatPolynomialRingZq::identity(2, 2, &modulus);
47/// let mat_ntt_poly_ring = MatNTTPolynomialRingZq::from(&mat_poly_ring);
48///
49/// // multiply, add and subtract objects
50/// let mut tmp_mat_ntt = mat_ntt_poly_ring * &mat_rnd;
51/// tmp_mat_ntt += &mat_rnd;
52/// tmp_mat_ntt -= &mat_rnd;
53///
54/// // Return to MatPolynomialRingZq
55/// let res = tmp_mat_ntt.inv_ntt();
56/// ```
57#[derive(PartialEq, Eq, Serialize, Deserialize, Display, Clone)]
58#[display("{} / {}", print_vec_z(&self.matrix), self.modulus)]
59pub struct MatNTTPolynomialRingZq {
60 pub matrix: Vec<Z>,
61 pub nr_rows: usize,
62 pub nr_columns: usize,
63 pub modulus: ModulusPolynomialRingZq,
64}
65
66impl fmt::Debug for MatNTTPolynomialRingZq {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 let short_print = print_vec_z(&self.matrix);
69 let a: Vec<&str> = short_print.split_whitespace().collect();
70 let short_print = format!("{}{} ..., {}{}", a[0], a[1], a[a.len() - 2], a[a.len() - 1]);
71
72 write!(
73 f,
74 "MatNTTPolynomialRingZq {{matrix: {}, nr_rows: {}, nr_columns: {}, modulus: {}, storage: {{matrix: {:?}, modulus: {:?}}}}}",
75 short_print, self.nr_rows, self.nr_columns, self.modulus, self.matrix, self.modulus
76 )
77 }
78}
79
80/// Quick solution to print a vector of [`Z`] values in the format `[1, 2, 3, 4, 5]`.
81pub(crate) fn print_vec_z(vector: &Vec<Z>) -> String {
82 let mut out = String::new();
83 for v in vector {
84 out.push_str(&format!("{}, ", v));
85 }
86 // Remove last whitespace and comma
87 out.pop().unwrap();
88 out.pop().unwrap();
89 format!("[{out}]")
90}