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}