2021-10-07 09:25:57 -07:00
use crate ::field ::extension_field ::Extendable ;
2021-10-12 11:41:52 -07:00
use crate ::field ::field_types ::RichField ;
2021-10-15 16:47:29 -07:00
use crate ::gates ::arithmetic_u32 ::U32ArithmeticGate ;
2021-10-14 13:41:51 -07:00
use crate ::gates ::subtraction_u32 ::U32SubtractionGate ;
2021-11-09 18:10:47 -08:00
use crate ::iop ::target ::Target ;
use crate ::plonk ::circuit_builder ::CircuitBuilder ;
2021-10-18 15:04:54 -07:00
#[ derive(Clone, Copy, Debug) ]
2021-11-10 09:53:27 -08:00
pub struct U32Target ( pub Target ) ;
2021-11-09 18:10:47 -08:00
impl < F : RichField + Extendable < D > , const D : usize > CircuitBuilder < F , D > {
2021-10-12 11:41:34 -07:00
pub fn add_virtual_u32_target ( & mut self ) -> U32Target {
2021-11-09 18:10:47 -08:00
U32Target ( self . add_virtual_target ( ) )
}
2021-10-12 11:41:34 -07:00
pub fn add_virtual_u32_targets ( & mut self , n : usize ) -> Vec < U32Target > {
2021-10-04 14:17:28 -07:00
self . add_virtual_targets ( n )
2021-10-07 09:25:57 -07:00
. into_iter ( )
2021-10-04 14:17:28 -07:00
. map ( U32Target )
. collect ( )
2021-10-04 14:17:19 -07:00
}
2021-10-12 11:41:34 -07:00
pub fn zero_u32 ( & mut self ) -> U32Target {
2021-11-09 18:10:47 -08:00
U32Target ( self . zero ( ) )
}
2021-10-12 11:41:34 -07:00
pub fn one_u32 ( & mut self ) -> U32Target {
2021-11-09 18:10:47 -08:00
U32Target ( self . one ( ) )
}
2021-10-18 15:04:54 -07:00
pub fn connect_u32 ( & mut self , x : U32Target , y : U32Target ) {
self . connect ( x . 0 , y . 0 )
}
2021-10-18 16:04:23 -07:00
pub fn assert_zero_u32 ( & mut self , x : U32Target ) {
2021-10-18 15:04:54 -07:00
self . assert_zero ( x . 0 )
}
2021-10-04 16:23:21 -07:00
// Returns x * y + z.
pub fn mul_add_u32 (
2021-11-09 18:10:47 -08:00
& mut self ,
x : U32Target ,
y : U32Target ,
z : U32Target ,
) -> ( U32Target , U32Target ) {
2021-11-10 09:56:21 -08:00
let ( gate_index , copy ) = self . find_u32_arithmetic_gate ( ) ;
2021-11-09 18:10:47 -08:00
2021-10-04 14:17:28 -07:00
self . connect (
Target ::wire (
gate_index ,
U32ArithmeticGate ::< F , D > ::wire_ith_multiplicand_0 ( copy ) ,
) ,
x . 0 ,
) ;
self . connect (
Target ::wire (
gate_index ,
U32ArithmeticGate ::< F , D > ::wire_ith_multiplicand_1 ( copy ) ,
) ,
y . 0 ,
) ;
self . connect (
Target ::wire ( gate_index , U32ArithmeticGate ::< F , D > ::wire_ith_addend ( copy ) ) ,
z . 0 ,
) ;
2021-10-07 09:25:57 -07:00
let output_low = U32Target ( Target ::wire (
gate_index ,
U32ArithmeticGate ::< F , D > ::wire_ith_output_low_half ( copy ) ,
) ) ;
let output_high = U32Target ( Target ::wire (
gate_index ,
U32ArithmeticGate ::< F , D > ::wire_ith_output_high_half ( copy ) ,
) ) ;
2021-11-09 18:10:47 -08:00
( output_low , output_high )
}
pub fn add_u32 ( & mut self , a : U32Target , b : U32Target ) -> ( U32Target , U32Target ) {
2021-10-12 11:41:34 -07:00
let one = self . one_u32 ( ) ;
self . mul_add_u32 ( a , one , b )
2021-11-09 18:10:47 -08:00
}
2021-10-04 14:17:28 -07:00
pub fn add_three_u32 (
& mut self ,
a : U32Target ,
b : U32Target ,
c : U32Target ,
) -> ( U32Target , U32Target ) {
2021-10-04 14:17:19 -07:00
let ( init_low , carry1 ) = self . add_u32 ( a , b ) ;
let ( final_low , carry2 ) = self . add_u32 ( c , init_low ) ;
let ( combined_carry , _zero ) = self . add_u32 ( carry1 , carry2 ) ;
( final_low , combined_carry )
}
2021-10-15 12:12:09 -07:00
pub fn add_many_u32 ( & mut self , to_add : Vec < U32Target > ) -> ( U32Target , U32Target ) {
match to_add . len ( ) {
0 = > ( self . zero_u32 ( ) , self . zero_u32 ( ) ) ,
1 = > ( to_add [ 0 ] , self . zero_u32 ( ) ) ,
2 = > self . add_u32 ( to_add [ 0 ] , to_add [ 1 ] ) ,
3 = > self . add_three_u32 ( to_add [ 0 ] , to_add [ 1 ] , to_add [ 2 ] ) ,
_ = > {
let ( mut low , mut carry ) = self . add_u32 ( to_add [ 0 ] , to_add [ 1 ] ) ;
for i in 2 .. to_add . len ( ) {
let ( new_low , new_carry ) = self . add_u32 ( to_add [ i ] , low ) ;
let ( combined_carry , _zero ) = self . add_u32 ( carry , new_carry ) ;
low = new_low ;
carry = combined_carry ;
}
( low , carry )
}
}
}
2021-11-09 18:10:47 -08:00
pub fn mul_u32 ( & mut self , a : U32Target , b : U32Target ) -> ( U32Target , U32Target ) {
2021-10-12 11:41:34 -07:00
let zero = self . zero_u32 ( ) ;
self . mul_add_u32 ( a , b , zero )
2021-11-09 18:10:47 -08:00
}
2021-11-10 09:56:21 -08:00
2021-10-14 13:41:51 -07:00
// Returns x - y - borrow, as a pair (result, borrow), where borrow is 0 or 1 depending on whether borrowing from the next digit is required (iff y + borrow > x).
2021-11-10 09:56:21 -08:00
pub fn sub_u32 (
& mut self ,
x : U32Target ,
y : U32Target ,
borrow : U32Target ,
) -> ( U32Target , U32Target ) {
let ( gate_index , copy ) = self . find_u32_subtraction_gate ( ) ;
self . connect (
Target ::wire (
gate_index ,
2021-10-14 13:41:51 -07:00
U32SubtractionGate ::< F , D > ::wire_ith_input_x ( copy ) ,
2021-11-10 09:56:21 -08:00
) ,
x . 0 ,
) ;
self . connect (
Target ::wire (
gate_index ,
2021-10-14 13:41:51 -07:00
U32SubtractionGate ::< F , D > ::wire_ith_input_y ( copy ) ,
2021-11-10 09:56:21 -08:00
) ,
y . 0 ,
) ;
self . connect (
2021-10-14 13:41:51 -07:00
Target ::wire (
gate_index ,
U32SubtractionGate ::< F , D > ::wire_ith_input_borrow ( copy ) ,
) ,
borrow . 0 ,
2021-11-10 09:56:21 -08:00
) ;
2021-10-14 13:41:51 -07:00
let output_result = U32Target ( Target ::wire (
2021-11-10 09:56:21 -08:00
gate_index ,
2021-10-14 13:41:51 -07:00
U32SubtractionGate ::< F , D > ::wire_ith_output_result ( copy ) ,
2021-11-10 09:56:21 -08:00
) ) ;
2021-10-14 13:41:51 -07:00
let output_borrow = U32Target ( Target ::wire (
2021-11-10 09:56:21 -08:00
gate_index ,
2021-10-14 13:41:51 -07:00
U32SubtractionGate ::< F , D > ::wire_ith_output_borrow ( copy ) ,
2021-11-10 09:56:21 -08:00
) ) ;
2021-10-14 13:41:51 -07:00
( output_result , output_borrow )
2021-11-10 09:56:21 -08:00
}
2021-11-09 18:10:47 -08:00
}