openvm_circuit_primitives/xor/
bus.rs

1use openvm_stark_backend::{
2    interaction::{InteractionBuilder, LookupBus},
3    p3_field::FieldAlgebra,
4};
5
6/// Represents a bus for `(x, y, x ^ y)` identified by a unique bus index (`usize`).
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct XorBus(pub LookupBus);
9
10impl XorBus {
11    pub fn send<T>(
12        &self,
13        x: impl Into<T>,
14        y: impl Into<T>,
15        x_xor_y: impl Into<T>,
16    ) -> XorBusInteraction<T> {
17        self.push(x, y, x_xor_y, true)
18    }
19
20    pub fn receive<T>(
21        &self,
22        x: impl Into<T>,
23        y: impl Into<T>,
24        x_xor_y: impl Into<T>,
25    ) -> XorBusInteraction<T> {
26        self.push(x, y, x_xor_y, false)
27    }
28
29    pub fn push<T>(
30        &self,
31        x: impl Into<T>,
32        y: impl Into<T>,
33        x_xor_y: impl Into<T>,
34        is_lookup: bool,
35    ) -> XorBusInteraction<T> {
36        XorBusInteraction {
37            x: x.into(),
38            y: y.into(),
39            x_xor_y: x_xor_y.into(),
40            bus: self.0,
41            is_lookup,
42        }
43    }
44}
45
46#[derive(Clone, Copy, Debug)]
47pub struct XorBusInteraction<T> {
48    pub x: T,
49    pub y: T,
50    pub x_xor_y: T,
51
52    pub bus: LookupBus,
53    pub is_lookup: bool,
54}
55
56impl<T: FieldAlgebra> XorBusInteraction<T> {
57    /// Finalizes and sends/receives over the Xor bus.
58    pub fn eval<AB>(self, builder: &mut AB, count: impl Into<AB::Expr>)
59    where
60        AB: InteractionBuilder<Expr = T>,
61    {
62        let key = [self.x, self.y, self.x_xor_y];
63        if self.is_lookup {
64            self.bus.lookup_key(builder, key, count);
65        } else {
66            self.bus.add_key_with_lookups(builder, key, count);
67        }
68    }
69}