arnaucube
arnaucube/mat-vec-prod-expPublic Self-hosted repository
mat-vec-prod-exp/src/utils.rs
src/utils.rsRaw
  1use ark_ff::PrimeField;
  2use ark_r1cs_std::{
  3    alloc::{AllocVar, AllocationMode},
  4    fields::nonnative::NonNativeFieldVar,
  5};
  6use ark_relations::r1cs::{Matrix as R1CSMatrix, Namespace, SynthesisError};
  7use core::{borrow::Borrow, marker::PhantomData};
  8
  9pub struct SparseMatrix<F: PrimeField> {
 10    pub n_rows: usize,
 11    pub n_cols: usize,
 12    /// coeffs = R1CSMatrix = Vec<Vec<(F, usize)>>, which contains each row and the F is the value
 13    /// of the coefficient and the usize indicates the column position
 14    pub coeffs: R1CSMatrix<F>,
 15}
 16
 17#[derive(Debug, Clone)]
 18pub struct SparseMatrixVar<F: PrimeField, CF: PrimeField> {
 19    _f: PhantomData<F>,
 20    _cf: PhantomData<CF>,
 21    pub n_rows: usize,
 22    pub n_cols: usize,
 23    // same format as the native SparseMatrix (which follows ark_relations::r1cs::Matrix format
 24    pub coeffs: Vec<Vec<(NonNativeFieldVar<F, CF>, usize)>>,
 25}
 26
 27impl<F, CF> AllocVar<SparseMatrix<F>, CF> for SparseMatrixVar<F, CF>
 28where
 29    F: PrimeField,
 30    CF: PrimeField,
 31{
 32    fn new_variable<T: Borrow<SparseMatrix<F>>>(
 33        cs: impl Into<Namespace<CF>>,
 34        f: impl FnOnce() -> Result<T, SynthesisError>,
 35        mode: AllocationMode,
 36    ) -> Result<Self, SynthesisError> {
 37        f().and_then(|val| {
 38            let cs = cs.into();
 39
 40            let mut coeffs: Vec<Vec<(NonNativeFieldVar<F, CF>, usize)>> = Vec::new();
 41            for row in val.borrow().coeffs.iter() {
 42                let mut rowVar: Vec<(NonNativeFieldVar<F, CF>, usize)> = Vec::new();
 43                for &(value, col_i) in row.iter() {
 44                    let coeffVar =
 45                        NonNativeFieldVar::<F, CF>::new_variable(cs.clone(), || Ok(value), mode)?;
 46                    rowVar.push((coeffVar, col_i));
 47                }
 48                coeffs.push(rowVar);
 49            }
 50
 51            Ok(Self {
 52                _f: PhantomData,
 53                _cf: PhantomData,
 54                n_rows: val.borrow().n_rows,
 55                n_cols: val.borrow().n_cols,
 56                coeffs,
 57            })
 58        })
 59    }
 60}
 61
 62pub fn mat_vec_mul_sparse<F: PrimeField>(M: &SparseMatrix<F>, z: &[F]) -> Vec<F> {
 63    assert_eq!(M.n_cols, z.len());
 64    let mut res = vec![F::zero(); M.n_rows];
 65    for (row_i, row) in M.coeffs.iter().enumerate() {
 66        for &(value, col_i) in row.iter() {
 67            res[row_i] += value * z[col_i];
 68        }
 69    }
 70    res
 71}
 72pub fn dense_matrix_to_sparse<F: PrimeField>(m: Vec<Vec<F>>) -> SparseMatrix<F> {
 73    let mut r = SparseMatrix::<F> {
 74        n_rows: m.len(),
 75        n_cols: m[0].len(),
 76        coeffs: Vec::new(),
 77    };
 78    for m_row in m.iter() {
 79        let mut row: Vec<(F, usize)> = Vec::new();
 80        for (col_i, value) in m_row.iter().enumerate() {
 81            if !value.is_zero() {
 82                row.push((*value, col_i));
 83            }
 84        }
 85        r.coeffs.push(row);
 86    }
 87    r
 88}
 89
 90// just some helpers to define matrices and vectors by hand
 91pub fn to_F_matrix<F: PrimeField>(M: Vec<Vec<usize>>) -> SparseMatrix<F> {
 92    dense_matrix_to_sparse(to_F_dense_matrix(M))
 93}
 94pub fn to_F_dense_matrix<F: PrimeField>(M: Vec<Vec<usize>>) -> Vec<Vec<F>> {
 95    M.iter()
 96        .map(|m| m.iter().map(|r| F::from(*r as u64)).collect())
 97        .collect()
 98}
 99pub fn to_F_vec<F: PrimeField>(z: Vec<usize>) -> Vec<F> {
100    z.iter().map(|c| F::from(*c as u64)).collect()
101}