rust_decimal/ops/
array.rs

1use crate::constants::{MAX_SCALE_U32, POWERS_10, U32_MASK};
2
3/// Rescales the given decimal to new scale.
4/// e.g. with 1.23 and new scale 3 rescale the value to 1.230
5#[inline]
6pub(crate) fn rescale_internal(value: &mut [u32; 3], value_scale: &mut u32, new_scale: u32) {
7    rescale::<true>(value, value_scale, new_scale);
8}
9
10#[inline(always)]
11fn rescale<const ROUND: bool>(value: &mut [u32; 3], value_scale: &mut u32, new_scale: u32) {
12    if *value_scale == new_scale {
13        // Nothing to do
14        return;
15    }
16
17    if is_all_zero(value) {
18        *value_scale = new_scale.min(MAX_SCALE_U32);
19        return;
20    }
21
22    if *value_scale > new_scale {
23        let mut diff = value_scale.wrapping_sub(new_scale);
24        // Scaling further isn't possible since we got an overflow
25        // In this case we need to reduce the accuracy of the "side to keep"
26
27        // Now do the necessary rounding
28        let mut remainder = 0;
29        while let Some(diff_minus_one) = diff.checked_sub(1) {
30            if is_all_zero(value) {
31                *value_scale = new_scale;
32                return;
33            }
34
35            diff = diff_minus_one;
36
37            // Any remainder is discarded if diff > 0 still (i.e. lost precision)
38            remainder = div_by_u32(value, 10);
39        }
40        if ROUND && remainder >= 5 {
41            for part in value.iter_mut() {
42                let digit = u64::from(*part) + 1u64;
43                remainder = if digit > U32_MASK { 1 } else { 0 };
44                *part = (digit & U32_MASK) as u32;
45                if remainder == 0 {
46                    break;
47                }
48            }
49        }
50        *value_scale = new_scale;
51    } else {
52        let mut diff = new_scale.wrapping_sub(*value_scale);
53        let mut working = [value[0], value[1], value[2]];
54        while let Some(diff_minus_one) = diff.checked_sub(1) {
55            if mul_by_10(&mut working) == 0 {
56                value.copy_from_slice(&working);
57                diff = diff_minus_one;
58            } else {
59                break;
60            }
61        }
62        *value_scale = new_scale.wrapping_sub(diff);
63    }
64}
65
66#[inline]
67pub(crate) fn truncate_internal(value: &mut [u32; 3], value_scale: &mut u32, desired_scale: u32) {
68    rescale::<false>(value, value_scale, desired_scale);
69}
70
71#[cfg(feature = "legacy-ops")]
72pub(crate) fn add_by_internal(value: &mut [u32], by: &[u32]) -> u32 {
73    let mut carry: u64 = 0;
74    let vl = value.len();
75    let bl = by.len();
76    if vl >= bl {
77        let mut sum: u64;
78        for i in 0..bl {
79            sum = u64::from(value[i]) + u64::from(by[i]) + carry;
80            value[i] = (sum & U32_MASK) as u32;
81            carry = sum >> 32;
82        }
83        if vl > bl && carry > 0 {
84            for i in value.iter_mut().skip(bl) {
85                sum = u64::from(*i) + carry;
86                *i = (sum & U32_MASK) as u32;
87                carry = sum >> 32;
88                if carry == 0 {
89                    break;
90                }
91            }
92        }
93    } else if vl + 1 == bl {
94        // Overflow, by default, is anything in the high portion of by
95        let mut sum: u64;
96        for i in 0..vl {
97            sum = u64::from(value[i]) + u64::from(by[i]) + carry;
98            value[i] = (sum & U32_MASK) as u32;
99            carry = sum >> 32;
100        }
101        if by[vl] > 0 {
102            carry += u64::from(by[vl]);
103        }
104    } else {
105        panic!("Internal error: add using incompatible length arrays. {} <- {}", vl, bl);
106    }
107    carry as u32
108}
109
110pub(crate) fn add_by_internal_flattened(value: &mut [u32; 3], by: u32) -> u32 {
111    manage_add_by_internal(by, value)
112}
113
114#[inline]
115pub(crate) fn add_one_internal(value: &mut [u32; 3]) -> u32 {
116    manage_add_by_internal(1, value)
117}
118
119// `u64 as u32` are safe because of widening and 32bits shifts
120#[inline]
121pub(crate) fn manage_add_by_internal<const N: usize>(initial_carry: u32, value: &mut [u32; N]) -> u32 {
122    let mut carry = u64::from(initial_carry);
123    let mut iter = 0..value.len();
124    let mut sum = 0;
125
126    let mut sum_fn = |local_carry: &mut u64, idx| {
127        sum = u64::from(value[idx]).wrapping_add(*local_carry);
128        value[idx] = (sum & U32_MASK) as u32;
129        *local_carry = sum.wrapping_shr(32);
130    };
131
132    if let Some(idx) = iter.next() {
133        sum_fn(&mut carry, idx);
134    }
135
136    for idx in iter {
137        if carry > 0 {
138            sum_fn(&mut carry, idx);
139        }
140    }
141
142    carry as u32
143}
144
145pub(crate) fn sub_by_internal(value: &mut [u32], by: &[u32]) -> u32 {
146    // The way this works is similar to long subtraction
147    // Let's assume we're working with bytes for simplicity in an example:
148    //   257 - 8 = 249
149    //   0000_0001 0000_0001 - 0000_0000 0000_1000 = 0000_0000 1111_1001
150    // We start by doing the first byte...
151    //   Overflow = 0
152    //   Left = 0000_0001 (1)
153    //   Right = 0000_1000 (8)
154    // Firstly, we make sure the left and right are scaled up to twice the size
155    //   Left = 0000_0000 0000_0001
156    //   Right = 0000_0000 0000_1000
157    // We then subtract right from left
158    //   Result = Left - Right = 1111_1111 1111_1001
159    // We subtract the overflow, which in this case is 0.
160    // Because left < right (1 < 8) we invert the high part.
161    //   Lo = 1111_1001
162    //   Hi = 1111_1111 -> 0000_0001
163    // Lo is the field, hi is the overflow.
164    // We do the same for the second byte...
165    //   Overflow = 1
166    //   Left = 0000_0001
167    //   Right = 0000_0000
168    //   Result = Left - Right = 0000_0000 0000_0001
169    // We subtract the overflow...
170    //   Result = 0000_0000 0000_0001 - 1 = 0
171    // And we invert the high, just because (invert 0 = 0).
172    // So our result is:
173    //   0000_0000 1111_1001
174    let mut overflow = 0;
175    let vl = value.len();
176    let bl = by.len();
177    for i in 0..vl {
178        if i >= bl {
179            break;
180        }
181        let (lo, hi) = sub_part(value[i], by[i], overflow);
182        value[i] = lo;
183        overflow = hi;
184    }
185    overflow
186}
187
188fn sub_part(left: u32, right: u32, overflow: u32) -> (u32, u32) {
189    let part = 0x1_0000_0000u64 + u64::from(left) - (u64::from(right) + u64::from(overflow));
190    let lo = part as u32;
191    let hi = 1 - ((part >> 32) as u32);
192    (lo, hi)
193}
194
195// Returns overflow
196#[inline]
197pub(crate) fn mul_by_10(bits: &mut [u32; 3]) -> u32 {
198    let mut overflow = 0u64;
199    for b in bits.iter_mut() {
200        let result = u64::from(*b) * 10u64 + overflow;
201        let hi = (result >> 32) & U32_MASK;
202        let lo = (result & U32_MASK) as u32;
203        *b = lo;
204        overflow = hi;
205    }
206
207    overflow as u32
208}
209
210// Returns overflow
211pub(crate) fn mul_by_u32(bits: &mut [u32], m: u32) -> u32 {
212    let mut overflow = 0;
213    for b in bits.iter_mut() {
214        let (lo, hi) = mul_part(*b, m, overflow);
215        *b = lo;
216        overflow = hi;
217    }
218    overflow
219}
220
221pub(crate) fn mul_part(left: u32, right: u32, high: u32) -> (u32, u32) {
222    let result = u64::from(left) * u64::from(right) + u64::from(high);
223    let hi = ((result >> 32) & U32_MASK) as u32;
224    let lo = (result & U32_MASK) as u32;
225    (lo, hi)
226}
227
228// Returns remainder
229pub(crate) fn div_by_u32<const N: usize>(bits: &mut [u32; N], divisor: u32) -> u32 {
230    if divisor == 0 {
231        // Divide by zero
232        panic!("Internal error: divide by zero");
233    } else if divisor == 1 {
234        // dividend remains unchanged
235        0
236    } else {
237        let mut remainder = 0u32;
238        let divisor = u64::from(divisor);
239        for part in bits.iter_mut().rev() {
240            let temp = (u64::from(remainder) << 32) + u64::from(*part);
241            remainder = (temp % divisor) as u32;
242            *part = (temp / divisor) as u32;
243        }
244
245        remainder
246    }
247}
248
249// This function should be used with caution. It unwraps the standard divide loop - it is intended
250// for small inputs (<10) and is optimized to be left as unchecked.
251pub(crate) fn div_by_power<const POWER: usize>(bits: &mut [u32; 3]) -> u32 {
252    let mut remainder = 0u32;
253    let divisor = POWERS_10[POWER] as u64;
254    let temp = ((remainder as u64) << 32) + (bits[2] as u64);
255    remainder = (temp % divisor) as u32;
256    bits[2] = (temp / divisor) as u32;
257    let temp = ((remainder as u64) << 32) + (bits[1] as u64);
258    remainder = (temp % divisor) as u32;
259    bits[1] = (temp / divisor) as u32;
260    let temp = ((remainder as u64) << 32) + (bits[0] as u64);
261    remainder = (temp % divisor) as u32;
262    bits[0] = (temp / divisor) as u32;
263    remainder
264}
265
266#[inline]
267pub(crate) fn shl1_internal(bits: &mut [u32], carry: u32) -> u32 {
268    let mut carry = carry;
269    for part in bits.iter_mut() {
270        let b = *part >> 31;
271        *part = (*part << 1) | carry;
272        carry = b;
273    }
274    carry
275}
276
277#[inline]
278pub(crate) fn cmp_internal(left: &[u32; 3], right: &[u32; 3]) -> core::cmp::Ordering {
279    let left_hi: u32 = left[2];
280    let right_hi: u32 = right[2];
281    let left_lo: u64 = (u64::from(left[1]) << 32) | u64::from(left[0]);
282    let right_lo: u64 = (u64::from(right[1]) << 32) | u64::from(right[0]);
283    if left_hi < right_hi || (left_hi <= right_hi && left_lo < right_lo) {
284        core::cmp::Ordering::Less
285    } else if left_hi == right_hi && left_lo == right_lo {
286        core::cmp::Ordering::Equal
287    } else {
288        core::cmp::Ordering::Greater
289    }
290}
291
292#[inline]
293pub(crate) fn is_all_zero<const N: usize>(bits: &[u32; N]) -> bool {
294    bits.iter().all(|b| *b == 0)
295}
296
297#[cfg(test)]
298mod test {
299    // Tests on private methods.
300    //
301    // All public tests should go under `tests/`.
302
303    use super::*;
304    use crate::prelude::*;
305
306    fn to_mantissa_array_with_scale(value: &str) -> ([u32; 3], u32) {
307        let v = Decimal::from_str(value).unwrap();
308        (v.mantissa_array3(), v.scale())
309    }
310
311    #[test]
312    fn it_can_rescale_internal() {
313        let tests = &[
314            ("1", 0, "1", 0),
315            ("1", 1, "1.0", 1),
316            ("1", 5, "1.00000", 5),
317            ("1", 10, "1.0000000000", 10),
318            ("1", 20, "1.00000000000000000000", 20),
319            (
320                "0.6386554621848739495798319328",
321                27,
322                "0.638655462184873949579831933",
323                27,
324            ),
325            (
326                "843.65000000", // Scale 8
327                25,
328                "843.6500000000000000000000000",
329                25,
330            ),
331            (
332                "843.65000000", // Scale 8
333                30,
334                "843.6500000000000000000000000",
335                25, // Only fits 25
336            ),
337            ("0", 130, "0.000000000000000000000000000000", 28),
338        ];
339
340        for &(value_raw, new_scale, expected_value, expected_scale) in tests {
341            let (expected_value, _) = to_mantissa_array_with_scale(expected_value);
342            let (mut value, mut value_scale) = to_mantissa_array_with_scale(value_raw);
343            rescale_internal(&mut value, &mut value_scale, new_scale);
344            assert_eq!(value, expected_value);
345            assert_eq!(
346                value_scale, expected_scale,
347                "value: {value_raw}, requested scale: {new_scale}"
348            );
349        }
350    }
351
352    #[test]
353    fn test_shl1_internal() {
354        struct TestCase {
355            // One thing to be cautious of is that the structure of a number here for shifting left is
356            // the reverse of how you may conceive this mentally. i.e. a[2] contains the higher order
357            // bits: a[2] a[1] a[0]
358            given: [u32; 3],
359            given_carry: u32,
360            expected: [u32; 3],
361            expected_carry: u32,
362        }
363        let tests = [
364            TestCase {
365                given: [1, 0, 0],
366                given_carry: 0,
367                expected: [2, 0, 0],
368                expected_carry: 0,
369            },
370            TestCase {
371                given: [1, 0, 2147483648],
372                given_carry: 1,
373                expected: [3, 0, 0],
374                expected_carry: 1,
375            },
376        ];
377        for case in &tests {
378            let mut test = [case.given[0], case.given[1], case.given[2]];
379            let carry = shl1_internal(&mut test, case.given_carry);
380            assert_eq!(
381                test, case.expected,
382                "Bits: {:?} << 1 | {}",
383                case.given, case.given_carry
384            );
385            assert_eq!(
386                carry, case.expected_carry,
387                "Carry: {:?} << 1 | {}",
388                case.given, case.given_carry
389            )
390        }
391    }
392}