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