1use honggfuzz::fuzz;
31use sp_arithmetic::biguint::{BigUint, Single};
32
33fn main() {
34 loop {
35 fuzz!(|data: (Vec<Single>, Vec<Single>, bool)| {
36 let (mut digits_u, mut digits_v, return_remainder) = data;
37
38 let mut u = BigUint::from_limbs(&digits_u);
39 let mut v = BigUint::from_limbs(&digits_v);
40
41 u.lstrip();
42 v.lstrip();
43
44 let ue = u128::try_from(u.clone());
45 let ve = u128::try_from(v.clone());
46
47 digits_u.reverse();
48 digits_v.reverse();
49
50 let num_u = num_bigint::BigUint::new(digits_u);
51 let num_v = num_bigint::BigUint::new(digits_v);
52
53 if check_digit_lengths(&u, &v, 4) {
54 assert_eq!(u.cmp(&v), ue.cmp(&ve));
55 assert_eq!(u.eq(&v), ue.eq(&ve));
56 }
57
58 if check_digit_lengths(&u, &v, 3) {
59 let expected = ue.unwrap() + ve.unwrap();
60 let t = u.clone().add(&v);
61 assert_eq!(
62 u128::try_from(t.clone()).unwrap(),
63 expected,
64 "{:?} + {:?} ===> {:?} != {:?}",
65 u,
66 v,
67 t,
68 expected,
69 );
70 }
71
72 if check_digit_lengths(&u, &v, 4) {
73 let expected = ue.unwrap().checked_sub(ve.unwrap());
74 let t = u.clone().sub(&v);
75 if expected.is_none() {
76 assert!(t.is_err())
77 } else {
78 let t = t.unwrap();
79 let expected = expected.unwrap();
80 assert_eq!(
81 u128::try_from(t.clone()).unwrap(),
82 expected,
83 "{:?} - {:?} ===> {:?} != {:?}",
84 u,
85 v,
86 t,
87 expected,
88 );
89 }
90 }
91
92 if check_digit_lengths(&u, &v, 2) {
93 let expected = ue.unwrap() * ve.unwrap();
94 let t = u.clone().mul(&v);
95 assert_eq!(
96 u128::try_from(t.clone()).unwrap(),
97 expected,
98 "{:?} * {:?} ===> {:?} != {:?}",
99 u,
100 v,
101 t,
102 expected,
103 );
104 }
105
106 if check_digit_lengths(&u, &v, 4) {
107 let (ue, ve) = (ue.unwrap(), ve.unwrap());
108 if ve == 0 {
109 return
110 }
111 let (q, r) = (ue / ve, ue % ve);
112 if let Some((qq, rr)) = u.clone().div(&v, true) {
113 assert_eq!(
114 u128::try_from(qq.clone()).unwrap(),
115 q,
116 "{:?} / {:?} ===> {:?} != {:?}",
117 u,
118 v,
119 qq,
120 q,
121 );
122 assert_eq!(
123 u128::try_from(rr.clone()).unwrap(),
124 r,
125 "{:?} % {:?} ===> {:?} != {:?}",
126 u,
127 v,
128 rr,
129 r,
130 );
131 } else if v.len() == 1 {
132 let qq = u.clone().div_unit(ve as Single);
133 assert_eq!(
134 u128::try_from(qq.clone()).unwrap(),
135 q,
136 "[single] {:?} / {:?} ===> {:?} != {:?}",
137 u,
138 v,
139 qq,
140 q,
141 );
142 } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() {
143 panic!("div returned none for an unexpected reason");
144 }
145 }
146
147 assert_eq!(u.cmp(&v), num_u.cmp(&num_v));
152
153 let w = u.clone().add(&v);
156 let num_w = num_u.clone() + &num_v;
157
158 assert_biguints_eq(&w, &num_w);
159
160 if let Ok(w) = u.clone().sub(&v) {
163 let num_w = num_u.clone() - &num_v;
164
165 assert_biguints_eq(&w, &num_w);
166 }
167
168 let w = u.clone().mul(&v);
171 let num_w = num_u.clone() * &num_v;
172
173 assert_biguints_eq(&w, &num_w);
174
175 if v.len() == 1 && v.get(0) != 0 {
178 let w = u.div_unit(v.get(0));
179 let num_w = num_u / &num_v;
180 assert_biguints_eq(&w, &num_w);
181 } else if u.len() > v.len() && v.len() > 1 {
182 let num_remainder = num_u.clone() % num_v.clone();
183
184 let (w, remainder) = u.div(&v, return_remainder).unwrap();
185 let num_w = num_u / &num_v;
186
187 assert_biguints_eq(&w, &num_w);
188
189 if return_remainder {
190 assert_biguints_eq(&remainder, &num_remainder);
191 }
192 }
193 });
194 }
195}
196
197fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool {
198 1 <= u.len() && u.len() <= max_limbs && 1 <= v.len() && v.len() <= max_limbs
199}
200
201fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) {
202 let mut a = a.clone();
203 a.lstrip();
204
205 let limbs = (0..a.len()).map(|i| a.get(i)).collect();
208 let num_a = num_bigint::BigUint::new(limbs);
209
210 assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b);
211}