Skip to main content

sonobe_primitives/algebra/ops/
vector.rs

1//! This module provides definitions and implementations of in-circuit vector
2//! operations.
3
4use ark_relations::gr1cs::SynthesisError;
5use ark_std::ops::{Add, Mul, Sub};
6
7/// [`VectorGadget`] defines operations on in-circuit vector variables.
8pub trait VectorGadget<FV> {
9    /// [`VectorGadget::add`] computes the element-wise sum of two vectors.
10    fn add(&self, other: &Self) -> Result<Vec<FV>, SynthesisError>;
11
12    /// [`VectorGadget::sub`] computes the element-wise difference of two
13    /// vectors.
14    fn sub(&self, other: &Self) -> Result<Vec<FV>, SynthesisError>;
15
16    /// [`VectorGadget::scale`] multiplies every element by a scalar.
17    fn scale<Scalar, Output>(&self, scalar: &Scalar) -> Result<Vec<Output>, SynthesisError>
18    where
19        for<'a> &'a Scalar: Mul<&'a FV, Output = Output>;
20
21    /// [`VectorGadget::hadamard`] computes the element-wise (Hadamard) product
22    /// of two vectors.
23    fn hadamard(&self, other: &Self) -> Result<Vec<FV>, SynthesisError>;
24}
25
26impl<FV> VectorGadget<FV> for [FV]
27where
28    for<'a> &'a FV: Add<&'a FV, Output = FV> + Sub<&'a FV, Output = FV> + Mul<&'a FV, Output = FV>,
29{
30    fn add(&self, other: &Self) -> Result<Vec<FV>, SynthesisError> {
31        if self.len() != other.len() {
32            return Err(SynthesisError::Unsatisfiable);
33        }
34        Ok(self.iter().zip(other.iter()).map(|(a, b)| a + b).collect())
35    }
36
37    fn sub(&self, other: &Self) -> Result<Vec<FV>, SynthesisError> {
38        if self.len() != other.len() {
39            return Err(SynthesisError::Unsatisfiable);
40        }
41        Ok(self.iter().zip(other.iter()).map(|(a, b)| a - b).collect())
42    }
43
44    fn scale<Scalar, Output>(&self, scalar: &Scalar) -> Result<Vec<Output>, SynthesisError>
45    where
46        for<'a> &'a Scalar: Mul<&'a FV, Output = Output>,
47    {
48        Ok(self.iter().map(|a| scalar * a).collect())
49    }
50
51    fn hadamard(&self, other: &Self) -> Result<Vec<FV>, SynthesisError> {
52        if self.len() != other.len() {
53            return Err(SynthesisError::Unsatisfiable);
54        }
55        Ok(self.iter().zip(other.iter()).map(|(a, b)| a * b).collect())
56    }
57}