tasm_lib/arithmetic/u128/
shift_right_static.rs1use triton_vm::prelude::*;
2
3use crate::prelude::*;
4
5#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
27pub struct ShiftRightStatic<const N: u8>;
28
29impl<const N: u8> BasicSnippet for ShiftRightStatic<N> {
30 fn inputs(&self) -> Vec<(DataType, String)> {
31 vec![(DataType::U128, "value".to_string())]
32 }
33
34 fn outputs(&self) -> Vec<(DataType, String)> {
35 vec![(DataType::U128, "shifted_value".to_string())]
36 }
37
38 fn entrypoint(&self) -> String {
39 format!("tasmlib_arithmetic_u128_shift_right_static_{N}")
40 }
41
42 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
43 assert!(N <= 32, "shift amount must be in range 0..=32");
44
45 triton_asm!(
46 {self.entrypoint()}:
49 pick 3
50 push {1_u64 << (32 - N)}
51 mul
52 place 3 push {1_u64 << (32 - N)}
54 xb_mul pick 3
58 split
59 pick 4
60 split
61 pick 5
62 split
63 pick 6
64 split
65
66 pop 1
67 add
68 place 4
69 add
70 place 3
71 add
72 place 2
73
74 return
75 )
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use crate::arithmetic::u128::shift_left_static::ShiftLeftStatic;
83 use crate::test_prelude::*;
84
85 impl<const N: u8> Closure for ShiftRightStatic<N> {
86 type Args = <ShiftLeftStatic<N> as Closure>::Args;
87
88 fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
89 let v = pop_encodable::<Self::Args>(stack);
90 push_encodable(stack, &(v >> N));
91 }
92
93 fn pseudorandom_args(
94 &self,
95 seed: [u8; 32],
96 bench_case: Option<BenchmarkCase>,
97 ) -> Self::Args {
98 ShiftLeftStatic::<N>.pseudorandom_args(seed, bench_case)
99 }
100
101 fn corner_case_args(&self) -> Vec<Self::Args> {
102 ShiftLeftStatic::<N>.corner_case_args()
103 }
104 }
105
106 #[test]
107 fn rust_shadow() {
108 macro_rules! test_shift_right_static {
109 ($($i:expr),*$(,)?) => {
110 $(ShadowedClosure::new(ShiftRightStatic::<$i>).test();)*
111 };
112 }
113
114 test_shift_right_static!(0, 1, 2, 3, 4, 5, 6, 7);
115 test_shift_right_static!(8, 9, 10, 11, 12, 13, 14, 15);
116 test_shift_right_static!(16, 17, 18, 19, 20, 21, 22, 23);
117 test_shift_right_static!(24, 25, 26, 27, 28, 29, 30, 31);
118 test_shift_right_static!(32);
119 }
120
121 #[test]
122 #[should_panic]
123 fn shift_beyond_limit() {
124 ShadowedClosure::new(ShiftRightStatic::<33>).test();
125 }
126}
127
128#[cfg(test)]
129mod benches {
130 use super::*;
131 use crate::test_prelude::*;
132
133 #[test]
134 fn benchmark() {
135 ShadowedClosure::new(ShiftRightStatic::<5>).bench();
136 }
137}