openvm_native_compiler/ir/
bits.rs1use std::{any::TypeId, array};
2
3use openvm_stark_backend::p3_field::FieldAlgebra;
4use openvm_stark_sdk::p3_baby_bear::BabyBear;
5
6use super::{Array, Builder, Config, DslIr, Felt, MemIndex, Var};
7
8impl<C: Config> Builder<C> {
9 pub fn num2bits_f(&mut self, num: Felt<C::F>, num_bits: u32) -> Array<C, Var<C::N>> {
12 assert_eq!(TypeId::of::<C::F>(), TypeId::of::<BabyBear>());
13
14 self.push(DslIr::HintBitsF(num, num_bits));
15 let output = self.dyn_array::<Felt<_>>(num_bits as usize);
16
17 let sum: Felt<_> = self.eval(C::F::ZERO);
18 let prefix_sum: Felt<_> = self.eval(C::F::ZERO);
21 let suffix_bit_sum: Felt<_> = self.eval(C::F::ZERO);
24 for i in 0..num_bits as usize {
25 let index = MemIndex {
26 index: i.into(),
27 offset: 0,
28 size: 1,
29 };
30 self.push(DslIr::StoreHintWord(output.ptr(), index));
31
32 let bit = self.get(&output, i);
33 self.assert_felt_eq(bit * (bit - C::F::ONE), C::F::ZERO);
34 self.assign(&sum, sum + bit * C::F::from_canonical_u32(1 << i));
35 if i == 26 {
36 self.assign(&prefix_sum, sum);
37 }
38 if i > 26 {
39 self.assign(&suffix_bit_sum, suffix_bit_sum + bit);
40 }
41 }
42 self.assert_felt_eq(sum, num);
43
44 let suffix_bit_sum_var = self.cast_felt_to_var(suffix_bit_sum);
56 self.if_eq(suffix_bit_sum_var, C::N::from_canonical_u32(4))
57 .then(|builder| {
58 builder.assert_felt_eq(prefix_sum, C::F::ZERO);
59 });
60
61 Array::Dyn(output.ptr(), output.len())
63 }
64
65 pub fn num2bits_f_circuit(&mut self, num: Felt<C::F>) -> Vec<Var<C::N>> {
67 let mut output = Vec::new();
68 for _ in 0..32 {
69 output.push(self.uninit());
70 }
71
72 self.push(DslIr::CircuitNum2BitsF(num, output.clone()));
73
74 output
75 }
76
77 pub fn bits2num_v_circuit(&mut self, bits: &[Var<C::N>]) -> Var<C::N> {
79 let result: Var<_> = self.eval(C::N::ZERO);
80 for i in 0..bits.len() {
81 self.assign(&result, result + bits[i] * C::N::from_canonical_u32(1 << i));
82 }
83 result
84 }
85
86 pub fn var_to_64bits_f_circuit(&mut self, value: Var<C::N>) -> [Felt<C::F>; 4] {
88 let ret = array::from_fn(|_| self.uninit());
89 self.push(DslIr::CircuitVarTo64BitsF(value, ret));
90 ret
91 }
92}