tasm_lib/arithmetic/u64/
incr.rs1use 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#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
28pub struct Incr;
29
30impl Incr {
31 pub const OVERFLOW_ERROR_ID: i128 = 440;
32}
33
34impl BasicSnippet for Incr {
35 fn inputs(&self) -> Vec<(DataType, String)> {
36 vec![(DataType::U64, "value".to_string())]
37 }
38
39 fn outputs(&self) -> Vec<(DataType, String)> {
40 vec![(DataType::U64, "value + 1".to_string())]
41 }
42
43 fn entrypoint(&self) -> String {
44 "tasmlib_arithmetic_u64_incr".to_string()
45 }
46
47 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
48 let entrypoint = self.entrypoint();
49 let carry = format!("{entrypoint}_carry");
50 triton_asm!(
51 {entrypoint}:
54 addi 1
55 dup 0
56 push {1_u64 << 32}
57 eq
58 skiz
59 call {carry}
60 return
61
62 {carry}:
63 pop 1
64 addi 1
65 dup 0
66 push {1_u64 << 32}
67 eq
68 push 0
69 eq
70 assert error_id {Self::OVERFLOW_ERROR_ID}
71 push 0
72 return
73 )
74 }
75
76 fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
77 let mut sign_offs = HashMap::new();
78 sign_offs.insert(Reviewer("ferdinand"), 0x786629a8064b2786.into());
79 sign_offs
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use crate::test_prelude::*;
87
88 impl Closure for Incr {
89 type Args = u64;
90
91 fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
92 let v = pop_encodable::<Self::Args>(stack);
93 let incr = v.checked_add(1).unwrap();
94 push_encodable(stack, &incr);
95 }
96
97 fn pseudorandom_args(
98 &self,
99 seed: [u8; 32],
100 bench_case: Option<BenchmarkCase>,
101 ) -> Self::Args {
102 match bench_case {
103 Some(BenchmarkCase::CommonCase) => (1000 << 32) + 7, Some(BenchmarkCase::WorstCase) => (1000 << 32) + u64::from(u32::MAX), None => StdRng::from_seed(seed).random(),
106 }
107 }
108
109 fn corner_case_args(&self) -> Vec<Self::Args> {
110 vec![0, u32::MAX.into(), u64::MAX - 1]
111 }
112 }
113
114 #[test]
115 fn rust_shadow() {
116 ShadowedClosure::new(Incr).test();
117 }
118
119 #[test]
120 fn u64_max_crashes_vm() {
121 test_assertion_failure(
122 &ShadowedClosure::new(Incr),
123 InitVmState::with_stack(Incr.set_up_test_stack(u64::MAX)),
124 &[Incr::OVERFLOW_ERROR_ID],
125 );
126 }
127}
128
129#[cfg(test)]
130mod benches {
131 use super::*;
132 use crate::test_prelude::*;
133
134 #[test]
135 fn benchmark() {
136 ShadowedClosure::new(Incr).bench();
137 }
138}