rust_decimal/ops/div.rs
1use crate::constants::{MAX_SCALE_I32, POWERS_10};
2use crate::decimal::{CalculationResult, Decimal};
3use crate::ops::common::{Buf12, Buf16, Dec64};
4
5use core::cmp::Ordering;
6use core::ops::BitXor;
7
8impl Buf12 {
9 // Returns true if successful, else false for an overflow
10 fn add32(&mut self, value: u32) -> Result<(), DivError> {
11 let value = value as u64;
12 let new = self.low64().wrapping_add(value);
13 self.set_low64(new);
14 if new < value {
15 self.data[2] = self.data[2].wrapping_add(1);
16 if self.data[2] == 0 {
17 return Err(DivError::Overflow);
18 }
19 }
20 Ok(())
21 }
22
23 // Divide a Decimal union by a 32 bit divisor.
24 // Self is overwritten with the quotient.
25 // Return value is a 32 bit remainder.
26 fn div32(&mut self, divisor: u32) -> u32 {
27 let divisor64 = divisor as u64;
28 // See if we can get by using a simple u64 division
29 if self.data[2] != 0 {
30 let mut temp = self.high64();
31 let q64 = temp / divisor64;
32 self.set_high64(q64);
33
34 // Calculate the "remainder"
35 temp = ((temp - q64 * divisor64) << 32) | (self.data[0] as u64);
36 if temp == 0 {
37 return 0;
38 }
39 let q32 = (temp / divisor64) as u32;
40 self.data[0] = q32;
41 (temp as u32).wrapping_sub(q32.wrapping_mul(divisor))
42 } else {
43 // Super easy divisor
44 let low64 = self.low64();
45 if low64 == 0 {
46 // Nothing to do
47 return 0;
48 }
49 // Do the calc
50 let quotient = low64 / divisor64;
51 self.set_low64(quotient);
52 // Remainder is the leftover that wasn't used
53 (low64.wrapping_sub(quotient.wrapping_mul(divisor64))) as u32
54 }
55 }
56
57 // Divide the number by a power constant
58 // Returns true if division was successful
59 fn div32_const(&mut self, pow: u32) -> bool {
60 let pow64 = pow as u64;
61 let high64 = self.high64();
62 let lo = self.data[0] as u64;
63 let div64: u64 = high64 / pow64;
64 let div = ((((high64 - div64 * pow64) << 32) + lo) / pow64) as u32;
65 if self.data[0] == div.wrapping_mul(pow) {
66 self.set_high64(div64);
67 self.data[0] = div;
68 true
69 } else {
70 false
71 }
72 }
73}
74
75impl Buf16 {
76 // Does a partial divide with a 64 bit divisor. The divisor in this case must be 64 bits
77 // otherwise various assumptions fail (e.g. 32 bit quotient).
78 // To assist, the upper 64 bits must be greater than the divisor for this to succeed.
79 // Consequently, it will return the quotient as a 32 bit number and overwrite self with the
80 // 64 bit remainder.
81 pub(super) fn partial_divide_64(&mut self, divisor: u64) -> u32 {
82 // We make this assertion here, however below we pivot based on the data
83 debug_assert!(divisor > self.mid64());
84
85 // If we have an empty high bit, then divisor must be greater than the dividend due to
86 // the assumption that the divisor REQUIRES 64 bits.
87 if self.data[2] == 0 {
88 let low64 = self.low64();
89 if low64 < divisor {
90 // We can't divide at at all so result is 0. The dividend remains untouched since
91 // the full amount is the remainder.
92 return 0;
93 }
94
95 let quotient = low64 / divisor;
96 self.set_low64(low64 - (quotient * divisor));
97 return quotient as u32;
98 }
99
100 // Do a simple check to see if the hi portion of the dividend is greater than the hi
101 // portion of the divisor.
102 let divisor_hi32 = (divisor >> 32) as u32;
103 if self.data[2] >= divisor_hi32 {
104 // We know that the divisor goes into this at MOST u32::max times.
105 // So we kick things off, with that assumption
106 let mut low64 = self.low64();
107 low64 = low64.wrapping_sub(divisor << 32).wrapping_add(divisor);
108 let mut quotient = u32::MAX;
109
110 // If we went negative then keep adding it back in
111 loop {
112 if low64 < divisor {
113 break;
114 }
115 quotient = quotient.wrapping_sub(1);
116 low64 = low64.wrapping_add(divisor);
117 }
118 self.set_low64(low64);
119 return quotient;
120 }
121
122 let mid64 = self.mid64();
123 let divisor_hi32_64 = divisor_hi32 as u64;
124 if mid64 < divisor_hi32_64 {
125 // similar situation as above where we've got nothing left to divide
126 return 0;
127 }
128
129 let mut quotient = mid64 / divisor_hi32_64;
130 let mut remainder = self.data[0] as u64 | ((mid64 - quotient * divisor_hi32_64) << 32);
131
132 // Do quotient * lo divisor
133 let product = quotient * (divisor & 0xFFFF_FFFF);
134 remainder = remainder.wrapping_sub(product);
135
136 // Check if we've gone negative. If so, add it back
137 if remainder > product.bitxor(u64::MAX) {
138 loop {
139 quotient = quotient.wrapping_sub(1);
140 remainder = remainder.wrapping_add(divisor);
141 if remainder < divisor {
142 break;
143 }
144 }
145 }
146
147 self.set_low64(remainder);
148 quotient as u32
149 }
150
151 // Does a partial divide with a 96 bit divisor. The divisor in this case must require 96 bits
152 // otherwise various assumptions fail (e.g. 32 bit quotient).
153 pub(super) fn partial_divide_96(&mut self, divisor: &Buf12) -> u32 {
154 let dividend = self.high64();
155 let divisor_hi = divisor.data[2];
156 if dividend < divisor_hi as u64 {
157 // Dividend is too small - entire number is remainder
158 return 0;
159 }
160
161 let mut quo = (dividend / divisor_hi as u64) as u32;
162 let mut remainder = (dividend as u32).wrapping_sub(quo.wrapping_mul(divisor_hi));
163
164 // Compute full remainder
165 let mut prod1 = quo as u64 * divisor.data[0] as u64;
166 let mut prod2 = quo as u64 * divisor.data[1] as u64;
167 prod2 += prod1 >> 32;
168 prod1 = (prod1 & 0xFFFF_FFFF) | (prod2 << 32);
169 prod2 >>= 32;
170
171 let mut num = self.low64();
172 num = num.wrapping_sub(prod1);
173 remainder = remainder.wrapping_sub(prod2 as u32);
174
175 // If there are carries make sure they are propagated
176 if num > prod1.bitxor(u64::MAX) {
177 remainder = remainder.wrapping_sub(1);
178 if remainder < (prod2 as u32).bitxor(u32::MAX) {
179 self.set_low64(num);
180 self.data[2] = remainder;
181 return quo;
182 }
183 } else if remainder <= (prod2 as u32).bitxor(u32::MAX) {
184 self.set_low64(num);
185 self.data[2] = remainder;
186 return quo;
187 }
188
189 // Remainder went negative, add divisor back until it's positive
190 prod1 = divisor.low64();
191 loop {
192 quo = quo.wrapping_sub(1);
193 num = num.wrapping_add(prod1);
194 remainder = remainder.wrapping_add(divisor_hi);
195
196 if num < prod1 {
197 // Detected carry.
198 let tmp = remainder;
199 remainder = remainder.wrapping_add(1);
200 if tmp < divisor_hi {
201 break;
202 }
203 }
204 if remainder < divisor_hi {
205 break; // detected carry
206 }
207 }
208
209 self.set_low64(num);
210 self.data[2] = remainder;
211 quo
212 }
213}
214
215enum DivError {
216 Overflow,
217}
218
219pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResult {
220 if divisor.is_zero() {
221 return CalculationResult::DivByZero;
222 }
223 if dividend.is_zero() {
224 return CalculationResult::Ok(Decimal::ZERO);
225 }
226 let dividend = Dec64::new(dividend);
227 let divisor = Dec64::new(divisor);
228
229 // Pre calculate the scale and the sign
230 let mut scale = (dividend.scale as i32) - (divisor.scale as i32);
231 let sign_negative = dividend.negative ^ divisor.negative;
232
233 // Set up some variables for modification throughout
234 let mut require_unscale = false;
235 let mut quotient = Buf12::from_dec64(÷nd);
236 let divisor = Buf12::from_dec64(&divisor);
237
238 // Branch depending on the complexity of the divisor
239 if divisor.data[2] | divisor.data[1] == 0 {
240 // We have a simple(r) divisor (32 bit)
241 let divisor32 = divisor.data[0];
242
243 // Remainder can only be 32 bits since the divisor is 32 bits.
244 let mut remainder = quotient.div32(divisor32);
245 let mut power_scale = 0;
246
247 // Figure out how to apply the remainder (i.e. we may have performed something like 10/3 or 8/5)
248 loop {
249 // Remainder is 0 so we have a simple situation
250 if remainder == 0 {
251 // If the scale is positive then we're actually done
252 if scale >= 0 {
253 break;
254 }
255 power_scale = 9usize.min((-scale) as usize);
256 } else {
257 // We may need to normalize later, so set the flag appropriately
258 require_unscale = true;
259
260 // We have a remainder so we effectively want to try to adjust the quotient and add
261 // the remainder into the quotient. We do this below, however first of all we want
262 // to try to avoid overflowing so we do that check first.
263 let will_overflow = if scale == MAX_SCALE_I32 {
264 true
265 } else {
266 // Figure out how much we can scale by
267 if let Some(s) = quotient.find_scale(scale) {
268 power_scale = s;
269 } else {
270 return CalculationResult::Overflow;
271 }
272 // If it comes back as 0 (i.e. 10^0 = 1) then we're going to overflow since
273 // we're doing nothing.
274 power_scale == 0
275 };
276 if will_overflow {
277 // No more scaling can be done, but remainder is non-zero so we round if necessary.
278 let tmp = remainder << 1;
279 let round = if tmp < remainder {
280 // We round if we wrapped around
281 true
282 } else if tmp >= divisor32 {
283 // If we're greater than the divisor (i.e. underflow)
284 // or if there is a lo bit set, we round
285 tmp > divisor32 || (quotient.data[0] & 0x1) > 0
286 } else {
287 false
288 };
289
290 // If we need to round, try to do so.
291 if round {
292 if let Ok(new_scale) = round_up(&mut quotient, scale) {
293 scale = new_scale;
294 } else {
295 // Overflowed
296 return CalculationResult::Overflow;
297 }
298 }
299 break;
300 }
301 }
302
303 // Do some scaling
304 let power = POWERS_10[power_scale];
305 scale += power_scale as i32;
306 // Increase the quotient by the power that was looked up
307 let overflow = increase_scale(&mut quotient, power as u64);
308 if overflow > 0 {
309 return CalculationResult::Overflow;
310 }
311
312 let remainder_scaled = (remainder as u64) * (power as u64);
313 let remainder_quotient = (remainder_scaled / (divisor32 as u64)) as u32;
314 remainder = (remainder_scaled - remainder_quotient as u64 * divisor32 as u64) as u32;
315 if let Err(DivError::Overflow) = quotient.add32(remainder_quotient) {
316 if let Ok(adj) = unscale_from_overflow(&mut quotient, scale, remainder != 0) {
317 scale = adj;
318 } else {
319 // Still overflowing
320 return CalculationResult::Overflow;
321 }
322 break;
323 }
324 }
325 } else {
326 // We have a divisor greater than 32 bits. Both of these share some quick calculation wins
327 // so we'll do those before branching into separate logic.
328 // The win we can do is shifting the bits to the left as much as possible. We do this to both
329 // the dividend and the divisor to ensure the quotient is not changed.
330 // As a simple contrived example: if we have 4 / 2 then we could bit shift all the way to the
331 // left meaning that the lo portion would have nothing inside of it. Of course, shifting these
332 // left one has the same result (8/4) etc.
333 // The advantage is that we may be able to write off lower portions of the number making things
334 // easier.
335 let mut power_scale = if divisor.data[2] == 0 {
336 divisor.data[1].leading_zeros()
337 } else {
338 divisor.data[2].leading_zeros()
339 } as usize;
340 let mut remainder = Buf16::zero();
341 remainder.set_low64(quotient.low64() << power_scale);
342 let tmp_high = ((quotient.data[1] as u64) + ((quotient.data[2] as u64) << 32)) >> (32 - power_scale);
343 remainder.set_high64(tmp_high);
344
345 // Work out the divisor after it's shifted
346 let divisor64 = divisor.low64() << power_scale;
347 // Check if the divisor is 64 bit or the full 96 bits
348 if divisor.data[2] == 0 {
349 // It's 64 bits
350 quotient.data[2] = 0;
351
352 // Calc mid/lo by shifting accordingly
353 let rem_lo = remainder.data[0];
354 remainder.data[0] = remainder.data[1];
355 remainder.data[1] = remainder.data[2];
356 remainder.data[2] = remainder.data[3];
357 quotient.data[1] = remainder.partial_divide_64(divisor64);
358
359 remainder.data[2] = remainder.data[1];
360 remainder.data[1] = remainder.data[0];
361 remainder.data[0] = rem_lo;
362 quotient.data[0] = remainder.partial_divide_64(divisor64);
363
364 loop {
365 let rem_low64 = remainder.low64();
366 if rem_low64 == 0 {
367 // If the scale is positive then we're actually done
368 if scale >= 0 {
369 break;
370 }
371 power_scale = 9usize.min((-scale) as usize);
372 } else {
373 // We may need to normalize later, so set the flag appropriately
374 require_unscale = true;
375
376 // We have a remainder so we effectively want to try to adjust the quotient and add
377 // the remainder into the quotient. We do this below, however first of all we want
378 // to try to avoid overflowing so we do that check first.
379 let will_overflow = if scale == MAX_SCALE_I32 {
380 true
381 } else {
382 // Figure out how much we can scale by
383 if let Some(s) = quotient.find_scale(scale) {
384 power_scale = s;
385 } else {
386 return CalculationResult::Overflow;
387 }
388 // If it comes back as 0 (i.e. 10^0 = 1) then we're going to overflow since
389 // we're doing nothing.
390 power_scale == 0
391 };
392 if will_overflow {
393 // No more scaling can be done, but remainder is non-zero so we round if necessary.
394 let mut tmp = remainder.low64();
395 let round = if (tmp as i64) < 0 {
396 // We round if we wrapped around
397 true
398 } else {
399 tmp <<= 1;
400 if tmp > divisor64 {
401 true
402 } else {
403 tmp == divisor64 && quotient.data[0] & 0x1 != 0
404 }
405 };
406
407 // If we need to round, try to do so.
408 if round {
409 if let Ok(new_scale) = round_up(&mut quotient, scale) {
410 scale = new_scale;
411 } else {
412 // Overflowed
413 return CalculationResult::Overflow;
414 }
415 }
416 break;
417 }
418 }
419
420 // Do some scaling
421 let power = POWERS_10[power_scale];
422 scale += power_scale as i32;
423
424 // Increase the quotient by the power that was looked up
425 let overflow = increase_scale(&mut quotient, power as u64);
426 if overflow > 0 {
427 return CalculationResult::Overflow;
428 }
429 increase_scale64(&mut remainder, power as u64);
430
431 let tmp = remainder.partial_divide_64(divisor64);
432 if let Err(DivError::Overflow) = quotient.add32(tmp) {
433 if let Ok(adj) = unscale_from_overflow(&mut quotient, scale, remainder.low64() != 0) {
434 scale = adj;
435 } else {
436 // Still overflowing
437 return CalculationResult::Overflow;
438 }
439 break;
440 }
441 }
442 } else {
443 // It's 96 bits
444 // Start by finishing the shift left
445 let divisor_mid = divisor.data[1];
446 let divisor_hi = divisor.data[2];
447 let mut divisor = divisor;
448 divisor.set_low64(divisor64);
449 divisor.data[2] = ((divisor_mid as u64 + ((divisor_hi as u64) << 32)) >> (32 - power_scale)) as u32;
450
451 let quo = remainder.partial_divide_96(&divisor);
452 quotient.set_low64(quo as u64);
453 quotient.data[2] = 0;
454
455 loop {
456 let mut rem_low64 = remainder.low64();
457 if rem_low64 == 0 && remainder.data[2] == 0 {
458 // If the scale is positive then we're actually done
459 if scale >= 0 {
460 break;
461 }
462 power_scale = 9usize.min((-scale) as usize);
463 } else {
464 // We may need to normalize later, so set the flag appropriately
465 require_unscale = true;
466
467 // We have a remainder so we effectively want to try to adjust the quotient and add
468 // the remainder into the quotient. We do this below, however first of all we want
469 // to try to avoid overflowing so we do that check first.
470 let will_overflow = if scale == MAX_SCALE_I32 {
471 true
472 } else {
473 // Figure out how much we can scale by
474 if let Some(s) = quotient.find_scale(scale) {
475 power_scale = s;
476 } else {
477 return CalculationResult::Overflow;
478 }
479 // If it comes back as 0 (i.e. 10^0 = 1) then we're going to overflow since
480 // we're doing nothing.
481 power_scale == 0
482 };
483 if will_overflow {
484 // No more scaling can be done, but remainder is non-zero so we round if necessary.
485 let round = if (remainder.data[2] as i32) < 0 {
486 // We round if we wrapped around
487 true
488 } else {
489 let tmp = remainder.data[1] >> 31;
490 rem_low64 <<= 1;
491 remainder.set_low64(rem_low64);
492 remainder.data[2] = (&remainder.data[2] << 1) + tmp;
493
494 match remainder.data[2].cmp(&divisor.data[2]) {
495 Ordering::Less => false,
496 Ordering::Equal => {
497 let divisor_low64 = divisor.low64();
498 if rem_low64 > divisor_low64 {
499 true
500 } else {
501 rem_low64 == divisor_low64 && (quotient.data[0] & 1) != 0
502 }
503 }
504 Ordering::Greater => true,
505 }
506 };
507
508 // If we need to round, try to do so.
509 if round {
510 if let Ok(new_scale) = round_up(&mut quotient, scale) {
511 scale = new_scale;
512 } else {
513 // Overflowed
514 return CalculationResult::Overflow;
515 }
516 }
517 break;
518 }
519 }
520
521 // Do some scaling
522 let power = POWERS_10[power_scale];
523 scale += power_scale as i32;
524
525 // Increase the quotient by the power that was looked up
526 let overflow = increase_scale(&mut quotient, power as u64);
527 if overflow > 0 {
528 return CalculationResult::Overflow;
529 }
530 let mut tmp_remainder = Buf12 {
531 data: [remainder.data[0], remainder.data[1], remainder.data[2]],
532 };
533 let overflow = increase_scale(&mut tmp_remainder, power as u64);
534 remainder.data[0] = tmp_remainder.data[0];
535 remainder.data[1] = tmp_remainder.data[1];
536 remainder.data[2] = tmp_remainder.data[2];
537 remainder.data[3] = overflow;
538
539 let tmp = remainder.partial_divide_96(&divisor);
540 if let Err(DivError::Overflow) = quotient.add32(tmp) {
541 if let Ok(adj) =
542 unscale_from_overflow(&mut quotient, scale, (remainder.low64() | remainder.high64()) != 0)
543 {
544 scale = adj;
545 } else {
546 // Still overflowing
547 return CalculationResult::Overflow;
548 }
549 break;
550 }
551 }
552 }
553 }
554 if require_unscale {
555 scale = unscale(&mut quotient, scale);
556 }
557 CalculationResult::Ok(Decimal::from_parts(
558 quotient.data[0],
559 quotient.data[1],
560 quotient.data[2],
561 sign_negative,
562 scale as u32,
563 ))
564}
565
566// Multiply num by power (multiple of 10). Power must be 32 bits.
567// Returns the overflow, if any
568fn increase_scale(num: &mut Buf12, power: u64) -> u32 {
569 let mut tmp = (num.data[0] as u64) * power;
570 num.data[0] = tmp as u32;
571 tmp >>= 32;
572 tmp += (num.data[1] as u64) * power;
573 num.data[1] = tmp as u32;
574 tmp >>= 32;
575 tmp += (num.data[2] as u64) * power;
576 num.data[2] = tmp as u32;
577 (tmp >> 32) as u32
578}
579
580// Multiply num by power (multiple of 10). Power must be 32 bits.
581fn increase_scale64(num: &mut Buf16, power: u64) {
582 let mut tmp = (num.data[0] as u64) * power;
583 num.data[0] = tmp as u32;
584 tmp >>= 32;
585 tmp += (num.data[1] as u64) * power;
586 num.set_mid64(tmp)
587}
588
589// Adjust the number to deal with an overflow. This function follows being scaled up (i.e. multiplied
590// by 10, so this effectively tries to reverse that by dividing by 10 then feeding in the high bit
591// to undo the overflow and rounding instead.
592// Returns the updated scale.
593fn unscale_from_overflow(num: &mut Buf12, scale: i32, sticky: bool) -> Result<i32, DivError> {
594 let scale = scale - 1;
595 if scale < 0 {
596 return Err(DivError::Overflow);
597 }
598
599 // This function is called when the hi portion has "overflowed" upon adding one and has wrapped
600 // back around to 0. Consequently, we need to "feed" that back in, but also rescaling down
601 // to reverse out the overflow.
602 const HIGH_BIT: u64 = 0x1_0000_0000;
603 num.data[2] = (HIGH_BIT / 10) as u32;
604
605 // Calc the mid
606 let mut tmp = ((HIGH_BIT % 10) << 32) + (num.data[1] as u64);
607 let mut val = (tmp / 10) as u32;
608 num.data[1] = val;
609
610 // Calc the lo using a similar method
611 tmp = ((tmp - (val as u64) * 10) << 32) + (num.data[0] as u64);
612 val = (tmp / 10) as u32;
613 num.data[0] = val;
614
615 // Work out the remainder, and round if we have one (since it doesn't fit)
616 let remainder = (tmp - (val as u64) * 10) as u32;
617 if remainder > 5 || (remainder == 5 && (sticky || num.data[0] & 0x1 > 0)) {
618 let _ = num.add32(1);
619 }
620 Ok(scale)
621}
622
623#[inline]
624fn round_up(num: &mut Buf12, scale: i32) -> Result<i32, DivError> {
625 let low64 = num.low64().wrapping_add(1);
626 num.set_low64(low64);
627 if low64 != 0 {
628 return Ok(scale);
629 }
630 let hi = num.data[2].wrapping_add(1);
631 num.data[2] = hi;
632 if hi != 0 {
633 return Ok(scale);
634 }
635 unscale_from_overflow(num, scale, true)
636}
637
638fn unscale(num: &mut Buf12, scale: i32) -> i32 {
639 // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 we can extract.
640 // We use this as a quick test on whether to try a given power.
641 let mut scale = scale;
642 while num.data[0] == 0 && scale >= 8 && num.div32_const(100000000) {
643 scale -= 8;
644 }
645
646 if (num.data[0] & 0xF) == 0 && scale >= 4 && num.div32_const(10000) {
647 scale -= 4;
648 }
649
650 if (num.data[0] & 0x3) == 0 && scale >= 2 && num.div32_const(100) {
651 scale -= 2;
652 }
653
654 if (num.data[0] & 0x1) == 0 && scale >= 1 && num.div32_const(10) {
655 scale -= 1;
656 }
657 scale
658}