tasm_lib/arithmetic/u64/
xor.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 xor][bitxor] of two `u64`s.
10///
11/// ### Behavior
12///
13/// ```text
14/// BEFORE: _ [right: u64] [left: u64]
15/// AFTER:  _ [xor: u64]
16/// ```
17///
18/// ### Preconditions
19///
20/// - all input arguments are properly [`BFieldCodec`] encoded
21///
22/// ### Postconditions
23///
24/// - the output is the bitwise “xor” of the input
25/// - the output is properly [`BFieldCodec`] encoded
26///
27/// [bitxor]: core::ops::BitXor
28#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
29pub struct Xor;
30
31impl BasicSnippet for Xor {
32    fn inputs(&self) -> Vec<(DataType, String)> {
33        ["right", "left"]
34            .map(|side| (DataType::U64, side.to_string()))
35            .to_vec()
36    }
37
38    fn outputs(&self) -> Vec<(DataType, String)> {
39        vec![(DataType::U64, "xor".to_string())]
40    }
41
42    fn entrypoint(&self) -> String {
43        "tasmlib_arithmetic_u64_xor".to_string()
44    }
45
46    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
47        triton_asm!(
48            // BEFORE: _ rhs_hi rhs_lo lhs_hi lhs_lo
49            // AFTER:  _ (rhs ^ lhs)_hi (rhs ^ lhs)_lo
50            {self.entrypoint()}:
51                swap 3
52                xor
53                // _ lhs_lo rhs_lo (lhs_hi ^ rhs_hi)
54
55                swap 2
56                xor
57                // _ (lhs_hi ^ rhs_hi) (lhs_lo ^ rhs_lo)
58                // _ (lhs ^ rhs)_hi    (lhs ^ rhs)_lo
59
60                return
61        )
62    }
63
64    fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
65        let mut sign_offs = HashMap::new();
66        sign_offs.insert(Reviewer("ferdinand"), 0x7ed1b73a89177516.into());
67        sign_offs
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74    use crate::test_prelude::*;
75
76    impl Closure for Xor {
77        type Args = (u64, u64);
78
79        fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
80            let (right, left) = pop_encodable::<Self::Args>(stack);
81            push_encodable(stack, &(left ^ right));
82        }
83
84        fn pseudorandom_args(
85            &self,
86            seed: [u8; 32],
87            bench_case: Option<BenchmarkCase>,
88        ) -> Self::Args {
89            match bench_case {
90                Some(BenchmarkCase::CommonCase) => (0x7fff_ffff, 0x3ff),
91                Some(BenchmarkCase::WorstCase) => (0x8000_0000_8000_0000, 0x4000_0000_8000_000a),
92                None => StdRng::from_seed(seed).random(),
93            }
94        }
95    }
96
97    #[test]
98    fn rust_shadow() {
99        ShadowedClosure::new(Xor).test();
100    }
101}
102
103#[cfg(test)]
104mod benches {
105    use super::*;
106    use crate::test_prelude::*;
107
108    #[test]
109    fn benchmark() {
110        ShadowedClosure::new(Xor).bench();
111    }
112}