Skip to main content

tasm_lib/arithmetic/u32/
or.rs

1use std::collections::HashMap;
2
3use triton_vm::prelude::*;
4
5use crate::prelude::*;
6use crate::traits::basic_snippet::Reviewer;
7use crate::traits::basic_snippet::SignOffFingerprint;
8
9/// [Bitwise “or”][bitor] (“`|`”) for `u32`s.
10///
11/// ### Behavior
12///
13/// ```text
14/// BEFORE: _ [right: u32] [left: u32]
15/// AFTER:  _ [left | right: u32]
16/// ```
17///
18/// ### Preconditions
19///
20/// - all input arguments are properly [`BFieldCodec`] encoded
21///
22/// ### Postconditions
23///
24/// - the output is the bitwise “or” of the input
25/// - the output is properly [`BFieldCodec`] encoded
26///
27/// [bitor]: core::ops::BitOr
28#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
29pub struct Or;
30
31impl BasicSnippet for Or {
32    fn parameters(&self) -> Vec<(DataType, String)> {
33        ["right", "left"]
34            .map(|s| (DataType::U32, s.to_string()))
35            .to_vec()
36    }
37
38    fn return_values(&self) -> Vec<(DataType, String)> {
39        vec![(DataType::U32, "left | right".to_string())]
40    }
41
42    fn entrypoint(&self) -> String {
43        "tasmlib_arithmetic_u32_or".to_string()
44    }
45
46    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
47        triton_asm!(
48            // BEFORE: _ right left
49            // AFTER:  _ (left | right)
50            {self.entrypoint()}:
51                dup 1
52                dup 1       // _ right left right left
53                xor         // _ right left (right ^ left)
54                place 2
55                and         // _ (right ^ left) (right & left)
56                add
57                return
58        )
59    }
60
61    fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
62        let mut sign_offs = HashMap::new();
63        sign_offs.insert(Reviewer("ferdinand"), 0x7e5a9b6cfb38b388.into());
64        sign_offs
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::test_prelude::*;
72
73    impl Closure for Or {
74        type Args = (u32, u32);
75
76        fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) -> Result<(), RustShadowError> {
77            let (right, left) = pop_encodable::<Self::Args>(stack)?;
78            let or = left | right;
79            push_encodable(stack, &or);
80            Ok(())
81        }
82
83        fn pseudorandom_args(
84            &self,
85            seed: [u8; 32],
86            bench_case: Option<BenchmarkCase>,
87        ) -> Self::Args {
88            match bench_case {
89                Some(BenchmarkCase::CommonCase) => (1 << 15, 1 << 16),
90                Some(BenchmarkCase::WorstCase) => (u32::MAX, u32::MAX),
91                None => StdRng::from_seed(seed).random(),
92            }
93        }
94
95        fn corner_case_args(&self) -> Vec<Self::Args> {
96            let edges = [0, 1, 2, 0b1110, 0b11110, 1 << 30, 1 << 31, u32::MAX];
97
98            edges.into_iter().cartesian_product(edges).collect()
99        }
100    }
101
102    #[macro_rules_attr::apply(test)]
103    fn rust_shadow() {
104        ShadowedClosure::new(Or).test();
105    }
106}
107
108#[cfg(test)]
109mod benches {
110    use super::*;
111    use crate::test_prelude::*;
112
113    #[macro_rules_attr::apply(test)]
114    fn benchmark() {
115        ShadowedClosure::new(Or).bench();
116    }
117}