openvm_circuit_primitives/bitwise_op_lookup/
bus.rs

1use openvm_stark_backend::{
2    interaction::{BusIndex, InteractionBuilder, LookupBus},
3    p3_field::FieldAlgebra,
4};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub struct BitwiseOperationLookupBus {
8    pub inner: LookupBus,
9}
10
11impl BitwiseOperationLookupBus {
12    pub const fn new(index: BusIndex) -> Self {
13        Self {
14            inner: LookupBus::new(index),
15        }
16    }
17
18    #[must_use]
19    pub fn send_range<T>(
20        &self,
21        x: impl Into<T>,
22        y: impl Into<T>,
23    ) -> BitwiseOperationLookupBusInteraction<T>
24    where
25        T: FieldAlgebra,
26    {
27        self.push(x, y, T::ZERO, T::ZERO, true)
28    }
29
30    #[must_use]
31    pub fn send_xor<T>(
32        &self,
33        x: impl Into<T>,
34        y: impl Into<T>,
35        z: impl Into<T>,
36    ) -> BitwiseOperationLookupBusInteraction<T>
37    where
38        T: FieldAlgebra,
39    {
40        self.push(x, y, z, T::ONE, true)
41    }
42
43    #[must_use]
44    pub fn receive<T>(
45        &self,
46        x: impl Into<T>,
47        y: impl Into<T>,
48        z: impl Into<T>,
49        op: impl Into<T>,
50    ) -> BitwiseOperationLookupBusInteraction<T> {
51        self.push(x, y, z, op, false)
52    }
53
54    pub fn push<T>(
55        &self,
56        x: impl Into<T>,
57        y: impl Into<T>,
58        z: impl Into<T>,
59        op: impl Into<T>,
60        is_lookup: bool,
61    ) -> BitwiseOperationLookupBusInteraction<T> {
62        BitwiseOperationLookupBusInteraction {
63            x: x.into(),
64            y: y.into(),
65            z: z.into(),
66            op: op.into(),
67            bus: self.inner,
68            is_lookup,
69        }
70    }
71}
72
73#[derive(Clone, Copy, Debug)]
74pub struct BitwiseOperationLookupBusInteraction<T> {
75    pub x: T,
76    pub y: T,
77    pub z: T,
78    pub op: T,
79    pub bus: LookupBus,
80    is_lookup: bool,
81}
82
83impl<T: FieldAlgebra> BitwiseOperationLookupBusInteraction<T> {
84    pub fn eval<AB>(self, builder: &mut AB, count: impl Into<AB::Expr>)
85    where
86        AB: InteractionBuilder<Expr = T>,
87    {
88        let key = [self.x, self.y, self.z, self.op];
89        if self.is_lookup {
90            self.bus.lookup_key(builder, key, count);
91        } else {
92            self.bus.add_key_with_lookups(builder, key, count);
93        }
94    }
95}