qfall_math/integer_mod_q/mat_ntt_polynomial_ring_zq/
get.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//! Implementations to get information about a [`MatNTTPolynomialRingZq`] matrix.
10
11use crate::{
12    integer::Z,
13    integer_mod_q::{MatNTTPolynomialRingZq, ModulusPolynomialRingZq},
14    traits::MatrixDimensions,
15};
16
17impl MatrixDimensions for MatNTTPolynomialRingZq {
18    /// Returns the number of rows of the matrix as an [`i64`].
19    ///
20    /// # Examples
21    /// ```
22    /// use qfall_math::{integer_mod_q::{MatNTTPolynomialRingZq, ModulusPolynomialRingZq}, traits::MatrixDimensions};
23    /// use std::str::FromStr;
24    /// let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
25    /// modulus.set_ntt_unchecked(64);
26    ///
27    /// let matrix = MatNTTPolynomialRingZq::sample_uniform(3, 2, &modulus);
28    /// let nr_rows = matrix.get_num_rows();
29    /// ```
30    fn get_num_rows(&self) -> i64 {
31        self.nr_rows as i64
32    }
33
34    /// Returns the number of columns of the matrix as an [`i64`].
35    ///
36    /// # Examples
37    /// ```
38    /// use qfall_math::{integer_mod_q::{MatNTTPolynomialRingZq, ModulusPolynomialRingZq}, traits::MatrixDimensions};
39    /// use std::str::FromStr;
40    /// let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
41    /// modulus.set_ntt_unchecked(64);
42    ///
43    /// let matrix = MatNTTPolynomialRingZq::sample_uniform(3, 2, &modulus);
44    /// let nr_columns = matrix.get_num_columns();
45    /// ```
46    fn get_num_columns(&self) -> i64 {
47        self.nr_columns as i64
48    }
49}
50
51impl MatNTTPolynomialRingZq {
52    /// Returns the modulus of the matrix in NTT representation as a [`ModulusPolynomialRingZq`].
53    ///
54    /// # Examples
55    /// ```
56    /// use qfall_math::integer_mod_q::{MatNTTPolynomialRingZq, ModulusPolynomialRingZq};
57    /// use std::str::FromStr;
58    ///
59    /// let modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 17").unwrap();
60    /// let matrix = MatNTTPolynomialRingZq::sample_uniform(2, 2, &modulus);
61    ///
62    /// let modulus = matrix.get_mod();
63    /// ```
64    pub fn get_mod(&self) -> ModulusPolynomialRingZq {
65        self.modulus.clone()
66    }
67
68    /// Returns the slice of `matrix` corresponding to the entry in row `row` and column `column`.
69    ///
70    /// Parameters:
71    /// - `row`: defines the row where the entry to fetch is located
72    /// - `column`: defines the column where the entry to fetch is located
73    ///
74    /// Returns a slice `&[Z]` containing the requested entry.
75    ///
76    /// # Examples
77    /// ```
78    /// use qfall_math::integer_mod_q::{MatNTTPolynomialRingZq, ModulusPolynomialRingZq};
79    /// use std::str::FromStr;
80    /// let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
81    /// modulus.set_ntt_unchecked(64);
82    ///
83    /// let matrix = MatNTTPolynomialRingZq::sample_uniform(2, 2, &modulus);
84    /// let entry = matrix.get_entry(0, 0);
85    ///
86    /// assert_eq!(4, entry.len());
87    /// ```
88    ///
89    /// # Panics ...
90    /// - if `row >= self.get_num_rows()` or `column >= self.get_num_columns()`.
91    pub fn get_entry(&self, row: usize, column: usize) -> &[Z] {
92        assert!(
93            row < self.nr_rows,
94            "`row` needs to be smaller than `nr_rows`."
95        );
96        assert!(
97            column < self.nr_columns,
98            "`column` needs to be smaller than `nr_columns`."
99        );
100
101        let index = self.modulus.get_degree() as usize * row
102            + self.modulus.get_degree() as usize * self.nr_rows * column;
103        &self.matrix[index..index + self.modulus.get_degree() as usize]
104    }
105}
106
107#[cfg(test)]
108mod test_matrix_dimensions {
109    use crate::{
110        integer::{MatPolyOverZ, Z},
111        integer_mod_q::{MatNTTPolynomialRingZq, MatPolynomialRingZq, ModulusPolynomialRingZq},
112        traits::MatrixDimensions,
113    };
114    use std::str::FromStr;
115
116    /// Ensures that the correct number of rows is returned.
117    #[test]
118    fn nr_rows() {
119        let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
120        modulus.set_ntt_unchecked(64);
121
122        let matrix = MatNTTPolynomialRingZq::sample_uniform(17, 2, &modulus);
123        let nr_rows = matrix.get_num_rows();
124
125        assert_eq!(17, nr_rows);
126    }
127
128    /// Ensures that the correct number of columns is returned.
129    #[test]
130    fn nr_columns() {
131        let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
132        modulus.set_ntt_unchecked(64);
133
134        let matrix = MatNTTPolynomialRingZq::sample_uniform(2, 13, &modulus);
135        let nr_columns = matrix.get_num_columns();
136
137        assert_eq!(13, nr_columns);
138    }
139
140    /// Ensures that the correct entries are returned.
141    #[test]
142    fn get_entry() {
143        let mut modulus = ModulusPolynomialRingZq::from_str("5  1 0 0 0 1 mod 257").unwrap();
144        modulus.set_ntt_unchecked(64);
145        let mat_poly = MatPolyOverZ::from_str("[[4  15 17 19 21],[4  1 2 3 4]]").unwrap();
146        let matrix = MatPolynomialRingZq::from((&mat_poly, &modulus));
147
148        let ntt_matrix = MatNTTPolynomialRingZq::from(&matrix);
149
150        assert_eq!(
151            [Z::from(112), Z::from(189), Z::from(81), Z::from(192)],
152            ntt_matrix.get_entry(0, 0)
153        );
154        assert_eq!(
155            [Z::from(97), Z::from(56), Z::from(66), Z::from(42)],
156            ntt_matrix.get_entry(1, 0)
157        );
158    }
159}