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 inputs(&self) -> Vec<(DataType, String)> {
10 vec![
11 (DataType::U32, "lhs".to_owned()),
12 (DataType::U32, "rhs".to_owned()),
13 ]
14 }
15
16 fn outputs(&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>) {
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 }
53
54 fn pseudorandom_args(
55 &self,
56 seed: [u8; 32],
57 bench_case: Option<BenchmarkCase>,
58 ) -> Self::Args {
59 match bench_case {
60 Some(BenchmarkCase::CommonCase) => (1 << 31, (1 << 31) - 1),
61 Some(BenchmarkCase::WorstCase) => (1 << 31, 1 << 31),
62 None => StdRng::from_seed(seed).random(),
63 }
64 }
65 }
66
67 #[test]
68 fn u32_overflowing_add_pbt() {
69 ShadowedClosure::new(OverflowingAdd).test()
70 }
71
72 #[test]
73 fn u32_overflowing_add_unit_test() {
74 for (lhs, rhs) in [
75 (0, 0),
76 (0, 1),
77 (1, 0),
78 (1, 1),
79 (1 << 16, 1 << 16),
80 (1 << 31, 1 << 31),
81 (u32::MAX, u32::MAX),
82 ] {
83 let initial_stack = OverflowingAdd.set_up_test_stack((lhs, rhs));
84
85 let mut expected_final_stack = initial_stack.clone();
86 OverflowingAdd.rust_shadow(&mut expected_final_stack);
87
88 let _vm_output_state = test_rust_equivalence_given_complete_state(
89 &ShadowedClosure::new(OverflowingAdd),
90 &initial_stack,
91 &[],
92 &NonDeterminism::default(),
93 &None,
94 Some(&expected_final_stack),
95 );
96 }
97 }
98}
99
100#[cfg(test)]
101mod benches {
102 use super::*;
103 use crate::test_prelude::*;
104
105 #[test]
106 fn benchmark() {
107 ShadowedClosure::new(OverflowingAdd).bench()
108 }
109}