tasm_lib/arithmetic/u32/
is_odd.rs1use std::collections::HashMap;
2use triton_vm::prelude::*;
3
4use crate::prelude::*;
5use crate::traits::basic_snippet::{Reviewer, SignOffFingerprint};
6
7#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
24pub struct IsOdd;
25
26impl BasicSnippet for IsOdd {
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".to_string())]
33 }
34
35 fn entrypoint(&self) -> String {
36 "tasmlib_arithmetic_u32_is_odd".to_string()
37 }
38
39 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
40 triton_asm!(
41 {self.entrypoint()}:
44 push 2
45 pick 1
46 div_mod
47 pick 1
48 pop 1
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"), 0xaa871f100a4a185.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 IsOdd {
66 type Args = u32;
67
68 fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
69 let v = pop_encodable::<Self::Args>(stack);
70 let is_odd = v % 2 == 1;
71 push_encodable(stack, &is_odd);
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) => 1 << 16,
81 Some(BenchmarkCase::WorstCase) => u32::MAX,
82 None => StdRng::from_seed(seed).random(),
83 }
84 }
85
86 fn corner_case_args(&self) -> Vec<Self::Args> {
87 (0..32).chain(u32::MAX - 32..=u32::MAX).collect_vec()
88 }
89 }
90
91 #[test]
92 fn rust_shadow() {
93 ShadowedClosure::new(IsOdd).test();
94 }
95}
96
97#[cfg(test)]
98mod benches {
99 use super::*;
100 use crate::test_prelude::*;
101
102 #[test]
103 fn benchmark() {
104 ShadowedClosure::new(IsOdd).bench();
105 }
106}