1#![allow(clippy::similar_names)] mod knuth;
18mod reciprocal;
19mod small;
20
21pub use self::{
22 knuth::{div_nxm, div_nxm_normalized},
23 reciprocal::{reciprocal, reciprocal_2, reciprocal_2_mg10, reciprocal_mg10, reciprocal_ref},
24 small::{
25 div_2x1, div_2x1_mg10, div_2x1_ref, div_3x2, div_3x2_mg10, div_3x2_ref, div_nx1,
26 div_nx1_normalized, div_nx2, div_nx2_normalized,
27 },
28};
29use crate::algorithms::DoubleWord;
30
31#[inline]
48pub fn div(numerator: &mut [u64], divisor: &mut [u64]) {
49 let i = divisor
51 .iter()
52 .rposition(|&x| x != 0)
53 .expect("Divisor is zero");
54 let divisor = &mut divisor[..=i];
55 debug_assert!(!divisor.is_empty());
56 debug_assert!(divisor.last() != Some(&0));
57
58 let numerator = if let Some(i) = numerator.iter().rposition(|&n| n != 0) {
60 &mut numerator[..=i]
61 } else {
62 divisor.fill(0);
64 return;
65 };
66 debug_assert!(!numerator.is_empty());
67 debug_assert!(*numerator.last().unwrap() != 0);
68
69 if numerator.len() < divisor.len() {
71 let (remainder, padding) = divisor.split_at_mut(numerator.len());
72 remainder.copy_from_slice(numerator);
73 padding.fill(0);
74 numerator.fill(0);
75 return;
76 }
77 debug_assert!(numerator.len() >= divisor.len());
78
79 if divisor.len() <= 2 {
81 if divisor.len() == 1 {
82 if numerator.len() == 1 {
83 let q = numerator[0] / divisor[0];
84 let r = numerator[0] % divisor[0];
85 numerator[0] = q;
86 divisor[0] = r;
87 } else {
88 divisor[0] = div_nx1(numerator, divisor[0]);
89 }
90 } else {
91 let d = u128::join(divisor[1], divisor[0]);
92 let remainder = div_nx2(numerator, d);
93 divisor[0] = remainder.low();
94 divisor[1] = remainder.high();
95 }
96 } else {
97 div_nxm(numerator, divisor);
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::aliases::U512;
105
106 const INTX_TESTS: [[U512; 4]; 45] = uint!([
109 [2_U512, 1_U512, 2_U512, 0_U512],
110 [
111 0x10000000000000000_U512,
112 2_U512,
113 0x8000000000000000_U512,
114 0_U512,
115 ],
116 [
117 0x7000000000000000_U512,
118 0x8000000000000000_U512,
119 0_U512,
120 0x7000000000000000_U512,
121 ],
122 [
123 0x8000000000000000_U512,
124 0x8000000000000000_U512,
125 1_U512,
126 0_U512,
127 ],
128 [
129 0x8000000000000001_U512,
130 0x8000000000000000_U512,
131 1_U512,
132 1_U512,
133 ],
134 [
135 0x80000000000000010000000000000000_U512,
136 0x80000000000000000000000000000000_U512,
137 1_U512,
138 0x10000000000000000_U512,
139 ],
140 [
141 0x80000000000000000000000000000000_U512,
142 0x80000000000000000000000000000001_U512,
143 0_U512,
144 0x80000000000000000000000000000000_U512,
145 ],
146 [
147 0x478392145435897052_U512,
148 0x111_U512,
149 0x430f89ebadad0baa_U512,
150 8_U512,
151 ],
152 [
153 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_U512,
154 0x800000000000000000000000000000000000000000000000_U512,
155 0x800000000000000000000000000000000000000000000000_U512,
156 0_U512,
157 ],
158 [
159 0x80000000000000000000000000000000000000000000000000000000000000000000000000000000_U512,
160 0x800000000000000000000000000000000000000000000000_U512,
161 0x100000000000000000000000000000000_U512,
162 0_U512,
163 ],
164 [
165 0x1e00000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000000_U512,
166 0xa_U512,
167 0x30000000000000000000000e6666666666666666666666666666666666666666666666666666666666666666666666666666666674ccccccccccccccccc_U512,
168 8_U512,
169 ],
170 [
171 0x767676767676767676000000767676767676_U512,
172 0x2900760076761e00020076760000000076767676000000_U512,
173 0_U512,
174 0x767676767676767676000000767676767676_U512,
175 ],
176 [
177 0x12121212121212121212121212121212_U512,
178 0x232323232323232323_U512,
179 0x83a83a83a83a83_U512,
180 0x171729292929292929_U512,
181 ],
182 [
183 0xabc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0abc0_U512,
184 0x1c01c01c01c01c01c01c01c01c_U512,
185 0x621ed21ed21ed21ed21ed21ed224f40bf40bf40bf40bf40bf40bf46e12de12de12de12de12de12de1900000000000000000_U512,
186 0xabc0abc0abc0abc0_U512,
187 ],
188 [
189 0xfffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00_U512,
190 0xfffff716b61616160b0b0b2b0b230b000008010d0a2b00_U512,
191 0xffffffffffffffffff_U512,
192 0xfffff7169e17030ac1ff082ed51796090b330cd3143500_U512,
193 ],
194 [
195 0x50beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00_U512,
196 0x2000110000000d0a300e750a000000090a0a_U512,
197 0x285f437064cd09ff8bc5b7857d_U512,
198 0x1fda1c384d86199e14bb4edfc6693042f11e_U512,
199 ],
200 [
201 0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000_U512,
202 0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a_U512,
203 0xffffffffffffff_U512,
204 0x4b00000b41000b0b0b2b0b0b0b0b0b400b35fbbafe151a0a_U512,
205 ],
206 [
207 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_U512,
208 7_U512,
209 0x22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222_U512,
210 0_U512,
211 ],
212 [
213 0xf6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0_U512,
214 0xb368d219438b7f3f_U512,
215 0x15f53bce87e9fb63c7c3ab03f6c0ba30d3ecf982fa97cdf0a_U512,
216 0x4bfd94dbec31523a_U512,
217 ],
218 [
219 0x0_U512,
220 0x10900000000000000000000000000000000000000000000000000_U512,
221 0x0_U512,
222 0x0_U512,
223 ],
224 [
225 0x77676767676760000000000000001002e000000000000040000000e000000000000007f0000000000000000000000000000000000000000f7000000000000_U512,
226 0xfffc000000000000767676240000000000002b05760476000000000000000000767676767600000000000000000000000000000000_U512,
227 0x7769450c7b994e65025_U512,
228 0x241cb1aa4f67c22ae65c9920bf3bb7ad8280311a887aee8be4054a3e242a5ea9ab35d800f2000000000000000000f7000000000000_U512,
229 ],
230 [
231 0xdffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000001000000000000000000000000008100000000001001_U512,
232 0xdffffffffffffffffffffffffffffffffffffffffffff3fffffffffffffffffffffffffffff_U512,
233 0xffffffffffffffffffffffffffffffffffedb6db6db6e9_U512,
234 0x200000000000000000000000000010000f2492492492ec000000000000080ffedb6db6dc6ea_U512,
235 ],
236 [
237 0xff000000000000000000000000000000000000000400000092767600000000000000000000000081000000000000000000000001020000000000eeffffffffff_U512,
238 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000005000000000000000000ffffffffff100000000000000000_U512,
239 0x0_U512,
240 0xff000000000000000000000000000000000000000400000092767600000000000000000000000081000000000000000000000001020000000000eeffffffffff_U512,
241 ],
242 [
243 0xfffffffffffffffffffffffffffffffffffffffbffffff6d8989ffffffffffffffffffffffff7efffffffffffffffffffffffefdffffffffff110000000001_U512,
244 0xfffffffffffffffffffffffaffffffffffffffffff0000000000f00000000000000000_U512,
245 0x1000000000000000000000004fffffffffffffffc00ffff8689890fff_U512,
246 0xffffffec09fffda0afa81efafc00ffff868d481fff71de0d8100efffff110000000001_U512,
247 ],
248 [
249 0x767676767676000000000076000000000000005600000000000000000000_U512,
250 0x767676767676000000000076000000760000_U512,
251 0xffffffffffffffffffffffff_U512,
252 0x767676007676005600000076000000760000_U512,
253 ],
254 [
255 0x8200000000000000000000000000000000000000000000000000000000000000_U512,
256 0x8200000000000000fe000004000000ffff000000fffff700_U512,
257 0xfffffffffffffffe_U512,
258 0x5fffffbffffff01fd00000700000afffe000001ffffee00_U512,
259 ],
260 [
261 0xdac7fff9ffd9e1322626262626262600_U512,
262 0xd021262626262626_U512,
263 0x10d1a094108c5da55_U512,
264 0x6f386ccc73c11f62_U512,
265 ],
266 [
267 0x8000000000000001800000000000000080000000000000008000000000000000_U512,
268 0x800000000000000080000000000000008000000000000000_U512,
269 0x10000000000000001_U512,
270 0x7fffffffffffffff80000000000000000000000000000000_U512,
271 ],
272 [
273 0x00e8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000000000000000000000000000000000000000000000000000000000000000000_U512,
274 0x00e8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff0000000000000000000000000000000000000000000000000000000000000000_U512,
275 0_U512,
276 0x00e8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000000000000000000000000000000000000000000000000000000000000000000_U512,
277 ],
278 [
279 0x000000c9700000000000000000023f00c00014ff0000000000000000223008050000000000000000000000000000000000000000000000000000000000000000_U512,
280 0x00000000c9700000000000000000023f00c00014ff002c0000000000002231080000000000000000000000000000000000000000000000000000000000000000_U512,
281 0xff_U512,
282 0x00000000c9700000000000000000023f00c00014fed42c00000000000021310d0000000000000000000000000000000000000000000000000000000000000000_U512,
283 ],
284 [
285 0x40000000fd000000db00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_U512,
286 0x40000000fd000000db0000000000000000000040000000fd000000db000001_U512,
287 0xfffffffffffffffffffffffffffffffffffffeffffffffffffffff_U512,
288 0x3ffffffffd000000db000040000000fd0000011b000001fd000000db000002_U512,
289 ],
290 [
291 0x40000000fd000000db00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_U512,
292 0x40000000fd000000db0000000000000000000040000000fd000000db0000d3_U512,
293 0xfffffffffffffffffffffffffffffffffffffeffffffffffffffff_U512,
294 0x3fffff2dfd000000db000040000000fd0000011b0000d3fd000000db0000d4_U512,
295 ],
296 [
297 0x001f000000000000000000000000000000200000000100000000000000000000_U512,
298 0x0000000000000000000100000000ffffffffffffffff0000000000002e000000_U512,
299 0x1effffffe10000001f_U512,
300 0xfffa6e20000591fffffa6e000000_U512,
301 ],
302 [
303 0x7effffff80000000000000000000000000020000440000000000000000000001_U512,
304 0x7effffff800000007effffff800000008000ff0000010000_U512,
305 0xfffffffffffffffe_U512,
306 0x7effffff800000007e0100ff43ff00010001fe0000020001_U512,
307 ],
308 [
309 0x5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001_U512,
310 0x2ffffffffffffffffffffffffffffffffff000000030000_U512,
311 0x1ff2ffffffffffffff_U512,
312 0x2fffffffffffffffc28f300ce102704d0c8ffffff030001_U512,
313 ],
314 [
315 0x62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001_U512,
316 0x2ffffffffffffffffffffffffffffffffff200000000000_U512,
317 0x20f2ffffffffffffff_U512,
318 0x2fffffffffffffffc34d49fffffffffffff20ca00000001_U512,
319 ],
320 [
321 0x7effffff8000000000000000000000000000000000000000d900000000000001_U512,
322 0x7effffff8000000000000000000000000000000000008001_U512,
323 0xffffffffffffffff_U512,
324 0x7effffff7fffffffffffffffffff7fffd900000000008002_U512,
325 ],
326 [
327 0x0000000000000006400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a_U512,
328 0x00000000000000210000000000000022_U512,
329 0x307c7456554d945ce57749fd52bfdb7f_U512,
330 0x1491254b5a0b84a32c_U512,
331 ],
332 [
333 0x7effffff8000000000000000000000000000000000150000d900000000000001_U512,
334 0x7effffff8000000000000000000000000000000000f9e101_U512,
335 0xffffffffffffffff_U512,
336 0x7effffff7fffffffffffffffff1b1effd900000000f9e102_U512,
337 ],
338 [
339 0xffffffff0100000000000000000000000000ffff0000ffffffff0100000000_U512,
340 0xffffffff010000000000000000000000ffff0000ffffff_U512,
341 0xffffffffffffffff_U512,
342 0xffffffff00ffffff0001fffe00010100fffe0100ffffff_U512,
343 ],
344 [
345 0xabfffff0000ffffffffff36363636363636363636d00500000000ffffffffffffe90000ff00000000000000000000ffff0000000000_U512,
346 0xabfffff0000ffffffffff36363636363636363636d00500000000ffffffffffffe9ff001f_U512,
347 0xffffffffffffffffffffffffffffffffff_U512,
348 0xabfffff0000ffffffffff36363636363537371636d00500000001000000fffeffe9ff001f_U512,
349 ],
350 [
351 0xff00ffffffffffffffcaffffffff0100_U512,
352 0x0100000000000000ff800000000000ff_U512,
353 0xff_U512,
354 0xffffffffff017f4afffffffe02ff_U512,
355 ],
356 [
357 0x9000ffffffffffffffcaffffffff0100_U512,
358 0x800000000000007fc000000000007f80_U512,
359 1_U512,
360 0x1000ffffffffff803fcafffffffe8180_U512,
361 ],
362 [
363 170141183460488574554024512018559533058_U512,
365 170141183460488574554024512018559533057_U512,
366 1_U512,
367 1_U512,
368 ],
369 [
370 0x6e2d23924d38f0ab643864e9b2a328a54914f48533114fae3475168bfd74a61ae91e676b4a4f33a5b3b6cc189536ccb4afc46d02b061d6daaf0298c993376ab4_U512,
371 170141183460488574554024512018559533057_U512,
372 0xdc5a47249a56560d078334729ffb61da211f5d2ec622c22f88bc3b4ebae1abdac6b03621554ef71070bc1e0dc5c301bc_U512,
373 0x6dc100ea02272bdcf68a4a5b95f468f8_U512,
374 ]
375 ]);
376
377 macro_rules! test_cases {
378 ($n:ty, $d:ty) => {
379 for [numerator, divisor, quotient, remainder] in INTX_TESTS {
380 if numerator.bit_len() > <$n>::BITS || divisor.bit_len() > <$d>::BITS {
381 continue;
382 }
383 let mut numerator = <$n>::from(numerator).into_limbs();
384 let mut divisor = <$d>::from(divisor).into_limbs();
385 let quotient = <$n>::from(quotient).into_limbs();
386 let remainder = <$d>::from(remainder).into_limbs();
387 div(&mut numerator, &mut divisor);
388 assert_eq!(numerator, quotient);
389 assert_eq!(divisor, remainder);
390 }
391 };
392 }
393
394 #[test]
395 fn test_div_8x8() {
396 use crate::aliases::U512;
397 test_cases!(U512, U512);
398 }
399
400 #[test]
401 fn test_div_6x6() {
402 use crate::aliases::U384;
403 test_cases!(U384, U384);
404 }
405
406 #[test]
407 fn test_div_4x4() {
408 use crate::aliases::U256;
409 test_cases!(U256, U256);
410 }
411
412 #[test]
413 fn test_div_5x4() {
414 use crate::aliases::{U256, U320};
415 test_cases!(U320, U256);
416 }
417
418 #[test]
419 fn test_div_8x4() {
420 use crate::aliases::{U256, U512};
421 test_cases!(U512, U256);
422 }
423
424 #[test]
425 #[allow(clippy::unreadable_literal)]
426 fn test_div_8by4_one() {
427 let mut numerator = [
428 0x9c2bcebfa9cca2c6_u64,
429 0x274e154bb5e24f7a_u64,
430 0xe1442d5d3842be2b_u64,
431 0xf18f5adfd420853f_u64,
432 0x04ed6127eba3b594_u64,
433 0xc5c179973cdb1663_u64,
434 0x7d7f67780bb268ff_u64,
435 0x0000000000000003_u64,
436 0x0000000000000000_u64,
437 ];
438 let mut divisor = [
439 0x0181880b078ab6a1_u64,
440 0x62d67f6b7b0bda6b_u64,
441 0x92b1840f9c792ded_u64,
442 0x0000000000000019_u64,
443 ];
444 let expected_quotient = [
445 0x9128464e61d6b5b3_u64,
446 0xd9eea4fc30c5ac6c_u64,
447 0x944a2d832d5a6a08_u64,
448 0x22f06722e8d883b1_u64,
449 0x0000000000000000_u64,
450 ];
451 let expected_remainder = [
452 0x1dfa5a7ea5191b33_u64,
453 0xb5aeb3f9ad5e294e_u64,
454 0xfc710038c13e4eed_u64,
455 0x000000000000000b_u64,
456 ];
457 div(&mut numerator, &mut divisor);
458 assert_eq!(numerator[..5], expected_quotient);
459 assert_eq!(divisor, expected_remainder);
460 }
461}