tasm_lib/arithmetic/u64/
decr.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, Clone, Copy, Eq, PartialEq, Hash)]
29pub struct Decr;
30
31impl Decr {
32 pub const OVERFLOW_ERROR_ID: i128 = 110;
33}
34
35impl BasicSnippet for Decr {
36 fn inputs(&self) -> Vec<(DataType, String)> {
37 vec![(DataType::U64, "arg".to_string())]
38 }
39
40 fn outputs(&self) -> Vec<(DataType, String)> {
41 vec![(DataType::U64, "(arg-1)".to_string())]
42 }
43
44 fn entrypoint(&self) -> String {
45 "tasmlib_arithmetic_u64_decr".to_string()
46 }
47
48 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
49 let entrypoint = self.entrypoint();
50 let propagate_carry = format!("{entrypoint}_propagate_carry");
51
52 triton_asm!(
53 {entrypoint}:
54 addi -1
55 dup 0
58 push -1
59 eq
60 skiz
61 call {propagate_carry}
62 return
63
64 {propagate_carry}:
67 add
68 dup 0
71 push -1
72 eq
73 push 0
77 eq
78 assert error_id {Self::OVERFLOW_ERROR_ID}
81
82 push {u32::MAX}
83 return
84 )
85 }
86
87 fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
88 let mut sign_offs = HashMap::new();
89 sign_offs.insert(Reviewer("ferdinand"), 0xc7d3ab3d4996bc9c.into());
90 sign_offs
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use crate::test_prelude::*;
98
99 impl Closure for Decr {
100 type Args = u64;
101
102 fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
103 let arg = pop_encodable::<Self::Args>(stack);
104 push_encodable(stack, &arg.checked_sub(1).unwrap());
105 }
106
107 fn pseudorandom_args(
108 &self,
109 seed: [u8; 32],
110 bench_case: Option<BenchmarkCase>,
111 ) -> Self::Args {
112 match bench_case {
113 Some(BenchmarkCase::CommonCase) => 7,
114 Some(BenchmarkCase::WorstCase) => 1 << 35,
115 None => StdRng::from_seed(seed).random_range(1..=u64::MAX),
116 }
117 }
118 }
119
120 #[test]
121 fn rust_shadow() {
122 ShadowedClosure::new(Decr).test();
123 }
124
125 #[test]
126 fn negative_test() {
127 test_assertion_failure(
128 &ShadowedClosure::new(Decr),
129 InitVmState::with_stack(Decr.set_up_test_stack(0)),
130 &[Decr::OVERFLOW_ERROR_ID],
131 );
132 }
133}
134
135#[cfg(test)]
136mod benches {
137 use super::*;
138 use crate::test_prelude::*;
139
140 #[test]
141 fn benchmark() {
142 ShadowedClosure::new(Decr).bench();
143 }
144}