openvm_circuit_primitives/
utils.rs

1use itertools::zip_eq;
2use openvm_stark_backend::{
3    p3_air::{AirBuilder, VirtualPairCol},
4    p3_field::{Field, FieldAlgebra},
5};
6
7/// Return either 0 if n is zero or the next power of two of n.
8/// Used to resize the number of rows in a trace matrix.
9pub const fn next_power_of_two_or_zero(n: usize) -> usize {
10    if n == 0 {
11        0
12    } else {
13        n.next_power_of_two()
14    }
15}
16
17pub fn not<F: FieldAlgebra>(a: impl Into<F>) -> F {
18    F::ONE - a.into()
19}
20
21pub fn and<F: FieldAlgebra>(a: impl Into<F>, b: impl Into<F>) -> F {
22    a.into() * b.into()
23}
24
25/// Assumes that a and b are boolean
26pub fn or<F: FieldAlgebra>(a: impl Into<F>, b: impl Into<F>) -> F {
27    let a = a.into();
28    let b = b.into();
29    a.clone() + b.clone() - and(a, b)
30}
31
32/// Assumes that a and b are boolean
33pub fn implies<F: FieldAlgebra>(a: impl Into<F>, b: impl Into<F>) -> F {
34    or(F::ONE - a.into(), b.into())
35}
36
37/// Assumes that `cond` is boolean. Returns `a` if `cond` is true, otherwise returns `b`.
38pub fn select<F: FieldAlgebra>(cond: impl Into<F>, a: impl Into<F>, b: impl Into<F>) -> F {
39    let cond = cond.into();
40    cond.clone() * a.into() + (F::ONE - cond) * b.into()
41}
42
43pub fn to_vcols<F: Field>(cols: &[usize]) -> Vec<VirtualPairCol<F>> {
44    cols.iter()
45        .copied()
46        .map(VirtualPairCol::single_main)
47        .collect()
48}
49
50pub fn fill_slc_to_f<F: Field>(dest: &mut [F], src: &[u32]) {
51    dest.iter_mut()
52        .zip(src.iter())
53        .for_each(|(d, s)| *d = F::from_canonical_u32(*s));
54}
55
56pub fn to_field_vec<F: Field>(src: &[u32]) -> Vec<F> {
57    src.iter().map(|s| F::from_canonical_u32(*s)).collect()
58}
59
60pub fn assert_array_eq<AB: AirBuilder, I1: Into<AB::Expr>, I2: Into<AB::Expr>, const N: usize>(
61    builder: &mut AB,
62    x: [I1; N],
63    y: [I2; N],
64) {
65    for (x, y) in zip_eq(x, y) {
66        builder.assert_eq(x, y);
67    }
68}
69
70/// Composes a list of limb values into a single field element
71#[inline]
72pub fn compose<F: FieldAlgebra>(a: &[impl Into<F> + Clone], limb_size: usize) -> F {
73    a.iter().enumerate().fold(F::ZERO, |acc, (i, x)| {
74        acc + x.clone().into() * F::from_canonical_usize(1 << (i * limb_size))
75    })
76}