Skip to main content

tasm_lib/arithmetic/u64/
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 `u64`s.
10///
11/// ### Behavior
12///
13/// ```text
14/// BEFORE: _ [right: u64] [left: u64]
15/// AFTER:  _ [left | right: u64]
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::U64, s.to_string()))
35            .to_vec()
36    }
37
38    fn return_values(&self) -> Vec<(DataType, String)> {
39        vec![(DataType::U64, "left | right".to_string())]
40    }
41
42    fn entrypoint(&self) -> String {
43        "tasmlib_arithmetic_u64_or".to_string()
44    }
45
46    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
47        let entrypoint = self.entrypoint();
48        triton_asm!(
49            // BEFORE: _ r_hi r_lo l_hi l_lo
50            // AFTER:  _ (l | r)_hi (l | r)_lo
51            {entrypoint}:
52                dup 2
53                dup 1
54                xor         // _ r_hi r_lo l_hi l_lo (r_lo ^ l_lo)
55                swap 3
56                and         // _ r_hi (r_lo ^ l_lo) l_hi (l_lo & r_lo)
57                swap 3      // _ (l_lo & r_lo) (r_lo ^ l_lo) l_hi r_hi
58                dup 1
59                dup 1
60                xor         // _ (l_lo & r_lo) (r_lo ^ l_lo) l_hi r_hi (l_hi ^ r_hi)
61                place 2
62                and         // _ (l_lo & r_lo) (r_lo ^ l_lo) (l_hi ^ r_hi) (r_hi & l_hi)
63                add         // _ (l_lo & r_lo) (r_lo ^ l_lo) (l_hi | r_hi)
64                place 2
65                add         // _ (l_hi | r_hi) (r_lo | l_lo)
66                return
67        )
68    }
69
70    fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
71        let mut sign_offs = HashMap::new();
72        sign_offs.insert(Reviewer("ferdinand"), 0x56e1a169cdc00179.into());
73        sign_offs
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use crate::arithmetic::u64::and::And;
81    use crate::test_prelude::*;
82
83    impl Closure for Or {
84        type Args = (u64, u64);
85
86        fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) -> Result<(), RustShadowError> {
87            let (right, left) = pop_encodable::<Self::Args>(stack)?;
88            let or = left | right;
89            push_encodable(stack, &or);
90            Ok(())
91        }
92
93        fn pseudorandom_args(
94            &self,
95            seed: [u8; 32],
96            bench_case: Option<BenchmarkCase>,
97        ) -> Self::Args {
98            match bench_case {
99                Some(BenchmarkCase::CommonCase) => (u32::MAX.into(), u32::MAX.into()),
100                Some(BenchmarkCase::WorstCase) => (u64::MAX, u64::MAX),
101                None => StdRng::from_seed(seed).random(),
102            }
103        }
104
105        fn corner_case_args(&self) -> Vec<Self::Args> {
106            And.corner_case_args()
107        }
108    }
109
110    #[macro_rules_attr::apply(test)]
111    fn rust_shadow() {
112        ShadowedClosure::new(Or).test();
113    }
114}
115
116#[cfg(test)]
117mod benches {
118    use super::*;
119    use crate::test_prelude::*;
120
121    #[macro_rules_attr::apply(test)]
122    fn benchmark() {
123        ShadowedClosure::new(Or).bench();
124    }
125}