11//! Definition of linear combinations.
22
33use curve25519_dalek:: scalar:: Scalar ;
4- use std:: iter:: { self , FromIterator } ;
5- use std:: ops:: { Add , Sub } ;
4+ use std:: iter:: FromIterator ;
5+ use std:: ops:: { Add , Mul , Neg , Sub } ;
66
77/// Represents a variable in a constraint system.
88#[ derive( Copy , Clone , Debug ) ]
@@ -19,62 +19,86 @@ pub enum Variable {
1919 One ( ) ,
2020}
2121
22- impl Add < Variable > for Variable {
23- type Output = LinearCombination ;
22+ impl From < Variable > for LinearCombination {
23+ fn from ( v : Variable ) -> LinearCombination {
24+ LinearCombination {
25+ terms : vec ! [ ( v, Scalar :: one( ) ) ] ,
26+ }
27+ }
28+ }
2429
25- fn add ( self , other : Variable ) -> LinearCombination {
30+ impl < S : Into < Scalar > > From < S > for LinearCombination {
31+ fn from ( s : S ) -> LinearCombination {
2632 LinearCombination {
27- terms : vec ! [ ( self , Scalar :: one ( ) ) , ( other , Scalar :: one ( ) ) ] ,
33+ terms : vec ! [ ( Variable :: One ( ) , s . into ( ) ) ] ,
2834 }
2935 }
3036}
3137
32- impl Sub < Variable > for Variable {
38+ // Arithmetic on variables produces linear combinations
39+
40+ impl Neg for Variable {
3341 type Output = LinearCombination ;
3442
35- fn sub ( self , other : Variable ) -> LinearCombination {
36- LinearCombination {
37- terms : vec ! [ ( self , Scalar :: one( ) ) , ( other, -Scalar :: one( ) ) ] ,
38- }
43+ fn neg ( self ) -> Self :: Output {
44+ -LinearCombination :: from ( self )
3945 }
4046}
4147
42- impl Add < Variable > for Scalar {
48+ impl < L : Into < LinearCombination > > Add < L > for Variable {
4349 type Output = LinearCombination ;
4450
45- fn add ( self , other : Variable ) -> LinearCombination {
51+ fn add ( self , other : L ) -> Self :: Output {
52+ LinearCombination :: from ( self ) + other. into ( )
53+ }
54+ }
55+
56+ impl < L : Into < LinearCombination > > Sub < L > for Variable {
57+ type Output = LinearCombination ;
58+
59+ fn sub ( self , other : L ) -> Self :: Output {
60+ LinearCombination :: from ( self ) - other. into ( )
61+ }
62+ }
63+
64+ impl < S : Into < Scalar > > Mul < S > for Variable {
65+ type Output = LinearCombination ;
66+
67+ fn mul ( self , other : S ) -> Self :: Output {
4668 LinearCombination {
47- terms : vec ! [ ( Variable :: One ( ) , self ) , ( other, Scalar :: one ( ) ) ] ,
69+ terms : vec ! [ ( self , other. into ( ) ) ] ,
4870 }
4971 }
5072}
5173
52- impl Sub < Variable > for Scalar {
74+ // Arithmetic on scalars with variables produces linear combinations
75+
76+ impl Add < Variable > for Scalar {
5377 type Output = LinearCombination ;
5478
55- fn sub ( self , other : Variable ) -> LinearCombination {
79+ fn add ( self , other : Variable ) -> Self :: Output {
5680 LinearCombination {
57- terms : vec ! [ ( Variable :: One ( ) , self ) , ( other, - Scalar :: one( ) ) ] ,
81+ terms : vec ! [ ( Variable :: One ( ) , self ) , ( other, Scalar :: one( ) ) ] ,
5882 }
5983 }
6084}
6185
62- impl Add < Scalar > for Variable {
86+ impl Sub < Variable > for Scalar {
6387 type Output = LinearCombination ;
6488
65- fn add ( self , other : Scalar ) -> LinearCombination {
89+ fn sub ( self , other : Variable ) -> Self :: Output {
6690 LinearCombination {
67- terms : vec ! [ ( self , Scalar :: one ( ) ) , ( Variable :: One ( ) , other ) ] ,
91+ terms : vec ! [ ( Variable :: One ( ) , self ) , ( other , - Scalar :: one ( ) ) ] ,
6892 }
6993 }
7094}
7195
72- impl Sub < Scalar > for Variable {
96+ impl Mul < Variable > for Scalar {
7397 type Output = LinearCombination ;
7498
75- fn sub ( self , other : Scalar ) -> LinearCombination {
99+ fn mul ( self , other : Variable ) -> Self :: Output {
76100 LinearCombination {
77- terms : vec ! [ ( self , Scalar :: one ( ) ) , ( Variable :: One ( ) , -other ) ] ,
101+ terms : vec ! [ ( other , self ) ] ,
78102 }
79103 }
80104}
@@ -93,18 +117,6 @@ impl Default for LinearCombination {
93117 }
94118}
95119
96- impl From < Scalar > for LinearCombination {
97- fn from ( s : Scalar ) -> Self {
98- iter:: once ( ( Variable :: One ( ) , s) ) . collect ( )
99- }
100- }
101-
102- impl From < Variable > for LinearCombination {
103- fn from ( v : Variable ) -> Self {
104- iter:: once ( ( v, Scalar :: one ( ) ) ) . collect ( )
105- }
106- }
107-
108120impl FromIterator < ( Variable , Scalar ) > for LinearCombination {
109121 fn from_iter < T > ( iter : T ) -> Self
110122 where
@@ -127,21 +139,59 @@ impl<'a> FromIterator<&'a (Variable, Scalar)> for LinearCombination {
127139 }
128140}
129141
130- impl Add < LinearCombination > for LinearCombination {
142+ // Arithmetic on linear combinations
143+
144+ impl < L : Into < LinearCombination > > Add < L > for LinearCombination {
131145 type Output = Self ;
132146
133- fn add ( mut self , rhs : LinearCombination ) -> Self {
134- self . terms . extend ( rhs. terms . iter ( ) . cloned ( ) ) ;
147+ fn add ( mut self , rhs : L ) -> Self :: Output {
148+ self . terms . extend ( rhs. into ( ) . terms . iter ( ) . cloned ( ) ) ;
135149 LinearCombination { terms : self . terms }
136150 }
137151}
138152
139- impl Sub < LinearCombination > for LinearCombination {
153+ impl < L : Into < LinearCombination > > Sub < L > for LinearCombination {
140154 type Output = Self ;
141155
142- fn sub ( mut self , rhs : LinearCombination ) -> Self {
156+ fn sub ( mut self , rhs : L ) -> Self :: Output {
143157 self . terms
144- . extend ( rhs. terms . iter ( ) . map ( |( var, coeff) | ( * var, -coeff) ) ) ;
158+ . extend ( rhs. into ( ) . terms . iter ( ) . map ( |( var, coeff) | ( * var, -coeff) ) ) ;
145159 LinearCombination { terms : self . terms }
146160 }
147161}
162+
163+ impl Mul < LinearCombination > for Scalar {
164+ type Output = LinearCombination ;
165+
166+ fn mul ( self , other : LinearCombination ) -> Self :: Output {
167+ let out_terms = other
168+ . terms
169+ . into_iter ( )
170+ . map ( |( var, scalar) | ( var, scalar * self ) )
171+ . collect ( ) ;
172+ LinearCombination { terms : out_terms }
173+ }
174+ }
175+
176+ impl Neg for LinearCombination {
177+ type Output = Self ;
178+
179+ fn neg ( mut self ) -> Self :: Output {
180+ for ( _, s) in self . terms . iter_mut ( ) {
181+ * s = -* s
182+ }
183+ self
184+ }
185+ }
186+
187+ impl < S : Into < Scalar > > Mul < S > for LinearCombination {
188+ type Output = Self ;
189+
190+ fn mul ( mut self , other : S ) -> Self :: Output {
191+ let other = other. into ( ) ;
192+ for ( _, s) in self . terms . iter_mut ( ) {
193+ * s *= other
194+ }
195+ self
196+ }
197+ }
0 commit comments