radix_common/math/bnum_integer/
test.rs

1#[cfg(test)]
2use super::*;
3use paste::paste;
4
5#[cfg(test)]
6use num_bigint::{BigInt, Sign};
7
8use radix_common::*;
9#[allow(unused_imports)] // It's needed by the `test_impl!` macro
10use sbor::rust::cmp::Ordering;
11
12test_impl! {I192, I256, I320, I384, I448, I512, I768}
13test_impl! {U192, U256, U320, U384, U448, U512, U768}
14
15test_add_all! {
16    (I192, I256, I320, I384, I448, I512, I768,
17     U192, U256, U320, U384, U448, U512, U768),
18    (I192, I256, I320, I384, I448, I512, I768,
19     U192, U256, U320, U384, U448, U512, U768)
20}
21
22test_signed! { I192, I256, I320, I384, I448, I512, I768 }
23test_unsigned! { U192, U256, U320, U384, U448, U512, U768 }
24
25test_from_all_types_safe_builtin! {I192, (i8, i16, i32, i64, i128)}
26test_from_all_types_safe_builtin! {I192, (u8, u16, u32, u64, u128)}
27
28test_from_all_types_safe_builtin! {I256, (i8, i16, i32, i64, i128)}
29test_from_all_types_safe_builtin! {I256, (u8, u16, u32, u64, u128)}
30
31test_from_all_types_safe_builtin! {I320, (i8, i16, i32, i64, i128)}
32test_from_all_types_safe_builtin! {I320, (u8, u16, u32, u64, u128)}
33
34test_from_all_types_safe_builtin! {I384, (i8, i16, i32, i64, i128)}
35test_from_all_types_safe_builtin! {I384, (u8, u16, u32, u64, u128)}
36
37test_from_all_types_safe_builtin! {I448, (i8, i16, i32, i64, i128)}
38test_from_all_types_safe_builtin! {I448, (u8, u16, u32, u64, u128)}
39
40test_from_all_types_safe_builtin! {I512, (i8, i16, i32, i64, i128)}
41test_from_all_types_safe_builtin! {I512, (u8, u16, u32, u64, u128)}
42
43test_from_all_types_safe_builtin! {I768, (i8, i16, i32, i64, i128)}
44test_from_all_types_safe_builtin! {I768, (u8, u16, u32, u64, u128)}
45
46test_from_all_types_safe_builtin! {U192, (u8, u16, u32, u64, u128)}
47test_from_all_types_safe_builtin! {U256, (u8, u16, u32, u64, u128)}
48test_from_all_types_safe_builtin! {U320, (u8, u16, u32, u64, u128)}
49test_from_all_types_safe_builtin! {U384, (u8, u16, u32, u64, u128)}
50test_from_all_types_safe_builtin! {U448, (u8, u16, u32, u64, u128)}
51test_from_all_types_safe_builtin! {U512, (u8, u16, u32, u64, u128)}
52test_from_all_types_safe_builtin! {U768, (u8, u16, u32, u64, u128)}
53
54test_from_all_types_safe_safe! {I192, (I256, I320, I384, I448, I512, I768)}
55test_from_all_types_safe_safe! {I256, (I192, I320, I384, I448, I512, I768)}
56test_from_all_types_safe_safe! {I320, (I192, I256, I384, I448, I512, I768)}
57test_from_all_types_safe_safe! {I384, (I192, I256, I320, I448, I512, I768)}
58test_from_all_types_safe_safe! {I448, (I192, I256, I320, I384, I512, I768)}
59test_from_all_types_safe_safe! {I512, (I192, I256, I320, I384, I448, I768)}
60test_from_all_types_safe_safe! {I768, (I192, I256, I320, I384, I448, I512)}
61
62test_from_all_types_safe_safe! {U192, (U256, U320, U384, U448, U512, U768)}
63test_from_all_types_safe_safe! {U256, (U192, U320, U384, U448, U512, U768)}
64test_from_all_types_safe_safe! {U320, (U192, U256, U384, U448, U512, U768)}
65test_from_all_types_safe_safe! {U384, (U192, U256, U320, U448, U512, U768)}
66test_from_all_types_safe_safe! {U448, (U192, U256, U320, U384, U512, U768)}
67test_from_all_types_safe_safe! {U512, (U192, U256, U320, U384, U448, U768)}
68test_from_all_types_safe_safe! {U768, (U192, U256, U320, U384, U448, U512)}
69
70#[cfg(test)]
71macro_rules! assert_int_size {
72    ($($bits: literal $t: ident),*)  => {
73        $(
74            assert_eq!($t::BITS, $bits);
75        )*
76    }
77}
78
79#[test]
80fn test_int_size() {
81    assert_int_size! {
82        192 I192,
83        256 I256,
84        320 I320,
85        384 I384,
86        448 I448,
87        512 I512,
88        768 I768,
89        192 U192,
90        256 U256,
91        320 U320,
92        384 U384,
93        448 U448,
94        512 U512,
95        768 U768
96    }
97}
98
99#[cfg(test)]
100macro_rules! test_bnums {
101    ($($t: ident),*)  => {
102        paste! {
103            $(
104                #[test]
105                fn [<test_ $t:lower _add>] () {
106                    assert_eq!((<$t>::ONE + <$t>::ONE).to_string(), "2");
107                    assert_eq!(<$t>::from(17_u32) + <$t>::from(31_u32), <$t>::from(48_u32));
108                    let mut bnum = <$t>::ONE;
109                    bnum += <$t>::from_str("101").unwrap();
110                    assert_eq!(bnum, <$t>::from_str("102").unwrap());
111
112                    if <$t>::MIN < <$t>::ZERO {
113                        let mut bnum = <$t>::MAX;
114                        bnum += <$t>::try_from(-1_i32).unwrap();
115                        assert_eq!(bnum, <$t>::MAX - <$t>::ONE);
116
117                        assert_eq!(<$t>::MIN + <$t>::MAX, <$t>::ZERO - <$t>::ONE);
118                    }
119                }
120
121                #[test]
122                fn [< test_ $t:lower _sub >]() {
123                    assert_eq!(<$t>::ONE - <$t>::ONE, <$t>::ZERO);
124
125                    if <$t>::MIN < <$t>::ZERO {
126                        assert_eq!(<$t>::from(17_u32) - <$t>::from(31_u32), <$t>::try_from(-14).unwrap());
127                        let mut bnum = <$t>::from(101_u32);
128                        bnum -= <$t>::from_str("102").unwrap();
129                        assert_eq!(bnum, <$t>::from_str("-1").unwrap());
130                    }
131
132                    let mut bnum = <$t>::MAX;
133                    bnum -= <$t>::ONE;
134                    assert_eq!(bnum, <$t>::MAX - <$t>::ONE);
135                }
136
137                #[test]
138                #[should_panic(expected = "Overflow")]
139                fn [<test_ $t:lower _add_overflow_panic_1>] () {
140                    let mut bnum = <$t>::MAX;
141                    bnum += <$t>::from(1_u32);
142                }
143
144                #[test]
145                #[should_panic(expected = "Overflow")]
146                fn [< test_ $t:lower _sub_overflow_panic_2 >]() {
147                    let mut bnum = <$t>::MIN;
148                    bnum -= <$t>::ONE;
149                }
150
151                #[test]
152                fn [< test_ $t:lower _mul >]() {
153                    assert_eq!(<$t>::from(4_u32) * <$t>::from(5_u32), <$t>::from(20_u32));
154                    let mut bnum = <$t>::from(12387_u32);
155                    bnum *= <$t>::from_str("1203203031").unwrap();
156                    assert_eq!(bnum, <$t>::from(14904075944997_u128));
157
158                    if <$t>::MIN < <$t>::ZERO {
159                        let mut bnum = <$t>::from(12387_u32);
160                        bnum *= <$t>::from_str("-1203203031").unwrap();
161                        assert_eq!(bnum, <$t>::try_from(-14904075944997_i128).unwrap());
162                    }
163                }
164
165                #[test]
166                #[should_panic(expected = "Overflow")]
167                fn [< test_ $t:lower _mul_overflow_panic_1 >] () {
168                    let mut bnum = <$t>::MAX;
169                    bnum *= <$t>::from(2_u32);
170                }
171
172
173                #[test]
174                fn [< test_ $t:lower _pow >](){
175                    assert_eq!(<$t>::from(3_u32).pow(3), <$t>::from(27_u32));
176
177                    assert_eq!(
178                        <$t>::from(153_u32).pow(20),
179                        <$t>::from_str("49411565790213547262766437937260727785410401").unwrap()
180                    );
181                    assert_eq!(
182                        <$t>::from(153_u32).pow(25),
183                        <$t>::from_str("4142721807044360524568533828494071080154747151557663193").unwrap()
184                    );
185                }
186
187                #[test]
188                #[should_panic(expected = "Overflow")]
189                fn [< test_ $t:lower _pow_overflow_panic_1 >]() {
190                    if <$t>::BITS == 192 {
191                        let _ = <$t>::from(153_u32).pow(40);
192                    } else if <$t>::BITS == 256 {
193                        let _ = <$t>::from(153_u32).pow(40);
194                    } else if <$t>::BITS == 320 {
195                        let _ = <$t>::from(153_u32).pow(60);
196                    } else if <$t>::BITS == 384 {
197                        let _ = <$t>::from(153_u32).pow(60);
198                    } else if <$t>::BITS == 448 {
199                        let _ = <$t>::from(153_u32).pow(70);
200                    } else if <$t>::BITS == 512 {
201                        let _ = <$t>::from(153_u32).pow(80);
202                    } else if <$t>::BITS == 768 {
203                        let _ = <$t>::from(153_u32).pow(120);
204                    } else {
205                        panic!("Unknown bits size {}", <$t>::BITS);
206                    }
207                }
208
209                #[test]
210                fn [< test_ $t:lower _root >]() {
211                    assert_eq!(<$t>::from(9_u32).sqrt(), <$t>::from(3_u32));
212                    assert_eq!(<$t>::from(27_u32).cbrt(), <$t>::from(3_u32));
213
214                    assert_eq!(<$t>::from(9_u32).nth_root(2), <$t>::from(3_u32));
215                    assert_eq!(<$t>::from(27_u32).nth_root(3), <$t>::from(3_u32));
216                    assert_eq!(<$t>::from(14966675814359580587845230627_u128).nth_root(13), <$t>::from(147_u32));
217                    assert_eq!(
218                        <$t>::from_str("290437112829027226192310037731274304321654649956335616").unwrap().nth_root(17),
219                        <$t>::from_str("1396").unwrap()
220                    );
221
222                    if <$t>::MIN < <$t>::ZERO {
223                        assert_eq!(<$t>::try_from(-27).unwrap().nth_root(3), <$t>::try_from(-3).unwrap());
224                        assert_eq!(<$t>::try_from(-14966675814359580587845230627_i128).unwrap().nth_root(13), <$t>::try_from(-147).unwrap());
225                    }
226                }
227
228                #[test]
229                fn [< test_ $t:lower _to_string >]() {
230                    assert_eq!(<$t>::ONE.to_string(), "1");
231                    assert_eq!(<$t>::ZERO.to_string(), "0");
232                    assert_eq!(<$t>::from_str("0").unwrap(), <$t>::ZERO);
233
234                    if <$t>::MIN < <$t>::ZERO {
235                        assert_eq!(<$t>::try_from(-1).unwrap().to_string(), "-1");
236
237                        assert_eq!(<$t>::from_str("-1").unwrap(), <$t>::try_from(-1).unwrap());
238                    }
239                }
240
241                #[test]
242                fn [< test_ $t:lower _to_primitive_ints >] () {
243                    assert_eq!(<$t>::from_i8(1).unwrap(), <$t>::ONE);
244                    assert_eq!(<$t>::try_from(21).unwrap().to_string(), "21");
245                    assert_eq!(<$t>::from(21_u8).to_string(), "21");
246
247                    let bnum: $t = 21_u32.into();
248                    assert_eq!(bnum.to_string(), 21.to_string());
249
250                    let i: i128 = <$t>::from(21_u8).try_into().unwrap();
251                    assert_eq!(i, 21_i128);
252
253                    let val = u8::try_from(<$t>::from(300_u32)).unwrap_err();
254                    assert_eq!(val, [< Parse $t Error >]::Overflow);
255
256                    if <$t>::MIN < <$t>::ZERO {
257                        let val = u8::try_from(<$t>::try_from(-300_i32).unwrap()).unwrap_err();
258                        assert_eq!(val, [< Parse $t Error >]::Overflow);
259                    }
260                }
261
262                #[test]
263                #[should_panic(expected = "Err")]
264                fn [< test_ $t:lower _from_string_panic_1 >]() {
265                    assert_eq!(<$t>::from_str("0x01").unwrap(), <$t>::try_from(-1).unwrap());
266                }
267
268                #[test]
269                #[should_panic(expected = "Overflow")]
270                fn [< test_ $t:lower _to_u128_panic >]() {
271                    if <$t>::MIN < <$t>::ZERO {
272                        let _u: u128 = <$t>::try_from(-21).unwrap().try_into().unwrap();
273                    } else {
274                        let _u: u128 = <$t>::from_str("290437112829027226192310037731274304321654649956335616").unwrap().try_into().unwrap();
275                    }
276                }
277                #[test]
278                #[should_panic(expected = "Overflow")]
279                fn [< test_ $t:lower _to_i8_panic >]() {
280                    let _i: i8 = <$t>::try_from(-260).unwrap().try_into().unwrap();
281                }
282
283                #[test]
284                #[should_panic(expected = "Overflow")]
285                fn [< test_ $t:lower _u16_panic >]() {
286                    let _i: u16 = <$t>::from(123123123_u32).try_into().unwrap();
287                }
288
289            )*
290        }
291    }
292}
293
294#[cfg(test)]
295test_bnums! { I192, I256, I320, I384, I448, I512, I768 }
296#[cfg(test)]
297test_bnums! { U192, U256, U320, U384, U448, U512, U768 }
298
299#[cfg(test)]
300macro_rules! test_bnums_signed {
301    ($($t: ident),*)  => {
302        paste! {
303            $(
304                #[test]
305                #[should_panic(expected = "Overflow")]
306                fn [< test_ $t:lower _mul_overflow_panic_2 >] () {
307                    let bnum = <$t>::MIN;
308                    let _m = bnum.mul(<$t>::from(2));
309                }
310
311            )*
312        }
313    }
314}
315#[cfg(test)]
316test_bnums_signed! { I192, I256, I320, I384, I448, I512, I768 }
317
318#[test]
319#[should_panic(expected = "Err")]
320fn test_string_to_bnum_panic_2() {
321    assert_eq!(
322        I256::MAX,
323        I256::from_str(
324            "578960446186580977117854925043439539266349923328202820197287920039565648199670"
325        )
326        .unwrap()
327    );
328}
329
330macro_rules! test_to_from_bigint {
331    ($($t: ident),*)  => {
332        paste!{
333            $(
334                #[test]
335                fn [<test_to_from_bigint_ $t:lower>]() {
336                    assert_eq!($t::try_from(BigInt::from(147)).unwrap(), $t::from(147_u32));
337
338                    assert_eq!(
339                        $t::try_from(BigInt::from(1470198230918_i128)).unwrap(),
340                        $t::from(1470198230918_u128)
341                    );
342
343                    let big = BigInt::from($t::MAX) + BigInt::from(1);
344                    let err = $t::try_from(big).unwrap_err();
345                    assert_eq!(err, [<Parse $t Error>]::Overflow);
346
347                    assert_eq!(BigInt::try_from($t::from(123_u32)).unwrap(), BigInt::from(123));
348                    assert_eq!(BigInt::from($t::ONE), BigInt::from(1));
349
350                    assert_eq!(
351                        BigInt::from($t::MAX),
352                        BigInt::from_str(
353                            &$t::MAX.to_string()
354                        )
355                        .unwrap()
356                    );
357
358                    assert_eq!(
359                        BigInt::from($t::MIN),
360                        BigInt::from_str(
361                            &$t::MIN.to_string()
362                        )
363                        .unwrap()
364                    );
365
366                    // test signed types
367                    if $t::MIN != $t::ZERO {
368                        assert_eq!($t::try_from(BigInt::from(-147)).unwrap(), $t::try_from(-147).unwrap());
369                        assert_eq!(
370                            $t::try_from(BigInt::from(-1470198230918_i128)).unwrap(),
371                            $t::try_from(-1470198230918_i128).unwrap()
372                        );
373                        let big = BigInt::from($t::MIN) - BigInt::from(1);
374                        let err = $t::try_from(big).unwrap_err();
375                        assert_eq!(err, [<Parse $t Error>]::Overflow);
376                    }
377                }
378            )*
379        }
380    }
381}
382test_to_from_bigint! { I192, I256, I320, I384, I448, I512, I768 }
383test_to_from_bigint! { U192, U256, U320, U384, U448, U512, U768 }
384
385#[test]
386fn test_bnum_to_bnum() {
387    let a = I192::from(1);
388    let b = U192::try_from(a).unwrap();
389    assert_eq!(b, U192::ONE);
390
391    let a = I256::from(1);
392    let b = U256::try_from(a).unwrap();
393    assert_eq!(b, U256::ONE);
394
395    let a = I256::from(-123);
396    let b = I512::from(a);
397    assert_eq!(a.to_string(), b.to_string());
398
399    let a = I256::MAX;
400    let b = U256::try_from(a).unwrap();
401    assert_eq!(a.to_string(), b.to_string());
402
403    let a = I256::MIN;
404    let b = I512::from(a);
405    assert_eq!(a.to_string(), b.to_string());
406
407    let a = U256::MAX;
408    let b = I512::from(a);
409    assert_eq!(a.to_string(), b.to_string());
410
411    let a = U256::MAX;
412    let b = I384::from(a);
413    assert_eq!(a.to_string(), b.to_string());
414}
415
416#[test]
417fn test_bnum_to_bnum_errors() {
418    let i512 = I512::MIN;
419    let err = I192::try_from(i512).unwrap_err();
420    assert_eq!(err, ParseI192Error::Overflow);
421
422    let i512 = I512::MIN;
423    let err = I256::try_from(i512).unwrap_err();
424    assert_eq!(err, ParseI256Error::Overflow);
425
426    // I256::MAX + 1
427    let i256_str = I256::MAX.to_string();
428    let i512 = I512::from_str(&i256_str).unwrap() + I512::ONE;
429    let err = I256::try_from(i512).unwrap_err();
430    assert_eq!(err, ParseI256Error::Overflow);
431
432    // I256::MIN - 1
433    let i256_str = I256::MIN.to_string();
434    let i512 = I512::from_str(&i256_str).unwrap() - I512::ONE;
435    let err = I256::try_from(i512).unwrap_err();
436    assert_eq!(err, ParseI256Error::Overflow);
437
438    let u256 = U256::MAX;
439    let err = I256::try_from(u256).unwrap_err();
440    assert_eq!(err, ParseI256Error::Overflow);
441
442    let i512_str = I512::MAX.to_string();
443    let u512 = U512::from_str(&i512_str).unwrap() + U512::ONE;
444    let err = U256::try_from(u512).unwrap_err();
445    assert_eq!(err, ParseU256Error::Overflow);
446
447    let u512 = U512::MAX;
448    let err = I256::try_from(u512).unwrap_err();
449    assert_eq!(err, ParseI256Error::Overflow);
450
451    let a = U256::MAX;
452    let b = I256::try_from(a).unwrap_err();
453    assert_eq!(b, ParseI256Error::Overflow);
454
455    let i512 = -I512::ONE;
456    let err = U256::try_from(i512).unwrap_err();
457    assert_eq!(err, ParseU256Error::NegativeToUnsigned);
458
459    let i256 = I256::from(-123);
460    let err = U512::try_from(i256).unwrap_err();
461    assert_eq!(err, ParseU512Error::NegativeToUnsigned);
462
463    let i384 = I384::MAX;
464    let err = U256::try_from(i384).unwrap_err();
465    assert_eq!(err, ParseU256Error::Overflow);
466}