tasm_lib/arithmetic/u32/
overflowing_add.rs1use triton_vm::prelude::*;
2
3use crate::prelude::*;
4
5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
6pub struct OverflowingAdd;
7
8impl BasicSnippet for OverflowingAdd {
9 fn parameters(&self) -> Vec<(DataType, String)> {
10 vec![
11 (DataType::U32, "lhs".to_owned()),
12 (DataType::U32, "rhs".to_owned()),
13 ]
14 }
15
16 fn return_values(&self) -> Vec<(DataType, String)> {
17 vec![
18 (DataType::U32, "wrapped_sum".to_owned()),
19 (DataType::Bool, "is_overflow".to_owned()),
20 ]
21 }
22
23 fn entrypoint(&self) -> String {
24 "tasmlib_arithmetic_u32_overflowing_add".to_string()
25 }
26
27 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
28 triton_asm!(
29 {self.entrypoint()}:
30 add
31 split
32 swap 1
33 return
34 )
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use crate::test_prelude::*;
42
43 impl Closure for OverflowingAdd {
44 type Args = (u32, u32);
45
46 fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) -> Result<(), RustShadowError> {
47 let (left, right) = pop_encodable::<Self::Args>(stack)?;
48 let (sum, is_overflow) = left.overflowing_add(right);
49
50 push_encodable(stack, &sum);
51 push_encodable(stack, &is_overflow);
52 Ok(())
53 }
54
55 fn pseudorandom_args(
56 &self,
57 seed: [u8; 32],
58 bench_case: Option<BenchmarkCase>,
59 ) -> Self::Args {
60 match bench_case {
61 Some(BenchmarkCase::CommonCase) => (1 << 31, (1 << 31) - 1),
62 Some(BenchmarkCase::WorstCase) => (1 << 31, 1 << 31),
63 None => StdRng::from_seed(seed).random(),
64 }
65 }
66 }
67
68 #[macro_rules_attr::apply(test)]
69 fn u32_overflowing_add_pbt() {
70 ShadowedClosure::new(OverflowingAdd).test()
71 }
72
73 #[macro_rules_attr::apply(test)]
74 fn u32_overflowing_add_unit_test() {
75 for (lhs, rhs) in [
76 (0, 0),
77 (0, 1),
78 (1, 0),
79 (1, 1),
80 (1 << 16, 1 << 16),
81 (1 << 31, 1 << 31),
82 (u32::MAX, u32::MAX),
83 ] {
84 let initial_stack = OverflowingAdd.set_up_test_stack((lhs, rhs));
85
86 let mut expected_final_stack = initial_stack.clone();
87 OverflowingAdd
88 .rust_shadow(&mut expected_final_stack)
89 .unwrap();
90
91 let _vm_output_state = test_rust_equivalence_given_complete_state(
92 &ShadowedClosure::new(OverflowingAdd),
93 &initial_stack,
94 &[],
95 &NonDeterminism::default(),
96 &None,
97 Some(&expected_final_stack),
98 );
99 }
100 }
101}
102
103#[cfg(test)]
104mod benches {
105 use super::*;
106 use crate::test_prelude::*;
107
108 #[macro_rules_attr::apply(test)]
109 fn benchmark() {
110 ShadowedClosure::new(OverflowingAdd).bench()
111 }
112}