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
189fn add_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
200 res.set_zero(); 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 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 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 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
282fn sub_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<bool> {
293 res.set_zero(); 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 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
387fn mul_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
391 res.set_zero(); 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 return Err(Error::Overflow);
399 }
400 if res_intg_units + res_frac_units > MAX_UNITS {
401 res_frac_units = MAX_UNITS - res_intg_units; }
404 if res_frac_units > MAX_FRAC_UNITS {
405 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 let shift_units = (lfu + rfu - res_frac_units) as isize;
420 let mut carry: i64 = 0;
421 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; continue;
436 }
437 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#[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(); 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; 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; 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 return Err(Error::DivisionByZero);
486 }
487
488 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 return Ok(());
499 }
500 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 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 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 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 res_frac_units = MAX_FRAC_UNITS;
518 }
519 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 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 if rhs_non_zero == 0 {
554 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; let mut j = res_start_idx; 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; rem = u - q * d; res.lsu[j as usize] = q as i32; 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 let norm_factor = UNIT as i64 / (rhs.lsu[rhs_non_zero as usize] as i64 + 1);
582 let mut buf1 = [0i32; MAX_UNITS * 2]; let mut buf2 = [0i32; MAX_UNITS]; 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 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 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; let d1 = buf2[rhs_non_zero as usize - 1] as i64; let mut i = res_units as isize + lhs_non_zero + dividend_shift; let mut j = res_start_idx; while j >= 0 {
622 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 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 qhat -= 1; rhat += d0; }
642 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; carry = mul_v / UNIT as i64; let mul_v0 = mul_v - carry * UNIT as i64; 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 -= 1; borrow = 0;
668 for i in 0..rhs_non_zero {
669 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; }
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
686fn rem_abs(lhs: &FixedDecimal, rhs: &FixedDecimal, res: &mut FixedDecimal) -> Result<()> {
688 res.set_zero(); 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 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 return Err(Error::DivisionByZero);
708 }
709 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 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 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 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(()), Ordering::Greater => (),
746 }
747 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 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 let d = rhs.lsu[0] as i64; 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; while i >= stop {
780 let u = rem * UNIT as i64 + buf[i as usize] as i64;
781 let q = u / d; rem = u - q * d; 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 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 let norm_factor = UNIT as i64 / (rhs.lsu[rhs_non_zero as usize] as i64 + 1);
814 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; 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 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; let d0 = buf2[(rhs_non_zero + rhs_shift_units) as usize] as i64; let d1 = buf2[(rhs_non_zero + rhs_shift_units - 1) as usize] as i64; let mut i = buf1_len + dividend_shift - 1;
849 while i >= stop {
850 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 qhat -= 1;
867 rhat += d0;
868 }
869 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; carry = mul_v / UNIT as i64; let mul_v0 = mul_v - carry * UNIT as i64; let (sub_v, b0) = sub_with_borrow(*b1, mul_v0 as i32, borrow);
880 borrow = b0; *b1 = sub_v; }
883
884 borrow += buf1[(i + 1) as usize] - carry as i32;
885 if borrow == -1 {
886 borrow = 0; 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 debug_assert_eq!(buf1[buf1_len as usize], 0, "value must be zero");
901
902 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; if q > 0 {
915 res.lsu[i as usize] = q as i32; if res_non_zero < 0 {
917 res_non_zero = i;
918 }
919 }
920 }
921 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; Ok(())
934}
935
936#[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#[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"), ("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"), ("-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}