tasm_lib/arithmetic/u32/
is_u32.rs

1use std::collections::HashMap;
2use triton_vm::prelude::*;
3
4use crate::prelude::*;
5use crate::traits::basic_snippet::{Reviewer, SignOffFingerprint};
6
7/// Is the top of the stack a u32?
8///
9/// ### Behavior
10///
11/// ```text
12/// BEFORE: _ value
13/// AFTER:  _ [is_u32: bool]
14/// ```
15///
16/// ### Preconditions
17///
18/// None.
19///
20/// ### Postconditions
21///
22/// - the output is properly [`BFieldCodec`] encoded
23#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
24pub struct IsU32;
25
26impl BasicSnippet for IsU32 {
27    fn inputs(&self) -> Vec<(DataType, String)> {
28        vec![(DataType::U32, "value".to_string())]
29    }
30
31    fn outputs(&self) -> Vec<(DataType, String)> {
32        vec![(DataType::Bool, "value < 2^32".to_string())]
33    }
34
35    fn entrypoint(&self) -> String {
36        "tasmlib_arithmetic_u32_is_u32".to_string()
37    }
38
39    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
40        triton_asm!(
41            {self.entrypoint()}:
42                        // _ a
43                split   // _ hi lo
44                pop 1   // _ hi
45                push 0  // _ hi 0
46                eq      // _ (hi == 0)
47                return
48        )
49    }
50
51    fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
52        let mut sign_offs = HashMap::new();
53        sign_offs.insert(Reviewer("ferdinand"), 0x95dae6d2fe11abda.into());
54        sign_offs
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::test_prelude::*;
62
63    impl Closure for IsU32 {
64        type Args = BFieldElement;
65
66        fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
67            let value = stack.pop().unwrap();
68            let is_u32 = u32::try_from(value).is_ok();
69            push_encodable(stack, &is_u32);
70        }
71
72        fn pseudorandom_args(
73            &self,
74            seed: [u8; 32],
75            bench_case: Option<BenchmarkCase>,
76        ) -> Self::Args {
77            match bench_case {
78                Some(BenchmarkCase::CommonCase) => bfe!(1 << 16),
79                Some(BenchmarkCase::WorstCase) => bfe!(u32::MAX),
80                None => StdRng::from_seed(seed).random(),
81            }
82        }
83
84        fn corner_case_args(&self) -> Vec<Self::Args> {
85            bfe_vec![0, u32::MAX, u64::from(u32::MAX) + 1, BFieldElement::MAX]
86        }
87    }
88
89    #[test]
90    fn rust_shadow() {
91        ShadowedClosure::new(IsU32).test();
92    }
93}
94
95#[cfg(test)]
96mod benches {
97    use super::*;
98    use crate::test_prelude::*;
99
100    #[test]
101    fn is_u32_benchmark() {
102        ShadowedClosure::new(IsU32).bench();
103    }
104}