fxd/
arith.rs

1use std::cmp::Ordering;
2use std::ops::{Add, Div, Mul, Rem, Sub};
3
4use crate::cmp::cmp_abs_lsu;
5use crate::decimal::{FixedDecimal, DIGITS_PER_UNIT, MAX_FRAC_UNITS, MAX_UNITS, UNIT};
6use crate::error::{Error, Result};
7use crate::utils::{get_units, unit_leading_zeroes, units_greater_equal};
8
9const DIV_INCR_FRAC: usize = 4;
10
11impl FixedDecimal {
12    #[inline]
13    pub fn add_to(lhs: &Self, rhs: &Self, res: &mut Self) -> Result<()> {
14        if lhs.is_zero() {
15            *res = rhs.clone();
16            return Ok(());
17        }
18        if rhs.is_zero() {
19            *res = lhs.clone();
20            return Ok(());
21        }
22        let lneg = lhs.is_neg();
23        let rneg = rhs.is_neg();
24        if lneg == rneg {
25            add_abs(lhs, rhs, res)?;
26            if lneg {
27                res.set_neg_and_check_zero();
28            }
29            return Ok(());
30        }
31        let sub_neg = sub_abs(lhs, rhs, res)?;
32        if sub_neg != lneg {
33            res.set_neg_and_check_zero();
34        }
35        Ok(())
36    }
37
38    #[inline]
39    pub fn sub_to(lhs: &Self, rhs: &Self, res: &mut Self) -> Result<()> {
40        if lhs.is_zero() {
41            *res = rhs.clone();
42            if res.is_neg() {
43                res.set_pos();
44            } else {
45                res.set_neg_and_check_zero();
46            }
47            return Ok(());
48        }
49        if rhs.is_zero() {
50            *res = lhs.clone();
51            return Ok(());
52        }
53        let lneg = lhs.is_neg();
54        let rneg = rhs.is_neg();
55        if lneg != rneg {
56            add_abs(lhs, rhs, res)?;
57            if lneg {
58                res.set_neg_and_check_zero();
59            }
60            return Ok(());
61        }
62        let sub_neg = sub_abs(lhs, rhs, res)?;
63        if sub_neg != lneg {
64            res.set_neg_and_check_zero();
65        }
66        Ok(())
67    }
68
69    #[inline]
70    pub fn mul_to(lhs: &Self, rhs: &Self, res: &mut Self) -> Result<()> {
71        if lhs.is_zero() || rhs.is_zero() {
72            res.set_zero();
73            return Ok(());
74        }
75        let res_neg = lhs.is_neg() != rhs.is_neg();
76        mul_abs(lhs, rhs, res)?;
77        if res_neg {
78            res.set_neg_and_check_zero();
79        }
80        Ok(())
81    }
82
83    #[inline]
84    pub fn div_to(lhs: &Self, rhs: &Self, res: &mut Self, incr_frac: usize) -> Result<()> {
85        let res_neg = lhs.is_neg() != rhs.is_neg();
86        div_abs(lhs, rhs, res, incr_frac as isize)?;
87        if res_neg {
88            res.set_neg_and_check_zero();
89        }
90        Ok(())
91    }
92
93    #[inline]
94    pub fn rem_to(lhs: &Self, rhs: &Self, res: &mut Self) -> Result<()> {
95        let res_neg = lhs.is_neg();
96        rem_abs(lhs, rhs, res)?;
97        if res_neg {
98            res.set_neg_and_check_zero();
99        }
100        Ok(())
101    }
102}
103
104impl Add for FixedDecimal {
105    type Output = FixedDecimal;
106
107    #[inline]
108    fn add(self, rhs: Self) -> Self::Output {
109        let mut res = FixedDecimal {
110            intg: 0,
111            frac: 0,
112            lsu: [0; MAX_UNITS],
113        };
114        if let Err(e) = Self::add_to(&self, &rhs, &mut res) {
115            panic!("addition failed: {}", e);
116        }
117        res
118    }
119}
120
121impl Sub for FixedDecimal {
122    type Output = FixedDecimal;
123
124    #[inline]
125    fn sub(self, rhs: Self) -> Self::Output {
126        let mut res = FixedDecimal {
127            intg: 0,
128            frac: 0,
129            lsu: [0; MAX_UNITS],
130        };
131        if let Err(e) = Self::sub_to(&self, &rhs, &mut res) {
132            panic!("subtraction failed: {}", e);
133        }
134        res
135    }
136}
137
138impl Mul for FixedDecimal {
139    type Output = FixedDecimal;
140
141    #[inline]
142    fn mul(self, rhs: Self) -> Self::Output {
143        let mut res = FixedDecimal {
144            intg: 0,
145            frac: 0,
146            lsu: [0; MAX_UNITS],
147        };
148        if let Err(e) = Self::mul_to(&self, &rhs, &mut res) {
149            panic!("multiplication failed: {}", e);
150        }
151        res
152    }
153}
154
155impl Div for FixedDecimal {
156    type Output = FixedDecimal;
157
158    #[inline]
159    fn div(self, rhs: Self) -> Self::Output {
160        let mut res = FixedDecimal {
161            intg: 0,
162            frac: 0,
163            lsu: [0; MAX_UNITS],
164        };
165        if let Err(e) = Self::div_to(&self, &rhs, &mut res, DIV_INCR_FRAC) {
166            panic!("division failed: {}", e);
167        }
168        res
169    }
170}
171
172impl Rem for FixedDecimal {
173    type Output = FixedDecimal;
174
175    #[inline]
176    fn rem(self, rhs: Self) -> Self::Output {
177        let mut res = FixedDecimal {
178            intg: 0,
179            frac: 0,
180            lsu: [0; MAX_UNITS],
181        };
182        if let Err(e) = Self::rem_to(&self, &rhs, &mut res) {
183            panic!("modulo failed: {}", e);
184        }
185        res
186    }
187}
188
189/// sums two decimals' absolute values.
190/// Separate units into 3 segments, intg, common, frac
191/// | lhs  |  xxxx  |  xxxx.xxxx  |        |
192/// | rhs  |        |  yyyy.yyyy  |  yyyy  |
193/// |------|--------|-------------|--------|
194/// |      |  intg  |   common    |  frac  |
195///
196/// frac can be directly added to result.
197/// common uses normal addition, taking care of carry.
198/// intg is added with 0 and carry.
199fn add_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
200    res.set_zero(); // always clear result first
201    let liu = lhs.intg_units();
202    let lfu = lhs.frac_units();
203    let riu = rhs.intg_units();
204    let rfu = rhs.frac_units();
205    let mut frac_unit_diff = lfu as isize - rfu as isize;
206    let mut lhs_idx: isize = 0;
207    let mut rhs_idx: isize = 0;
208    let mut res_idx: isize = 0;
209    match frac_unit_diff.cmp(&0) {
210        Ordering::Greater => {
211            res.lsu[..frac_unit_diff as usize].copy_from_slice(&lhs.lsu[..frac_unit_diff as usize]);
212            lhs_idx = frac_unit_diff;
213            res_idx = frac_unit_diff;
214        }
215        Ordering::Less => {
216            frac_unit_diff = -frac_unit_diff;
217            res.lsu[..frac_unit_diff as usize].copy_from_slice(&rhs.lsu[..frac_unit_diff as usize]);
218            rhs_idx = frac_unit_diff;
219            res_idx = frac_unit_diff;
220        }
221        Ordering::Equal => (),
222    }
223    let mut stop = res_idx + liu.min(riu) as isize + lfu.min(rfu) as isize;
224    let mut carry: i32 = 0;
225    while res_idx < stop {
226        let (r0, c0) = add_with_carry(lhs.lsu[lhs_idx as usize], rhs.lsu[rhs_idx as usize], carry);
227        res.lsu[res_idx as usize] = r0;
228        carry = c0;
229        lhs_idx += 1;
230        rhs_idx += 1;
231        res_idx += 1;
232    }
233    let intg_unit_diff = liu as isize - riu as isize;
234    if intg_unit_diff > 0 {
235        // lhs has more intg
236        stop = lhs_idx + intg_unit_diff;
237        while lhs_idx < stop {
238            let (r0, c0) = add_with_carry(lhs.lsu[lhs_idx as usize], 0, carry);
239            res.lsu[res_idx as usize] = r0;
240            carry = c0;
241            res_idx += 1;
242            lhs_idx += 1;
243        }
244        if carry > 0 {
245            res.lsu[res_idx as usize] = carry;
246        }
247    } else if intg_unit_diff < 0 {
248        // rhs has more intg
249        stop = rhs_idx - intg_unit_diff;
250        while rhs_idx < stop {
251            let (r0, c0) = add_with_carry(rhs.lsu[rhs_idx as usize], 0, carry);
252            res.lsu[res_idx as usize] = r0;
253            carry = c0;
254            res_idx += 1;
255            rhs_idx += 1;
256        }
257        if carry > 0 {
258            res.lsu[res_idx as usize] = carry;
259        }
260    } else if carry != 0 {
261        // no more intg but carry is non-zero
262        res.lsu[res_idx as usize] = carry;
263    }
264
265    let mut res_intg_non_zero = liu.max(riu) as isize + carry as isize;
266    res.frac = lhs.frac.max(rhs.frac);
267    let res_frac_units = res.frac_units() as isize;
268    while res_intg_non_zero >= 0 {
269        if res.lsu[(res_intg_non_zero + res_frac_units) as usize] > 0 {
270            break;
271        }
272        res_intg_non_zero -= 1;
273    }
274    if res_intg_non_zero >= 0 {
275        res.intg = ((res_intg_non_zero + 1) * DIGITS_PER_UNIT as isize) as i8;
276    } else {
277        res.intg = 0;
278    }
279    Ok(())
280}
281
282/// differs two decimals' absolute values, returns the negative flag.
283/// Similar to addAbs(), but if lhs is smaller than rhs, we will have
284/// borrow=-1 at end. Then we can traverse all units and apply subtraction
285/// again.
286///
287/// Separate units into 3 segments, intgSeg, commonSeg, fracSeg
288/// | lhs  |  xxxx  |  xxxx.xxxx  |        |
289/// | rhs  |        |  yyyy.yyyy  |  yyyy  |
290/// |------|--------|-------------|--------|
291/// |      |  intg  |   common    |  frac  |
292fn sub_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<bool> {
293    res.set_zero(); // always clear result first
294    let liu = lhs.intg_units();
295    let lfu = lhs.frac_units();
296    let riu = rhs.intg_units();
297    let rfu = rhs.frac_units();
298    let mut frac_unit_diff = lfu as isize - rfu as isize;
299    let mut lhs_idx: isize = 0;
300    let mut rhs_idx: isize = 0;
301    let mut res_idx: isize = 0;
302    let mut borrow: i32 = 0;
303    match frac_unit_diff.cmp(&0) {
304        // lhs has more frac
305        Ordering::Greater => {
306            res.lsu[..frac_unit_diff as usize].copy_from_slice(&lhs.lsu[..frac_unit_diff as usize]);
307            lhs_idx = frac_unit_diff;
308            res_idx = frac_unit_diff;
309        }
310        Ordering::Less => {
311            frac_unit_diff = -frac_unit_diff;
312            for (rst, rv) in res
313                .lsu
314                .iter_mut()
315                .zip(rhs.lsu.iter())
316                .take(frac_unit_diff as usize)
317            {
318                let (r0, b0) = sub_with_borrow(0, *rv, borrow);
319                *rst = r0;
320                borrow = b0;
321            }
322            rhs_idx = frac_unit_diff;
323            res_idx = frac_unit_diff;
324        }
325        Ordering::Equal => (),
326    }
327    let mut stop = res_idx + liu.min(riu) as isize + lfu.min(rfu) as isize;
328    while res_idx < stop {
329        let (r0, b0) =
330            sub_with_borrow(lhs.lsu[lhs_idx as usize], rhs.lsu[rhs_idx as usize], borrow);
331        res.lsu[res_idx as usize] = r0;
332        borrow = b0;
333        res_idx += 1;
334        lhs_idx += 1;
335        rhs_idx += 1;
336    }
337    let intg_unit_diff = liu as isize - riu as isize;
338    match intg_unit_diff.cmp(&0) {
339        Ordering::Greater => {
340            stop = lhs_idx + intg_unit_diff;
341            while lhs_idx < stop {
342                let (r0, b0) = sub_with_borrow(lhs.lsu[lhs_idx as usize], 0, borrow);
343                res.lsu[res_idx as usize] = r0;
344                borrow = b0;
345                res_idx += 1;
346                lhs_idx += 1;
347            }
348        }
349        Ordering::Less => {
350            stop = rhs_idx - intg_unit_diff;
351            while rhs_idx < stop {
352                let (r0, b0) = sub_with_borrow(0, rhs.lsu[rhs_idx as usize], borrow);
353                res.lsu[res_idx as usize] = r0;
354                borrow = b0;
355                res_idx += 1;
356                rhs_idx += 1;
357            }
358        }
359        Ordering::Equal => (),
360    }
361    let neg = borrow == -1;
362    if neg {
363        borrow = 0;
364        for i in 0..res_idx {
365            let (r0, b0) = sub_with_borrow(0, res.lsu[i as usize], borrow);
366            res.lsu[i as usize] = r0;
367            borrow = b0;
368        }
369    }
370    let mut res_intg_non_zero = liu.max(riu) as isize;
371    res.frac = lhs.frac.max(rhs.frac);
372    let result_frac_units = res.frac_units();
373    while res_intg_non_zero >= 0 {
374        if res.lsu[(res_intg_non_zero + result_frac_units as isize) as usize] > 0 {
375            break;
376        }
377        res_intg_non_zero -= 1;
378    }
379    if res_intg_non_zero >= 0 {
380        res.intg = ((res_intg_non_zero + 1) * DIGITS_PER_UNIT as isize) as i8;
381    } else {
382        res.intg = 0;
383    }
384    Ok(neg)
385}
386
387/// multiplies two decimals' absolute values.
388/// The result frac precision is extended to sum of both precisions. until
389/// reaching the limitation of MAX_UNITS or MAX_FRAC_UNITS.
390fn mul_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
391    res.set_zero(); // always clear result first
392    let res_intg_digits = lhs.intg() + rhs.intg();
393    let res_intg_units = get_units(res_intg_digits);
394    let res_frac_digits = lhs.frac() + rhs.frac();
395    let mut res_frac_units = get_units(res_frac_digits);
396    if res_intg_units > MAX_UNITS {
397        // integral overflow
398        return Err(Error::Overflow);
399    }
400    if res_intg_units + res_frac_units > MAX_UNITS {
401        // integral+fractional overflow
402        res_frac_units = MAX_UNITS - res_intg_units; // fractional truncation required
403    }
404    if res_frac_units > MAX_FRAC_UNITS {
405        // exceeds maximum fractional units
406        res_frac_units = MAX_FRAC_UNITS;
407    }
408    let liu = lhs.intg_units();
409    let lfu = lhs.frac_units();
410    let riu = rhs.intg_units();
411    let rfu = rhs.frac_units();
412    // because result fractional part may be truncated, we need to calculate
413    // how many units has to be shifted and can be ignored in calculation.
414    // 1. If lhsIdx + rhsIdx - shiftUnits < -1, we can ignore the result
415    //    of left.lsu[lhsIdx]*right.lsu[rhsIdx].
416    // 2. If lhsIdx + rhsIdx - shiftUnits = -1, we need to take care of the
417    //    carry and add to result.lsu[0].
418    // 3. If lhsIdx + rhsIdx - shiftUnits >= 0, follow normal calcuation.
419    let shift_units = (lfu + rfu - res_frac_units) as isize;
420    let mut carry: i64 = 0;
421    // let mut res_idx: isize = 0;
422    for (rhs_idx, rv) in rhs.lsu[..(riu + rfu) as usize].iter().enumerate() {
423        let mut res_idx = -1;
424        for (lhs_idx, lv) in lhs.lsu[..(liu + lfu) as usize].iter().enumerate() {
425            res_idx = (lhs_idx + rhs_idx) as isize - shift_units;
426            if res_idx < -1 {
427                continue;
428            }
429            if res_idx == -1 {
430                let v = (*lv as i64) * (*rv as i64);
431                if v < UNIT as i64 {
432                    continue;
433                }
434                carry = v / UNIT as i64; // we only need the carry for lsu of result
435                continue;
436            }
437            // calculate product and sum with previous result and carry
438            let v = *lv as i64 * *rv as i64 + res.lsu[res_idx as usize] as i64 + carry;
439            carry = v / UNIT as i64;
440            res.lsu[res_idx as usize] = (v - carry * UNIT as i64) as i32;
441        }
442        debug_assert!(res_idx >= 0);
443        if res_idx + 1 < MAX_UNITS as isize {
444            res.lsu[(res_idx + 1) as usize] = carry as i32;
445        } else if carry > 0 {
446            return Err(Error::Overflow);
447        }
448        carry = 0
449    }
450    res.frac = res_frac_digits.min((res_frac_units * DIGITS_PER_UNIT) as i8);
451    res.intg = (res_intg_units * DIGITS_PER_UNIT) as i8;
452    Ok(())
453}
454
455/// Divides two decimals' absolute values.
456/// It's implementation of Knuth's Algorithm 4.3.1 D, with support on fractional numbers.
457#[allow(clippy::many_single_char_names)]
458fn div_abs(
459    lhs: &FixedDecimal,
460    rhs: &FixedDecimal,
461    res: &mut FixedDecimal,
462    mut incr_frac: isize,
463) -> Result<()> {
464    res.set_zero(); // always clear result first
465    let lhs_intg = lhs.intg();
466    let liu = get_units(lhs_intg);
467    let lhs_frac = lhs.frac();
468    let lfu = get_units(lhs_frac);
469    let lhs_ext_frac = (lfu * DIGITS_PER_UNIT) as isize; // extended frac with unit size
470    let rhs_intg = rhs.intg();
471    let riu = get_units(rhs_intg);
472    let rhs_frac = rhs.frac();
473    let rfu = get_units(rhs_frac);
474    let rhs_ext_frac = (rfu * DIGITS_PER_UNIT) as isize; // extended frac with unit size
475                                                         // leading non-zero unit of lhs and rhs
476    let mut rhs_non_zero = (riu + rfu) as isize - 1;
477    while rhs_non_zero >= 0 {
478        if rhs.lsu[rhs_non_zero as usize] > 0 {
479            break;
480        }
481        rhs_non_zero -= 1;
482    }
483    if rhs_non_zero < 0 {
484        // divider is zero
485        return Err(Error::DivisionByZero);
486    }
487
488    // check and remove leading zeroes in lhs
489    let mut lhs_non_zero = (liu + lfu) as isize - 1;
490    while lhs_non_zero >= 0 {
491        if lhs.lsu[lhs_non_zero as usize] > 0 {
492            break;
493        }
494        lhs_non_zero -= 1;
495    }
496    if lhs_non_zero < 0 {
497        // dividend is zero
498        return Ok(());
499    }
500    // digits of rhs from leading non-zero position
501    let rhs_prec = (rhs_non_zero + 1) * DIGITS_PER_UNIT as isize
502        - unit_leading_zeroes(rhs.lsu[rhs_non_zero as usize]) as isize;
503    // digits of lhs from leading non-zero position
504    let lhs_prec = (lhs_non_zero + 1) * DIGITS_PER_UNIT as isize
505        - unit_leading_zeroes(lhs.lsu[lhs_non_zero as usize]) as isize;
506    // because we store fractional part in units, we always extend frac precision
507    // to multiple of 9. Here check if incrPrec is already covered by the auto-extension.
508    // if so, reset incrPrec to 0.
509    incr_frac -= lhs_ext_frac - lhs_frac as isize + rhs_ext_frac - rhs_frac as isize;
510    if incr_frac < 0 {
511        incr_frac = 0;
512    }
513    // calculate result frac units
514    let mut res_frac_units = get_units((lhs_ext_frac + rhs_ext_frac + incr_frac) as i8);
515    if res_frac_units > MAX_FRAC_UNITS {
516        // exceeds maximum fractional digits
517        res_frac_units = MAX_FRAC_UNITS;
518    }
519    // calculate result intg units
520    let mut res_intg = (lhs_prec - lhs_ext_frac) - (rhs_prec - rhs_ext_frac);
521    let mut dividend_shift: isize = 0;
522    if units_greater_equal(
523        &lhs.lsu[..(lhs_non_zero + 1) as usize],
524        &rhs.lsu[..(rhs_non_zero + 1) as usize],
525    ) {
526        res_intg += 1;
527    } else {
528        dividend_shift = -1;
529    }
530    // now adjust result units based on limitation of maximum precision and determine
531    // the start position of result unit.
532    let res_intg_units: usize;
533    let res_start_idx: isize;
534    if res_intg > 0 {
535        res_intg_units = get_units(res_intg as i8);
536        if res_intg_units > MAX_UNITS {
537            return Err(Error::Overflow);
538        }
539        if res_intg_units + res_frac_units > MAX_UNITS {
540            res_frac_units = MAX_UNITS - res_intg_units;
541        }
542        res_start_idx = (res_frac_units + res_intg_units) as isize - 1;
543    } else {
544        res_intg_units = 0;
545        let res_start_offset = get_units((1 - res_intg) as i8) as isize;
546        res_start_idx = res_frac_units as isize - res_start_offset;
547        res_intg = 0;
548    }
549    let res_units = res_intg_units + res_frac_units;
550
551    // here we identify short/long division
552    // short division means the divider only has single unit.
553    if rhs_non_zero == 0 {
554        // short division
555        let d = rhs.lsu[0] as i64;
556        let mut rem: i64 = 0;
557        if dividend_shift < 0 {
558            rem = lhs.lsu[lhs_non_zero as usize] as i64;
559        }
560        let mut i = lhs_non_zero + dividend_shift; // index of lhs
561        let mut j = res_start_idx; // index of result
562        while j >= 0 {
563            let u = if i >= 0 {
564                rem * UNIT as i64 + lhs.lsu[i as usize] as i64
565            } else {
566                rem * UNIT as i64
567            };
568            let q = u / d; // div
569            rem = u - q * d; // update remainder
570            res.lsu[j as usize] = q as i32; // update result
571            i -= 1;
572            j -= 1;
573        }
574        res.intg = res_intg as i8;
575        res.frac = (res_frac_units * DIGITS_PER_UNIT) as i8;
576        return Ok(());
577    }
578
579    // long division using Knuth's algorithm
580    // D1. normalization
581    let norm_factor = UNIT as i64 / (rhs.lsu[rhs_non_zero as usize] as i64 + 1);
582    // normalize buf1 and buf2
583    let mut buf1 = [0i32; MAX_UNITS * 2]; // store normalized lhs
584    let mut buf2 = [0i32; MAX_UNITS]; // store normalized rhs
585    if norm_factor == 1 {
586        buf1[res_units..res_units + lhs_non_zero as usize + 1]
587            .copy_from_slice(&lhs.lsu[..lhs_non_zero as usize + 1]);
588        buf2[..rhs_non_zero as usize + 1].copy_from_slice(&rhs.lsu[..rhs_non_zero as usize + 1]);
589    } else {
590        let mut carry: i64 = 0;
591        // normalize lhs into buf1
592        let buf1_end = res_units + lhs_non_zero as usize + 1;
593        for (b1, lv) in buf1[res_units..buf1_end]
594            .iter_mut()
595            .zip(lhs.lsu[..lhs_non_zero as usize + 1].iter())
596        {
597            let u = *lv as i64 * norm_factor + carry;
598            carry = u / UNIT as i64;
599            *b1 = (u - carry * UNIT as i64) as i32;
600        }
601        if carry > 0 {
602            buf1[buf1_end] = carry as i32;
603            carry = 0;
604        }
605        // normalize rhs into buf2
606        for (b2, rv) in buf2[..rhs_non_zero as usize + 1]
607            .iter_mut()
608            .zip(rhs.lsu[..rhs_non_zero as usize + 1].iter())
609        {
610            let u = *rv as i64 * norm_factor + carry;
611            carry = u / UNIT as i64;
612            *b2 = (u - carry * UNIT as i64) as i32;
613        }
614        debug_assert!(carry == 0, "carry must be zero in divider normalization");
615    }
616
617    let d0 = buf2[rhs_non_zero as usize] as i64; // rhs most significant unit
618    let d1 = buf2[rhs_non_zero as usize - 1] as i64; // rhs second significant unit
619    let mut i = res_units as isize + lhs_non_zero + dividend_shift; // index of normalized lhs
620    let mut j = res_start_idx; // index of result
621    while j >= 0 {
622        // D3. make the guess on u1
623        let u0 = buf1[i as usize + 1] as i64;
624        let mut u1: i64 = 0;
625        if i >= 0 {
626            u1 = buf1[i as usize] as i64;
627        }
628        let u = u0 * UNIT as i64 + u1;
629        let mut qhat = u / d0;
630        let mut rhat = u - qhat * d0;
631        // qhat cannot be greater or equal to UNIT
632        debug_assert!(qhat < UNIT as i64, "qhat must be less than UNIT");
633        let mut u2: i64 = 0;
634        if i > 0 {
635            u2 = buf1[i as usize - 1] as i64;
636        }
637        while qhat * d1 > rhat * UNIT as i64 + u2 {
638            // check if qhat can satisfy next unit
639            qhat -= 1; // decrease qhat
640            rhat += d0; // increase rhat
641        }
642        // D4. multiply and subtract
643        let mut ms_idx: isize = i - rhs_non_zero;
644        let mut k: isize = 0;
645        let mut carry: i64 = 0;
646        let mut borrow: i32 = 0;
647        while k <= rhs_non_zero {
648            let mul_v = qhat * buf2[k as usize] as i64 + carry; // mul
649            carry = mul_v / UNIT as i64; // update carry
650            let mul_v0 = mul_v - carry * UNIT as i64; // in current unit
651            if ms_idx < 0 {
652                let (_, b0) = sub_with_borrow(0, mul_v0 as i32, borrow);
653                borrow = b0;
654            } else {
655                let (sub_v, b0) = sub_with_borrow(buf1[ms_idx as usize], mul_v0 as i32, borrow);
656                buf1[ms_idx as usize] = sub_v;
657                borrow = b0;
658            }
659            k += 1;
660            ms_idx += 1;
661        }
662        borrow += buf1[ms_idx as usize] - carry as i32;
663        if borrow == -1 {
664            // qhat is larger, cannot satisfy the whole decimal
665            // D6. add back (reverse subtract)
666            qhat -= 1; // decrease qhat
667            borrow = 0;
668            for i in 0..rhs_non_zero {
669                // reverse subtract
670                let (r0, b0) = sub_with_borrow(0, buf1[(i + j) as usize], borrow);
671                buf1[(i + j) as usize] = r0;
672                borrow = b0;
673            }
674        } else {
675            buf1[ms_idx as usize] = 0; // clear buf1 because multiply w/ subtract succeeds
676        }
677        res.lsu[j as usize] = qhat as i32;
678        i -= 1;
679        j -= 1;
680    }
681    res.intg = res_intg as i8;
682    res.frac = (res_frac_units * DIGITS_PER_UNIT) as i8;
683    Ok(())
684}
685
686/// Modulos two decimals' absolute values.
687fn rem_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
688    res.set_zero(); // always clear result first
689    let lhs_intg = lhs.intg();
690    let liu = get_units(lhs_intg);
691    let lhs_frac = lhs.frac();
692    let lfu = get_units(lhs_frac);
693    let rhs_intg = rhs.intg();
694    let riu = get_units(rhs_intg);
695    let rhs_frac = rhs.frac();
696    let rfu = get_units(rhs_frac);
697    // leading non-zero unit of lhs and rhs
698    let mut rhs_non_zero = (riu + rfu) as isize - 1;
699    while rhs_non_zero >= 0 {
700        if rhs.lsu[rhs_non_zero as usize] > 0 {
701            break;
702        }
703        rhs_non_zero -= 1;
704    }
705    if rhs_non_zero < 0 {
706        // divider is zero
707        return Err(Error::DivisionByZero);
708    }
709    // check and remove leading zeroes in lhs
710    let mut lhs_non_zero = (liu + lfu) as isize - 1;
711    while lhs_non_zero >= 0 {
712        if lhs.lsu[lhs_non_zero as usize] > 0 {
713            break;
714        }
715        lhs_non_zero -= 1;
716    }
717    if lhs_non_zero < 0 {
718        // dividend is zero
719        return Ok(());
720    }
721
722    match cmp_abs_lsu(
723        liu as isize,
724        lfu as isize,
725        &lhs.lsu[..],
726        riu as isize,
727        rfu as isize,
728        &rhs.lsu[..],
729    ) {
730        Ordering::Less => {
731            if rfu > lfu {
732                // rhs has higher fractional precision
733                res.lsu[rfu - lfu..liu + rfu].copy_from_slice(&lhs.lsu[..lfu + liu]);
734                res.frac = rhs_frac;
735                res.intg = lhs_intg;
736                return Ok(());
737            }
738            // lhs has higher or same fractional precision
739            res.lsu[..lfu + liu].copy_from_slice(&lhs.lsu[..lfu + liu]);
740            res.frac = lhs_frac.max(rhs_frac);
741            res.intg = lhs_intg;
742            return Ok(());
743        }
744        Ordering::Equal => return Ok(()), // lhs equals to rhs, result is zero
745        Ordering::Greater => (),
746    }
747    // calculate remainder frac units
748    let rem_frac = lhs_frac.max(rhs_frac);
749    let rem_frac_units = get_units(rem_frac);
750    let dividend_shift: isize = if units_greater_equal(
751        &lhs.lsu[..(lhs_non_zero + 1) as usize],
752        &rhs.lsu[..(rhs_non_zero + 1) as usize],
753    ) {
754        0
755    } else {
756        -1
757    };
758
759    // align frac units between lhs and rhs
760    let (lhs_shift_units, rhs_shift_units) = if lfu < rfu {
761        (rfu as isize - lfu as isize, 0)
762    } else {
763        (0, lfu as isize - rfu as isize)
764    };
765
766    if rhs_non_zero == 0 {
767        // short division
768        let d = rhs.lsu[0] as i64; // single divider
769        let mut buf = [0i32; MAX_UNITS * 2];
770        let buf_len = lhs_shift_units + lhs_non_zero + 1;
771        buf[lhs_shift_units as usize..buf_len as usize]
772            .copy_from_slice(&lhs.lsu[..(lhs_non_zero + 1) as usize]);
773        let mut rem = 0;
774        if dividend_shift < 0 {
775            rem = lhs.lsu[lhs_non_zero as usize] as i64;
776        }
777        let stop = rhs_non_zero + rhs_shift_units;
778        let mut i: isize = buf_len - 1 + dividend_shift; // i is lhs index
779        while i >= stop {
780            let u = rem * UNIT as i64 + buf[i as usize] as i64;
781            let q = u / d; // div
782            rem = u - q * d; // update remainder
783            i -= 1;
784        }
785        let mut res_non_zero = -1;
786        if rem > 0 {
787            res.lsu[(i + 1) as usize] = rem as i32;
788            res_non_zero = i + 1;
789        }
790        while i >= 0 {
791            // copy rest of lhs into result
792            let v = buf[i as usize];
793            res.lsu[i as usize] = v;
794            if v > 0 && res_non_zero < 0 {
795                res_non_zero = i;
796            }
797            i -= 1;
798        }
799        if res_non_zero >= rem_frac_units as isize {
800            let res_intg_units = (res_non_zero + 1 - rem_frac_units as isize) as i8;
801            res.intg = (res_intg_units * DIGITS_PER_UNIT as i8)
802                - unit_leading_zeroes(res.lsu[(res_intg_units + rem_frac_units as i8 - 1) as usize])
803                    as i8;
804        } else {
805            res.intg = 0;
806        }
807        res.frac = rem_frac;
808        return Ok(());
809    }
810    let buf1_len = lhs_non_zero + 1 + lhs_shift_units;
811    let buf2_len = rhs_non_zero + 1 + rhs_shift_units;
812    // D1. normalization
813    let norm_factor = UNIT as i64 / (rhs.lsu[rhs_non_zero as usize] as i64 + 1);
814    // normalize buf1 and buf2
815    let mut buf1 = [0i32; MAX_UNITS * 2];
816    let mut buf2 = [0i32; MAX_UNITS * 2];
817    if norm_factor == 1 {
818        buf1[lhs_shift_units as usize..buf1_len as usize]
819            .copy_from_slice(&lhs.lsu[..(lhs_non_zero + 1) as usize]);
820        buf2[rhs_shift_units as usize..buf2_len as usize]
821            .copy_from_slice(&rhs.lsu[..(rhs_non_zero + 1) as usize]);
822    } else {
823        let mut carry: i64 = 0;
824        let mut i = 0;
825        while i <= lhs_non_zero {
826            let u = lhs.lsu[i as usize] as i64 * norm_factor + carry;
827            carry = u / UNIT as i64; // update carry
828            buf1[(i + lhs_shift_units) as usize] = (u - carry * UNIT as i64) as i32;
829            i += 1;
830        }
831        if carry > 0 {
832            buf1[buf1_len as usize] = carry as i32;
833            carry = 0;
834        }
835        // normalize rhs into buf2
836        i = 0;
837        while i <= rhs_non_zero {
838            let u = rhs.lsu[i as usize] as i64 * norm_factor + carry;
839            carry = u / UNIT as i64;
840            buf2[(i + rhs_shift_units) as usize] = (u - carry * UNIT as i64) as i32;
841            i += 1;
842        }
843        debug_assert!(carry == 0, "carry must be 0 in divider normalization");
844    }
845    let stop = buf2_len - 1; // stop index
846    let d0 = buf2[(rhs_non_zero + rhs_shift_units) as usize] as i64; // rhs most significant unit
847    let d1 = buf2[(rhs_non_zero + rhs_shift_units - 1) as usize] as i64; // rhs second significant unit
848    let mut i = buf1_len + dividend_shift - 1;
849    while i >= stop {
850        // D3. make the guess on u1
851        let u0 = buf1[(i + 1) as usize] as i64;
852        let mut u1 = 0;
853        if i >= 0 {
854            u1 = buf1[i as usize] as i64;
855        }
856        let u = u0 * UNIT as i64 + u1;
857        let mut qhat = u / d0;
858        let mut rhat = u - qhat * d0 as i64;
859        debug_assert!(qhat < UNIT as i64, "qhat must be less than Unit");
860        let mut u2 = 0;
861        if i > 0 {
862            u2 = buf1[(i - 1) as usize] as i64;
863        }
864        while qhat * d1 > rhat * UNIT as i64 + u2 {
865            // check if qhat can satisfy next unit
866            qhat -= 1;
867            rhat += d0;
868        }
869        // D4. multiply and subtract
870        let mut carry: i64 = 0;
871        let mut borrow: i32 = 0;
872        for (b1, b2) in buf1[(i - buf2_len + 1) as usize..(i + 1) as usize]
873            .iter_mut()
874            .zip(buf2[..buf2_len as usize].iter())
875        {
876            let mul_v = qhat * *b2 as i64 + carry; // mul
877            carry = mul_v / UNIT as i64; // update carry
878            let mul_v0 = mul_v - carry * UNIT as i64; // in current unit
879            let (sub_v, b0) = sub_with_borrow(*b1, mul_v0 as i32, borrow);
880            borrow = b0; // update borrow
881            *b1 = sub_v; // update buf1
882        }
883
884        borrow += buf1[(i + 1) as usize] - carry as i32;
885        if borrow == -1 {
886            // qhat is larger, cannot satisfy the whole decimal
887            // D6. add back (reverse subtract)
888            // should decrease qhat, but not used in remainder
889            borrow = 0; // reset borrow to zero
890            for b in &mut buf1[(i - buf2_len + 1) as usize..(i + 1) as usize] {
891                let (r0, b0) = sub_with_borrow(0, *b, borrow);
892                borrow = b0;
893                *b = r0;
894            }
895        }
896        buf1[(i + 1) as usize] = 0;
897        i -= 1;
898    }
899    // now we have remainder in buf1
900    debug_assert_eq!(buf1[buf1_len as usize], 0, "value must be zero");
901
902    // divide by norm factor, put quotient in result
903    let mut rem: i64 = 0;
904    let mut res_non_zero: isize = -1;
905    i = buf1_len;
906    while i > 0 {
907        i -= 1;
908        let u = rem * UNIT as i64 + buf1[i as usize] as i64;
909        if u == 0 {
910            continue;
911        }
912        let q = u / norm_factor;
913        rem = u - q * norm_factor; // update remainder
914        if q > 0 {
915            res.lsu[i as usize] = q as i32; // update result
916            if res_non_zero < 0 {
917                res_non_zero = i;
918            }
919        }
920    }
921    // because we multiply lhs and rhs with identical normFactor, the remainder must be zero.
922    debug_assert!(rem == 0, "remainder must be zero");
923
924    if res_non_zero >= rem_frac_units as isize {
925        let res_intg_units = (res_non_zero + 1 - rem_frac_units as isize) as i8;
926        res.intg = (res_intg_units * DIGITS_PER_UNIT as i8)
927            - unit_leading_zeroes(res.lsu[(res_intg_units + rem_frac_units as i8 - 1) as usize])
928                as i8;
929    } else {
930        res.intg = 0;
931    }
932    res.frac = rem_frac; // keep fractional precision like subtraction
933    Ok(())
934}
935
936// NOTE: carry can only be 0 or 1
937#[inline]
938pub(crate) fn add_with_carry(a: i32, b: i32, carry: i32) -> (i32, i32) {
939    let r = a + b + carry;
940    if r >= UNIT {
941        return (r - UNIT, 1);
942    }
943    (r, 0)
944}
945
946// NOTE: borrow can only be 0 or -1
947#[inline]
948pub(crate) fn sub_with_borrow(a: i32, b: i32, borrow: i32) -> (i32, i32) {
949    let r = a - b + borrow;
950    if r < 0 {
951        return (UNIT + r, -1);
952    }
953    (r, 0)
954}
955
956#[cfg(test)]
957mod tests {
958    use super::*;
959
960    #[test]
961    fn test_add() {
962        let mut fd1 = FixedDecimal::zero();
963        let mut fd2 = FixedDecimal::zero();
964        let mut fd3 = FixedDecimal::zero();
965        for (input1, input2, expected) in vec![
966            ("0", "0", "0"),
967            ("0", "1", "1"),
968            ("1", "1", "2"),
969            ("1", "-1", "0"),
970            ("-1", "1", "0"),
971            ("-1", "-100", "-101"),
972            ("5", "5", "10"),
973            ("1.0", "0", "1.0"),
974            ("1.0", "0.0", "1.0"),
975            ("-1.0", "0.01", "-0.99"),
976            ("-0.3", "1.27", "0.97"),
977            ("-0.3", "0.2", "-0.1"),
978            ("-0.01", "0.001", "-0.009"),
979            ("-123", "0.1", "-122.9"),
980            ("1", "-12.5", "-11.5"),
981            ("-5.0", "5.0", "0.0"),
982            ("1.0", "0.1", "1.1"),
983            ("1.01", "0.1", "1.11"),
984            ("1.00000000001", "1000.01", "1001.01000000001"),
985            ("1.234567890", "0.0000000001", "1.2345678901"),
986            ("-1.234567890", "0.0000000001", "-1.2345678899"),
987            ("10000000000", "1", "10000000001"),
988            ("1", "10000000000", "10000000001"),
989            ("999999999", "1", "1000000000"),
990            ("1", "999999999", "1000000000"),
991            ("999999999999999999", "1", "1000000000000000000"),
992            ("1", "999999999999999999", "1000000000000000000"),
993        ] {
994            assert!(fd1.from_ascii_str(input1, true).is_ok());
995            assert!(fd2.from_ascii_str(input2, true).is_ok());
996            assert!(FixedDecimal::add_to(&fd1, &fd2, &mut fd3).is_ok());
997            let actual = fd3.to_string(-1);
998            println!("fd3={:?}", fd3);
999            println!(
1000                "{} + {} = {} , intg={}, frac={}",
1001                fd1.to_string(-1),
1002                fd2.to_string(-1),
1003                actual,
1004                fd3.intg(),
1005                fd3.frac()
1006            );
1007            assert_eq!(&actual[..], expected);
1008            let actual = (fd1.clone() + fd2.clone()).to_string(-1);
1009            assert_eq!(&actual[..], expected);
1010        }
1011    }
1012
1013    #[test]
1014    fn test_sub() {
1015        let mut fd1 = FixedDecimal::zero();
1016        let mut fd2 = FixedDecimal::zero();
1017        let mut fd3 = FixedDecimal::zero();
1018        for (input1, input2, expected) in vec![
1019            ("0", "0", "0"),
1020            ("0", "1", "-1"),
1021            ("0", "-1", "1"),
1022            ("-1", "0", "-1"),
1023            ("1", "0", "1"),
1024            ("1", "1", "0"),
1025            ("1", "2", "-1"),
1026            ("2", "1", "1"),
1027            ("1", "-1", "2"),
1028            ("-1", "1", "-2"),
1029            ("-1", "-100", "99"),
1030            ("1.0", "0", "1.0"),
1031            ("1.0", "0.0", "1.0"),
1032            ("-1.0", "0.01", "-1.01"),
1033            ("-0.3", "1.27", "-1.57"),
1034            ("-0.3", "-0.2", "-0.1"),
1035            ("-0.3", "0.2", "-0.5"),
1036            ("-0.01", "0.001", "-0.011"),
1037            ("-123", "0.1", "-123.1"),
1038            ("1", "-12.5", "13.5"),
1039            ("-5.0", "5.0", "-10.0"),
1040            ("1.0", "0.1", "0.9"),
1041            ("1.01", "0.1", "0.91"),
1042            ("1.00000000001", "1000.01", "-999.00999999999"),
1043            ("1.234567890", "0.0000000001", "1.2345678899"),
1044            ("-1.234567890", "0.0000000001", "-1.2345678901"),
1045            ("1000000000", "1", "999999999"),
1046            ("1", "1000000000", "-999999999"),
1047        ] {
1048            assert!(fd1.from_ascii_str(input1, true).is_ok());
1049            assert!(fd2.from_ascii_str(input2, true).is_ok());
1050            assert!(FixedDecimal::sub_to(&fd1, &fd2, &mut fd3).is_ok());
1051            let actual = fd3.to_string(-1);
1052            println!("fd3={:?}", fd3);
1053            println!(
1054                "{} - {} = {} , intg={}, frac={}",
1055                fd1.to_string(-1),
1056                fd2.to_string(-1),
1057                actual,
1058                fd3.intg(),
1059                fd3.frac()
1060            );
1061            assert_eq!(&actual[..], expected);
1062            let actual = (fd1.clone() - fd2.clone()).to_string(-1);
1063            assert_eq!(&actual[..], expected);
1064        }
1065    }
1066
1067    #[test]
1068    fn test_mul() {
1069        let mut fd1 = FixedDecimal::zero();
1070        let mut fd2 = FixedDecimal::zero();
1071        let mut fd3 = FixedDecimal::zero();
1072        for (input1, input2, expected) in vec![
1073            ("0", "0", "0"),
1074            ("0", "1", "0"),
1075            ("1", "0", "0"),
1076            ("1", "1", "1"),
1077            ("1", "2", "2"),
1078            ("2", "1", "2"),
1079            ("1", "-1", "-1"),
1080            ("-1", "1", "-1"),
1081            ("-1", "-100", "100"),
1082            ("1.0", "0", "0"),
1083            ("1.0", "0.0", "0"),
1084            ("-1.0", "0.01", "-0.010"),
1085            ("-0.3", "1.27", "-0.381"),
1086            ("-0.3", "-0.2", "0.06"),
1087            ("-0.3", "0.2", "-0.06"),
1088            ("-0.01", "0.001", "-0.00001"),
1089            ("-0.10", "0.001", "-0.00010"),
1090            ("-123", "0.1", "-12.3"),
1091            ("1", "-12.5", "-12.5"),
1092            ("-5.0", "5.0", "-25.00"),
1093            ("1.0", "0.1", "0.10"),
1094            ("1.01", "0.1", "0.101"),
1095            ("1.00000000001", "1000.01", "1000.0100000100001"),
1096            ("1.234567890", "0.0000000001", "0.0000000001234567890"),
1097            ("-1.234567890", "0.0000000001", "-0.0000000001234567890"),
1098        ] {
1099            assert!(fd1.from_ascii_str(input1, true).is_ok());
1100            assert!(fd2.from_ascii_str(input2, true).is_ok());
1101            assert!(FixedDecimal::mul_to(&fd1, &fd2, &mut fd3).is_ok());
1102            let actual = fd3.to_string(-1);
1103            println!("fd3={:?}", fd3);
1104            println!(
1105                "{} * {} = {} , intg={}, frac={}",
1106                fd1.to_string(-1),
1107                fd2.to_string(-1),
1108                actual,
1109                fd3.intg(),
1110                fd3.frac()
1111            );
1112            assert_eq!(&actual[..], expected);
1113            let actual = (fd1.clone() * fd2.clone()).to_string(-1);
1114            assert_eq!(&actual[..], expected);
1115        }
1116    }
1117
1118    #[test]
1119    fn test_div() {
1120        let mut fd1 = FixedDecimal::zero();
1121        let mut fd2 = FixedDecimal::zero();
1122        let mut fd3 = FixedDecimal::zero();
1123        for (input1, input2, expected) in vec![
1124            ("0", "1", "0"),
1125            ("1", "1", "1.000000000"), // incremental frac is already multiple of 9
1126            ("1", "1", "1.000000000"),
1127            ("1", "2", "0.500000000"),
1128            ("2", "1", "2.000000000"),
1129            ("1", "-1", "-1.000000000"),
1130            ("-1", "1", "-1.000000000"),
1131            ("-1", "-100", "0.010000000"),
1132            ("100", "1", "100.000000000"),
1133            ("100", "100", "1.000000000"),
1134            ("0.000000002", "1", "0.000000002000000000"),
1135            ("1.0", "2", "0.500000000"),
1136            ("1.0", "2.0", "0.500000000000000000"), // two fractional units
1137            ("-1", "0.01", "-100.000000000"),
1138            ("0.27", "0.3", "0.900000000000000000"),
1139            ("-0.3", "-0.2", "1.500000000000000000"),
1140            ("0.3", "0.7", "0.428571428571428571"),
1141            ("0.6", "0.9", "0.666666666666666666"),
1142            ("-0.3", "0.2", "-1.500000000000000000"),
1143            ("1000000000.1", "7", "142857142.871428571"),
1144            ("1000000000.1", "9", "111111111.122222222"),
1145            ("101000000000.1", "7", "14428571428.585714285"),
1146            ("101000000000.1", "7.1", "14225352112.690140845070422535"),
1147            ("101000000000.1", "5", "20200000000.020000000"),
1148            ("101000000000.1", "5.0", "20200000000.020000000000000000"),
1149            ("100.10000000001", "7", "14.300000000001428571"),
1150            ("100.10000000001", "7.0", "14.300000000001428571428571428"),
1151            ("100.1", "7.0000000001", "14.299999999795714285717204081"),
1152            ("205.6", "9.5000000001", "21.642105262930083102495472809"),
1153            (
1154                "2000000005.1",
1155                "7.5000000001",
1156                "266666667.343111111102091851851972108",
1157            ),
1158            ("1.2", "0.7", "1.714285714285714285"),
1159            ("1.22", "0.77", "1.584415584415584415"),
1160            ("1.222", "0.777", "1.572715572715572715"),
1161            ("1.2222", "0.7777", "1.571557155715571557"),
1162            ("1.22222", "0.77777", "1.571441428700001285"),
1163            ("1.222222", "0.777777", "1.571429857144142858"),
1164            ("1.2222222", "0.7777777", "1.571428700000012857"),
1165            ("1.22222222", "0.77777777", "1.571428584285714414285715571"),
1166            (
1167                "1.222222222",
1168                "0.777777777",
1169                "1.571428572714285715571428572",
1170            ),
1171            ("9.8", "1", "9.800000000"),
1172            ("98.7", "1.2", "82.250000000000000000"),
1173            ("987.6", "12.3", "80.292682926829268292"),
1174            ("9876.5", "123.4", "80.036466774716369529"),
1175            ("98765.4", "1234.5", "80.004374240583232077"),
1176            ("987654.3", "12345.6", "80.000510303265940902"),
1177            ("9876543.2", "123456.7", "80.000058320042573631"),
1178            ("98765432.1", "1234567.8", "80.000006561000538002"),
1179            ("987654321.1", "12345678.9", "80.000000737100006707"),
1180            ("987654321.12", "12345678.99", "80.000000155520000281"),
1181            ("987654321.123", "12345678.998", "80.000000103923000120"),
1182            ("987654321.1234", "12345678.9987", "80.000000099419400109"),
1183            ("987654321.12345", "12345678.99876", "80.000000099034650108"),
1184            (
1185                "987654321.123456",
1186                "12345678.998765",
1187                "80.000000099002736108",
1188            ),
1189            (
1190                "987654321.1234567",
1191                "12345678.9987654",
1192                "80.000000099000200808",
1193            ),
1194            (
1195                "987654321.12345678",
1196                "12345678.99876543",
1197                "80.000000099000012888900031007",
1198            ),
1199            (
1200                "987654321.123456789",
1201                "12345678.998765432",
1202                "80.000000099000000657900001515",
1203            ),
1204            ("-9.8", "1", "-9.800000000"),
1205            ("-98.7", "1.2", "-82.250000000000000000"),
1206            ("-987.6", "12.3", "-80.292682926829268292"),
1207            ("-9876.5", "123.4", "-80.036466774716369529"),
1208            ("-98765.4", "1234.5", "-80.004374240583232077"),
1209            ("-987654.3", "12345.6", "-80.000510303265940902"),
1210            ("-9876543.2", "123456.7", "-80.000058320042573631"),
1211            ("-98765432.1", "1234567.8", "-80.000006561000538002"),
1212            ("-987654321.1", "12345678.9", "-80.000000737100006707"),
1213            ("-987654321.12", "12345678.99", "-80.000000155520000281"),
1214            ("-987654321.123", "12345678.998", "-80.000000103923000120"),
1215            ("-987654321.1234", "12345678.9987", "-80.000000099419400109"),
1216            (
1217                "-987654321.12345",
1218                "12345678.99876",
1219                "-80.000000099034650108",
1220            ),
1221            (
1222                "-987654321.123456",
1223                "12345678.998765",
1224                "-80.000000099002736108",
1225            ),
1226            (
1227                "-987654321.1234567",
1228                "12345678.9987654",
1229                "-80.000000099000200808",
1230            ),
1231            (
1232                "-987654321.12345678",
1233                "12345678.99876543",
1234                "-80.000000099000012888900031007",
1235            ),
1236            (
1237                "-987654321.123456789",
1238                "12345678.998765432",
1239                "-80.000000099000000657900001515",
1240            ),
1241            ("0.170511", "-353390023.459963", "-0.000000000482500887"),
1242            ("0.170511", "-353390023", "-0.000000000482500888"),
1243            ("0.1", "300000000", "0.000000000"),
1244            ("0.1", "300000000.0", "0.000000000333333333"),
1245            ("0.1", "3000000000", "0.000000000"),
1246            ("0.1", "3000000000.0", "0.000000000033333333"),
1247            ("0.0000000001", "300000000", "0.000000000000000000"),
1248            (
1249                "0.0000000001",
1250                "300000000.0",
1251                "0.000000000000000000333333333",
1252            ),
1253            ("0.0000000001", "3000000000", "0.000000000000000000"),
1254            (
1255                "0.0000000001",
1256                "3000000000.0",
1257                "0.000000000000000000033333333",
1258            ),
1259            ("1", "300000000", "0.000000003"),
1260            ("1", "300000000.0", "0.000000003"),
1261            ("1", "3000000000", "0.000000000"),
1262            ("1", "3000000000.0", "0.000000000"),
1263            ("1.0", "300000000", "0.000000003"),
1264            ("1.0", "300000000.0", "0.000000003333333333"),
1265            ("1.0", "3000000000", "0.000000000"),
1266            ("1.0", "3000000000.0", "0.000000000333333333"),
1267            ("0.4", "0.000000003", "133333333.333333333333333333"),
1268            (
1269                "0.4",
1270                "0.0000000003",
1271                "1333333333.333333333333333333333333333",
1272            ),
1273            ("0.2", "0.000000003", "66666666.666666666666666666"),
1274            (
1275                "0.2",
1276                "0.0000000003",
1277                "666666666.666666666666666666666666666",
1278            ),
1279            ("400000000", "300000000", "1.333333333"),
1280            ("400000000.0", "300000000.0", "1.333333333333333333"),
1281            ("4000000000", "3000000000", "1.333333333"),
1282            ("4000000000.0", "3000000000.0", "1.333333333333333333"),
1283            ("200000000", "300000000", "0.666666666"),
1284            ("200000000.0", "300000000.0", "0.666666666666666666"),
1285            ("2000000000", "3000000000", "0.666666666"),
1286            ("2000000000.0", "3000000000.0", "0.666666666666666666"),
1287            (
1288                "400000000",
1289                "0.000000003",
1290                "133333333333333333.333333333333333333",
1291            ),
1292            (
1293                "4000000000",
1294                "0.000000003",
1295                "1333333333333333333.333333333333333333",
1296            ),
1297            ("1", "500000000.1", "0.000000001"),
1298        ] {
1299            assert!(fd1.from_ascii_str(input1, true).is_ok());
1300            assert!(fd2.from_ascii_str(input2, true).is_ok());
1301            assert!(FixedDecimal::div_to(&fd1, &fd2, &mut fd3, DIV_INCR_FRAC).is_ok());
1302            let actual = fd3.to_string(-1);
1303            println!("fd3={:?}", fd3);
1304            println!(
1305                "{} / {} = {} , intg={}, frac={}",
1306                fd1.to_string(-1),
1307                fd2.to_string(-1),
1308                actual,
1309                fd3.intg(),
1310                fd3.frac()
1311            );
1312            assert_eq!(&actual[..], expected);
1313            let actual = (fd1.clone() / fd2.clone()).to_string(-1);
1314            assert_eq!(&actual[..], expected);
1315        }
1316    }
1317
1318    #[test]
1319    fn test_rem() {
1320        let mut fd1 = FixedDecimal::zero();
1321        let mut fd2 = FixedDecimal::zero();
1322        let mut fd3 = FixedDecimal::zero();
1323        for (input1, input2, expected) in vec![
1324            ("0", "1", "0"),
1325            ("1", "1", "0"),
1326            ("1", "2", "1"),
1327            ("2", "1", "0"),
1328            ("1000000001", "2", "1"),
1329            ("-1000000001", "2", "-1"),
1330            ("-1", "2", "-1"),
1331            ("-1", "-2", "-1"),
1332            ("1", "-2", "1"),
1333            ("-1", "-100", "-1"),
1334            ("100", "3", "1"),
1335            ("100", "1001", "100"),
1336            ("0.2", "1", "0.2"),
1337            ("0.02", "1", "0.02"),
1338            ("0.002", "1", "0.002"),
1339            ("0.0002", "1", "0.0002"),
1340            ("0.00002", "1", "0.00002"),
1341            ("0.000002", "1", "0.000002"),
1342            ("0.0000002", "1", "0.0000002"),
1343            ("0.00000002", "1", "0.00000002"),
1344            ("0.000000002", "1", "0.000000002"),
1345            ("0.2", "1.0", "0.2"),
1346            ("0.2", "1.00", "0.20"),
1347            ("0.2", "1.000", "0.200"),
1348            ("0.2", "1.0000", "0.2000"),
1349            ("0.2", "1.00000", "0.20000"),
1350            ("0.2", "1.000000", "0.200000"),
1351            ("0.2", "1.0000000", "0.2000000"),
1352            ("0.2", "1.00000000", "0.20000000"),
1353            ("0.2", "1.000000000", "0.200000000"),
1354            ("-0.2", "1.0", "-0.2"),
1355            ("-0.2", "1.00", "-0.20"),
1356            ("-0.2", "1.000", "-0.200"),
1357            ("-0.2", "1.0000", "-0.2000"),
1358            ("-0.2", "1.00000", "-0.20000"),
1359            ("-0.2", "1.000000", "-0.200000"),
1360            ("-0.2", "1.0000000", "-0.2000000"),
1361            ("-0.2", "1.00000000", "-0.20000000"),
1362            ("-0.2", "1.000000000", "-0.200000000"),
1363            ("-0.3", "-0.2", "-0.1"),
1364            ("0.3", "0.2", "0.1"),
1365            ("0.3", "-0.2", "0.1"),
1366            ("-0.3", "0.2", "-0.1"),
1367            ("-0.3", "-0.7", "-0.3"),
1368            ("0.3", "-0.7", "0.3"),
1369            ("-0.3", "0.7", "-0.3"),
1370            ("0.3", "0.7", "0.3"),
1371            ("1000000000.1", "7", "6.1"),
1372            ("1000000000.1", "70", "20.1"),
1373            ("101000000000.1", "2000000000", "1000000000.1"),
1374            ("1000000000.1", "9", "1.1"),
1375            ("1000000000.1", "9.00", "1.10"),
1376            ("100.10000000001", "7", "2.10000000001"),
1377            ("101000000000.1", "7.1", "4.9"),
1378            ("101000000000.1", "5", "0.1"),
1379            ("101000000000.1", "5.291", "0.201"),
1380            ("100.1", "7.0000000001", "2.0999999986"),
1381            ("205.6", "9.5000000001", "6.0999999979"),
1382            ("2000000005.1", "7.5000000001", "2.5733333333"),
1383            ("1.2", "0.7", "0.5"),
1384            ("1.22", "0.77", "0.45"),
1385            ("1.222", "0.777", "0.445"),
1386            ("1.2222", "0.7777", "0.4445"),
1387            ("1.22222", "0.77777", "0.44445"),
1388            ("1.222222", "0.777777", "0.444445"),
1389            ("1.2222222", "0.7777777", "0.4444445"),
1390            ("1.22222222", "0.77777777", "0.44444445"),
1391            ("1.222222222", "0.777777777", "0.444444445"),
1392            ("9.8", "1", "0.8"),
1393            ("98.7", "1.2", "0.3"),
1394            ("987.6", "1.23", "1.14"),
1395            ("9876.5", "1.234", "0.798"),
1396            ("98765.4", "1.2345", "0.4620"),
1397            ("987654.3", "1.23456", "0.12720"),
1398            ("9876543.2", "1.234567", "1.027165"),
1399            ("98765432.1", "1.2345678", "0.6925932"),
1400            ("987654321.1", "1.23456789", "0.45802477"),
1401            ("987654321.12", "1.234567899", "0.685432101"),
1402            ("987654321.123", "1.2345678998", "0.0484321002"),
1403            ("987654321.1234", "1.23456789987", "1.22740000000"),
1404            ("987654321.12345", "1.234567899876", "1.222650000000"),
1405            ("987654321.123456", "1.2345678998765", "1.2222560000000"),
1406            ("987654321.1234567", "1.23456789987654", "1.22222470000000"),
1407            (
1408                "987654321.12345678",
1409                "1.234567899876543",
1410                "1.222222380000000",
1411            ),
1412            (
1413                "987654321.123456789",
1414                "1.2345678998765432",
1415                "1.2222222290000000",
1416            ),
1417            ("-9.8", "1", "-0.8"),
1418            ("-98.7", "1.2", "-0.3"),
1419            ("-987.6", "1.23", "-1.14"),
1420            ("-9876.5", "1.234", "-0.798"),
1421            ("-98765.4", "1.2345", "-0.4620"),
1422            ("-987654.3", "1.23456", "-0.12720"),
1423            ("-9876543.2", "1.234567", "-1.027165"),
1424            ("-98765432.1", "1.2345678", "-0.6925932"),
1425            ("-987654321.1", "1.23456789", "-0.45802477"),
1426            ("-987654321.12", "1.234567899", "-0.685432101"),
1427            ("-987654321.123", "1.2345678998", "-0.0484321002"),
1428            ("-987654321.1234", "1.23456789987", "-1.22740000000"),
1429            ("-987654321.12345", "1.234567899876", "-1.222650000000"),
1430            ("-987654321.123456", "1.2345678998765", "-1.2222560000000"),
1431            (
1432                "-987654321.1234567",
1433                "1.23456789987654",
1434                "-1.22222470000000",
1435            ),
1436            (
1437                "-987654321.12345678",
1438                "1.234567899876543",
1439                "-1.222222380000000",
1440            ),
1441            (
1442                "-987654321.123456789",
1443                "1.2345678998765432",
1444                "-1.2222222290000000",
1445            ),
1446            ("0.170511", "-353390023.459963", "0.170511"),
1447            ("-353390023.459963", "0.170511", "-0.060946"),
1448            ("0.170511", "-353390023", "0.170511"),
1449            ("-353390023", "0.170511", "-0.112516"),
1450            ("0.4", "0.000000003", "0.000000001"),
1451            ("0.4", "0.0000000003", "0.0000000001"),
1452            ("0.2", "0.000000003", "0.000000002"),
1453            ("0.2", "0.0000000003", "0.0000000002"),
1454            ("1000000000000000001", "70298007", "68215565"),
1455            ("1000000000000000001", "0.70298007", "0.07924142"),
1456            ("1000000000000000001", "500000000.1", "300000001.1"),
1457            ("0.1", "0.20000000001", "0.10000000000"),
1458        ] {
1459            assert!(fd1.from_ascii_str(input1, true).is_ok());
1460            assert!(fd2.from_ascii_str(input2, true).is_ok());
1461            assert!(FixedDecimal::rem_to(&fd1, &fd2, &mut fd3).is_ok());
1462            let actual = fd3.to_string(-1);
1463            println!("fd3={:?}", fd3);
1464            println!(
1465                "{} % {} = {} , intg={}, frac={}",
1466                fd1.to_string(-1),
1467                fd2.to_string(-1),
1468                actual,
1469                fd3.intg(),
1470                fd3.frac()
1471            );
1472            assert_eq!(&actual[..], expected);
1473            let actual = (fd1.clone() % fd2.clone()).to_string(-1);
1474            assert_eq!(&actual[..], expected);
1475        }
1476    }
1477}