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, "ient);
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("ient) {
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