@@ -10,7 +10,7 @@ use ark_ff::{to_bytes, FpParameters};
10
10
use ark_relations:: r1cs:: Result as R1CSResult ;
11
11
use ark_relations:: r1cs:: { ConstraintSystemRef , Namespace , SynthesisError } ;
12
12
use ark_std:: hash:: { Hash , Hasher } ;
13
- use ark_std:: { borrow:: Borrow , vec:: Vec } ;
13
+ use ark_std:: { borrow:: Borrow , iter :: Sum , vec:: Vec } ;
14
14
15
15
/// A gadget for representing non-native (`TargetField`) field elements over the constraint field (`BaseField`).
16
16
#[ derive( Clone , Debug ) ]
@@ -116,11 +116,30 @@ impl<TargetField: PrimeField, BaseField: PrimeField> FieldVar<TargetField, BaseF
116
116
}
117
117
118
118
#[ tracing:: instrument( target = "r1cs" ) ]
119
- fn negate ( & self ) -> R1CSResult < Self > {
120
- match self {
121
- Self :: Constant ( c) => Ok ( Self :: Constant ( -* c) ) ,
122
- Self :: Var ( v) => Ok ( Self :: Var ( v. negate ( ) ?) ) ,
123
- }
119
+ fn negate_in_place ( & mut self ) -> R1CSResult < & mut Self > {
120
+ * self = match self {
121
+ Self :: Constant ( c) => Self :: Constant ( -* c) ,
122
+ Self :: Var ( v) => Self :: Var ( v. negate ( ) ?) ,
123
+ } ;
124
+ Ok ( self )
125
+ }
126
+
127
+ #[ tracing:: instrument( target = "r1cs" ) ]
128
+ fn double_in_place ( & mut self ) -> R1CSResult < & mut Self > {
129
+ * self = match self {
130
+ Self :: Constant ( c) => Self :: Constant ( c. double ( ) ) ,
131
+ Self :: Var ( v) => Self :: Var ( v. add ( & * v) ?) ,
132
+ } ;
133
+ Ok ( self )
134
+ }
135
+
136
+ #[ tracing:: instrument( target = "r1cs" ) ]
137
+ fn square_in_place ( & mut self ) -> R1CSResult < & mut Self > {
138
+ * self = match self {
139
+ Self :: Constant ( c) => Self :: Constant ( c. square ( ) ) ,
140
+ Self :: Var ( v) => Self :: Var ( v. mul ( & * v) ?) ,
141
+ } ;
142
+ Ok ( self )
124
143
}
125
144
126
145
#[ tracing:: instrument( target = "r1cs" ) ]
@@ -154,15 +173,15 @@ impl_bounded_ops!(
154
173
add,
155
174
AddAssign ,
156
175
add_assign,
157
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
176
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
158
177
use NonNativeFieldVar :: * ;
159
- match ( this, other) {
178
+ * this = match ( & * this, other) {
160
179
( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 + c2) ,
161
180
( Constant ( c) , Var ( v) ) | ( Var ( v) , Constant ( c) ) => Var ( v. add_constant( c) . unwrap( ) ) ,
162
181
( Var ( v1) , Var ( v2) ) => Var ( v1. add( v2) . unwrap( ) ) ,
163
- }
182
+ } ;
164
183
} ,
165
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: TargetField | { this + & NonNativeFieldVar :: Constant ( other) } ,
184
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: TargetField | { * this = & * this + & NonNativeFieldVar :: Constant ( other) } ,
166
185
( TargetField : PrimeField , BaseField : PrimeField ) ,
167
186
) ;
168
187
@@ -173,17 +192,17 @@ impl_bounded_ops!(
173
192
sub,
174
193
SubAssign ,
175
194
sub_assign,
176
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
195
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
177
196
use NonNativeFieldVar :: * ;
178
- match ( this, other) {
197
+ * this = match ( & * this, other) {
179
198
( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 - c2) ,
180
199
( Var ( v) , Constant ( c) ) => Var ( v. sub_constant( c) . unwrap( ) ) ,
181
200
( Constant ( c) , Var ( v) ) => Var ( v. sub_constant( c) . unwrap( ) . negate( ) . unwrap( ) ) ,
182
201
( Var ( v1) , Var ( v2) ) => Var ( v1. sub( v2) . unwrap( ) ) ,
183
- }
202
+ } ;
184
203
} ,
185
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: TargetField | {
186
- this - & NonNativeFieldVar :: Constant ( other)
204
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: TargetField | {
205
+ * this = & * this - & NonNativeFieldVar :: Constant ( other)
187
206
} ,
188
207
( TargetField : PrimeField , BaseField : PrimeField ) ,
189
208
) ;
@@ -195,20 +214,20 @@ impl_bounded_ops!(
195
214
mul,
196
215
MulAssign ,
197
216
mul_assign,
198
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
217
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
199
218
use NonNativeFieldVar :: * ;
200
- match ( this, other) {
219
+ * this = match ( & * this, other) {
201
220
( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 * c2) ,
202
221
( Constant ( c) , Var ( v) ) | ( Var ( v) , Constant ( c) ) => Var ( v. mul_constant( c) . unwrap( ) ) ,
203
222
( Var ( v1) , Var ( v2) ) => Var ( v1. mul( v2) . unwrap( ) ) ,
204
223
}
205
224
} ,
206
- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: TargetField | {
207
- if other. is_zero( ) {
225
+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: TargetField | {
226
+ * this = if other. is_zero( ) {
208
227
NonNativeFieldVar :: zero( )
209
228
} else {
210
- this * & NonNativeFieldVar :: Constant ( other)
211
- }
229
+ & * this * & NonNativeFieldVar :: Constant ( other)
230
+ } ;
212
231
} ,
213
232
( TargetField : PrimeField , BaseField : PrimeField ) ,
214
233
) ;
@@ -454,6 +473,54 @@ impl<TargetField: PrimeField, BaseField: PrimeField> ToConstraintFieldGadget<Bas
454
473
}
455
474
}
456
475
476
+ impl < ' a , TargetField : PrimeField , BaseField : PrimeField > Sum < & ' a Self >
477
+ for NonNativeFieldVar < TargetField , BaseField >
478
+ {
479
+ fn sum < I : Iterator < Item = & ' a Self > > ( iter : I ) -> Self {
480
+ let mut sum_constants = TargetField :: zero ( ) ;
481
+ let vars = iter
482
+ . filter_map ( |x| match x {
483
+ Self :: Constant ( c) => {
484
+ sum_constants += c;
485
+ None
486
+ }
487
+ Self :: Var ( v) => Some ( v) ,
488
+ } )
489
+ . collect :: < Vec < _ > > ( ) ;
490
+ let sum_variables = AllocatedNonNativeFieldVar :: add_many ( vars. into_iter ( ) )
491
+ . unwrap ( )
492
+ . map ( Self :: Var )
493
+ . unwrap_or ( Self :: zero ( ) ) ;
494
+
495
+ let sum = sum_variables + sum_constants;
496
+ sum
497
+ }
498
+ }
499
+
500
+ impl < TargetField : PrimeField , BaseField : PrimeField > Sum < Self >
501
+ for NonNativeFieldVar < TargetField , BaseField >
502
+ {
503
+ fn sum < I : Iterator < Item = Self > > ( iter : I ) -> Self {
504
+ let mut sum_constants = TargetField :: zero ( ) ;
505
+ let vars = iter
506
+ . filter_map ( |x| match x {
507
+ Self :: Constant ( c) => {
508
+ sum_constants += c;
509
+ None
510
+ }
511
+ Self :: Var ( v) => Some ( v) ,
512
+ } )
513
+ . collect :: < Vec < _ > > ( ) ;
514
+ let sum_variables = AllocatedNonNativeFieldVar :: add_many ( vars. iter ( ) )
515
+ . unwrap ( )
516
+ . map ( Self :: Var )
517
+ . unwrap_or ( Self :: zero ( ) ) ;
518
+
519
+ let sum = sum_variables + sum_constants;
520
+ sum
521
+ }
522
+ }
523
+
457
524
impl < TargetField : PrimeField , BaseField : PrimeField > NonNativeFieldVar < TargetField , BaseField > {
458
525
/// The `mul_without_reduce` for `NonNativeFieldVar`
459
526
#[ tracing:: instrument( target = "r1cs" ) ]
0 commit comments