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}