@@ -594,11 +594,37 @@ fn divmod_31(numerator: u16) -> (u16, u16) {
594
594
(quotient , remainder )
595
595
}
596
596
597
+ /**
598
+ * @brief converts a 16 bit value into 16 fake bools (Field elements that are 0 or 1)
599
+ **/
600
+ unconstrained fn decompose (val : Field ) -> [Field ; 16 ] {
601
+ let mut r : [Field ; 16 ] = [0 ; 16 ];
602
+
603
+ let mut it = val as u32 ;
604
+ for i in 0 ..16 {
605
+ r [i ] = (it & 1 ) as Field ;
606
+ it >>= 1 ;
607
+ }
608
+ r
609
+ }
610
+
597
611
// 5 gates?
598
- pub fn get_last_limb_path <let OutputFields : u32 >(last_limb_index : Field ) -> [u1 ; OutputFields ] {
612
+ pub fn get_last_limb_path <let OutputFields : u32 >(last_limb_index : Field ) -> [Field ; OutputFields ] {
599
613
// TODO we offset by 1 explain why (0 byte length produces 0 - 1 which = invalid array index. we just add 1 and increase array length by 1 to compensate)
600
614
let path = LAST_LIMB_PATH [cast_num_to_u32 (last_limb_index + 1 )]; // 2
601
- path .to_le_bits ::<OutputFields >()
615
+ // Safety: check the comments below
616
+ let path_valid_bits = unsafe { decompose (path ) };
617
+ let mut path_valid_sum : Field = 0 ;
618
+ let mut path_valid_output : [Field ; OutputFields ] = [0 ; OutputFields ];
619
+ for i in 0 ..OutputFields {
620
+ // we check that the path valid bits are binary
621
+ assert (path_valid_bits [i ] * path_valid_bits [i ] - path_valid_bits [i ] == 0 );
622
+ path_valid_sum += (path_valid_bits [i ] * (1 << i as u8 ) as Field );
623
+ path_valid_output [i ] = path_valid_bits [i ];
624
+ }
625
+ // we check that the path valid bits sum to the path
626
+ assert (path_valid_sum == path );
627
+ path_valid_output
602
628
}
603
629
604
630
/**
@@ -702,13 +728,13 @@ pub fn slice_fields<let InputFields: u32, let OutputFields: u32>(
702
728
// 1, 70.5
703
729
let index_of_output_limb : Field = (num_bytes_div_31 as Field - num_bytes_mod_31_is_0 as Field );
704
730
// 5, 75.5
705
- let path_valid_output : [u1 ; OutputFields ] = get_last_limb_path (index_of_output_limb );
731
+ let path_valid_output : [Field ; OutputFields ] = get_last_limb_path (index_of_output_limb );
706
732
707
733
// 2, 77.5
708
734
let tail_shift = BYTE_SHIFT [cast_num_to_u32 (num_unused_bytes_in_start_limb )];
709
735
710
736
// 51, 128.5
711
- let mut result : [ Field ; OutputFields ] = [0 ; OutputFields ];
737
+ let mut result = [0 ; OutputFields ];
712
738
let mut previous = tail ;
713
739
for i in 0 ..(OutputFields - 1 ) {
714
740
// 0
@@ -722,9 +748,9 @@ pub fn slice_fields<let InputFields: u32, let OutputFields: u32>(
722
748
// 1, 48
723
749
let combined = previous * tail_shift + head ;
724
750
// 1, 49
725
- result [i ] = if slice_valid == 1 { combined } else { 0 } ;
751
+ result [i ] = combined * slice_valid ;
726
752
// 2, 51
727
- previous = if slice_valid == 1 { tail } else { previous } ;
753
+ previous = ( tail - previous ) * slice_valid + previous ;
728
754
}
729
755
730
756
// 2, 130.5
@@ -761,10 +787,9 @@ pub fn slice_fields<let InputFields: u32, let OutputFields: u32>(
761
787
std:: as_witness (last_limb );
762
788
763
789
let mut path : [Field ; OutputFields ] = [0 ; OutputFields ];
764
- path [0 ] = (1 - path_valid_output [0 ] as Field );
790
+ path [0 ] = (1 - path_valid_output [0 ]);
765
791
for i in 1 ..OutputFields {
766
- path [i ] = path_valid_output [i - 1 ] as Field
767
- - path_valid_output [i ] as Field * path_valid_output [i - 1 ] as Field ;
792
+ path [i ] = path_valid_output [i ] * -path_valid_output [i - 1 ] + path_valid_output [i - 1 ];
768
793
}
769
794
770
795
for i in 0 ..OutputFields {
@@ -857,7 +882,7 @@ mod test {
857
882
for j in 0 ..18 {
858
883
let start_byte : u32 = text .len () - num_bytes - byte_positions [j ];
859
884
let mut expected_slices : [Field ; 3 ] =
860
- // Safety: this is a test
885
+ // Safety: this is a test
861
886
unsafe { build_slices_for_test (text , start_byte , num_bytes ) };
862
887
let result_slices : [Field ; 3 ] =
863
888
slice_fields (slices , start_byte as Field , num_bytes as Field );
0 commit comments