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