Skip to main content

tfhe/integer/bigint/
u512.rs

1pub type U512 = super::static_unsigned::StaticUnsignedBigInt<8>;
2
3impl From<(u128, u128, u128, u128)> for U512 {
4    fn from((value0, value1, value2, value3): (u128, u128, u128, u128)) -> Self {
5        Self([
6            (value0 & u128::from(u64::MAX)) as u64,
7            (value0 >> 64) as u64,
8            (value1 & u128::from(u64::MAX)) as u64,
9            (value1 >> 64) as u64,
10            (value2 & u128::from(u64::MAX)) as u64,
11            (value2 >> 64) as u64,
12            (value3 & u128::from(u64::MAX)) as u64,
13            (value3 >> 64) as u64,
14        ])
15    }
16}
17
18#[cfg(test)]
19mod tests {
20    use super::super::{u64_with_even_bits_set, u64_with_odd_bits_set};
21    use super::*;
22    use std::panic::catch_unwind;
23
24    #[test]
25    fn test_const() {
26        assert_eq!(U512::BITS, 512);
27    }
28
29    #[test]
30    fn test_u64_even_odd_bits() {
31        let all_even_bits_set = u64_with_even_bits_set();
32        let all_odd_bits_set = u64_with_odd_bits_set();
33
34        assert_ne!(all_odd_bits_set, all_even_bits_set);
35
36        assert_eq!(all_even_bits_set.rotate_right(1), all_odd_bits_set);
37        assert_eq!(all_even_bits_set, all_odd_bits_set.rotate_left(1));
38    }
39
40    #[test]
41    fn test_bitand() {
42        let all_even_bits_set = U512::from([u64_with_even_bits_set(); 8]);
43        let all_odd_bits_set = U512::from([u64_with_odd_bits_set(); 8]);
44
45        assert_ne!(all_odd_bits_set, all_even_bits_set);
46        assert_eq!(all_odd_bits_set & all_odd_bits_set, all_odd_bits_set);
47        assert_eq!(all_even_bits_set & all_even_bits_set, all_even_bits_set);
48        assert_eq!(all_even_bits_set & all_odd_bits_set, U512::ZERO);
49    }
50
51    #[test]
52    fn test_bitor() {
53        let all_even_bits_set = U512::from([u64_with_even_bits_set(); 8]);
54        let all_odd_bits_set = U512::from([u64_with_odd_bits_set(); 8]);
55
56        assert_ne!(all_odd_bits_set, all_even_bits_set);
57        assert_eq!(all_odd_bits_set | all_odd_bits_set, all_odd_bits_set);
58        assert_eq!(all_even_bits_set | all_even_bits_set, all_even_bits_set);
59        assert_eq!(all_even_bits_set | all_odd_bits_set, U512::MAX);
60    }
61
62    #[test]
63    fn test_bitxor() {
64        let all_even_bits_set = U512::from([u64_with_even_bits_set(); 8]);
65        let all_odd_bits_set = U512::from([u64_with_odd_bits_set(); 8]);
66
67        assert_ne!(all_odd_bits_set, all_even_bits_set);
68        assert_eq!(all_odd_bits_set ^ all_odd_bits_set, U512::ZERO);
69        assert_eq!(all_even_bits_set ^ all_even_bits_set, U512::ZERO);
70        assert_eq!(all_even_bits_set ^ all_odd_bits_set, U512::MAX);
71    }
72
73    #[test]
74    fn test_is_power_of_two() {
75        assert!(!U512::ZERO.is_power_of_two());
76        assert!(!U512::MAX.is_power_of_two());
77        assert!(!U512::from(8329842348123u64).is_power_of_two());
78
79        for i in 0..U512::BITS {
80            assert!((U512::ONE << i).is_power_of_two());
81        }
82    }
83
84    #[test]
85    fn test_ilog2() {
86        assert!(catch_unwind(|| { U512::ZERO.ilog2() }).is_err());
87
88        assert_eq!(U512::MAX.ilog2(), 511);
89        assert_eq!(
90            U512::from(8329842348123u64).ilog2(),
91            8329842348123u64.ilog2()
92        );
93
94        assert_eq!(
95            U512::from(8320912948329842348123u128).ilog2(),
96            8320912948329842348123u128.ilog2()
97        );
98
99        assert_eq!(
100            U512::from(2323912928329942718123u128).ilog2(),
101            2323912928329942718123u128.ilog2()
102        );
103
104        for i in 0..U512::BITS {
105            assert_eq!((U512::ONE << i).ilog2(), i);
106        }
107    }
108
109    #[test]
110    fn test_add_wrap_around() {
111        assert_eq!(U512::MAX + U512::from(1u32), U512::MIN);
112    }
113
114    #[test]
115    fn test_sub_wrap_around() {
116        assert_eq!(U512::MIN - U512::from(1u32), U512::MAX);
117    }
118
119    #[test]
120    fn test_bitnot() {
121        assert_eq!(!U512::MAX, U512::MIN);
122        assert_eq!(!U512::MIN, U512::MAX);
123
124        // To prove we are testing the correct thing
125        assert_eq!(!u128::MAX, u128::MIN);
126        assert_eq!(!u128::MIN, u128::MAX);
127    }
128
129    #[test]
130    fn test_shl_limits() {
131        assert_eq!(U512::ONE << 512u32, U512::ONE << (512u32 % U512::BITS));
132        assert_eq!(U512::ONE << 513u32, U512::ONE << (513u32 % U512::BITS));
133
134        // We aim to have same behaviour as rust native types
135        assert_eq!(1u128.wrapping_shl(128), 1u128 << (128 % u128::BITS));
136        assert_eq!(1u128.wrapping_shl(129), 1u128 << (129 % u128::BITS));
137    }
138
139    #[test]
140    #[allow(clippy::identity_op)]
141    fn test_shr_limits() {
142        assert_eq!(U512::MAX >> 512u32, U512::MAX >> (512u32 % U512::BITS));
143        assert_eq!(U512::MAX >> 513u32, U512::MAX >> (513u32 % U512::BITS));
144
145        // We aim to have same behaviour as rust native types
146        assert_eq!(u128::MAX.wrapping_shr(128), u128::MAX >> (128 % u128::BITS));
147        assert_eq!(u128::MAX.wrapping_shr(129), u128::MAX >> (129 % u128::BITS));
148    }
149
150    #[test]
151    fn test_div_rem() {
152        let a = U512::from([
153            14069555808489703714,
154            3908590842307590452,
155            9855978718424440147,
156            13896218366640697882,
157            12201638264960915474,
158            18057167307258037924,
159            3883391760393286388,
160            13564609649884598296,
161        ]);
162
163        let b = U512::from([
164            13572348791597489471,
165            13066001923991081603,
166            15152085515464322039,
167            5769296961266547928,
168            4345306966403270406,
169            14861723594231331435,
170            12450980561267212543,
171            13551971813301316858,
172        ]);
173
174        let expected_d = U512::from([1, 0, 0, 0, 0, 0, 0, 0]);
175
176        let expected_r = U512::from([
177            497207016892214243,
178            9289332992026060465,
179            13150637276669669723,
180            8126921405374149953,
181            7856331298557645068,
182            3195443713026706489,
183            9879155272835625461,
184            12637836583281437,
185        ]);
186
187        let d = a / b;
188        let r = a % b;
189        assert_eq!(d, expected_d);
190        assert_eq!(r, expected_r);
191
192        let a = U512::from([
193            3916138088563380184,
194            11471505607132531241,
195            11764394181449351249,
196            3009844506142576707,
197            5954421029540908215,
198            493654323038934126,
199            6030625548640772789,
200            12886253569586615920,
201        ]);
202
203        let b = U512::from([
204            15734844303166734968,
205            18157387122068819778,
206            7947001930394566593,
207            11842813283329086337,
208            13455790396220372987,
209            16771555752599506498,
210            12734235444062124671,
211            984106389135760972,
212        ]);
213
214        let expected_d = U512::from([13, 0, 0, 0, 0, 0, 0, 0]);
215
216        let expected_r = U512::from([
217            2277346958200893376,
218            15233145978462045124,
219            687089454867743607,
220            15073968486250418865,
221            15496586615771575535,
222            3824358423759969034,
223            6506261439219116598,
224            92870510821723275,
225        ]);
226
227        let d = a / b;
228        let r = a % b;
229        assert_eq!(d, expected_d);
230        assert_eq!(r, expected_r);
231    }
232
233    #[test]
234    fn test_mul() {
235        let a = U512::from([
236            14069555808489703714,
237            3908590842307590452,
238            9855978718424440147,
239            13896218366640697882,
240            12201638264960915474,
241            18057167307258037924,
242            3883391760393286388,
243            13564609649884598296,
244        ]);
245
246        let b = U512::from([
247            13572348791597489471,
248            13066001923991081603,
249            15152085515464322039,
250            5769296961266547928,
251            4345306966403270406,
252            14861723594231331435,
253            12450980561267212543,
254            13551971813301316858,
255        ]);
256
257        let expected_result = U512::from([
258            4156026748591446366,
259            5494944174831101103,
260            18238946655790339985,
261            7541952578616659641,
262            13348226788602217476,
263            12942926403796405442,
264            8114377417900506174,
265            14085526951817456422,
266        ]);
267
268        let result = a * b;
269        assert_eq!(result, expected_result);
270
271        let a = U512::from([
272            3916138088563380184,
273            11471505607132531241,
274            11764394181449351249,
275            3009844506142576707,
276            5954421029540908215,
277            493654323038934126,
278            6030625548640772789,
279            12886253569586615920,
280        ]);
281
282        let b = U512::from([
283            15734844303166734968,
284            18157387122068819778,
285            7947001930394566593,
286            11842813283329086337,
287            13455790396220372987,
288            16771555752599506498,
289            12734235444062124671,
290            984106389135760972,
291        ]);
292
293        let expected_result = U512::from([
294            959128001500093760,
295            16717200888364732243,
296            4987629022208480162,
297            13025491345955469749,
298            3380626290232599789,
299            4346647371474752052,
300            13274445184588134645,
301            9592080887013845353,
302        ]);
303
304        let result = a * b;
305        assert_eq!(result, expected_result);
306    }
307
308    #[test]
309    fn test_le_byte_slice() {
310        // Create a u128 where each bytes stores its index:
311        // u128 as &[u8] = [0u8, 1 , 2, 3, .., 15]
312        let v0 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| i as u8));
313        let v1 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 16 + i as u8));
314        let v2 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 32 + i as u8));
315        let v3 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 48 + i as u8));
316
317        let mut le_bytes = vec![0u8; 64];
318        le_bytes[..16].copy_from_slice(v0.to_le_bytes().as_slice());
319        le_bytes[16..32].copy_from_slice(v1.to_le_bytes().as_slice());
320        le_bytes[32..48].copy_from_slice(v2.to_le_bytes().as_slice());
321        le_bytes[48..].copy_from_slice(v3.to_le_bytes().as_slice());
322
323        let mut b = U512::from(1u128 << 64); // To make sure copy cleans self
324        b.copy_from_le_byte_slice(le_bytes.as_slice());
325
326        assert_eq!(b, U512::from((v0, v1, v2, v3)));
327
328        let mut le_bytes_2 = vec![0u8; 64];
329        b.copy_to_le_byte_slice(&mut le_bytes_2);
330
331        assert_eq!(le_bytes_2, le_bytes);
332    }
333
334    #[test]
335    fn test_be_byte_slice() {
336        let v0 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| i as u8));
337        let v1 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 16 + i as u8));
338        let v2 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 32 + i as u8));
339        let v3 = u128::from_le_bytes(core::array::from_fn::<u8, 16, _>(|i| 48 + i as u8));
340
341        let mut be_bytes = vec![0u8; 64];
342        be_bytes[..16].copy_from_slice(v3.to_be_bytes().as_slice());
343        be_bytes[16..32].copy_from_slice(v2.to_be_bytes().as_slice());
344        be_bytes[32..48].copy_from_slice(v1.to_be_bytes().as_slice());
345        be_bytes[48..].copy_from_slice(v0.to_be_bytes().as_slice());
346
347        let mut b = U512::from(1u128 << 64); // To make sure copy cleans self
348        b.copy_from_be_byte_slice(be_bytes.as_slice());
349
350        assert_eq!(b, U512::from((v0, v1, v2, v3)));
351
352        let mut be_bytes_2 = vec![0u8; 64];
353        b.copy_to_be_byte_slice(&mut be_bytes_2);
354
355        assert_eq!(be_bytes_2, be_bytes);
356    }
357}