sonobe_primitives/algebra/ops/
matrix.rs1use ark_ff::PrimeField;
5use ark_r1cs_std::{
6 GR1CSVar,
7 alloc::{AllocVar, AllocationMode},
8 fields::{FieldVar, fp::FpVar},
9};
10use ark_relations::gr1cs::{Matrix, Namespace, SynthesisError};
11use ark_std::{borrow::Borrow, ops::Index};
12
13pub trait MatrixGadget<FV> {
15 fn mul_vector(&self, v: &impl Index<usize, Output = FV>) -> Result<Vec<FV>, SynthesisError>;
18}
19
20#[derive(Debug, Clone)]
25pub struct SparseMatrixVar<FV>(pub Vec<Vec<(FV, usize)>>);
26
27impl<F: PrimeField, CF: PrimeField, FV: AllocVar<F, CF>> AllocVar<Matrix<F>, CF>
28 for SparseMatrixVar<FV>
29{
30 fn new_variable<T: Borrow<Matrix<F>>>(
31 cs: impl Into<Namespace<CF>>,
32 f: impl FnOnce() -> Result<T, SynthesisError>,
33 mode: AllocationMode,
34 ) -> Result<Self, SynthesisError> {
35 f().and_then(|val| {
36 let cs = cs.into();
37
38 let mut coeffs: Vec<Vec<(FV, usize)>> = Vec::new();
39 for row in val.borrow().iter() {
40 coeffs.push(
41 row.iter()
42 .map(|&(value, col)| {
43 Ok((FV::new_variable(cs.clone(), || Ok(value), mode)?, col))
44 })
45 .collect::<Result<Vec<_>, _>>()?,
46 );
47 }
48
49 Ok(Self(coeffs))
50 })
51 }
52}
53
54impl<F: PrimeField> MatrixGadget<FpVar<F>> for SparseMatrixVar<FpVar<F>> {
55 fn mul_vector(
56 &self,
57 v: &impl Index<usize, Output = FpVar<F>>,
58 ) -> Result<Vec<FpVar<F>>, SynthesisError> {
59 Ok(self
60 .0
61 .iter()
62 .map(|row| {
63 let products = row
73 .iter()
74 .map(|(value, col_i)| value * &v[*col_i])
75 .collect::<Vec<_>>();
76 if products.is_constant() {
77 FpVar::constant(products.value().unwrap_or_default().into_iter().sum())
78 } else {
79 products.iter().sum()
80 }
81 })
82 .collect())
83 }
84}