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