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