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 inputs(&self) -> Vec<(DataType, String)> {
33        ["right", "left"]
34            .map(|s| (DataType::U64, s.to_string()))
35            .to_vec()
36    }
37
38    fn outputs(&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"), 0x9304a37ae367ed6.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>) {
87            let (right, left) = pop_encodable::<Self::Args>(stack);
88            let or = left | right;
89            push_encodable(stack, &or);
90        }
91
92        fn pseudorandom_args(
93            &self,
94            seed: [u8; 32],
95            bench_case: Option<BenchmarkCase>,
96        ) -> Self::Args {
97            match bench_case {
98                Some(BenchmarkCase::CommonCase) => (u32::MAX.into(), u32::MAX.into()),
99                Some(BenchmarkCase::WorstCase) => (u64::MAX, u64::MAX),
100                None => StdRng::from_seed(seed).random(),
101            }
102        }
103
104        fn corner_case_args(&self) -> Vec<Self::Args> {
105            And.corner_case_args()
106        }
107    }
108
109    #[test]
110    fn rust_shadow() {
111        ShadowedClosure::new(Or).test();
112    }
113}
114
115#[cfg(test)]
116mod benches {
117    use super::*;
118    use crate::test_prelude::*;
119
120    #[test]
121    fn benchmark() {
122        ShadowedClosure::new(Or).bench();
123    }
124}