arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/folding-schemes/src/utils/vec.rs
folding-schemes/src/utils/vec.rsRaw
  1use ark_ff::PrimeField;
  2use ark_poly::{
  3    univariate::DensePolynomial, EvaluationDomain, Evaluations, GeneralEvaluationDomain,
  4};
  5pub use ark_relations::r1cs::Matrix as R1CSMatrix;
  6use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
  7use ark_std::cfg_iter;
  8use ark_std::rand::Rng;
  9use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
 10
 11use crate::Error;
 12
 13#[derive(Clone, Debug, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
 14pub struct SparseMatrix<F: PrimeField> {
 15    pub n_rows: usize,
 16    pub n_cols: usize,
 17    /// coeffs = R1CSMatrix = Vec<Vec<(F, usize)>>, which contains each row and the F is the value
 18    /// of the coefficient and the usize indicates the column position
 19    pub coeffs: R1CSMatrix<F>,
 20}
 21
 22impl<F: PrimeField> SparseMatrix<F> {
 23    pub fn rand<R: Rng>(rng: &mut R, n_rows: usize, n_cols: usize) -> Self {
 24        const ZERO_VAL_PROBABILITY: f64 = 0.8f64;
 25
 26        let dense = (0..n_rows)
 27            .map(|_| {
 28                (0..n_cols)
 29                    .map(|_| {
 30                        if !rng.gen_bool(ZERO_VAL_PROBABILITY) {
 31                            return F::rand(rng);
 32                        }
 33                        F::zero()
 34                    })
 35                    .collect::<Vec<F>>()
 36            })
 37            .collect::<Vec<Vec<F>>>();
 38        dense_matrix_to_sparse(dense)
 39    }
 40    pub fn to_dense(&self) -> Vec<Vec<F>> {
 41        let mut r: Vec<Vec<F>> = vec![vec![F::zero(); self.n_cols]; self.n_rows];
 42        for (row_i, row) in self.coeffs.iter().enumerate() {
 43            for &(value, col_i) in row.iter() {
 44                r[row_i][col_i] = value;
 45            }
 46        }
 47        r
 48    }
 49}
 50
 51pub fn dense_matrix_to_sparse<F: PrimeField>(m: Vec<Vec<F>>) -> SparseMatrix<F> {
 52    let mut r = SparseMatrix::<F> {
 53        n_rows: m.len(),
 54        n_cols: m[0].len(),
 55        coeffs: Vec::new(),
 56    };
 57    for m_row in m.iter() {
 58        let mut row: Vec<(F, usize)> = Vec::new();
 59        for (col_i, value) in m_row.iter().enumerate() {
 60            if !value.is_zero() {
 61                row.push((*value, col_i));
 62            }
 63        }
 64        r.coeffs.push(row);
 65    }
 66    r
 67}
 68
 69pub fn vec_add<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
 70    if a.len() != b.len() {
 71        return Err(Error::NotSameLength(
 72            "a.len()".to_string(),
 73            a.len(),
 74            "b.len()".to_string(),
 75            b.len(),
 76        ));
 77    }
 78    Ok(a.iter().zip(b.iter()).map(|(x, y)| *x + y).collect())
 79}
 80
 81pub fn vec_sub<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
 82    if a.len() != b.len() {
 83        return Err(Error::NotSameLength(
 84            "a.len()".to_string(),
 85            a.len(),
 86            "b.len()".to_string(),
 87            b.len(),
 88        ));
 89    }
 90    Ok(a.iter().zip(b.iter()).map(|(x, y)| *x - y).collect())
 91}
 92
 93pub fn vec_scalar_mul<F: PrimeField>(vec: &[F], c: &F) -> Vec<F> {
 94    vec.iter().map(|a| *a * c).collect()
 95}
 96
 97pub fn is_zero_vec<F: PrimeField>(vec: &[F]) -> bool {
 98    vec.iter().all(|a| a.is_zero())
 99}
100
101pub fn mat_vec_mul_dense<F: PrimeField>(M: &[Vec<F>], z: &[F]) -> Result<Vec<F>, Error> {
102    if M.is_empty() {
103        return Err(Error::Empty);
104    }
105    if M[0].len() != z.len() {
106        return Err(Error::NotSameLength(
107            "M[0].len()".to_string(),
108            M[0].len(),
109            "z.len()".to_string(),
110            z.len(),
111        ));
112    }
113
114    let mut r: Vec<F> = vec![F::zero(); M.len()];
115    for (i, M_i) in M.iter().enumerate() {
116        for (j, M_ij) in M_i.iter().enumerate() {
117            r[i] += *M_ij * z[j];
118        }
119    }
120    Ok(r)
121}
122
123pub fn mat_vec_mul<F: PrimeField>(M: &SparseMatrix<F>, z: &[F]) -> Result<Vec<F>, Error> {
124    if M.n_cols != z.len() {
125        return Err(Error::NotSameLength(
126            "M.n_cols".to_string(),
127            M.n_cols,
128            "z.len()".to_string(),
129            z.len(),
130        ));
131    }
132    let mut res = vec![F::zero(); M.n_rows];
133    for (row_i, row) in M.coeffs.iter().enumerate() {
134        for &(value, col_i) in row.iter() {
135            res[row_i] += value * z[col_i];
136        }
137    }
138    Ok(res)
139}
140
141pub fn mat_from_str_mat<F: PrimeField>(str_mat: Vec<Vec<&str>>) -> Result<Vec<Vec<F>>, Error> {
142    str_mat
143        .into_iter()
144        .map(|row| {
145            row.into_iter()
146                .map(|s| {
147                    F::from_str(s).map_err(|_| Error::Other("Invalid decimal string".to_string()))
148                })
149                .collect()
150        })
151        .collect()
152}
153
154pub fn hadamard<F: PrimeField>(a: &[F], b: &[F]) -> Result<Vec<F>, Error> {
155    if a.len() != b.len() {
156        return Err(Error::NotSameLength(
157            "a.len()".to_string(),
158            a.len(),
159            "b.len()".to_string(),
160            b.len(),
161        ));
162    }
163    Ok(cfg_iter!(a).zip(b).map(|(a, b)| *a * b).collect())
164}
165
166/// returns the interpolated polynomial of degree=v.len().next_power_of_two(), which passes through all
167/// the given elements of v.
168pub fn poly_from_vec<F: PrimeField>(v: Vec<F>) -> Result<DensePolynomial<F>, Error> {
169    let D = GeneralEvaluationDomain::<F>::new(v.len()).ok_or(Error::NewDomainFail)?;
170    Ok(Evaluations::from_vec_and_domain(v, D).interpolate())
171}
172
173#[cfg(test)]
174pub mod tests {
175    use super::*;
176    use ark_pallas::Fr;
177
178    pub fn to_F_matrix<F: PrimeField>(M: Vec<Vec<usize>>) -> SparseMatrix<F> {
179        dense_matrix_to_sparse(to_F_dense_matrix(M))
180    }
181    pub fn to_F_dense_matrix<F: PrimeField>(M: Vec<Vec<usize>>) -> Vec<Vec<F>> {
182        M.iter()
183            .map(|m| m.iter().map(|r| F::from(*r as u64)).collect())
184            .collect()
185    }
186    pub fn to_F_vec<F: PrimeField>(z: Vec<usize>) -> Vec<F> {
187        z.iter().map(|c| F::from(*c as u64)).collect()
188    }
189
190    #[test]
191    fn test_dense_sparse_conversions() {
192        let A = to_F_dense_matrix::<Fr>(vec![
193            vec![0, 1, 0, 0, 0, 0],
194            vec![0, 0, 0, 1, 0, 0],
195            vec![0, 1, 0, 0, 1, 0],
196            vec![5, 0, 0, 0, 0, 1],
197        ]);
198        let A_sparse = dense_matrix_to_sparse(A.clone());
199        assert_eq!(A_sparse.to_dense(), A);
200    }
201
202    // test mat_vec_mul & mat_vec_mul_sparse
203    #[test]
204    fn test_mat_vec_mul() {
205        let A = to_F_matrix::<Fr>(vec![
206            vec![0, 1, 0, 0, 0, 0],
207            vec![0, 0, 0, 1, 0, 0],
208            vec![0, 1, 0, 0, 1, 0],
209            vec![5, 0, 0, 0, 0, 1],
210        ])
211        .to_dense();
212        let z = to_F_vec(vec![1, 3, 35, 9, 27, 30]);
213        assert_eq!(
214            mat_vec_mul_dense(&A, &z).unwrap(),
215            to_F_vec(vec![3, 9, 30, 35])
216        );
217        assert_eq!(
218            mat_vec_mul(&dense_matrix_to_sparse(A), &z).unwrap(),
219            to_F_vec(vec![3, 9, 30, 35])
220        );
221
222        let A = to_F_matrix::<Fr>(vec![vec![2, 3, 4, 5], vec![4, 8, 12, 14], vec![9, 8, 7, 6]]);
223        let v = to_F_vec(vec![19, 55, 50, 3]);
224
225        assert_eq!(
226            mat_vec_mul_dense(&A.to_dense(), &v).unwrap(),
227            to_F_vec(vec![418, 1158, 979])
228        );
229        assert_eq!(mat_vec_mul(&A, &v).unwrap(), to_F_vec(vec![418, 1158, 979]));
230    }
231
232    #[test]
233    fn test_hadamard_product() {
234        let a = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
235        let b = to_F_vec(vec![7, 8, 9, 10, 11, 12]);
236        assert_eq!(
237            hadamard(&a, &b).unwrap(),
238            to_F_vec(vec![7, 16, 27, 40, 55, 72])
239        );
240    }
241
242    #[test]
243    fn test_vec_add() {
244        let a: Vec<Fr> = to_F_vec::<Fr>(vec![1, 2, 3, 4, 5, 6]);
245        let b: Vec<Fr> = to_F_vec(vec![7, 8, 9, 10, 11, 12]);
246        assert_eq!(
247            vec_add(&a, &b).unwrap(),
248            to_F_vec(vec![8, 10, 12, 14, 16, 18])
249        );
250    }
251}