@ -1,7 +1,7 @@ 
			
		
	
		
			
				
					use   super ::{ 
  
			
		
	
		
			
				
					     params ::{ get_params ,   OptimizationType } , 
  
			
		
	
		
			
				
					     reduce ::{ bigint_to_basefield ,   limbs_to_bigint ,   Reducer } , 
  
			
		
	
		
			
				
					     AllocatedNonNativeField MulResultVar , 
  
			
		
	
		
			
				
					     AllocatedMulResultVar , 
  
			
		
	
		
			
				
					} ; 
  
			
		
	
		
			
				
					use   crate ::{ fields ::fp ::FpVar ,   prelude ::* ,   ToConstraintFieldGadget } ; 
  
			
		
	
		
			
				
					use   ark_ff ::{ BigInteger ,   PrimeField } ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -19,58 +19,53 @@ use ark_std::{ 
			
		
	
		
			
				
					     vec ::Vec , 
  
			
		
	
		
			
				
					} ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/// The allocated version of `NonNativeField Var` (introduced below)
  
			
		
	
		
			
				
					/// The allocated version of `EmulatedFp Var` (introduced below)
  
			
		
	
		
			
				
					#[ derive(Debug) ] 
  
			
		
	
		
			
				
					#[ must_use ] 
  
			
		
	
		
			
				
					pub   struct  AllocatedNonNativeField Var < TargetField  : PrimeField ,   BaseField  : PrimeField >   { 
  
			
		
	
		
			
				
					pub   struct  AllocatedEmulatedFp Var < TargetF : PrimeField ,   BaseF : PrimeField >   { 
  
			
		
	
		
			
				
					     /// Constraint system reference
  
			
		
	
		
			
				
					     pub   cs : ConstraintSystemRef < BaseField  > , 
  
			
		
	
		
			
				
					     /// The limbs, each of which is a BaseField  gadget.
  
			
		
	
		
			
				
					     pub   limbs : Vec < FpVar < BaseField  > > , 
  
			
		
	
		
			
				
					     pub   cs : ConstraintSystemRef < BaseF > , 
  
			
		
	
		
			
				
					     /// The limbs, each of which is a BaseF gadget.
  
			
		
	
		
			
				
					     pub   limbs : Vec < FpVar < BaseF > > , 
  
			
		
	
		
			
				
					     /// Number of additions done over this gadget, using which the gadget
  
			
		
	
		
			
				
					     /// decides when to reduce.
  
			
		
	
		
			
				
					     pub   num_of_additions_over_normal_form : BaseField  , 
  
			
		
	
		
			
				
					     pub   num_of_additions_over_normal_form : BaseF , 
  
			
		
	
		
			
				
					     /// Whether the limb representation is the normal form (using only the bits
  
			
		
	
		
			
				
					     /// specified in the parameters, and the representation is strictly within
  
			
		
	
		
			
				
					     /// the range of TargetField ).
  
			
		
	
		
			
				
					     /// the range of TargetF).
  
			
		
	
		
			
				
					     pub   is_in_the_normal_form : bool , 
  
			
		
	
		
			
				
					     #[ doc(hidden) ] 
  
			
		
	
		
			
				
					     pub   target_phantom : PhantomData < TargetField  > , 
  
			
		
	
		
			
				
					     pub   target_phantom : PhantomData < TargetF > , 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField : PrimeField ,   BaseField : PrimeField > 
  
			
		
	
		
			
				
					     AllocatedNonNativeFieldVar < TargetField ,   BaseField > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   AllocatedEmulatedFpVar < TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					     /// Return cs
  
			
		
	
		
			
				
					     pub   fn  cs ( & self )   -> ConstraintSystemRef < BaseField  >   { 
  
			
		
	
		
			
				
					     pub   fn  cs ( & self )   -> ConstraintSystemRef < BaseF >   { 
  
			
		
	
		
			
				
					         self . cs . clone ( ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the value of limbs
  
			
		
	
		
			
				
					     pub   fn  limbs_to_value ( 
  
			
		
	
		
			
				
					         limbs : Vec < BaseField > , 
  
			
		
	
		
			
				
					         optimization_type : OptimizationType , 
  
			
		
	
		
			
				
					     )   -> TargetField   { 
  
			
		
	
		
			
				
					     pub   fn  limbs_to_value ( limbs : Vec < BaseF > ,   optimization_type : OptimizationType )   -> TargetF   { 
  
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             optimization_type , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Convert 2^{(params.bits_per_limb - 1)} into the TargetField  and then double
  
			
		
	
		
			
				
					         // Convert 2^{(params.bits_per_limb - 1)} into the TargetF and then double
  
			
		
	
		
			
				
					         // the base This is because 2^{(params.bits_per_limb)} might indeed be
  
			
		
	
		
			
				
					         // larger than the target field's prime.
  
			
		
	
		
			
				
					         let   base_repr   =   TargetField  ::ONE . into_bigint ( )   < <   ( params . bits_per_limb   -   1 )   as   u32 ; 
  
			
		
	
		
			
				
					         let   base_repr   =   TargetF ::ONE . into_bigint ( )   < <   ( params . bits_per_limb   -   1 )   as   u32 ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   base   =   TargetField  ::from_bigint ( base_repr ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					         let   mut   base   =   TargetF ::from_bigint ( base_repr ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					         base . double_in_place ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   result   =   TargetField  ::zero ( ) ; 
  
			
		
	
		
			
				
					         let   mut   power   =   TargetField  ::one ( ) ; 
  
			
		
	
		
			
				
					         let   mut   result   =   TargetF ::zero ( ) ; 
  
			
		
	
		
			
				
					         let   mut   power   =   TargetF ::one ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   limb   in   limbs . iter ( ) . rev ( )   { 
  
			
		
	
		
			
				
					             let   mut   val   =   TargetField  ::zero ( ) ; 
  
			
		
	
		
			
				
					             let   mut   cur   =   TargetField  ::one ( ) ; 
  
			
		
	
		
			
				
					             let   mut   val   =   TargetF ::zero ( ) ; 
  
			
		
	
		
			
				
					             let   mut   cur   =   TargetF ::one ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             for   bit   in   limb . into_bigint ( ) . to_bits_be ( ) . iter ( ) . rev ( )   { 
  
			
		
	
		
			
				
					                 if   * bit   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -86,8 +81,8 @@ impl 
			
		
	
		
			
				
					         result 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the value of a nonnative  field element
  
			
		
	
		
			
				
					     pub   fn  value ( & self )   -> R1CSResult < TargetField  >   { 
  
			
		
	
		
			
				
					     /// Obtain the value of a emulated  field element
  
			
		
	
		
			
				
					     pub   fn  value ( & self )   -> R1CSResult < TargetF >   { 
  
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limb   in   self . limbs . iter ( )   { 
  
			
		
	
		
			
				
					             limbs . push ( limb . value ( ) ? ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -96,8 +91,8 @@ impl 
			
		
	
		
			
				
					         Ok ( Self ::limbs_to_value ( limbs ,   self . get_optimization_type ( ) ) ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the nonnative  field element of a constant value
  
			
		
	
		
			
				
					     pub   fn  constant ( cs : ConstraintSystemRef < BaseField  > ,   value : TargetField  )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					     /// Obtain the emulated  field element of a constant value
  
			
		
	
		
			
				
					     pub   fn  constant ( cs : ConstraintSystemRef < BaseF > ,   value : TargetF )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         let   optimization_type   =   match   cs . optimization_goal ( )   { 
  
			
		
	
		
			
				
					             OptimizationGoal ::None   = >   OptimizationType ::Constraints , 
  
			
		
	
		
			
				
					             OptimizationGoal ::Constraints   = >   OptimizationType ::Constraints , 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -109,32 +104,29 @@ impl 
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   limb_value   in   limbs_value . iter ( )   { 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseField > ::new_constant ( 
  
			
		
	
		
			
				
					                 ns ! ( cs ,   "limb" ) , 
  
			
		
	
		
			
				
					                 limb_value , 
  
			
		
	
		
			
				
					             ) ? ) ; 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseF > ::new_constant ( ns ! ( cs ,   "limb" ) ,   limb_value ) ? ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( Self   { 
  
			
		
	
		
			
				
					             cs , 
  
			
		
	
		
			
				
					             limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseField  ::zero ( ) , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseF ::zero ( ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : true , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the nonnative  field element of one
  
			
		
	
		
			
				
					     pub   fn  one ( cs : ConstraintSystemRef < BaseField  > )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         Self ::constant ( cs ,   TargetField  ::one ( ) ) 
  
			
		
	
		
			
				
					     /// Obtain the emulated  field element of one
  
			
		
	
		
			
				
					     pub   fn  one ( cs : ConstraintSystemRef < BaseF > )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         Self ::constant ( cs ,   TargetF ::one ( ) ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the nonnative  field element of zero
  
			
		
	
		
			
				
					     pub   fn  zero ( cs : ConstraintSystemRef < BaseField  > )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         Self ::constant ( cs ,   TargetField  ::zero ( ) ) 
  
			
		
	
		
			
				
					     /// Obtain the emulated  field element of zero
  
			
		
	
		
			
				
					     pub   fn  zero ( cs : ConstraintSystemRef < BaseF > )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         Self ::constant ( cs ,   TargetF ::zero ( ) ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Add a nonnative  field element
  
			
		
	
		
			
				
					     /// Add a emulated  field element
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  add ( & self ,   other : & Self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -150,18 +142,18 @@ impl 
			
		
	
		
			
				
					             num_of_additions_over_normal_form : self 
  
			
		
	
		
			
				
					                 . num_of_additions_over_normal_form 
  
			
		
	
		
			
				
					                 . add ( & other . num_of_additions_over_normal_form ) 
  
			
		
	
		
			
				
					                 . add ( & BaseField  ::one ( ) ) , 
  
			
		
	
		
			
				
					                 . add ( & BaseF ::one ( ) ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : false , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::post_add_reduce ( & mut   res ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::post_add_reduce ( & mut   res ) ? ; 
  
			
		
	
		
			
				
					         Ok ( res ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Add a constant
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  add_constant ( & self ,   other : & TargetField  )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					     pub   fn  add_constant ( & self ,   other : & TargetF )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         let   other_limbs   =   Self ::get_limbs_representations ( other ,   self . get_optimization_type ( ) ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -174,50 +166,50 @@ impl 
			
		
	
		
			
				
					             limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : self 
  
			
		
	
		
			
				
					                 . num_of_additions_over_normal_form 
  
			
		
	
		
			
				
					                 . add ( & BaseField  ::one ( ) ) , 
  
			
		
	
		
			
				
					                 . add ( & BaseF ::one ( ) ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : false , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::post_add_reduce ( & mut   res ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::post_add_reduce ( & mut   res ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( res ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Subtract a nonnative  field element, without the final reduction step
  
			
		
	
		
			
				
					     /// Subtract a emulated  field element, without the final reduction step
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  sub_without_reduce ( & self ,   other : & Self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             self . get_optimization_type ( ) , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Step 1: reduce the `other` if needed
  
			
		
	
		
			
				
					         let   mut   surfeit   =   overhead ! ( other . num_of_additions_over_normal_form   +   BaseField  ::one ( ) )   +   1 ; 
  
			
		
	
		
			
				
					         let   mut   surfeit   =   overhead ! ( other . num_of_additions_over_normal_form   +   BaseF ::one ( ) )   +   1 ; 
  
			
		
	
		
			
				
					         let   mut   other   =   other . clone ( ) ; 
  
			
		
	
		
			
				
					         if   ( surfeit   +   params . bits_per_limb   >   BaseField  ::MODULUS_BIT_SIZE   as   usize   -   1 ) 
  
			
		
	
		
			
				
					         if   ( surfeit   +   params . bits_per_limb   >   BaseF ::MODULUS_BIT_SIZE   as   usize   -   1 ) 
  
			
		
	
		
			
				
					             | |   ( surfeit 
  
			
		
	
		
			
				
					                 +   ( TargetField  ::MODULUS_BIT_SIZE   as   usize 
  
			
		
	
		
			
				
					                 +   ( TargetF ::MODULUS_BIT_SIZE   as   usize 
  
			
		
	
		
			
				
					                     -   params . bits_per_limb   *   ( params . num_limbs   -   1 ) ) 
  
			
		
	
		
			
				
					                 >   BaseField  ::MODULUS_BIT_SIZE   as   usize   -   1 ) 
  
			
		
	
		
			
				
					                 >   BaseF ::MODULUS_BIT_SIZE   as   usize   -   1 ) 
  
			
		
	
		
			
				
					         { 
  
			
		
	
		
			
				
					             Reducer ::reduce ( & mut   other ) ? ; 
  
			
		
	
		
			
				
					             surfeit   =   overhead ! ( other . num_of_additions_over_normal_form   +   BaseField  ::ONE )   +   1 ; 
  
			
		
	
		
			
				
					             surfeit   =   overhead ! ( other . num_of_additions_over_normal_form   +   BaseF ::ONE )   +   1 ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Step 2: construct the padding
  
			
		
	
		
			
				
					         let   mut   pad_non_top_limb   =   BaseField  ::ONE . into_bigint ( ) ; 
  
			
		
	
		
			
				
					         let   mut   pad_non_top_limb   =   BaseF ::ONE . into_bigint ( ) ; 
  
			
		
	
		
			
				
					         let   mut   pad_top_limb   =   pad_non_top_limb ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         pad_non_top_limb   < < =   ( surfeit   +   params . bits_per_limb )   as   u32 ; 
  
			
		
	
		
			
				
					         let   pad_non_top_limb   =   BaseField  ::from_bigint ( pad_non_top_limb ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					         let   pad_non_top_limb   =   BaseF ::from_bigint ( pad_non_top_limb ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         pad_top_limb   < < =   ( surfeit   +   TargetField  ::MODULUS_BIT_SIZE   as   usize 
  
			
		
	
		
			
				
					         pad_top_limb   < < =   ( surfeit   +   TargetF ::MODULUS_BIT_SIZE   as   usize 
  
			
		
	
		
			
				
					             -   params . bits_per_limb   *   ( params . num_limbs   -   1 ) )   as   u32 ; 
  
			
		
	
		
			
				
					         let   pad_top_limb   =   BaseField  ::from_bigint ( pad_top_limb ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					         let   pad_top_limb   =   BaseF ::from_bigint ( pad_top_limb ) . unwrap ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   pad_limbs   =   Vec ::with_capacity ( self . limbs . len ( ) ) ; 
  
			
		
	
		
			
				
					         pad_limbs . push ( pad_top_limb ) ; 
  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -246,12 +238,12 @@ impl 
			
		
	
		
			
				
					             } 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   result   =   AllocatedNonNativeField Var ::< TargetField  ,   BaseField  >   { 
  
			
		
	
		
			
				
					         let   result   =   AllocatedEmulatedFp Var ::< TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					             cs : self . cs ( ) , 
  
			
		
	
		
			
				
					             limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : self . num_of_additions_over_normal_form 
  
			
		
	
		
			
				
					                 +   ( other . num_of_additions_over_normal_form   +   BaseField  ::one ( ) ) 
  
			
		
	
		
			
				
					                 +   ( other . num_of_additions_over_normal_form   +   BaseField  ::one ( ) ) , 
  
			
		
	
		
			
				
					                 +   ( other . num_of_additions_over_normal_form   +   BaseF ::one ( ) ) 
  
			
		
	
		
			
				
					                 +   ( other . num_of_additions_over_normal_form   +   BaseF ::one ( ) ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : false , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -259,23 +251,23 @@ impl 
			
		
	
		
			
				
					         Ok ( result ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Subtract a nonnative  field element
  
			
		
	
		
			
				
					     /// Subtract a emulated  field element
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  sub ( & self ,   other : & Self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   result   =   self . sub_without_reduce ( other ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::post_add_reduce ( & mut   result ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::post_add_reduce ( & mut   result ) ? ; 
  
			
		
	
		
			
				
					         Ok ( result ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Subtract a constant
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  sub_constant ( & self ,   other : & TargetField  )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					     pub   fn  sub_constant ( & self ,   other : & TargetF )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         self . sub ( & Self ::constant ( self . cs ( ) ,   * other ) ? ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Multiply a nonnative  field element
  
			
		
	
		
			
				
					     /// Multiply a emulated  field element
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  mul ( & self ,   other : & Self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -284,21 +276,21 @@ impl 
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Multiply a constant
  
			
		
	
		
			
				
					     pub   fn  mul_constant ( & self ,   other : & TargetField  )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					     pub   fn  mul_constant ( & self ,   other : & TargetF )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         self . mul ( & Self ::constant ( self . cs ( ) ,   * other ) ? ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Compute the negate of a nonnative  field element
  
			
		
	
		
			
				
					     /// Compute the negate of a emulated  field element
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  negate ( & self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         Self ::zero ( self . cs ( ) ) ? . sub ( self ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Compute the inverse of a nonnative  field element
  
			
		
	
		
			
				
					     /// Compute the inverse of a emulated  field element
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  inverse ( & self )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         let   inverse   =   Self ::new_witness ( self . cs ( ) ,   | |   { 
  
			
		
	
		
			
				
					             Ok ( self . value ( ) ? . inverse ( ) . unwrap_or_else ( TargetField  ::zero ) ) 
  
			
		
	
		
			
				
					             Ok ( self . value ( ) ? . inverse ( ) . unwrap_or_else ( TargetF ::zero ) ) 
  
			
		
	
		
			
				
					         } ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   actual_result   =   self . clone ( ) . mul ( & inverse ) ? ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -306,36 +298,36 @@ impl 
			
		
	
		
			
				
					         Ok ( inverse ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Convert a `TargetField ` element into limbs (not constraints)
  
			
		
	
		
			
				
					     /// Convert a `TargetF` element into limbs (not constraints)
  
			
		
	
		
			
				
					     /// This is an internal function that would be reused by a number of other
  
			
		
	
		
			
				
					     /// functions
  
			
		
	
		
			
				
					     pub   fn  get_limbs_representations ( 
  
			
		
	
		
			
				
					         elem : & TargetField  , 
  
			
		
	
		
			
				
					         elem : & TargetF , 
  
			
		
	
		
			
				
					         optimization_type : OptimizationType , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Vec < BaseField  > >   { 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Vec < BaseF > >   { 
  
			
		
	
		
			
				
					         Self ::get_limbs_representations_from_big_integer ( & elem . into_bigint ( ) ,   optimization_type ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Obtain the limbs directly from a big int
  
			
		
	
		
			
				
					     pub   fn  get_limbs_representations_from_big_integer ( 
  
			
		
	
		
			
				
					         elem : & < TargetField    as   PrimeField > ::BigInt , 
  
			
		
	
		
			
				
					         elem : & < TargetF   as   PrimeField > ::BigInt , 
  
			
		
	
		
			
				
					         optimization_type : OptimizationType , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Vec < BaseField  > >   { 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Vec < BaseF > >   { 
  
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             optimization_type , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // push the lower limbs first
  
			
		
	
		
			
				
					         let   mut   limbs : Vec < BaseField  >   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         let   mut   limbs : Vec < BaseF >   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         let   mut   cur   =   * elem ; 
  
			
		
	
		
			
				
					         for   _   in   0 . . params . num_limbs   { 
  
			
		
	
		
			
				
					             let   cur_bits   =   cur . to_bits_be ( ) ;   // `to_bits` is big endian
  
			
		
	
		
			
				
					             let   cur_mod_r   =   < BaseField    as   PrimeField > ::BigInt ::from_bits_be ( 
  
			
		
	
		
			
				
					             let   cur_mod_r   =   < BaseF   as   PrimeField > ::BigInt ::from_bits_be ( 
  
			
		
	
		
			
				
					                 & cur_bits [ cur_bits . len ( )   -   params . bits_per_limb . . ] , 
  
			
		
	
		
			
				
					             ) ;   // therefore, the lowest `bits_per_non_top_limb` bits is what we want.
  
			
		
	
		
			
				
					             limbs . push ( BaseField  ::from_bigint ( cur_mod_r ) . unwrap ( ) ) ; 
  
			
		
	
		
			
				
					             limbs . push ( BaseF ::from_bigint ( cur_mod_r ) . unwrap ( ) ) ; 
  
			
		
	
		
			
				
					             cur   > > =   params . bits_per_limb   as   u32 ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -348,28 +340,28 @@ impl 
			
		
	
		
			
				
					     /// for advanced use, multiply and output the intermediate representations
  
			
		
	
		
			
				
					     /// (without reduction) This intermediate representations can be added
  
			
		
	
		
			
				
					     /// with each other, and they can later be reduced back to the
  
			
		
	
		
			
				
					     /// `NonNativeField Var`.
  
			
		
	
		
			
				
					     /// `EmulatedFp Var`.
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     pub   fn  mul_without_reduce ( 
  
			
		
	
		
			
				
					         & self , 
  
			
		
	
		
			
				
					         other : & Self , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < AllocatedNonNativeField MulResultVar < TargetField  ,   BaseField  > >   { 
  
			
		
	
		
			
				
					     )   -> R1CSResult < AllocatedMulResultVar < TargetF ,   BaseF > >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             self . get_optimization_type ( ) , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Step 1: reduce `self` and `other` if neceessary
  
			
		
	
		
			
				
					         let   mut   self_reduced   =   self . clone ( ) ; 
  
			
		
	
		
			
				
					         let   mut   other_reduced   =   other . clone ( ) ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::pre_mul_reduce ( & mut   self_reduced ,   & mut   other_reduced ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::pre_mul_reduce ( & mut   self_reduced ,   & mut   other_reduced ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   prod_limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         if   self . get_optimization_type ( )   = =   OptimizationType ::Weight   { 
  
			
		
	
		
			
				
					             let   zero   =   FpVar ::< BaseField  > ::zero ( ) ; 
  
			
		
	
		
			
				
					             let   zero   =   FpVar ::< BaseF > ::zero ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             for   _   in   0 . . 2   *   params . num_limbs   -   1   { 
  
			
		
	
		
			
				
					                 prod_limbs . push ( zero . clone ( ) ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -386,7 +378,7 @@ impl 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             for   z_index   in   0 . . 2   *   params . num_limbs   -   1   { 
  
			
		
	
		
			
				
					                 prod_limbs . push ( FpVar ::new_witness ( ns ! ( cs ,   "limb product" ) ,   | |   { 
  
			
		
	
		
			
				
					                     let   mut   z_i   =   BaseField  ::zero ( ) ; 
  
			
		
	
		
			
				
					                     let   mut   z_i   =   BaseF ::zero ( ) ; 
  
			
		
	
		
			
				
					                     for   i   in   0 . . = min ( params . num_limbs   -   1 ,   z_index )   { 
  
			
		
	
		
			
				
					                         let   j   =   z_index   -   i ; 
  
			
		
	
		
			
				
					                         if   j   <   params . num_limbs   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -402,7 +394,7 @@ impl 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             for   c   in   0 . . ( 2   *   params . num_limbs   -   1 )   { 
  
			
		
	
		
			
				
					                 let   c_pows : Vec < _ >   =   ( 0 . . ( 2   *   params . num_limbs   -   1 ) ) 
  
			
		
	
		
			
				
					                     . map ( | i |   BaseField  ::from ( ( c   +   1 )   as   u128 ) . pow ( & vec ! [ i   as   u64 ] ) ) 
  
			
		
	
		
			
				
					                     . map ( | i |   BaseF ::from ( ( c   +   1 )   as   u128 ) . pow ( & vec ! [ i   as   u64 ] ) ) 
  
			
		
	
		
			
				
					                     . collect ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                 let   x   =   self_reduced 
  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -429,12 +421,12 @@ impl 
			
		
	
		
			
				
					             } 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( AllocatedNonNativeField MulResultVar   { 
  
			
		
	
		
			
				
					         Ok ( AllocatedMulResultVar   { 
  
			
		
	
		
			
				
					             cs : self . cs ( ) , 
  
			
		
	
		
			
				
					             limbs : prod_limbs , 
  
			
		
	
		
			
				
					             prod_of_num_of_additions : ( self_reduced . num_of_additions_over_normal_form 
  
			
		
	
		
			
				
					                 +   BaseField  ::one ( ) ) 
  
			
		
	
		
			
				
					                 *   ( other_reduced . num_of_additions_over_normal_form   +   BaseField  ::one ( ) ) , 
  
			
		
	
		
			
				
					                 +   BaseF ::one ( ) ) 
  
			
		
	
		
			
				
					                 *   ( other_reduced . num_of_additions_over_normal_form   +   BaseF ::one ( ) ) , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -446,32 +438,32 @@ impl 
			
		
	
		
			
				
					     pub ( crate )   fn  conditional_enforce_equal ( 
  
			
		
	
		
			
				
					         & self , 
  
			
		
	
		
			
				
					         other : & Self , 
  
			
		
	
		
			
				
					         should_enforce : & Boolean < BaseField  > , 
  
			
		
	
		
			
				
					         should_enforce : & Boolean < BaseF > , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < ( ) >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             self . get_optimization_type ( ) , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Get p
  
			
		
	
		
			
				
					         let   p_representations   = 
  
			
		
	
		
			
				
					             AllocatedNonNativeField Var ::< TargetField  ,   BaseField  > ::get_limbs_representations_from_big_integer ( 
  
			
		
	
		
			
				
					                 & < TargetField    as   PrimeField > ::MODULUS , 
  
			
		
	
		
			
				
					                 self . get_optimization_type ( ) 
  
			
		
	
		
			
				
					             AllocatedEmulatedFp Var ::< TargetF ,   BaseF > ::get_limbs_representations_from_big_integer ( 
  
			
		
	
		
			
				
					                 & < TargetF   as   PrimeField > ::MODULUS , 
  
			
		
	
		
			
				
					                 self . get_optimization_type ( ) , 
  
			
		
	
		
			
				
					             ) ? ; 
  
			
		
	
		
			
				
					         let   p_bigint   =   limbs_to_bigint ( params . bits_per_limb ,   & p_representations ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   p_gadget_limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limb   in   p_representations . iter ( )   { 
  
			
		
	
		
			
				
					             p_gadget_limbs . push ( FpVar ::< BaseField  > ::Constant ( * limb ) ) ; 
  
			
		
	
		
			
				
					             p_gadget_limbs . push ( FpVar ::< BaseF > ::Constant ( * limb ) ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					         let   p_gadget   =   AllocatedNonNativeField Var ::< TargetField  ,   BaseField  >   { 
  
			
		
	
		
			
				
					         let   p_gadget   =   AllocatedEmulatedFp Var ::< TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					             cs : self . cs ( ) , 
  
			
		
	
		
			
				
					             limbs : p_gadget_limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseField  ::one ( ) , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseF ::one ( ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : false , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -482,19 +474,19 @@ impl 
			
		
	
		
			
				
					         delta   =   should_enforce . select ( & delta ,   & Self ::zero ( cs . clone ( ) ) ? ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Allocate k = delta / p
  
			
		
	
		
			
				
					         let   k_gadget   =   FpVar ::< BaseField  > ::new_witness ( ns ! ( cs ,   "k" ) ,   | |   { 
  
			
		
	
		
			
				
					             let   mut   delta_limbs_values   =   Vec ::< BaseField  > ::new ( ) ; 
  
			
		
	
		
			
				
					         let   k_gadget   =   FpVar ::< BaseF > ::new_witness ( ns ! ( cs ,   "k" ) ,   | |   { 
  
			
		
	
		
			
				
					             let   mut   delta_limbs_values   =   Vec ::< BaseF > ::new ( ) ; 
  
			
		
	
		
			
				
					             for   limb   in   delta . limbs . iter ( )   { 
  
			
		
	
		
			
				
					                 delta_limbs_values . push ( limb . value ( ) ? ) ; 
  
			
		
	
		
			
				
					             } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             let   delta_bigint   =   limbs_to_bigint ( params . bits_per_limb ,   & delta_limbs_values ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					             Ok ( bigint_to_basefield ::< BaseField  > ( & ( delta_bigint   /   p_bigint ) ) ) 
  
			
		
	
		
			
				
					             Ok ( bigint_to_basefield ::< BaseF > ( & ( delta_bigint   /   p_bigint ) ) ) 
  
			
		
	
		
			
				
					         } ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   surfeit   =   overhead ! ( delta . num_of_additions_over_normal_form   +   BaseField  ::one ( ) )   +   1 ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::limb_to_bits ( & k_gadget ,   surfeit ) ? ; 
  
			
		
	
		
			
				
					         let   surfeit   =   overhead ! ( delta . num_of_additions_over_normal_form   +   BaseF ::one ( ) )   +   1 ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::limb_to_bits ( & k_gadget ,   surfeit ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Compute k * p
  
			
		
	
		
			
				
					         let   mut   kp_gadget_limbs   =   Vec ::new ( ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -503,7 +495,7 @@ impl 
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Enforce delta = kp
  
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::group_and_check_equality ( 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::group_and_check_equality ( 
  
			
		
	
		
			
				
					             surfeit , 
  
			
		
	
		
			
				
					             params . bits_per_limb , 
  
			
		
	
		
			
				
					             params . bits_per_limb , 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -518,7 +510,7 @@ impl 
			
		
	
		
			
				
					     pub ( crate )   fn  conditional_enforce_not_equal ( 
  
			
		
	
		
			
				
					         & self , 
  
			
		
	
		
			
				
					         other : & Self , 
  
			
		
	
		
			
				
					         should_enforce : & Boolean < BaseField  > , 
  
			
		
	
		
			
				
					         should_enforce : & Boolean < BaseF > , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < ( ) >   { 
  
			
		
	
		
			
				
					         assert_eq ! ( self . get_optimization_type ( ) ,   other . get_optimization_type ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -541,8 +533,8 @@ impl 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     /// Allocates a new variable, but does not check that the allocation's limbs
  
			
		
	
		
			
				
					     /// are in-range.
  
			
		
	
		
			
				
					     fn  new_variable_unchecked < T : Borrow < TargetField  > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseField  > > , 
  
			
		
	
		
			
				
					     fn  new_variable_unchecked < T : Borrow < TargetF > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseF > > , 
  
			
		
	
		
			
				
					         f : impl   FnOnce ( )   -> Result < T ,   SynthesisError > , 
  
			
		
	
		
			
				
					         mode : AllocationMode , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Self >   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -555,7 +547,7 @@ impl 
			
		
	
		
			
				
					             OptimizationGoal ::Weight   = >   OptimizationType ::Weight , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   zero   =   TargetField  ::zero ( ) ; 
  
			
		
	
		
			
				
					         let   zero   =   TargetF ::zero ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   elem   =   match   f ( )   { 
  
			
		
	
		
			
				
					             Ok ( t )   = >   * ( t . borrow ( ) ) , 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -565,7 +557,7 @@ impl 
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   limb   in   elem_representations . iter ( )   { 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseField  > ::new_variable ( 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseF > ::new_variable ( 
  
			
		
	
		
			
				
					                 ark_relations ::ns ! ( cs ,   "alloc" ) , 
  
			
		
	
		
			
				
					                 | |   Ok ( limb ) , 
  
			
		
	
		
			
				
					                 mode , 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -573,9 +565,9 @@ impl 
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   num_of_additions_over_normal_form   =   if   mode   ! =   AllocationMode ::Witness   { 
  
			
		
	
		
			
				
					             BaseField  ::zero ( ) 
  
			
		
	
		
			
				
					             BaseF ::zero ( ) 
  
			
		
	
		
			
				
					         }   else   { 
  
			
		
	
		
			
				
					             BaseField  ::one ( ) 
  
			
		
	
		
			
				
					             BaseF ::one ( ) 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( Self   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -591,10 +583,7 @@ impl 
			
		
	
		
			
				
					     /// the whole number is less than the modulus.
  
			
		
	
		
			
				
					     ///
  
			
		
	
		
			
				
					     /// Returns the bits of the element, in little-endian form
  
			
		
	
		
			
				
					     fn  enforce_in_range ( 
  
			
		
	
		
			
				
					         & self , 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseField > > , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Vec < Boolean < BaseField > > >   { 
  
			
		
	
		
			
				
					     fn  enforce_in_range ( & self ,   cs : impl   Into < Namespace < BaseF > > )   -> R1CSResult < Vec < Boolean < BaseF > > >   { 
  
			
		
	
		
			
				
					         let   ns   =   cs . into ( ) ; 
  
			
		
	
		
			
				
					         let   cs   =   ns . cs ( ) ; 
  
			
		
	
		
			
				
					         let   optimization_type   =   match   cs . optimization_goal ( )   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -603,24 +592,23 @@ impl 
			
		
	
		
			
				
					             OptimizationGoal ::Weight   = >   OptimizationType ::Weight , 
  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             optimization_type , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					         let   mut   bits   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limb   in   self . limbs . iter ( ) . rev ( ) . take ( params . num_limbs   -   1 )   { 
  
			
		
	
		
			
				
					             bits . extend ( 
  
			
		
	
		
			
				
					                 Reducer ::< TargetField  ,   BaseField  > ::limb_to_bits ( limb ,   params . bits_per_limb ) ? 
  
			
		
	
		
			
				
					                 Reducer ::< TargetF ,   BaseF > ::limb_to_bits ( limb ,   params . bits_per_limb ) ? 
  
			
		
	
		
			
				
					                     . into_iter ( ) 
  
			
		
	
		
			
				
					                     . rev ( ) , 
  
			
		
	
		
			
				
					             ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         bits . extend ( 
  
			
		
	
		
			
				
					             Reducer ::< TargetField  ,   BaseField  > ::limb_to_bits ( 
  
			
		
	
		
			
				
					             Reducer ::< TargetF ,   BaseF > ::limb_to_bits ( 
  
			
		
	
		
			
				
					                 & self . limbs [ 0 ] , 
  
			
		
	
		
			
				
					                 TargetField ::MODULUS_BIT_SIZE   as   usize 
  
			
		
	
		
			
				
					                     -   ( params . num_limbs   -   1 )   *   params . bits_per_limb , 
  
			
		
	
		
			
				
					                 TargetF ::MODULUS_BIT_SIZE   as   usize   -   ( params . num_limbs   -   1 )   *   params . bits_per_limb , 
  
			
		
	
		
			
				
					             ) ? 
  
			
		
	
		
			
				
					             . into_iter ( ) 
  
			
		
	
		
			
				
					             . rev ( ) , 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -633,10 +621,10 @@ impl 
			
		
	
		
			
				
					     /// and returns the bits of its binary representation.
  
			
		
	
		
			
				
					     /// The bits are in little-endian (i.e., the bit at index 0 is the LSB) and the
  
			
		
	
		
			
				
					     /// bit-vector is empty in non-witness allocation modes.
  
			
		
	
		
			
				
					     pub   fn  new_witness_with_le_bits < T : Borrow < TargetField  > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseField  > > , 
  
			
		
	
		
			
				
					     pub   fn  new_witness_with_le_bits < T : Borrow < TargetF > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseF > > , 
  
			
		
	
		
			
				
					         f : impl   FnOnce ( )   -> Result < T ,   SynthesisError > , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < ( Self ,   Vec < Boolean < BaseField  > > ) >   { 
  
			
		
	
		
			
				
					     )   -> R1CSResult < ( Self ,   Vec < Boolean < BaseF > > ) >   { 
  
			
		
	
		
			
				
					         let   ns   =   cs . into ( ) ; 
  
			
		
	
		
			
				
					         let   cs   =   ns . cs ( ) ; 
  
			
		
	
		
			
				
					         let   this   =   Self ::new_variable_unchecked ( ns ! ( cs ,   "alloc" ) ,   f ,   AllocationMode ::Witness ) ? ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -645,36 +633,36 @@ impl 
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   ToBitsGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   ToBitsGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     fn  to_bits_le ( & self )   -> R1CSResult < Vec < Boolean < BaseField  > > >   { 
  
			
		
	
		
			
				
					     fn  to_bits_le ( & self )   -> R1CSResult < Vec < Boolean < BaseF > > >   { 
  
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             self . get_optimization_type ( ) , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Reduce to the normal form
  
			
		
	
		
			
				
					         // Though, a malicious prover can make it slightly larger than p
  
			
		
	
		
			
				
					         let   mut   self_normal   =   self . clone ( ) ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetField  ,   BaseField  > ::pre_eq_reduce ( & mut   self_normal ) ? ; 
  
			
		
	
		
			
				
					         Reducer ::< TargetF ,   BaseF > ::pre_eq_reduce ( & mut   self_normal ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // Therefore, we convert it to bits and enforce that it is in the field
  
			
		
	
		
			
				
					         let   mut   bits   =   Vec ::< Boolean < BaseField  > > ::new ( ) ; 
  
			
		
	
		
			
				
					         let   mut   bits   =   Vec ::< Boolean < BaseF > > ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limb   in   self_normal . limbs . iter ( )   { 
  
			
		
	
		
			
				
					             bits . extend_from_slice ( & Reducer ::< TargetField  ,   BaseField  > ::limb_to_bits ( 
  
			
		
	
		
			
				
					             bits . extend_from_slice ( & Reducer ::< TargetF ,   BaseF > ::limb_to_bits ( 
  
			
		
	
		
			
				
					                 & limb , 
  
			
		
	
		
			
				
					                 params . bits_per_limb , 
  
			
		
	
		
			
				
					             ) ? ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					         bits . reverse ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   b   =   TargetField  ::characteristic ( ) . to_vec ( ) ; 
  
			
		
	
		
			
				
					         let   mut   b   =   TargetF ::characteristic ( ) . to_vec ( ) ; 
  
			
		
	
		
			
				
					         assert_eq ! ( b [ 0 ]   %   2 ,   1 ) ; 
  
			
		
	
		
			
				
					         b [ 0 ]   - =   1 ;   // This works, because the LSB is one, so there's no borrows.
  
			
		
	
		
			
				
					         let   run   =   Boolean ::< BaseField  > ::enforce_smaller_or_equal_than_le ( & bits ,   b ) ? ; 
  
			
		
	
		
			
				
					         let   run   =   Boolean ::< BaseF > ::enforce_smaller_or_equal_than_le ( & bits ,   b ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // We should always end in a "run" of zeros, because
  
			
		
	
		
			
				
					         // the characteristic is an odd prime. So, this should
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -685,14 +673,14 @@ impl ToBitsGadget  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   ToBytesGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   ToBytesGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     fn  to_bytes ( & self )   -> R1CSResult < Vec < UInt8 < BaseField  > > >   { 
  
			
		
	
		
			
				
					     fn  to_bytes ( & self )   -> R1CSResult < Vec < UInt8 < BaseF > > >   { 
  
			
		
	
		
			
				
					         let   mut   bits   =   self . to_bits_le ( ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   num_bits   =   TargetField  ::BigInt ::NUM_LIMBS   *   64 ; 
  
			
		
	
		
			
				
					         let   num_bits   =   TargetF ::BigInt ::NUM_LIMBS   *   64 ; 
  
			
		
	
		
			
				
					         assert ! ( bits . len ( )   < =   num_bits ) ; 
  
			
		
	
		
			
				
					         bits . resize_with ( num_bits ,   | |   Boolean ::constant ( false ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -701,12 +689,12 @@ impl ToBytesGadget  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   CondSelectGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   CondSelectGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     fn  conditionally_select ( 
  
			
		
	
		
			
				
					         cond : & Boolean < BaseField  > , 
  
			
		
	
		
			
				
					         cond : & Boolean < BaseF > , 
  
			
		
	
		
			
				
					         true_value : & Self , 
  
			
		
	
		
			
				
					         false_value : & Self , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Self >   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -718,7 +706,7 @@ impl CondSelectGadget  
			
		
	
		
			
				
					         let   mut   limbs_sel   =   Vec ::with_capacity ( true_value . limbs . len ( ) ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   ( x ,   y )   in   true_value . limbs . iter ( ) . zip ( & false_value . limbs )   { 
  
			
		
	
		
			
				
					             limbs_sel . push ( FpVar ::< BaseField  > ::conditionally_select ( cond ,   x ,   y ) ? ) ; 
  
			
		
	
		
			
				
					             limbs_sel . push ( FpVar ::< BaseF > ::conditionally_select ( cond ,   x ,   y ) ? ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( Self   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -735,14 +723,14 @@ impl CondSelectGadget  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   TwoBitLookupGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   TwoBitLookupGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     type  TableConstant   =   TargetField  ; 
  
			
		
	
		
			
				
					     type  TableConstant   =   TargetF ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     fn  two_bit_lookup ( 
  
			
		
	
		
			
				
					         bits : & [ Boolean < BaseField  > ] , 
  
			
		
	
		
			
				
					         bits : & [ Boolean < BaseF > ] , 
  
			
		
	
		
			
				
					         constants : & [ Self ::TableConstant ] , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         debug_assert ! ( bits . len ( )   = =   2 ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -757,8 +745,8 @@ impl TwoBitLookupGadget  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             optimization_type , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					         let   mut   limbs_constants   =   Vec ::new ( ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -768,7 +756,7 @@ impl TwoBitLookupGadget  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   constant   in   constants . iter ( )   { 
  
			
		
	
		
			
				
					             let   representations   = 
  
			
		
	
		
			
				
					                 AllocatedNonNativeField Var ::< TargetField  ,   BaseField  > ::get_limbs_representations ( 
  
			
		
	
		
			
				
					                 AllocatedEmulatedFp Var ::< TargetF ,   BaseF > ::get_limbs_representations ( 
  
			
		
	
		
			
				
					                     constant , 
  
			
		
	
		
			
				
					                     optimization_type , 
  
			
		
	
		
			
				
					                 ) ? ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -780,28 +768,28 @@ impl TwoBitLookupGadget  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limbs_constant   in   limbs_constants . iter ( )   { 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseField  > ::two_bit_lookup ( bits ,   limbs_constant ) ? ) ; 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseF > ::two_bit_lookup ( bits ,   limbs_constant ) ? ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( AllocatedNonNativeField Var ::< TargetField  ,   BaseField  >   { 
  
			
		
	
		
			
				
					         Ok ( AllocatedEmulatedFp Var ::< TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					             cs , 
  
			
		
	
		
			
				
					             limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseField  ::zero ( ) , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseF ::zero ( ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : true , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   ThreeBitCondNegLookupGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   ThreeBitCondNegLookupGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     type  TableConstant   =   TargetField  ; 
  
			
		
	
		
			
				
					     type  TableConstant   =   TargetF ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     #[ tracing::instrument(target =  " r1cs " ) ] 
  
			
		
	
		
			
				
					     fn  three_bit_cond_neg_lookup ( 
  
			
		
	
		
			
				
					         bits : & [ Boolean < BaseField  > ] , 
  
			
		
	
		
			
				
					         b0b1 : & Boolean < BaseField  > , 
  
			
		
	
		
			
				
					         bits : & [ Boolean < BaseF > ] , 
  
			
		
	
		
			
				
					         b0b1 : & Boolean < BaseF > , 
  
			
		
	
		
			
				
					         constants : & [ Self ::TableConstant ] , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Self >   { 
  
			
		
	
		
			
				
					         debug_assert ! ( bits . len ( )   = =   3 ) ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -816,8 +804,8 @@ impl ThreeBitCondNegLookupGadget  
			
		
	
		
			
				
					         } ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             optimization_type , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -828,7 +816,7 @@ impl ThreeBitCondNegLookupGadget  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         for   constant   in   constants . iter ( )   { 
  
			
		
	
		
			
				
					             let   representations   = 
  
			
		
	
		
			
				
					                 AllocatedNonNativeField Var ::< TargetField  ,   BaseField  > ::get_limbs_representations ( 
  
			
		
	
		
			
				
					                 AllocatedEmulatedFp Var ::< TargetF ,   BaseF > ::get_limbs_representations ( 
  
			
		
	
		
			
				
					                     constant , 
  
			
		
	
		
			
				
					                     optimization_type , 
  
			
		
	
		
			
				
					                 ) ? ; 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -840,28 +828,28 @@ impl ThreeBitCondNegLookupGadget  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         let   mut   limbs   =   Vec ::new ( ) ; 
  
			
		
	
		
			
				
					         for   limbs_constant   in   limbs_constants . iter ( )   { 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseField  > ::three_bit_cond_neg_lookup ( 
  
			
		
	
		
			
				
					             limbs . push ( FpVar ::< BaseF > ::three_bit_cond_neg_lookup ( 
  
			
		
	
		
			
				
					                 bits , 
  
			
		
	
		
			
				
					                 b0b1 , 
  
			
		
	
		
			
				
					                 limbs_constant , 
  
			
		
	
		
			
				
					             ) ? ) ; 
  
			
		
	
		
			
				
					         } 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         Ok ( AllocatedNonNativeField Var ::< TargetField  ,   BaseField  >   { 
  
			
		
	
		
			
				
					         Ok ( AllocatedEmulatedFp Var ::< TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					             cs , 
  
			
		
	
		
			
				
					             limbs , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseField  ::zero ( ) , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : BaseF ::zero ( ) , 
  
			
		
	
		
			
				
					             is_in_the_normal_form : true , 
  
			
		
	
		
			
				
					             target_phantom : PhantomData , 
  
			
		
	
		
			
				
					         } ) 
  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   AllocVar < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   AllocVar < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     fn  new_variable < T : Borrow < TargetField  > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseField  > > , 
  
			
		
	
		
			
				
					     fn  new_variable < T : Borrow < TargetF > > ( 
  
			
		
	
		
			
				
					         cs : impl   Into < Namespace < BaseF > > , 
  
			
		
	
		
			
				
					         f : impl   FnOnce ( )   -> Result < T ,   SynthesisError > , 
  
			
		
	
		
			
				
					         mode : AllocationMode , 
  
			
		
	
		
			
				
					     )   -> R1CSResult < Self >   { 
  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -875,18 +863,18 @@ impl AllocVar  
			
		
	
		
			
				
					     } 
  
			
		
	
		
			
				
					} 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField  : PrimeField ,   BaseField  : PrimeField >   ToConstraintFieldGadget < BaseField  > 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeField Var < TargetField  ,   BaseField  > 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   ToConstraintFieldGadget < BaseF > 
  
			
		
	
		
			
				
					     for   AllocatedEmulatedFp Var < TargetF ,   BaseF > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					     fn  to_constraint_field ( & self )   -> R1CSResult < Vec < FpVar < BaseField  > > >   { 
  
			
		
	
		
			
				
					         // provide a unique representation of the nonnative  variable
  
			
		
	
		
			
				
					     fn  to_constraint_field ( & self )   -> R1CSResult < Vec < FpVar < BaseF > > >   { 
  
			
		
	
		
			
				
					         // provide a unique representation of the emulated  variable
  
			
		
	
		
			
				
					         // step 1: convert it into a bit sequence
  
			
		
	
		
			
				
					         let   bits   =   self . to_bits_le ( ) ? ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         // step 2: obtain the parameters for weight-optimized (often, fewer limbs)
  
			
		
	
		
			
				
					         let   params   =   get_params ( 
  
			
		
	
		
			
				
					             TargetField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseField  ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             TargetF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             BaseF ::MODULUS_BIT_SIZE   as   usize , 
  
			
		
	
		
			
				
					             OptimizationType ::Weight , 
  
			
		
	
		
			
				
					         ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -894,15 +882,15 @@ impl ToConstraintFieldGadget  
			
		
	
		
			
				
					         let   mut   limbs   =   bits 
  
			
		
	
		
			
				
					             . chunks ( params . bits_per_limb ) 
  
			
		
	
		
			
				
					             . map ( | chunk |   { 
  
			
		
	
		
			
				
					                 let   mut   limb   =   FpVar ::< BaseField  > ::zero ( ) ; 
  
			
		
	
		
			
				
					                 let   mut   w   =   BaseField  ::one ( ) ; 
  
			
		
	
		
			
				
					                 let   mut   limb   =   FpVar ::< BaseF > ::zero ( ) ; 
  
			
		
	
		
			
				
					                 let   mut   w   =   BaseF ::one ( ) ; 
  
			
		
	
		
			
				
					                 for   b   in   chunk . iter ( )   { 
  
			
		
	
		
			
				
					                     limb   + =   FpVar ::from ( b . clone ( ) )   *   w ; 
  
			
		
	
		
			
				
					                     w . double_in_place ( ) ; 
  
			
		
	
		
			
				
					                 } 
  
			
		
	
		
			
				
					                 limb 
  
			
		
	
		
			
				
					             } ) 
  
			
		
	
		
			
				
					             . collect ::< Vec < FpVar < BaseField  > > > ( ) ; 
  
			
		
	
		
			
				
					             . collect ::< Vec < FpVar < BaseF > > > ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         limbs . reverse ( ) ; 
  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -913,11 +901,9 @@ impl ToConstraintFieldGadget  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					// Implementation of a few traits
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					impl < TargetField : PrimeField ,   BaseField : PrimeField >   Clone 
  
			
		
	
		
			
				
					     for   AllocatedNonNativeFieldVar < TargetField ,   BaseField > 
  
			
		
	
		
			
				
					{ 
  
			
		
	
		
			
				
					impl < TargetF : PrimeField ,   BaseF : PrimeField >   Clone   for   AllocatedEmulatedFpVar < TargetF ,   BaseF >   { 
  
			
		
	
		
			
				
					     fn  clone ( & self )   -> Self   { 
  
			
		
	
		
			
				
					         AllocatedNonNativeField Var   { 
  
			
		
	
		
			
				
					         AllocatedEmulatedFpVar   { 
  
			
		
	
		
			
				
					             cs : self . cs ( ) , 
  
			
		
	
		
			
				
					             limbs : self . limbs . clone ( ) , 
  
			
		
	
		
			
				
					             num_of_additions_over_normal_form : self . num_of_additions_over_normal_form ,