qfall_math/integer/mat_z/sample/
uniform.rs1use crate::{
12 error::MathError,
13 integer::{MatZ, Z},
14 traits::{MatrixDimensions, MatrixSetEntry},
15 utils::sample::uniform::UniformIntegerSampler,
16};
17use std::fmt::Display;
18
19impl MatZ {
20 pub fn sample_uniform(
54 num_rows: impl TryInto<i64> + Display,
55 num_cols: impl TryInto<i64> + Display,
56 lower_bound: impl Into<Z>,
57 upper_bound: impl Into<Z>,
58 ) -> Result<Self, MathError> {
59 let lower_bound: Z = lower_bound.into();
60 let upper_bound: Z = upper_bound.into();
61 let mut matrix = MatZ::new(num_rows, num_cols);
62
63 let interval_size = &upper_bound - &lower_bound;
64 let mut uis = UniformIntegerSampler::init(&interval_size)?;
65 for row in 0..matrix.get_num_rows() {
66 for col in 0..matrix.get_num_columns() {
67 let sample = uis.sample();
68 unsafe { matrix.set_entry_unchecked(row, col, &lower_bound + sample) };
69 }
70 }
71
72 Ok(matrix)
73 }
74}
75
76#[cfg(test)]
77mod test_sample_uniform {
78 use crate::traits::{MatrixDimensions, MatrixGetEntry};
79 use crate::{
80 integer::{MatZ, Z},
81 integer_mod_q::Modulus,
82 };
83
84 #[test]
86 fn boundaries_kept_small() {
87 let lower_bound = Z::from(17);
88 let upper_bound = Z::from(32);
89 for _ in 0..32 {
90 let matrix = MatZ::sample_uniform(1, 1, &lower_bound, &upper_bound).unwrap();
91 let sample = matrix.get_entry(0, 0).unwrap();
92 assert!(lower_bound <= sample);
93 assert!(sample < upper_bound);
94 }
95 }
96
97 #[test]
99 fn boundaries_kept_large() {
100 let lower_bound = Z::from(i64::MIN) - Z::from(u64::MAX);
101 let upper_bound = Z::from(i64::MIN);
102 for _ in 0..256 {
103 let matrix = MatZ::sample_uniform(1, 1, &lower_bound, &upper_bound).unwrap();
104 let sample = matrix.get_entry(0, 0).unwrap();
105 assert!(lower_bound <= sample);
106 assert!(sample < upper_bound);
107 }
108 }
109
110 #[should_panic]
113 #[test]
114 fn false_size() {
115 let lower_bound = Z::from(-15);
116 let upper_bound = Z::from(15);
117
118 let _ = MatZ::sample_uniform(0, 3, &lower_bound, &upper_bound);
119 }
120
121 #[test]
123 fn invalid_interval() {
124 let lb_0 = Z::from(i64::MIN);
125 let lb_1 = Z::from(i64::MIN);
126 let lb_2 = Z::ZERO;
127 let upper_bound = Z::from(i64::MIN);
128
129 let mat_0 = MatZ::sample_uniform(3, 3, &lb_0, &upper_bound);
130 let mat_1 = MatZ::sample_uniform(4, 1, &lb_1, &upper_bound);
131 let mat_2 = MatZ::sample_uniform(1, 5, &lb_2, &upper_bound);
132
133 assert!(mat_0.is_err());
134 assert!(mat_1.is_err());
135 assert!(mat_2.is_err());
136 }
137
138 #[test]
141 fn availability() {
142 let modulus = Modulus::from(7);
143 let z = Z::from(7);
144
145 let _ = MatZ::sample_uniform(1, 1, 0u16, 7u8);
146 let _ = MatZ::sample_uniform(1, 1, 0u32, 7u16);
147 let _ = MatZ::sample_uniform(1, 1, 0u64, 7u32);
148 let _ = MatZ::sample_uniform(1, 1, 0i8, 7u64);
149 let _ = MatZ::sample_uniform(1, 1, 0i16, 7i8);
150 let _ = MatZ::sample_uniform(1, 1, 0i32, 7i16);
151 let _ = MatZ::sample_uniform(1, 1, 0i64, 7i32);
152 let _ = MatZ::sample_uniform(1, 1, &Z::ZERO, 7i64);
153 let _ = MatZ::sample_uniform(1, 1, 0u8, &modulus);
154 let _ = MatZ::sample_uniform(1, 1, 0, &z);
155 }
156
157 #[test]
160 fn matrix_size() {
161 let lower_bound = Z::from(-15);
162 let upper_bound = Z::from(15);
163
164 let mat_0 = MatZ::sample_uniform(3, 3, &lower_bound, &upper_bound).unwrap();
165 let mat_1 = MatZ::sample_uniform(4, 1, &lower_bound, &upper_bound).unwrap();
166 let mat_2 = MatZ::sample_uniform(1, 5, &lower_bound, &upper_bound).unwrap();
167 let mat_3 = MatZ::sample_uniform(15, 20, &lower_bound, &upper_bound).unwrap();
168
169 assert_eq!(3, mat_0.get_num_rows());
170 assert_eq!(3, mat_0.get_num_columns());
171 assert_eq!(4, mat_1.get_num_rows());
172 assert_eq!(1, mat_1.get_num_columns());
173 assert_eq!(1, mat_2.get_num_rows());
174 assert_eq!(5, mat_2.get_num_columns());
175 assert_eq!(15, mat_3.get_num_rows());
176 assert_eq!(20, mat_3.get_num_columns());
177 }
178}