qfall_math/integer_mod_q/mat_zq/sample/
uniform.rs1use crate::{
12 integer::Z,
13 integer_mod_q::MatZq,
14 macros::seeded::seedable_function,
15 traits::{MatrixDimensions, MatrixSetEntry},
16 utils::sample::uniform::UniformIntegerSampler,
17};
18use std::fmt::Display;
19
20impl MatZq {
21 seedable_function!(
22 #[unseeded]
27 #[seeded]
29 #[optionally_seeded]
31 #[optionally_seeded]
33 #[seeded]
42 #[optionally_seeded]
44 #[optionally_seeded]
46 #[unseeded]
56 #[seeded]
58 pub(crate) fn sample_uniform(
65 num_rows: impl TryInto<i64> + Display,
66 num_cols: impl TryInto<i64> + Display,
67 modulus: impl Into<Z>,
68 seed: Option<[u8; 32]>,
69 ) -> Self {
70 let modulus: Z = modulus.into();
71 let mut uis = UniformIntegerSampler::init(&modulus, seed).unwrap();
72 let mut matrix = MatZq::new(num_rows, num_cols, modulus);
73
74 for row in 0..matrix.get_num_rows() {
75 for col in 0..matrix.get_num_columns() {
76 let sample = uis.sample();
77 unsafe { matrix.set_entry_unchecked(row, col, sample) };
78 }
79 }
80
81 matrix
82 }
83 );
84}
85
86#[cfg(test)]
87mod test_sample_uniform {
88 use crate::traits::{MatrixDimensions, MatrixGetEntry};
89 use crate::utils::sample::test_seed;
90 use crate::{
91 integer::Z,
92 integer_mod_q::{MatZq, Modulus},
93 };
94
95 #[test]
97 fn boundaries_kept_small() {
98 for seeded in [false, true] {
99 for _ in 0..32 {
100 let matrix =
101 MatZq::sample_uniform_optionally_seeded(1, 1, 17, seeded.then(test_seed));
102 let sample: Z = matrix.get_entry(0, 0).unwrap();
103 assert!(Z::ZERO <= sample);
104 assert!(sample < 17);
105 }
106 }
107 }
108
109 #[test]
111 fn boundaries_kept_large() {
112 for seeded in [false, true] {
113 let modulus = Z::from(u64::MAX);
114 for _ in 0..256 {
115 let matrix =
116 MatZq::sample_uniform_optionally_seeded(1, 1, &modulus, seeded.then(test_seed));
117 let sample: Z = matrix.get_entry(0, 0).unwrap();
118 assert!(Z::ZERO <= sample);
119 assert!(sample < modulus);
120 }
121 }
122 }
123
124 #[test]
127 fn false_size() {
128 for seeded in [false, true] {
129 let result = std::panic::catch_unwind(|| {
130 let modulus = Z::from(15);
131
132 let _ =
133 MatZq::sample_uniform_optionally_seeded(0, 3, &modulus, seeded.then(test_seed));
134 });
135 assert!(result.is_err());
136 }
137 }
138
139 #[test]
141 fn invalid_modulus() {
142 for seeded in [false, true] {
143 let result = std::panic::catch_unwind(|| {
144 let _ = MatZq::sample_uniform_optionally_seeded(4, 1, 1, seeded.then(test_seed));
145 });
146 assert!(result.is_err());
147 }
148 }
149
150 #[test]
153 fn availability() {
154 for seeded in [false, true] {
155 let modulus = Modulus::from(7);
156 let z = Z::from(7);
157
158 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7u8, seeded.then(test_seed));
159 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7u16, seeded.then(test_seed));
160 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7u32, seeded.then(test_seed));
161 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7u64, seeded.then(test_seed));
162 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7i8, seeded.then(test_seed));
163 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7i16, seeded.then(test_seed));
164 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7i32, seeded.then(test_seed));
165 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, 7i64, seeded.then(test_seed));
166 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, &modulus, seeded.then(test_seed));
167 let _ = MatZq::sample_uniform_optionally_seeded(1, 1, &z, seeded.then(test_seed));
168
169 if seeded {
171 let _ = MatZq::sample_uniform_seeded(1, 1, 7u8, test_seed());
172 } else {
173 let _ = MatZq::sample_uniform(1, 1, 7u8);
174 }
175 }
176 }
177
178 #[test]
181 fn matrix_size() {
182 for seeded in [false, true] {
183 let modulus = Z::from(15);
184
185 let mat_0 =
186 MatZq::sample_uniform_optionally_seeded(3, 3, &modulus, seeded.then(test_seed));
187 let mat_1 =
188 MatZq::sample_uniform_optionally_seeded(4, 1, &modulus, seeded.then(test_seed));
189 let mat_2 =
190 MatZq::sample_uniform_optionally_seeded(1, 5, &modulus, seeded.then(test_seed));
191 let mat_3 =
192 MatZq::sample_uniform_optionally_seeded(15, 20, &modulus, seeded.then(test_seed));
193
194 assert_eq!(3, mat_0.get_num_rows());
195 assert_eq!(3, mat_0.get_num_columns());
196 assert_eq!(4, mat_1.get_num_rows());
197 assert_eq!(1, mat_1.get_num_columns());
198 assert_eq!(1, mat_2.get_num_rows());
199 assert_eq!(5, mat_2.get_num_columns());
200 assert_eq!(15, mat_3.get_num_rows());
201 assert_eq!(20, mat_3.get_num_columns());
202 }
203 }
204
205 #[test]
207 fn same_seed_same_sample() {
208 use crate::integer_mod_q::MatZq;
209 let sample_0 = MatZq::sample_uniform_seeded(3, 3, 17, [42; 32]);
210 let sample_1 = MatZq::sample_uniform_seeded(3, 3, 17, [42; 32]);
211
212 assert_eq!(sample_0, sample_1);
213 }
214
215 #[test]
217 fn known_answer() {
218 use crate::integer_mod_q::MatZq;
219 let sample = MatZq::sample_uniform_seeded(3, 3, 17, [42; 32]);
220
221 assert_eq!(
222 "[[2, 16, 3],[7, 7, 16],[4, 13, 0]] mod 17",
223 sample.to_string()
224 );
225 }
226}