ark_bulletproofs/r1cs/
linear_combination.rs1use ark_ff::PrimeField;
4use ark_std::{
5 iter::FromIterator,
6 ops::{Add, Mul, Neg, Sub},
7 vec,
8 vec::Vec,
9};
10use core::marker::PhantomData;
11
12#[derive(Copy, Clone, Debug, PartialEq)]
14pub enum Variable<F: PrimeField> {
15 Committed(usize),
17 MultiplierLeft(usize),
19 MultiplierRight(usize),
21 MultiplierOutput(usize),
23 One(),
25 Phantom(PhantomData<F>),
27}
28
29impl<F: PrimeField> From<Variable<F>> for LinearCombination<F> {
30 fn from(v: Variable<F>) -> LinearCombination<F> {
31 LinearCombination {
32 terms: vec![(v, F::one())],
33 }
34 }
35}
36
37impl<F: PrimeField> From<F> for LinearCombination<F> {
38 fn from(s: F) -> LinearCombination<F> {
39 LinearCombination {
40 terms: vec![(Variable::One(), s)],
41 }
42 }
43}
44
45impl<F: PrimeField> Neg for Variable<F> {
48 type Output = LinearCombination<F>;
49
50 fn neg(self) -> Self::Output {
51 -LinearCombination::from(self)
52 }
53}
54
55impl<F: PrimeField, L: Into<LinearCombination<F>>> Add<L> for Variable<F> {
56 type Output = LinearCombination<F>;
57
58 fn add(self, other: L) -> Self::Output {
59 LinearCombination::from(self) + other.into()
60 }
61}
62
63impl<F: PrimeField, L: Into<LinearCombination<F>>> Sub<L> for Variable<F> {
64 type Output = LinearCombination<F>;
65
66 fn sub(self, other: L) -> Self::Output {
67 LinearCombination::from(self) - other.into()
68 }
69}
70
71impl<F: PrimeField, S: Into<F>> Mul<S> for Variable<F> {
72 type Output = LinearCombination<F>;
73
74 fn mul(self, other: S) -> Self::Output {
75 LinearCombination {
76 terms: vec![(self, other.into())],
77 }
78 }
79}
80
81#[derive(Clone, Debug, PartialEq)]
85pub struct LinearCombination<F: PrimeField> {
86 pub(super) terms: Vec<(Variable<F>, F)>,
87}
88
89impl<F: PrimeField> Default for LinearCombination<F> {
90 fn default() -> Self {
91 LinearCombination { terms: Vec::new() }
92 }
93}
94
95impl<F: PrimeField> FromIterator<(Variable<F>, F)> for LinearCombination<F> {
96 fn from_iter<T>(iter: T) -> Self
97 where
98 T: IntoIterator<Item = (Variable<F>, F)>,
99 {
100 LinearCombination {
101 terms: iter.into_iter().collect(),
102 }
103 }
104}
105
106impl<'a, F: PrimeField> FromIterator<&'a (Variable<F>, F)> for LinearCombination<F> {
107 fn from_iter<T>(iter: T) -> Self
108 where
109 T: IntoIterator<Item = &'a (Variable<F>, F)>,
110 {
111 LinearCombination {
112 terms: iter.into_iter().cloned().collect(),
113 }
114 }
115}
116
117impl<F: PrimeField, L: Into<LinearCombination<F>>> Add<L> for LinearCombination<F> {
120 type Output = Self;
121
122 fn add(mut self, rhs: L) -> Self::Output {
123 self.terms.extend(rhs.into().terms.iter().cloned());
124 LinearCombination { terms: self.terms }
125 }
126}
127
128impl<F: PrimeField, L: Into<LinearCombination<F>>> Sub<L> for LinearCombination<F> {
129 type Output = Self;
130
131 fn sub(mut self, rhs: L) -> Self::Output {
132 self.terms.extend(
133 rhs.into()
134 .terms
135 .iter()
136 .map(|(var, coeff)| (*var, coeff.neg())),
137 );
138 LinearCombination { terms: self.terms }
139 }
140}
141
142impl<F: PrimeField> Neg for LinearCombination<F> {
143 type Output = Self;
144
145 fn neg(mut self) -> Self::Output {
146 for (_, s) in self.terms.iter_mut() {
147 *s = -*s
148 }
149 self
150 }
151}
152
153impl<F: PrimeField, S: Into<F>> Mul<S> for LinearCombination<F> {
154 type Output = Self;
155
156 fn mul(mut self, other: S) -> Self::Output {
157 let other = other.into();
158 for (_, s) in self.terms.iter_mut() {
159 *s *= other
160 }
161 self
162 }
163}