arnaucube
arnaucube/nova-studyPublic Self-hosted repository
nova-study/src/utils.rs
src/utils.rsRaw
  1use ark_ec::AffineRepr;
  2use ark_ff::fields::PrimeField;
  3use core::ops::{Add, Sub};
  4use std::fmt;
  5
  6pub fn vector_elem_product<F: PrimeField>(a: &Vec<F>, e: &F) -> Vec<F> {
  7    // maybe move this method to operator a * e
  8    let mut r: Vec<F> = vec![F::zero(); a.len()];
  9    for i in 0..a.len() {
 10        r[i] = a[i] * e;
 11    }
 12    r
 13}
 14pub fn matrix_vector_product<F: PrimeField>(M: &Vec<Vec<F>>, z: &Vec<F>) -> Vec<F> {
 15    // TODO assert len
 16    let mut r: Vec<F> = vec![F::zero(); M.len()];
 17    for i in 0..M.len() {
 18        for j in 0..M[i].len() {
 19            r[i] += M[i][j] * z[j];
 20        }
 21    }
 22    r
 23}
 24pub fn hadamard_product<F: PrimeField>(a: Vec<F>, b: Vec<F>) -> Vec<F> {
 25    // maybe move this method to operator a * b
 26    // TODO assert equals len
 27    let mut r: Vec<F> = vec![F::zero(); a.len()];
 28    for i in 0..a.len() {
 29        r[i] = a[i] * b[i];
 30    }
 31    r
 32}
 33
 34// rlin: random linear combination
 35// pub fn rlin<F: PrimeField>(a: Vec<F>, b: Vec<F>, r: F) -> Vec<F> {
 36//     vec_add(a, vector_elem_product(&b, &r)) // WIP probably group loops
 37// }
 38
 39pub fn naive_msm<C: AffineRepr>(s: &Vec<C::ScalarField>, p: &Vec<C>) -> C {
 40    // TODO check lengths, or at least check s.len()>= p.len()
 41
 42    let mut r = p[0].mul(s[0]);
 43    for i in 1..s.len() {
 44        r = p[i].mul(s[i]);
 45    }
 46    r.into()
 47}
 48
 49pub fn vec_add<F: PrimeField>(a: &Vec<F>, b: &Vec<F>) -> Vec<F> {
 50    let mut r: Vec<F> = vec![F::zero(); a.len()];
 51    for i in 0..a.len() {
 52        r[i] = a[i] + b[i];
 53    }
 54    r
 55}
 56pub fn vec_sub<F: PrimeField>(a: Vec<F>, b: Vec<F>) -> Vec<F> {
 57    let mut r: Vec<F> = vec![F::zero(); a.len()];
 58    for i in 0..a.len() {
 59        r[i] = a[i] - b[i];
 60    }
 61    r
 62}
 63
 64// instead of vec_{add/sub} can use Ve wrapper which has '+', '-' operators
 65#[derive(Debug, Clone, PartialEq)]
 66pub struct Ve<F: PrimeField>(pub Vec<F>);
 67
 68impl<F: PrimeField> fmt::Display for Ve<F> {
 69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 70        for (i, e) in self.0.iter().enumerate() {
 71            if i == self.0.len() - 1 {
 72                write!(f, "{}", e)?;
 73                break;
 74            }
 75            write!(f, "{}, ", e)?;
 76        }
 77        Ok(())
 78    }
 79}
 80
 81impl<F: PrimeField> Add<Ve<F>> for Ve<F> {
 82    type Output = Ve<F>;
 83    fn add(self, rhs_vec: Self) -> Ve<F> {
 84        let lhs = self.0.clone();
 85        let rhs = rhs_vec.0.clone();
 86        let mut r: Vec<F> = vec![F::zero(); lhs.len()];
 87        for i in 0..self.0.len() {
 88            r[i] = lhs[i] + rhs[i];
 89        }
 90        Ve(r)
 91    }
 92}
 93impl<F: PrimeField> Sub<Ve<F>> for Ve<F> {
 94    type Output = Ve<F>;
 95    fn sub(self, rhs_vec: Self) -> Ve<F> {
 96        let lhs = self.0.clone();
 97        let rhs = rhs_vec.0.clone();
 98        let mut r: Vec<F> = vec![F::zero(); lhs.len()];
 99        for i in 0..self.0.len() {
100            r[i] = lhs[i] - rhs[i];
101        }
102        Ve(r)
103    }
104}
105
106pub fn to_F_matrix<F: PrimeField>(M: Vec<Vec<usize>>) -> Vec<Vec<F>> {
107    let mut R: Vec<Vec<F>> = vec![Vec::new(); M.len()];
108    for i in 0..M.len() {
109        R[i] = vec![F::zero(); M[i].len()];
110        for j in 0..M[i].len() {
111            R[i][j] = F::from(M[i][j] as u64);
112        }
113    }
114    R
115}
116pub fn to_F_vec<F: PrimeField>(z: Vec<usize>) -> Vec<F> {
117    let mut r: Vec<F> = vec![F::zero(); z.len()];
118    for i in 0..z.len() {
119        r[i] = F::from(z[i] as u64);
120    }
121    r
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127    use ark_bn254::{g1::G1Affine, Fr};
128    use ark_ec::CurveGroup;
129    use ark_std::{One, Zero};
130    use std::ops::Mul;
131
132    #[test]
133    fn test_matrix_vector_product() {
134        let A = to_F_matrix::<Fr>(vec![
135            vec![0, 1, 0, 0, 0, 0],
136            vec![0, 0, 0, 1, 0, 0],
137            vec![0, 1, 0, 0, 1, 0],
138            vec![5, 0, 0, 0, 0, 1],
139        ]);
140        let z = to_F_vec(vec![1, 3, 35, 9, 27, 30]);
141        let Az = matrix_vector_product(&A, &z);
142        assert_eq!(Az, to_F_vec(vec![3, 9, 30, 35]));
143    }
144
145    #[test]
146    fn test_hadamard_product() {
147        let a = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
148        let b = to_F_vec(vec![7, 8, 9, 10, 11, 12]);
149        assert_eq!(
150            hadamard_product(a, b),
151            to_F_vec(vec![7, 16, 27, 40, 55, 72])
152        );
153    }
154    #[test]
155    fn test_vec_add() {
156        let a: Vec<Fr> = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
157        let b: Vec<Fr> = to_F_vec(vec![7, 8, 9, 10, 11, 12]);
158        assert_eq!(vec_add(&a, &b), (Ve(a) + Ve(b)).0);
159    }
160
161    #[test]
162    fn test_ABC_hadamard() {
163        let A = to_F_matrix::<Fr>(vec![
164            vec![0, 1, 0, 0, 0, 0],
165            vec![0, 0, 0, 1, 0, 0],
166            vec![0, 1, 0, 0, 1, 0],
167            vec![5, 0, 0, 0, 0, 1],
168        ]);
169        let B = to_F_matrix(vec![
170            vec![0, 1, 0, 0, 0, 0],
171            vec![0, 1, 0, 0, 0, 0],
172            vec![1, 0, 0, 0, 0, 0],
173            vec![1, 0, 0, 0, 0, 0],
174        ]);
175        let C = to_F_matrix(vec![
176            vec![0, 0, 0, 1, 0, 0],
177            vec![0, 0, 0, 0, 1, 0],
178            vec![0, 0, 0, 0, 0, 1],
179            vec![0, 0, 1, 0, 0, 0],
180        ]);
181        let z = to_F_vec(vec![1, 3, 35, 9, 27, 30]);
182
183        let Az = matrix_vector_product(&A, &z);
184        let Bz = matrix_vector_product(&B, &z);
185        let Cz = matrix_vector_product(&C, &z);
186        assert_eq!(hadamard_product(Az, Bz), Cz);
187    }
188}