1 use num_bigint::BigInt;
2 use num_bigint::Sign::Plus;
3 use num_traits::{One, Signed, ToPrimitive, Zero};
4
5 use std::ops::Neg;
6 use std::panic::catch_unwind;
7
8 mod consts;
9 use crate::consts::*;
10
11 #[macro_use]
12 mod macros;
13
14 #[test]
test_scalar_add()15 fn test_scalar_add() {
16 fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
17 let (x, y, z) = (x.clone(), y.clone(), z.clone());
18 assert_signed_scalar_op!(x + y == z);
19 assert_signed_scalar_assign_op!(x += y == z);
20 }
21
22 for elm in SUM_TRIPLES.iter() {
23 let (a_vec, b_vec, c_vec) = *elm;
24 let a = BigInt::from_slice(Plus, a_vec);
25 let b = BigInt::from_slice(Plus, b_vec);
26 let c = BigInt::from_slice(Plus, c_vec);
27 let (na, nb, nc) = (-&a, -&b, -&c);
28
29 check(&a, &b, &c);
30 check(&b, &a, &c);
31 check(&c, &na, &b);
32 check(&c, &nb, &a);
33 check(&a, &nc, &nb);
34 check(&b, &nc, &na);
35 check(&na, &nb, &nc);
36 check(&a, &na, &Zero::zero());
37 }
38 }
39
40 #[test]
test_scalar_sub()41 fn test_scalar_sub() {
42 fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
43 let (x, y, z) = (x.clone(), y.clone(), z.clone());
44 assert_signed_scalar_op!(x - y == z);
45 assert_signed_scalar_assign_op!(x -= y == z);
46 }
47
48 for elm in SUM_TRIPLES.iter() {
49 let (a_vec, b_vec, c_vec) = *elm;
50 let a = BigInt::from_slice(Plus, a_vec);
51 let b = BigInt::from_slice(Plus, b_vec);
52 let c = BigInt::from_slice(Plus, c_vec);
53 let (na, nb, nc) = (-&a, -&b, -&c);
54
55 check(&c, &a, &b);
56 check(&c, &b, &a);
57 check(&nb, &a, &nc);
58 check(&na, &b, &nc);
59 check(&b, &na, &c);
60 check(&a, &nb, &c);
61 check(&nc, &na, &nb);
62 check(&a, &a, &Zero::zero());
63 }
64 }
65
66 #[test]
test_scalar_mul()67 fn test_scalar_mul() {
68 fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
69 let (x, y, z) = (x.clone(), y.clone(), z.clone());
70 assert_signed_scalar_op!(x * y == z);
71 assert_signed_scalar_assign_op!(x *= y == z);
72 }
73
74 for elm in MUL_TRIPLES.iter() {
75 let (a_vec, b_vec, c_vec) = *elm;
76 let a = BigInt::from_slice(Plus, a_vec);
77 let b = BigInt::from_slice(Plus, b_vec);
78 let c = BigInt::from_slice(Plus, c_vec);
79 let (na, nb, nc) = (-&a, -&b, -&c);
80
81 check(&a, &b, &c);
82 check(&b, &a, &c);
83 check(&na, &nb, &c);
84
85 check(&na, &b, &nc);
86 check(&nb, &a, &nc);
87 }
88 }
89
90 #[test]
test_scalar_div_rem()91 fn test_scalar_div_rem() {
92 fn check_sub(a: &BigInt, b: u32, ans_q: &BigInt, ans_r: &BigInt) {
93 let (q, r) = (a / b, a % b);
94 if !r.is_zero() {
95 assert_eq!(r.sign(), a.sign());
96 }
97 assert!(r.abs() <= BigInt::from(b));
98 assert!(*a == b * &q + &r);
99 assert!(q == *ans_q);
100 assert!(r == *ans_r);
101
102 let b = BigInt::from(b);
103 let (a, ans_q, ans_r) = (a.clone(), ans_q.clone(), ans_r.clone());
104 assert_signed_scalar_op!(a / b == ans_q);
105 assert_signed_scalar_op!(a % b == ans_r);
106 assert_signed_scalar_assign_op!(a /= b == ans_q);
107 assert_signed_scalar_assign_op!(a %= b == ans_r);
108
109 let nb = -b;
110 assert_signed_scalar_op!(a / nb == -ans_q.clone());
111 assert_signed_scalar_op!(a % nb == ans_r);
112 assert_signed_scalar_assign_op!(a /= nb == -ans_q.clone());
113 assert_signed_scalar_assign_op!(a %= nb == ans_r);
114 }
115
116 fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) {
117 check_sub(a, b, q, r);
118 check_sub(&a.neg(), b, &q.neg(), &r.neg());
119 }
120
121 for elm in MUL_TRIPLES.iter() {
122 let (a_vec, b_vec, c_vec) = *elm;
123 let a = BigInt::from_slice(Plus, a_vec);
124 let b = BigInt::from_slice(Plus, b_vec);
125 let c = BigInt::from_slice(Plus, c_vec);
126
127 if a_vec.len() == 1 && a_vec[0] != 0 {
128 let a = a_vec[0];
129 check(&c, a, &b, &Zero::zero());
130 }
131
132 if b_vec.len() == 1 && b_vec[0] != 0 {
133 let b = b_vec[0];
134 check(&c, b, &a, &Zero::zero());
135 }
136 }
137
138 for elm in DIV_REM_QUADRUPLES.iter() {
139 let (a_vec, b_vec, c_vec, d_vec) = *elm;
140 let a = BigInt::from_slice(Plus, a_vec);
141 let c = BigInt::from_slice(Plus, c_vec);
142 let d = BigInt::from_slice(Plus, d_vec);
143
144 if b_vec.len() == 1 && b_vec[0] != 0 {
145 let b = b_vec[0];
146 check(&a, b, &c, &d);
147 }
148 }
149 }
150
151 #[test]
152 #[ignore = "Android sometimes uses panic_abort"]
test_scalar_div_rem_zero()153 fn test_scalar_div_rem_zero() {
154 catch_unwind(|| BigInt::zero() / 0u32).unwrap_err();
155 catch_unwind(|| BigInt::zero() % 0u32).unwrap_err();
156 catch_unwind(|| BigInt::one() / 0u32).unwrap_err();
157 catch_unwind(|| BigInt::one() % 0u32).unwrap_err();
158 }
159