use ark_ec::{
pairing::Pairing, scalar_mul::fixed_base::FixedBase, AffineRepr, CurveGroup, VariableBaseMSM,
};
use ark_ff::{PrimeField, Zero};
use ark_std::{
marker::PhantomData,
ops::{AddAssign, Mul},
vec,
vec::Vec,
};
use crate::link::error::LinkError;
#[derive(Clone, Debug)]
pub struct CoeffPos<T> {
val: T,
pos: usize,
}
type Col<T> = Vec<CoeffPos<T>>;
#[derive(Clone, Debug)]
pub struct SparseMatrix<T> {
cols: Vec<Col<T>>, pub nr: usize, pub nc: usize, }
impl<T: Copy> SparseMatrix<T> {
pub fn new(nr: usize, nc: usize) -> SparseMatrix<T> {
SparseMatrix {
cols: vec![vec![]; nc],
nr,
nc,
}
}
pub fn insert_val(&mut self, r: usize, c: usize, v: T) -> Result<(), LinkError> {
if self.cols.len() < c {
return Err(LinkError::InvalidIndex(c, self.cols.len()));
}
let coeff_pos = CoeffPos { pos: r, val: v };
self.cols[c].push(coeff_pos);
Ok(())
}
pub fn insert_row_slice(
&mut self,
r: usize,
c_offset: usize,
vs: Vec<T>,
) -> Result<(), LinkError> {
for (i, x) in vs.into_iter().enumerate() {
self.insert_val(r, c_offset + i, x)?;
}
Ok(())
}
pub fn get_col(&self, c: usize) -> Result<&Col<T>, LinkError> {
if self.cols.len() < c {
return Err(LinkError::InvalidIndex(c, self.cols.len()));
}
Ok(&self.cols[c])
}
}
pub struct SparseLinAlgebra<PE: Pairing> {
pairing_engine_type: PhantomData<PE>,
}
impl<PE: Pairing> SparseLinAlgebra<PE> {
pub fn sparse_inner_product(
v: &Vec<PE::ScalarField>,
w: &Col<PE::G1Affine>,
) -> Result<PE::G1Affine, LinkError> {
let mut res = PE::G1::zero();
for coeffpos in w {
let g = coeffpos.val;
let i = coeffpos.pos;
if v.len() < i {
return Err(LinkError::InvalidIndex(i, v.len()));
}
let tmp = g.mul(v[i]);
res.add_assign(&tmp);
}
Ok(res.into_affine())
}
pub fn sparse_vector_matrix_mult(
v: &Vec<PE::ScalarField>,
m: &SparseMatrix<PE::G1Affine>,
) -> Result<Vec<PE::G1Affine>, LinkError> {
let mut res: Vec<PE::G1Affine> = Vec::with_capacity(m.nc);
for c in 0..m.nc {
res.push(Self::sparse_inner_product(&v, m.get_col(c)?)?);
}
Ok(res)
}
}
pub fn inner_product<PE: Pairing>(a: &[PE::ScalarField], b: &[PE::G1Affine]) -> PE::G1Affine {
PE::G1::msm_unchecked(b, &a).into_affine()
}
pub fn scale_vector<PE: Pairing>(
a: &PE::ScalarField,
v: &[PE::ScalarField],
) -> Vec<PE::ScalarField> {
let mut res: Vec<PE::ScalarField> = Vec::with_capacity(v.len());
for i in 0..v.len() {
let x: PE::ScalarField = a.mul(&v[i]);
res.push(x);
}
res
}
pub fn multiples_of_g<G: AffineRepr>(g: &G, multiples: &[G::ScalarField]) -> Vec<G> {
let scalar_size = G::ScalarField::MODULUS_BIT_SIZE as usize;
let window_size = FixedBase::get_mul_window_size(multiples.len());
let table = FixedBase::get_window_table(scalar_size, window_size, g.into_group());
let muls = FixedBase::msm(scalar_size, window_size, &table, multiples);
G::Group::normalize_batch(&muls)
}