Skip to content

Commit 3616b24

Browse files
committed
Merge BigDecimalRef impl into trunk
2 parents 9520e96 + de40b5a commit 3616b24

File tree

4 files changed

+245
-77
lines changed

4 files changed

+245
-77
lines changed

build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ fn main() {
77
let ac = autocfg::new();
88
ac.emit_rustc_version(1, 70);
99

10+
// Option::zip
11+
ac.emit_rustc_version(1, 46);
12+
1013
let outdir: PathBuf = std::env::var_os("OUT_DIR").unwrap().into();
1114
write_default_precision_file(&outdir);
1215
}

src/impl_cmp.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! Implementation of comparsion operations
2+
//!
3+
//! Comparisons between decimals and decimal refs
4+
//! are not directly supported as we lose some type
5+
//! inference features at the savings of a single
6+
//! '&' character.
7+
//!
8+
//! &BigDecimal and BigDecimalRef are comparible.
9+
//!
10+
11+
use crate::{
12+
BigDecimal,
13+
BigDecimalRef,
14+
Sign,
15+
};
16+
17+
use stdlib::cmp::Ordering;
18+
use stdlib::iter;
19+
20+
impl PartialEq for BigDecimal
21+
{
22+
fn eq(&self, rhs: &BigDecimal) -> bool {
23+
self.to_ref() == rhs.to_ref()
24+
}
25+
}
26+
27+
impl<'rhs, T> PartialEq<T> for BigDecimalRef<'_>
28+
where
29+
T: Into<BigDecimalRef<'rhs>> + Copy
30+
{
31+
fn eq(&self, rhs: &T) -> bool {
32+
let rhs: BigDecimalRef<'rhs> = (*rhs).into();
33+
34+
match (self.sign(), rhs.sign()) {
35+
// both zero
36+
(Sign::NoSign, Sign::NoSign) => return true,
37+
// signs are different
38+
(a, b) if a != b => return false,
39+
// signs are same, do nothing
40+
_ => {}
41+
}
42+
43+
let unscaled_int;
44+
let scaled_int;
45+
let trailing_zero_count;
46+
match self.scale.cmp(&rhs.scale) {
47+
Ordering::Greater => {
48+
unscaled_int = self.digits;
49+
scaled_int = rhs.digits;
50+
trailing_zero_count = (self.scale - rhs.scale) as usize;
51+
}
52+
Ordering::Less => {
53+
unscaled_int = rhs.digits;
54+
scaled_int = self.digits;
55+
trailing_zero_count = (rhs.scale - self.scale) as usize;
56+
}
57+
Ordering::Equal => return self.digits == rhs.digits,
58+
}
59+
60+
if trailing_zero_count < 20 {
61+
let scaled_int = scaled_int * crate::ten_to_the(trailing_zero_count as u64).magnitude();
62+
return &scaled_int == unscaled_int;
63+
}
64+
65+
let unscaled_digits = unscaled_int.to_radix_le(10);
66+
let scaled_digits = scaled_int.to_radix_le(10);
67+
68+
// different lengths with trailing zeros
69+
if unscaled_digits.len() != scaled_digits.len() + trailing_zero_count {
70+
return false;
71+
}
72+
73+
// add leading zero digits to digits that need scaled
74+
let scaled = iter::repeat(&0u8).take(trailing_zero_count).chain(scaled_digits.iter());
75+
76+
// return true if all digits are the same
77+
unscaled_digits.iter().zip(scaled).all(|(digit_a, digit_b)| { digit_a == digit_b })
78+
}
79+
}
80+
81+
82+
#[cfg(test)]
83+
mod test_bigintref {
84+
use super::*;
85+
use stdlib::ops::Neg;
86+
87+
#[test]
88+
fn test_borrow_neg_cmp() {
89+
let x: BigDecimal = "1514932018891593.916341142773".parse().unwrap();
90+
let y: BigDecimal = "1514932018891593916341142773e-12".parse().unwrap();
91+
92+
assert_eq!(x, y);
93+
94+
let x_ref = x.to_ref();
95+
assert_eq!(x_ref, &y);
96+
assert_ne!(x_ref.neg(), x_ref);
97+
assert_eq!(x_ref.neg().neg(), x_ref);
98+
}
99+
}

src/impl_ops.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//! Implement math operations: Add,Sub, etc
22
3-
use crate::BigDecimal;
3+
use crate::{
4+
BigDecimal,
5+
BigDecimalRef,
6+
};
47
use crate::stdlib::ops::{
58
Add, AddAssign,
69
Sub, SubAssign,
@@ -439,3 +442,35 @@ impl_div_for_primitive!(i128);
439442

440443
impl_div_for_primitive!(f32);
441444
impl_div_for_primitive!(f64);
445+
446+
447+
impl Neg for BigDecimal {
448+
type Output = BigDecimal;
449+
450+
#[inline]
451+
fn neg(mut self) -> BigDecimal {
452+
self.int_val = -self.int_val;
453+
self
454+
}
455+
}
456+
457+
impl<'a> Neg for &'a BigDecimal {
458+
type Output = BigDecimal;
459+
460+
#[inline]
461+
fn neg(self) -> BigDecimal {
462+
-self.clone()
463+
}
464+
}
465+
466+
impl Neg for BigDecimalRef<'_> {
467+
type Output = Self;
468+
469+
fn neg(self) -> Self::Output {
470+
Self {
471+
sign: self.sign.neg(),
472+
digits: self.digits,
473+
scale: self.scale,
474+
}
475+
}
476+
}

0 commit comments

Comments
 (0)