@@ -10,7 +10,7 @@ use ark_ff::{to_bytes, FpParameters};
1010use ark_relations:: r1cs:: Result as R1CSResult ;
1111use ark_relations:: r1cs:: { ConstraintSystemRef , Namespace , SynthesisError } ;
1212use ark_std:: hash:: { Hash , Hasher } ;
13- use ark_std:: { borrow:: Borrow , vec:: Vec } ;
13+ use ark_std:: { borrow:: Borrow , iter :: Sum , vec:: Vec } ;
1414
1515/// A gadget for representing non-native (`TargetField`) field elements over the constraint field (`BaseField`).
1616#[ derive( Clone , Debug ) ]
@@ -116,11 +116,30 @@ impl<TargetField: PrimeField, BaseField: PrimeField> FieldVar<TargetField, BaseF
116116 }
117117
118118 #[ 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 )
124143 }
125144
126145 #[ tracing:: instrument( target = "r1cs" ) ]
@@ -154,15 +173,15 @@ impl_bounded_ops!(
154173 add,
155174 AddAssign ,
156175 add_assign,
157- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
176+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
158177 use NonNativeFieldVar :: * ;
159- match ( this, other) {
178+ * this = match ( & * this, other) {
160179 ( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 + c2) ,
161180 ( Constant ( c) , Var ( v) ) | ( Var ( v) , Constant ( c) ) => Var ( v. add_constant( c) . unwrap( ) ) ,
162181 ( Var ( v1) , Var ( v2) ) => Var ( v1. add( v2) . unwrap( ) ) ,
163- }
182+ } ;
164183 } ,
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) } ,
166185 ( TargetField : PrimeField , BaseField : PrimeField ) ,
167186) ;
168187
@@ -173,17 +192,17 @@ impl_bounded_ops!(
173192 sub,
174193 SubAssign ,
175194 sub_assign,
176- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
195+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
177196 use NonNativeFieldVar :: * ;
178- match ( this, other) {
197+ * this = match ( & * this, other) {
179198 ( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 - c2) ,
180199 ( Var ( v) , Constant ( c) ) => Var ( v. sub_constant( c) . unwrap( ) ) ,
181200 ( Constant ( c) , Var ( v) ) => Var ( v. sub_constant( c) . unwrap( ) . negate( ) . unwrap( ) ) ,
182201 ( Var ( v1) , Var ( v2) ) => Var ( v1. sub( v2) . unwrap( ) ) ,
183- }
202+ } ;
184203 } ,
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)
187206 } ,
188207 ( TargetField : PrimeField , BaseField : PrimeField ) ,
189208) ;
@@ -195,20 +214,20 @@ impl_bounded_ops!(
195214 mul,
196215 MulAssign ,
197216 mul_assign,
198- |this: & ' a NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
217+ |this: & mut NonNativeFieldVar <TargetField , BaseField >, other: & ' a NonNativeFieldVar <TargetField , BaseField >| {
199218 use NonNativeFieldVar :: * ;
200- match ( this, other) {
219+ * this = match ( & * this, other) {
201220 ( Constant ( c1) , Constant ( c2) ) => Constant ( * c1 * c2) ,
202221 ( Constant ( c) , Var ( v) ) | ( Var ( v) , Constant ( c) ) => Var ( v. mul_constant( c) . unwrap( ) ) ,
203222 ( Var ( v1) , Var ( v2) ) => Var ( v1. mul( v2) . unwrap( ) ) ,
204223 }
205224 } ,
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( ) {
208227 NonNativeFieldVar :: zero( )
209228 } else {
210- this * & NonNativeFieldVar :: Constant ( other)
211- }
229+ & * this * & NonNativeFieldVar :: Constant ( other)
230+ } ;
212231 } ,
213232 ( TargetField : PrimeField , BaseField : PrimeField ) ,
214233) ;
@@ -454,6 +473,54 @@ impl<TargetField: PrimeField, BaseField: PrimeField> ToConstraintFieldGadget<Bas
454473 }
455474}
456475
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+
457524impl < TargetField : PrimeField , BaseField : PrimeField > NonNativeFieldVar < TargetField , BaseField > {
458525 /// The `mul_without_reduce` for `NonNativeFieldVar`
459526 #[ tracing:: instrument( target = "r1cs" ) ]
0 commit comments