labrador/ring/
rq_vector.rs1use crate::ring::rq::Rq;
2use crate::ring::zq::Zq;
3use core::ops::{Index, IndexMut, Mul};
4use core::slice::Iter;
5use rand::{CryptoRng, Rng};
6use std::ops::Add;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct RqVector {
11 elements: Vec<Rq>,
12}
13
14impl RqVector {
15 pub fn new(elements: Vec<Rq>) -> Self {
16 Self { elements }
17 }
18
19 pub fn zero(length: usize) -> Self {
21 Self {
22 elements: vec![Rq::zero(); length],
23 }
24 }
25
26 pub fn get_length(&self) -> usize {
27 self.elements.len()
28 }
29
30 pub fn get_elements(&self) -> &Vec<Rq> {
31 &self.elements
32 }
33
34 pub fn random<R: Rng + CryptoRng>(rng: &mut R, length: usize) -> Self {
36 Self {
37 elements: (0..length).map(|_| Rq::random(rng)).collect(),
38 }
39 }
40
41 pub fn random_ternary<R: Rng + CryptoRng>(rng: &mut R, length: usize) -> Self {
43 Self {
44 elements: (0..length).map(|_| Rq::random_ternary(rng)).collect(),
45 }
46 }
47
48 pub fn concatenate_coefficients(&self) -> Vec<Zq> {
50 let total_coeffs = self.elements.len() * Rq::DEGREE;
51 let mut concatenated_coeffs: Vec<Zq> = Vec::with_capacity(total_coeffs);
52 for rq in &self.elements {
54 let coeffs = rq.get_coefficients();
55 concatenated_coeffs.extend_from_slice(coeffs);
56 }
57 concatenated_coeffs
58 }
59
60 pub fn inner_product_poly_vector(&self, other: &RqVector) -> Rq {
61 self.iter()
62 .zip(other.iter())
63 .map(|(a, b)| a.multiplication(b))
64 .fold(Rq::zero(), |acc, val| acc + val)
65 }
66
67 pub fn as_slice(&self) -> &[Rq] {
69 &self.elements
70 }
71
72 pub fn iter(&self) -> Iter<'_, Rq> {
73 self.elements.iter()
74 }
75
76 pub fn compute_norm_squared(&self) -> Zq {
78 self.elements
79 .iter()
80 .flat_map(|poly| poly.get_coefficients()) .map(|coeff| *coeff * *coeff)
82 .sum()
83 }
84
85 pub fn decompose(&self, b: Zq, parts: usize) -> Vec<RqVector> {
86 self.iter().map(|i| Rq::decompose(i, b, parts)).collect()
87 }
88}
89
90impl FromIterator<Rq> for RqVector {
91 fn from_iter<T: IntoIterator<Item = Rq>>(iter: T) -> Self {
92 let mut elements = Vec::new();
93 for item in iter {
94 elements.push(item);
95 }
96 RqVector::new(elements)
97 }
98}
99
100impl Add<&RqVector> for &RqVector {
101 type Output = RqVector;
102 fn add(self, other: &RqVector) -> RqVector {
104 self.iter().zip(other.iter()).map(|(a, b)| a + b).collect()
105 }
106}
107
108impl Index<usize> for RqVector {
110 type Output = Rq;
111
112 fn index(&self, index: usize) -> &Self::Output {
113 &self.elements[index]
114 }
115}
116
117impl IndexMut<usize> for RqVector {
118 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
119 &mut self.elements[index]
120 }
121}
122
123impl From<Vec<Rq>> for RqVector {
125 fn from(elements: Vec<Rq>) -> Self {
126 Self { elements }
127 }
128}
129
130impl Mul<&Vec<RqVector>> for &RqVector {
131 type Output = RqVector;
132 fn mul(self, other: &Vec<RqVector>) -> RqVector {
133 other
134 .iter()
135 .map(|o| o.inner_product_poly_vector(self))
136 .collect()
137 }
138}
139
140impl Mul<&Rq> for &RqVector {
141 type Output = RqVector;
142 fn mul(self, other: &Rq) -> RqVector {
144 self.iter().map(|s| s * other).collect()
145 }
146}
147
148impl Mul for &RqVector {
150 type Output = Rq;
151
152 fn mul(self, rhs: Self) -> Self::Output {
153 self.elements
154 .iter()
155 .zip(rhs.elements.iter())
156 .map(|(a, b)| a * b)
157 .fold(Rq::zero(), |acc, x| acc + x)
158 }
159}
160
161#[cfg(test)]
162mod tests {
163
164 use super::*;
165
166 #[test]
167 fn test_rqvector_mul() {
168 let poly1: Rq = vec![Zq::ONE, Zq::new(2)].into();
169 let poly2: Rq = vec![Zq::ONE, Zq::new(4)].into();
170 let vec_1: RqVector = RqVector::from(vec![poly1]);
171 let vec_2: RqVector = RqVector::from(vec![poly2]);
172 let result = vec_1.mul(&vec_2);
173 let poly_exp: Rq = vec![Zq::new(1), Zq::new(6), Zq::new(8)].into();
174 assert_eq!(result, poly_exp);
175
176 let poly3: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
177 let poly4: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
178 let vec_3: RqVector = RqVector::from(vec![poly3]);
179 let vec_4: RqVector = RqVector::from(vec![poly4]);
180 let result_1 = vec_3.mul(&vec_4);
181 let poly_exp_1: Rq = vec![
182 Zq::new(1),
183 Zq::new(2),
184 Zq::new(3),
185 Zq::new(4),
186 Zq::new(3),
187 Zq::new(2),
188 Zq::new(1),
189 ]
190 .into();
191 assert_eq!(result_1, poly_exp_1);
192
193 let poly5: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
194 let poly6: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
195 let poly7: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
196 let poly8: Rq = vec![Zq::ONE, Zq::ONE, Zq::ONE, Zq::ONE].into();
197 let vec_5: RqVector = RqVector::from(vec![poly5, poly6]);
198 let vec_6: RqVector = RqVector::from(vec![poly7, poly8]);
199 let result_2 = vec_5.mul(&vec_6);
200 let poly_exp_2: Rq = vec![
201 Zq::new(2),
202 Zq::new(4),
203 Zq::new(6),
204 Zq::new(8),
205 Zq::new(6),
206 Zq::new(4),
207 Zq::new(2),
208 ]
209 .into();
210 assert_eq!(result_2, poly_exp_2);
211 }
212
213 #[test]
215 fn test_norm() {
216 let poly: RqVector = vec![
217 vec![Zq::ONE, Zq::ZERO, Zq::new(5), Zq::MAX].into(),
218 vec![Zq::ZERO, Zq::ZERO, Zq::new(5), Zq::ONE].into(),
219 ]
220 .into();
221 let result = Zq::new(53);
222 assert!(poly.compute_norm_squared() == result);
223
224 let poly2: RqVector = vec![vec![Zq::new(5), Zq::ONE, Zq::MAX, Zq::ZERO].into()].into();
225 let result2 = Zq::new(27);
226 assert!(poly2.compute_norm_squared() == result2);
227
228 let poly_zero: RqVector = RqVector::zero(4);
229 let result_zero = Zq::ZERO;
230 assert!(poly_zero.compute_norm_squared() == result_zero);
231 }
232}