tasm_lib/arithmetic/u64/
wrapping_mul.rs

1use 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, Copy, Clone, Eq, PartialEq, Hash)]
10pub struct WrappingMul;
11
12impl BasicSnippet for WrappingMul {
13    fn inputs(&self) -> Vec<(DataType, String)> {
14        ["rhs", "lhs"]
15            .map(|side| (DataType::U64, side.to_string()))
16            .to_vec()
17    }
18
19    fn outputs(&self) -> Vec<(DataType, String)> {
20        vec![(DataType::U64, "product".to_string())]
21    }
22
23    fn entrypoint(&self) -> String {
24        "tasmlib_arithmetic_u64_wrapping_mul".to_string()
25    }
26
27    fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
28        triton_asm!(
29            // BEFORE: _ right_hi right_lo left_hi left_lo
30            // AFTER:  _ prod_hi prod_lo
31            {self.entrypoint()}:
32                /* left_lo · right_lo */
33                dup 0
34                dup 3
35                mul
36                // _ right_hi right_lo left_hi left_lo (left_lo · right_lo)
37
38                /* left_lo · right_hi (consume both) */
39                swap 4
40                mul
41                // _ (left_lo · right_lo) right_lo left_hi (left_lo · right_hi)
42
43                /* left_hi · right_lo (consume both) */
44                swap 2
45                mul
46                // _ (left_lo · right_lo) (left_lo · right_hi) (left_hi · right_lo)
47                // _ lolo                 lohi                 hilo
48
49                /* prod_hi = lolo_hi + lohi_lo + hilo_lo */
50                split
51                pick 1
52                pop 1
53                // _ lolo lohi hilo_lo
54
55                pick 1
56                split
57                pick 1
58                pop 1
59                // _ lolo hilo_lo lohi_lo
60
61                pick 2
62                split
63                // _ hilo_lo lohi_lo lolo_hi lolo_lo
64                // _ hilo_lo lohi_lo lolo_hi prod_lo
65
66                place 3
67                add
68                add
69                // _ prod_lo (hilo_lo + lohi_lo + lolo_hi)
70
71                split
72                pick 1
73                pop 1
74                // _ prod_lo (hilo_lo + lohi_lo + lolo_hi)_lo
75                // _ prod_lo prod_hi
76
77                place 1
78                return
79        )
80    }
81
82    fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
83        let mut sign_offs = HashMap::new();
84        sign_offs.insert(Reviewer("ferdinand"), 0x98526c7c401009ed.into());
85        sign_offs
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92    use crate::test_prelude::*;
93
94    impl Closure for WrappingMul {
95        type Args = (u64, u64);
96
97        fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
98            let (right, left) = pop_encodable::<Self::Args>(stack);
99            push_encodable(stack, &left.wrapping_mul(right));
100        }
101
102        fn pseudorandom_args(
103            &self,
104            seed: [u8; 32],
105            bench_case: Option<BenchmarkCase>,
106        ) -> Self::Args {
107            match bench_case {
108                Some(BenchmarkCase::CommonCase) => (1 << 31, (1 << 25) - 1),
109                Some(BenchmarkCase::WorstCase) => (1 << 53, (1 << 33) - 1),
110                None => StdRng::from_seed(seed).random(),
111            }
112        }
113    }
114
115    #[test]
116    fn rust_shadow() {
117        ShadowedClosure::new(WrappingMul).test();
118    }
119}
120
121#[cfg(test)]
122mod benches {
123    use super::*;
124    use crate::test_prelude::*;
125
126    #[test]
127    fn benchmark() {
128        ShadowedClosure::new(WrappingMul).bench();
129    }
130}