labrador/ring/
rq_vector.rs

1use 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/// Vector of polynomials in Rq
9#[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    /// Create a zero vector
20    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    /// Create a random vector
35    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    /// Create a random vector
42    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    /// Function to concatenate coefficients from multiple Rq into a Vec<Zq>
49    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        // Iterate over each Rq, extracting the coefficients and concatenating them
53        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    /// Get the underlying vector as slice
68    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    // Compute the squared norm of a vector of polynomials
77    pub fn compute_norm_squared(&self) -> Zq {
78        self.elements
79            .iter()
80            .flat_map(|poly| poly.get_coefficients()) // Collect coefficients from all polynomials
81            .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    // add two poly vectors
103    fn add(self, other: &RqVector) -> RqVector {
104        self.iter().zip(other.iter()).map(|(a, b)| a + b).collect()
105    }
106}
107
108// Enable array-like indexing
109impl 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
123/// Create a new vector from a `Vec` of elements
124impl 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    // A poly vector multiple by a PolyRing
143    fn mul(self, other: &Rq) -> RqVector {
144        self.iter().map(|s| s * other).collect()
145    }
146}
147
148// Dot product between two vectors
149impl 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 the square of the norm
214    #[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}