sp1_core_machine/operations/
baby_bear_range.rs1use std::array;
2
3use p3_air::AirBuilder;
4use p3_field::{AbstractField, Field};
5use sp1_derive::AlignedBorrow;
6use sp1_stark::air::SP1AirBuilder;
7
8#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
9#[repr(C)]
10pub struct BabyBearBitDecomposition<T> {
11 pub bits: [T; 32],
13
14 pub and_most_sig_byte_decomp_3_to_5: T,
16
17 pub and_most_sig_byte_decomp_3_to_6: T,
19
20 pub and_most_sig_byte_decomp_3_to_7: T,
22}
23
24impl<F: Field> BabyBearBitDecomposition<F> {
25 pub fn populate(&mut self, value: u32) {
26 self.bits = array::from_fn(|i| F::from_canonical_u32((value >> i) & 1));
27 let most_sig_byte_decomp = &self.bits[24..32];
28 self.and_most_sig_byte_decomp_3_to_5 = most_sig_byte_decomp[3] * most_sig_byte_decomp[4];
29 self.and_most_sig_byte_decomp_3_to_6 =
30 self.and_most_sig_byte_decomp_3_to_5 * most_sig_byte_decomp[5];
31 self.and_most_sig_byte_decomp_3_to_7 =
32 self.and_most_sig_byte_decomp_3_to_6 * most_sig_byte_decomp[6];
33 }
34
35 pub fn range_check<AB: SP1AirBuilder>(
36 builder: &mut AB,
37 value: AB::Var,
38 cols: BabyBearBitDecomposition<AB::Var>,
39 is_real: AB::Expr,
40 ) {
41 let mut reconstructed_value = AB::Expr::zero();
42 for (i, bit) in cols.bits.iter().enumerate() {
43 builder.when(is_real.clone()).assert_bool(*bit);
44 reconstructed_value =
45 reconstructed_value.clone() + AB::Expr::from_wrapped_u32(1 << i) * *bit;
46 }
47
48 builder.when(is_real.clone()).assert_eq(reconstructed_value, value);
50
51 let most_sig_byte_decomp = &cols.bits[24..32];
59 builder.when(is_real.clone()).assert_zero(most_sig_byte_decomp[7]);
60
61 builder.when(is_real.clone()).assert_eq(
63 cols.and_most_sig_byte_decomp_3_to_5,
64 most_sig_byte_decomp[3] * most_sig_byte_decomp[4],
65 );
66 builder.when(is_real.clone()).assert_eq(
67 cols.and_most_sig_byte_decomp_3_to_6,
68 cols.and_most_sig_byte_decomp_3_to_5 * most_sig_byte_decomp[5],
69 );
70 builder.when(is_real.clone()).assert_eq(
71 cols.and_most_sig_byte_decomp_3_to_7,
72 cols.and_most_sig_byte_decomp_3_to_6 * most_sig_byte_decomp[6],
73 );
74
75 let mut lower_bits_sum: AB::Expr = AB::Expr::zero();
77 for bit in cols.bits[0..27].iter() {
78 lower_bits_sum = lower_bits_sum + *bit;
79 }
80 builder
81 .when(is_real)
82 .when(cols.and_most_sig_byte_decomp_3_to_7)
83 .assert_zero(lower_bits_sum);
84 }
85}