1 use crate::{
2     constants::{MAX_PRECISION_U32, POWERS_10, U32_MASK},
3     decimal::{CalculationResult, Decimal},
4     ops::array::{
5         add_by_internal, cmp_internal, div_by_u32, is_all_zero, mul_by_u32, mul_part, rescale_internal, shl1_internal,
6     },
7 };
8 
9 use core::cmp::Ordering;
10 use num_traits::Zero;
11 
add_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult12 pub(crate) fn add_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
13     // Convert to the same scale
14     let mut my = d1.mantissa_array3();
15     let mut my_scale = d1.scale();
16     let mut ot = d2.mantissa_array3();
17     let mut other_scale = d2.scale();
18     rescale_to_maximum_scale(&mut my, &mut my_scale, &mut ot, &mut other_scale);
19     let mut final_scale = my_scale.max(other_scale);
20 
21     // Add the items together
22     let my_negative = d1.is_sign_negative();
23     let other_negative = d2.is_sign_negative();
24     let mut negative = false;
25     let carry;
26     if !(my_negative ^ other_negative) {
27         negative = my_negative;
28         carry = add_by_internal3(&mut my, &ot);
29     } else {
30         let cmp = cmp_internal(&my, &ot);
31         // -x + y
32         // if x > y then it's negative (i.e. -2 + 1)
33         match cmp {
34             Ordering::Less => {
35                 negative = other_negative;
36                 sub_by_internal3(&mut ot, &my);
37                 my[0] = ot[0];
38                 my[1] = ot[1];
39                 my[2] = ot[2];
40             }
41             Ordering::Greater => {
42                 negative = my_negative;
43                 sub_by_internal3(&mut my, &ot);
44             }
45             Ordering::Equal => {
46                 // -2 + 2
47                 my[0] = 0;
48                 my[1] = 0;
49                 my[2] = 0;
50             }
51         }
52         carry = 0;
53     }
54 
55     // If we have a carry we underflowed.
56     // We need to lose some significant digits (if possible)
57     if carry > 0 {
58         if final_scale == 0 {
59             return CalculationResult::Overflow;
60         }
61 
62         // Copy it over to a temp array for modification
63         let mut temp = [my[0], my[1], my[2], carry];
64         while final_scale > 0 && temp[3] != 0 {
65             div_by_u32(&mut temp, 10);
66             final_scale -= 1;
67         }
68 
69         // If we still have a carry bit then we overflowed
70         if temp[3] > 0 {
71             return CalculationResult::Overflow;
72         }
73 
74         // Copy it back - we're done
75         my[0] = temp[0];
76         my[1] = temp[1];
77         my[2] = temp[2];
78     }
79 
80     CalculationResult::Ok(Decimal::from_parts(my[0], my[1], my[2], negative, final_scale))
81 }
82 
sub_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult83 pub(crate) fn sub_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
84     add_impl(d1, &(-*d2))
85 }
86 
div_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult87 pub(crate) fn div_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
88     if d2.is_zero() {
89         return CalculationResult::DivByZero;
90     }
91     if d1.is_zero() {
92         return CalculationResult::Ok(Decimal::zero());
93     }
94 
95     let dividend = d1.mantissa_array3();
96     let divisor = d2.mantissa_array3();
97     let mut quotient = [0u32, 0u32, 0u32];
98     let mut quotient_scale: i32 = d1.scale() as i32 - d2.scale() as i32;
99 
100     // We supply an extra overflow word for each of the dividend and the remainder
101     let mut working_quotient = [dividend[0], dividend[1], dividend[2], 0u32];
102     let mut working_remainder = [0u32, 0u32, 0u32, 0u32];
103     let mut working_scale = quotient_scale;
104     let mut remainder_scale = quotient_scale;
105     let mut underflow;
106 
107     loop {
108         div_internal(&mut working_quotient, &mut working_remainder, &divisor);
109         underflow = add_with_scale_internal(
110             &mut quotient,
111             &mut quotient_scale,
112             &mut working_quotient,
113             &mut working_scale,
114         );
115 
116         // Multiply the remainder by 10
117         let mut overflow = 0;
118         for part in working_remainder.iter_mut() {
119             let (lo, hi) = mul_part(*part, 10, overflow);
120             *part = lo;
121             overflow = hi;
122         }
123         // Copy temp remainder into the temp quotient section
124         working_quotient.copy_from_slice(&working_remainder);
125 
126         remainder_scale += 1;
127         working_scale = remainder_scale;
128 
129         if underflow || is_all_zero(&working_remainder) {
130             break;
131         }
132     }
133 
134     // If we have a really big number try to adjust the scale to 0
135     while quotient_scale < 0 {
136         copy_array_diff_lengths(&mut working_quotient, &quotient);
137         working_quotient[3] = 0;
138         working_remainder.iter_mut().for_each(|x| *x = 0);
139 
140         // Mul 10
141         let mut overflow = 0;
142         for part in &mut working_quotient {
143             let (lo, hi) = mul_part(*part, 10, overflow);
144             *part = lo;
145             overflow = hi;
146         }
147         for part in &mut working_remainder {
148             let (lo, hi) = mul_part(*part, 10, overflow);
149             *part = lo;
150             overflow = hi;
151         }
152         if working_quotient[3] == 0 && is_all_zero(&working_remainder) {
153             quotient_scale += 1;
154             quotient[0] = working_quotient[0];
155             quotient[1] = working_quotient[1];
156             quotient[2] = working_quotient[2];
157         } else {
158             // Overflow
159             return CalculationResult::Overflow;
160         }
161     }
162 
163     if quotient_scale > 255 {
164         quotient[0] = 0;
165         quotient[1] = 0;
166         quotient[2] = 0;
167         quotient_scale = 0;
168     }
169 
170     let mut quotient_negative = d1.is_sign_negative() ^ d2.is_sign_negative();
171 
172     // Check for underflow
173     let mut final_scale: u32 = quotient_scale as u32;
174     if final_scale > MAX_PRECISION_U32 {
175         let mut remainder = 0;
176 
177         // Division underflowed. We must remove some significant digits over using
178         //  an invalid scale.
179         while final_scale > MAX_PRECISION_U32 && !is_all_zero(&quotient) {
180             remainder = div_by_u32(&mut quotient, 10);
181             final_scale -= 1;
182         }
183         if final_scale > MAX_PRECISION_U32 {
184             // Result underflowed so set to zero
185             final_scale = 0;
186             quotient_negative = false;
187         } else if remainder >= 5 {
188             for part in &mut quotient {
189                 if remainder == 0 {
190                     break;
191                 }
192                 let digit: u64 = u64::from(*part) + 1;
193                 remainder = if digit > 0xFFFF_FFFF { 1 } else { 0 };
194                 *part = (digit & 0xFFFF_FFFF) as u32;
195             }
196         }
197     }
198 
199     CalculationResult::Ok(Decimal::from_parts(
200         quotient[0],
201         quotient[1],
202         quotient[2],
203         quotient_negative,
204         final_scale,
205     ))
206 }
207 
mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult208 pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
209     // Early exit if either is zero
210     if d1.is_zero() || d2.is_zero() {
211         return CalculationResult::Ok(Decimal::zero());
212     }
213 
214     // We are only resulting in a negative if we have mismatched signs
215     let negative = d1.is_sign_negative() ^ d2.is_sign_negative();
216 
217     // We get the scale of the result by adding the operands. This may be too big, however
218     //  we'll correct later
219     let mut final_scale = d1.scale() + d2.scale();
220 
221     // First of all, if ONLY the lo parts of both numbers is filled
222     // then we can simply do a standard 64 bit calculation. It's a minor
223     // optimization however prevents the need for long form multiplication
224     let my = d1.mantissa_array3();
225     let ot = d2.mantissa_array3();
226     if my[1] == 0 && my[2] == 0 && ot[1] == 0 && ot[2] == 0 {
227         // Simply multiplication
228         let mut u64_result = u64_to_array(u64::from(my[0]) * u64::from(ot[0]));
229 
230         // If we're above max precision then this is a very small number
231         if final_scale > MAX_PRECISION_U32 {
232             final_scale -= MAX_PRECISION_U32;
233 
234             // If the number is above 19 then this will equate to zero.
235             // This is because the max value in 64 bits is 1.84E19
236             if final_scale > 19 {
237                 return CalculationResult::Ok(Decimal::zero());
238             }
239 
240             let mut rem_lo = 0;
241             let mut power;
242             if final_scale > 9 {
243                 // Since 10^10 doesn't fit into u32, we divide by 10^10/4
244                 // and multiply the next divisor by 4.
245                 rem_lo = div_by_u32(&mut u64_result, 2_500_000_000);
246                 power = POWERS_10[final_scale as usize - 10] << 2;
247             } else {
248                 power = POWERS_10[final_scale as usize];
249             }
250 
251             // Divide fits in 32 bits
252             let rem_hi = div_by_u32(&mut u64_result, power);
253 
254             // Round the result. Since the divisor is a power of 10
255             // we check to see if the remainder is >= 1/2 divisor
256             power >>= 1;
257             if rem_hi >= power && (rem_hi > power || (rem_lo | (u64_result[0] & 0x1)) != 0) {
258                 u64_result[0] += 1;
259             }
260 
261             final_scale = MAX_PRECISION_U32;
262         }
263         return CalculationResult::Ok(Decimal::from_parts(
264             u64_result[0],
265             u64_result[1],
266             0,
267             negative,
268             final_scale,
269         ));
270     }
271 
272     // We're using some of the high bits, so we essentially perform
273     // long form multiplication. We compute the 9 partial products
274     // into a 192 bit result array.
275     //
276     //                     [my-h][my-m][my-l]
277     //                  x  [ot-h][ot-m][ot-l]
278     // --------------------------------------
279     // 1.                        [r-hi][r-lo] my-l * ot-l [0, 0]
280     // 2.                  [r-hi][r-lo]       my-l * ot-m [0, 1]
281     // 3.                  [r-hi][r-lo]       my-m * ot-l [1, 0]
282     // 4.            [r-hi][r-lo]             my-m * ot-m [1, 1]
283     // 5.            [r-hi][r-lo]             my-l * ot-h [0, 2]
284     // 6.            [r-hi][r-lo]             my-h * ot-l [2, 0]
285     // 7.      [r-hi][r-lo]                   my-m * ot-h [1, 2]
286     // 8.      [r-hi][r-lo]                   my-h * ot-m [2, 1]
287     // 9.[r-hi][r-lo]                         my-h * ot-h [2, 2]
288     let mut product = [0u32, 0u32, 0u32, 0u32, 0u32, 0u32];
289 
290     // We can perform a minor short circuit here. If the
291     // high portions are both 0 then we can skip portions 5-9
292     let to = if my[2] == 0 && ot[2] == 0 { 2 } else { 3 };
293 
294     for (my_index, my_item) in my.iter().enumerate().take(to) {
295         for (ot_index, ot_item) in ot.iter().enumerate().take(to) {
296             let (mut rlo, mut rhi) = mul_part(*my_item, *ot_item, 0);
297 
298             // Get the index for the lo portion of the product
299             for prod in product.iter_mut().skip(my_index + ot_index) {
300                 let (res, overflow) = add_part(rlo, *prod);
301                 *prod = res;
302 
303                 // If we have something in rhi from before then promote that
304                 if rhi > 0 {
305                     // If we overflowed in the last add, add that with rhi
306                     if overflow > 0 {
307                         let (nlo, nhi) = add_part(rhi, overflow);
308                         rlo = nlo;
309                         rhi = nhi;
310                     } else {
311                         rlo = rhi;
312                         rhi = 0;
313                     }
314                 } else if overflow > 0 {
315                     rlo = overflow;
316                     rhi = 0;
317                 } else {
318                     break;
319                 }
320 
321                 // If nothing to do next round then break out
322                 if rlo == 0 {
323                     break;
324                 }
325             }
326         }
327     }
328 
329     // If our result has used up the high portion of the product
330     // then we either have an overflow or an underflow situation
331     // Overflow will occur if we can't scale it back, whereas underflow
332     // with kick in rounding
333     let mut remainder = 0;
334     while final_scale > 0 && (product[3] != 0 || product[4] != 0 || product[5] != 0) {
335         remainder = div_by_u32(&mut product, 10u32);
336         final_scale -= 1;
337     }
338 
339     // Round up the carry if we need to
340     if remainder >= 5 {
341         for part in product.iter_mut() {
342             if remainder == 0 {
343                 break;
344             }
345             let digit: u64 = u64::from(*part) + 1;
346             remainder = if digit > 0xFFFF_FFFF { 1 } else { 0 };
347             *part = (digit & 0xFFFF_FFFF) as u32;
348         }
349     }
350 
351     // If we're still above max precision then we'll try again to
352     // reduce precision - we may be dealing with a limit of "0"
353     if final_scale > MAX_PRECISION_U32 {
354         // We're in an underflow situation
355         // The easiest way to remove precision is to divide off the result
356         while final_scale > MAX_PRECISION_U32 && !is_all_zero(&product) {
357             div_by_u32(&mut product, 10);
358             final_scale -= 1;
359         }
360         // If we're still at limit then we can't represent any
361         // significant decimal digits and will return an integer only
362         // Can also be invoked while representing 0.
363         if final_scale > MAX_PRECISION_U32 {
364             final_scale = 0;
365         }
366     } else if !(product[3] == 0 && product[4] == 0 && product[5] == 0) {
367         // We're in an overflow situation - we're within our precision bounds
368         // but still have bits in overflow
369         return CalculationResult::Overflow;
370     }
371 
372     CalculationResult::Ok(Decimal::from_parts(
373         product[0],
374         product[1],
375         product[2],
376         negative,
377         final_scale,
378     ))
379 }
380 
rem_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult381 pub(crate) fn rem_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
382     if d2.is_zero() {
383         return CalculationResult::DivByZero;
384     }
385     if d1.is_zero() {
386         return CalculationResult::Ok(Decimal::zero());
387     }
388 
389     // Rescale so comparable
390     let initial_scale = d1.scale();
391     let mut quotient = d1.mantissa_array3();
392     let mut quotient_scale = initial_scale;
393     let mut divisor = d2.mantissa_array3();
394     let mut divisor_scale = d2.scale();
395     rescale_to_maximum_scale(&mut quotient, &mut quotient_scale, &mut divisor, &mut divisor_scale);
396 
397     // Working is the remainder + the quotient
398     // We use an aligned array since we'll be using it a lot.
399     let mut working_quotient = [quotient[0], quotient[1], quotient[2], 0u32];
400     let mut working_remainder = [0u32, 0u32, 0u32, 0u32];
401     div_internal(&mut working_quotient, &mut working_remainder, &divisor);
402 
403     // Round if necessary. This is for semantic correctness, but could feasibly be removed for
404     // performance improvements.
405     if quotient_scale > initial_scale {
406         let mut working = [
407             working_remainder[0],
408             working_remainder[1],
409             working_remainder[2],
410             working_remainder[3],
411         ];
412         while quotient_scale > initial_scale {
413             if div_by_u32(&mut working, 10) > 0 {
414                 break;
415             }
416             quotient_scale -= 1;
417             working_remainder.copy_from_slice(&working);
418         }
419     }
420 
421     CalculationResult::Ok(Decimal::from_parts(
422         working_remainder[0],
423         working_remainder[1],
424         working_remainder[2],
425         d1.is_sign_negative(),
426         quotient_scale,
427     ))
428 }
429 
cmp_impl(d1: &Decimal, d2: &Decimal) -> Ordering430 pub(crate) fn cmp_impl(d1: &Decimal, d2: &Decimal) -> Ordering {
431     // Quick exit if major differences
432     if d1.is_zero() && d2.is_zero() {
433         return Ordering::Equal;
434     }
435     let self_negative = d1.is_sign_negative();
436     let other_negative = d2.is_sign_negative();
437     if self_negative && !other_negative {
438         return Ordering::Less;
439     } else if !self_negative && other_negative {
440         return Ordering::Greater;
441     }
442 
443     // If we have 1.23 and 1.2345 then we have
444     //  123 scale 2 and 12345 scale 4
445     //  We need to convert the first to
446     //  12300 scale 4 so we can compare equally
447     let left: &Decimal;
448     let right: &Decimal;
449     if self_negative && other_negative {
450         // Both are negative, so reverse cmp
451         left = d2;
452         right = d1;
453     } else {
454         left = d1;
455         right = d2;
456     }
457     let mut left_scale = left.scale();
458     let mut right_scale = right.scale();
459     let mut left_raw = left.mantissa_array3();
460     let mut right_raw = right.mantissa_array3();
461 
462     if left_scale == right_scale {
463         // Fast path for same scale
464         if left_raw[2] != right_raw[2] {
465             return left_raw[2].cmp(&right_raw[2]);
466         }
467         if left_raw[1] != right_raw[1] {
468             return left_raw[1].cmp(&right_raw[1]);
469         }
470         return left_raw[0].cmp(&right_raw[0]);
471     }
472 
473     // Rescale and compare
474     rescale_to_maximum_scale(&mut left_raw, &mut left_scale, &mut right_raw, &mut right_scale);
475     cmp_internal(&left_raw, &right_raw)
476 }
477 
478 #[inline]
add_part(left: u32, right: u32) -> (u32, u32)479 fn add_part(left: u32, right: u32) -> (u32, u32) {
480     let added = u64::from(left) + u64::from(right);
481     ((added & U32_MASK) as u32, (added >> 32 & U32_MASK) as u32)
482 }
483 
484 #[inline(always)]
sub_by_internal3(value: &mut [u32; 3], by: &[u32; 3])485 fn sub_by_internal3(value: &mut [u32; 3], by: &[u32; 3]) {
486     let mut overflow = 0;
487     let vl = value.len();
488     for i in 0..vl {
489         let part = (0x1_0000_0000u64 + u64::from(value[i])) - (u64::from(by[i]) + overflow);
490         value[i] = part as u32;
491         overflow = 1 - (part >> 32);
492     }
493 }
494 
div_internal(quotient: &mut [u32; 4], remainder: &mut [u32; 4], divisor: &[u32; 3])495 fn div_internal(quotient: &mut [u32; 4], remainder: &mut [u32; 4], divisor: &[u32; 3]) {
496     // There are a couple of ways to do division on binary numbers:
497     //   1. Using long division
498     //   2. Using the complement method
499     // ref: http://paulmason.me/dividing-binary-numbers-part-2/
500     // The complement method basically keeps trying to subtract the
501     // divisor until it can't anymore and placing the rest in remainder.
502     let mut complement = [
503         divisor[0] ^ 0xFFFF_FFFF,
504         divisor[1] ^ 0xFFFF_FFFF,
505         divisor[2] ^ 0xFFFF_FFFF,
506         0xFFFF_FFFF,
507     ];
508 
509     // Add one onto the complement
510     add_one_internal4(&mut complement);
511 
512     // Make sure the remainder is 0
513     remainder.iter_mut().for_each(|x| *x = 0);
514 
515     // If we have nothing in our hi+ block then shift over till we do
516     let mut blocks_to_process = 0;
517     while blocks_to_process < 4 && quotient[3] == 0 {
518         // memcpy would be useful here
519         quotient[3] = quotient[2];
520         quotient[2] = quotient[1];
521         quotient[1] = quotient[0];
522         quotient[0] = 0;
523 
524         // Increment the counter
525         blocks_to_process += 1;
526     }
527 
528     // Let's try and do the addition...
529     let mut block = blocks_to_process << 5;
530     let mut working = [0u32, 0u32, 0u32, 0u32];
531     while block < 128 {
532         // << 1 for quotient AND remainder. Moving the carry from the quotient to the bottom of the
533         // remainder.
534         let carry = shl1_internal(quotient, 0);
535         shl1_internal(remainder, carry);
536 
537         // Copy the remainder of working into sub
538         working.copy_from_slice(remainder);
539 
540         // Add the remainder with the complement
541         add_by_internal(&mut working, &complement);
542 
543         // Check for the significant bit - move over to the quotient
544         // as necessary
545         if (working[3] & 0x8000_0000) == 0 {
546             remainder.copy_from_slice(&working);
547             quotient[0] |= 1;
548         }
549 
550         // Increment our pointer
551         block += 1;
552     }
553 }
554 
555 #[inline]
copy_array_diff_lengths(into: &mut [u32], from: &[u32])556 fn copy_array_diff_lengths(into: &mut [u32], from: &[u32]) {
557     for i in 0..into.len() {
558         if i >= from.len() {
559             break;
560         }
561         into[i] = from[i];
562     }
563 }
564 
565 #[inline]
add_one_internal4(value: &mut [u32; 4]) -> u32566 fn add_one_internal4(value: &mut [u32; 4]) -> u32 {
567     let mut carry: u64 = 1; // Start with one, since adding one
568     let mut sum: u64;
569     for i in value.iter_mut() {
570         sum = (*i as u64) + carry;
571         *i = (sum & U32_MASK) as u32;
572         carry = sum >> 32;
573     }
574 
575     carry as u32
576 }
577 
578 #[inline]
add_by_internal3(value: &mut [u32; 3], by: &[u32; 3]) -> u32579 fn add_by_internal3(value: &mut [u32; 3], by: &[u32; 3]) -> u32 {
580     let mut carry: u32 = 0;
581     let bl = by.len();
582     for i in 0..bl {
583         let res1 = value[i].overflowing_add(by[i]);
584         let res2 = res1.0.overflowing_add(carry);
585         value[i] = res2.0;
586         carry = (res1.1 | res2.1) as u32;
587     }
588     carry
589 }
590 
591 #[inline]
u64_to_array(value: u64) -> [u32; 2]592 const fn u64_to_array(value: u64) -> [u32; 2] {
593     [(value & U32_MASK) as u32, (value >> 32 & U32_MASK) as u32]
594 }
595 
add_with_scale_internal( quotient: &mut [u32; 3], quotient_scale: &mut i32, working_quotient: &mut [u32; 4], working_scale: &mut i32, ) -> bool596 fn add_with_scale_internal(
597     quotient: &mut [u32; 3],
598     quotient_scale: &mut i32,
599     working_quotient: &mut [u32; 4],
600     working_scale: &mut i32,
601 ) -> bool {
602     // Add quotient and the working (i.e. quotient = quotient + working)
603     if is_all_zero(quotient) {
604         // Quotient is zero so we can just copy the working quotient in directly
605         // First, make sure they are both 96 bit.
606         while working_quotient[3] != 0 {
607             div_by_u32(working_quotient, 10);
608             *working_scale -= 1;
609         }
610         copy_array_diff_lengths(quotient, working_quotient);
611         *quotient_scale = *working_scale;
612         return false;
613     }
614 
615     if is_all_zero(working_quotient) {
616         return false;
617     }
618 
619     // We have ensured that our working is not zero so we should do the addition
620 
621     // If our two quotients are different then
622     // try to scale down the one with the bigger scale
623     let mut temp3 = [0u32, 0u32, 0u32];
624     let mut temp4 = [0u32, 0u32, 0u32, 0u32];
625     if *quotient_scale != *working_scale {
626         // TODO: Remove necessity for temp (without performance impact)
div_by_10<const N: usize>(target: &mut [u32], temp: &mut [u32; N], scale: &mut i32, target_scale: i32)627         fn div_by_10<const N: usize>(target: &mut [u32], temp: &mut [u32; N], scale: &mut i32, target_scale: i32) {
628             // Copy to the temp array
629             temp.copy_from_slice(target);
630             // divide by 10 until target scale is reached
631             while *scale > target_scale {
632                 let remainder = div_by_u32(temp, 10);
633                 if remainder == 0 {
634                     *scale -= 1;
635                     target.copy_from_slice(temp);
636                 } else {
637                     break;
638                 }
639             }
640         }
641 
642         if *quotient_scale < *working_scale {
643             div_by_10(working_quotient, &mut temp4, working_scale, *quotient_scale);
644         } else {
645             div_by_10(quotient, &mut temp3, quotient_scale, *working_scale);
646         }
647     }
648 
649     // If our two quotients are still different then
650     // try to scale up the smaller scale
651     if *quotient_scale != *working_scale {
652         // TODO: Remove necessity for temp (without performance impact)
mul_by_10(target: &mut [u32], temp: &mut [u32], scale: &mut i32, target_scale: i32)653         fn mul_by_10(target: &mut [u32], temp: &mut [u32], scale: &mut i32, target_scale: i32) {
654             temp.copy_from_slice(target);
655             let mut overflow = 0;
656             // Multiply by 10 until target scale reached or overflow
657             while *scale < target_scale && overflow == 0 {
658                 overflow = mul_by_u32(temp, 10);
659                 if overflow == 0 {
660                     // Still no overflow
661                     *scale += 1;
662                     target.copy_from_slice(temp);
663                 }
664             }
665         }
666 
667         if *quotient_scale > *working_scale {
668             mul_by_10(working_quotient, &mut temp4, working_scale, *quotient_scale);
669         } else {
670             mul_by_10(quotient, &mut temp3, quotient_scale, *working_scale);
671         }
672     }
673 
674     // If our two quotients are still different then
675     // try to scale down the one with the bigger scale
676     // (ultimately losing significant digits)
677     if *quotient_scale != *working_scale {
678         // TODO: Remove necessity for temp (without performance impact)
div_by_10_lossy<const N: usize>( target: &mut [u32], temp: &mut [u32; N], scale: &mut i32, target_scale: i32, )679         fn div_by_10_lossy<const N: usize>(
680             target: &mut [u32],
681             temp: &mut [u32; N],
682             scale: &mut i32,
683             target_scale: i32,
684         ) {
685             temp.copy_from_slice(target);
686             // divide by 10 until target scale is reached
687             while *scale > target_scale {
688                 div_by_u32(temp, 10);
689                 *scale -= 1;
690                 target.copy_from_slice(temp);
691             }
692         }
693         if *quotient_scale < *working_scale {
694             div_by_10_lossy(working_quotient, &mut temp4, working_scale, *quotient_scale);
695         } else {
696             div_by_10_lossy(quotient, &mut temp3, quotient_scale, *working_scale);
697         }
698     }
699 
700     // If quotient or working are zero we have an underflow condition
701     if is_all_zero(quotient) || is_all_zero(working_quotient) {
702         // Underflow
703         return true;
704     } else {
705         // Both numbers have the same scale and can be added.
706         // We just need to know whether we can fit them in
707         let mut underflow = false;
708         let mut temp = [0u32, 0u32, 0u32];
709         while !underflow {
710             temp.copy_from_slice(quotient);
711 
712             // Add the working quotient
713             let overflow = add_by_internal(&mut temp, working_quotient);
714             if overflow == 0 {
715                 // addition was successful
716                 quotient.copy_from_slice(&temp);
717                 break;
718             } else {
719                 // addition overflowed - remove significant digits and try again
720                 div_by_u32(quotient, 10);
721                 *quotient_scale -= 1;
722                 div_by_u32(working_quotient, 10);
723                 *working_scale -= 1;
724                 // Check for underflow
725                 underflow = is_all_zero(quotient) || is_all_zero(working_quotient);
726             }
727         }
728         if underflow {
729             return true;
730         }
731     }
732     false
733 }
734 
735 /// Rescales the given decimals to equivalent scales.
736 /// It will firstly try to scale both the left and the right side to
737 /// the maximum scale of left/right. If it is unable to do that it
738 /// will try to reduce the accuracy of the other argument.
739 /// e.g. with 1.23 and 2.345 it'll rescale the first arg to 1.230
740 #[inline(always)]
rescale_to_maximum_scale(left: &mut [u32; 3], left_scale: &mut u32, right: &mut [u32; 3], right_scale: &mut u32)741 fn rescale_to_maximum_scale(left: &mut [u32; 3], left_scale: &mut u32, right: &mut [u32; 3], right_scale: &mut u32) {
742     if left_scale == right_scale {
743         // Nothing to do
744         return;
745     }
746 
747     if is_all_zero(left) {
748         *left_scale = *right_scale;
749         return;
750     } else if is_all_zero(right) {
751         *right_scale = *left_scale;
752         return;
753     }
754 
755     if left_scale > right_scale {
756         rescale_internal(right, right_scale, *left_scale);
757         if right_scale != left_scale {
758             rescale_internal(left, left_scale, *right_scale);
759         }
760     } else {
761         rescale_internal(left, left_scale, *right_scale);
762         if right_scale != left_scale {
763             rescale_internal(right, right_scale, *left_scale);
764         }
765     }
766 }
767 
768 #[cfg(test)]
769 mod test {
770     // Tests on private methods.
771     //
772     // All public tests should go under `tests/`.
773 
774     use super::*;
775     use crate::prelude::*;
776 
777     #[test]
it_can_rescale_to_maximum_scale()778     fn it_can_rescale_to_maximum_scale() {
779         fn extract(value: &str) -> ([u32; 3], u32) {
780             let v = Decimal::from_str(value).unwrap();
781             (v.mantissa_array3(), v.scale())
782         }
783 
784         let tests = &[
785             ("1", "1", "1", "1"),
786             ("1", "1.0", "1.0", "1.0"),
787             ("1", "1.00000", "1.00000", "1.00000"),
788             ("1", "1.0000000000", "1.0000000000", "1.0000000000"),
789             (
790                 "1",
791                 "1.00000000000000000000",
792                 "1.00000000000000000000",
793                 "1.00000000000000000000",
794             ),
795             ("1.1", "1.1", "1.1", "1.1"),
796             ("1.1", "1.10000", "1.10000", "1.10000"),
797             ("1.1", "1.1000000000", "1.1000000000", "1.1000000000"),
798             (
799                 "1.1",
800                 "1.10000000000000000000",
801                 "1.10000000000000000000",
802                 "1.10000000000000000000",
803             ),
804             (
805                 "0.6386554621848739495798319328",
806                 "11.815126050420168067226890757",
807                 "0.638655462184873949579831933",
808                 "11.815126050420168067226890757",
809             ),
810             (
811                 "0.0872727272727272727272727272", // Scale 28
812                 "843.65000000",                   // Scale 8
813                 "0.0872727272727272727272727",    // 25
814                 "843.6500000000000000000000000",  // 25
815             ),
816         ];
817 
818         for &(left_raw, right_raw, expected_left, expected_right) in tests {
819             // Left = the value to rescale
820             // Right = the new scale we're scaling to
821             // Expected = the expected left value after rescale
822             let (expected_left, expected_lscale) = extract(expected_left);
823             let (expected_right, expected_rscale) = extract(expected_right);
824 
825             let (mut left, mut left_scale) = extract(left_raw);
826             let (mut right, mut right_scale) = extract(right_raw);
827             rescale_to_maximum_scale(&mut left, &mut left_scale, &mut right, &mut right_scale);
828             assert_eq!(left, expected_left);
829             assert_eq!(left_scale, expected_lscale);
830             assert_eq!(right, expected_right);
831             assert_eq!(right_scale, expected_rscale);
832 
833             // Also test the transitive case
834             let (mut left, mut left_scale) = extract(left_raw);
835             let (mut right, mut right_scale) = extract(right_raw);
836             rescale_to_maximum_scale(&mut right, &mut right_scale, &mut left, &mut left_scale);
837             assert_eq!(left, expected_left);
838             assert_eq!(left_scale, expected_lscale);
839             assert_eq!(right, expected_right);
840             assert_eq!(right_scale, expected_rscale);
841         }
842     }
843 }
844