1use decimal::d128;
2use std::str::FromStr;
3use std::fmt;
4use std::hash::{Hash, Hasher};
5use std::default::Default;
6use std::ops::{Add, Div, Mul, Neg, Rem, Sub, AddAssign, SubAssign, MulAssign};
7use std::borrow::Borrow;
8use std::iter::Sum;
9
10use super::error::Error;
11
12
13#[derive(Clone, Copy)]
35pub struct Decimal(pub(crate) d128);
36
37impl Decimal {
38 pub fn zero() -> Self {
40 Decimal(d128::zero())
41 }
42
43 pub fn max<O: AsRef<Decimal>>(self, other: O) -> Decimal {
45 Decimal(self.0.max(other.as_ref().0))
46 }
47
48 pub fn min<O: AsRef<Decimal>>(self, other: O) -> Decimal {
50 Decimal(self.0.min(other.as_ref().0))
51 }
52
53 pub fn abs(&self) -> Decimal {
55 Decimal(self.0.abs())
56 }
57
58 pub fn mul_add<O: AsRef<Decimal>>(self, a: O, b: O) -> Decimal {
61 Decimal(self.0.mul_add(a.as_ref().0, b.as_ref().0))
62 }
63
64 pub fn is_negative(&self) -> bool {
66 self.0.is_negative()
67 }
68
69 pub fn is_positive(&self) -> bool {
70 self.0.is_positive()
71 }
72
73 pub fn is_zero(&self) -> bool {
75 self.0.is_zero()
76 }
77
78 pub fn pow<O: AsRef<Decimal>>(self, exp: O) -> Decimal {
80 Decimal(self.as_ref().0.pow(exp.as_ref().0))
81 }
82}
83
84impl Default for Decimal {
85 fn default() -> Self {
86 Self::zero()
87 }
88}
89
90impl Hash for Decimal {
91 fn hash<H: Hasher>(&self, state: &mut H) {
92 self.0.hash(state);
93 }
94}
95
96impl FromStr for Decimal {
97 type Err = Error;
98
99 fn from_str(s: &str) -> Result<Self, Error> {
100 let val = d128::from_str(s);
101 if val.is_ok() {
102 let dec = val.unwrap();
103 if dec.is_nan() {
104 Err(Error::new("NaN is not supported"))
105 } else if dec.is_infinite() {
106 Err(Error::new("Infinity is not supported"))
107 } else {
108 Ok(Decimal(dec))
109 }
110 } else {
111 Err(Error::new("Failed to parse"))
112 }
113 }
114}
115
116impl fmt::Display for Decimal {
118 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
119 self.0.fmt(fmt)
120 }
121}
122
123impl fmt::Debug for Decimal {
125 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
126 self.0.fmt(fmt)
127 }
128}
129
130impl fmt::LowerExp for Decimal {
132 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
133 self.0.fmt(fmt)
134 }
135}
136
137impl fmt::LowerHex for Decimal {
139 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
140 self.0.fmt(fmt)
141 }
142}
143
144
145impl PartialEq<Decimal> for Decimal {
146 fn eq(&self, other: &Decimal) -> bool {
147 self.0.eq(&other.0)
148 }
149}
150
151impl Eq for Decimal {}
152
153impl PartialOrd<Decimal> for Decimal {
154 fn partial_cmp(&self, other: &Decimal) -> Option<::std::cmp::Ordering> {
155 self.0.partial_cmp(&other.0)
156 }
157}
158
159impl Ord for Decimal {
160 fn cmp(&self, other: &Decimal) -> ::std::cmp::Ordering {
161 let res = self.0.partial_cmp(&other.0);
162 match res {
163 None => panic!("Ordering not possible. Possible bug"),
164 Some(ord) => ord,
165 }
166 }
167}
168
169impl From<i32> for Decimal {
170 fn from(val: i32) -> Decimal {
171 Decimal(d128::from(val))
172 }
173}
174
175impl From<u32> for Decimal {
177 fn from(val: u32) -> Decimal {
178 Decimal(d128::from(val))
179 }
180}
181
182impl From<u64> for Decimal {
184 fn from(val: u64) -> Decimal {
185 Decimal(d128::from(val))
186 }
187}
188
189impl From<i64> for Decimal {
191 fn from(val: i64) -> Decimal {
192 Decimal(d128::from(val))
193 }
194}
195
196impl AsRef<Decimal> for Decimal {
197 fn as_ref(&self) -> &Decimal {
198 self
199 }
200}
201
202macro_rules! unary_op {
203 ($(#[$attr:meta])* impl $op:ident, $method:ident) => {
204 $(#[$attr])*
205 impl $op for Decimal {
206 type Output = Decimal;
207
208 fn $method(self) -> Decimal {
209 Decimal((self.0).$method())
210 }
211 }
212
213 impl<'a> $op for &'a Decimal {
214 type Output = Decimal;
215
216 fn $method(self) -> Decimal {
217 Decimal((self.0).$method())
218 }
219 }
220 }
221}
222
223unary_op!(impl Neg, neg);
224
225macro_rules! binary_op {
226 ($(#[$attr:meta])* impl $op:ident, $method:ident, $t:ident) => {
227 $(#[$attr])*
228 impl $op<$t> for $t {
229 type Output = $t;
230
231 fn $method(self, other: $t) -> $t {
232 Decimal((self.0).$method(other.0))
233 }
234 }
235
236 impl<'a> $op<$t> for &'a $t {
237 type Output = $t;
238
239 fn $method(self, other: $t) -> $t {
240 Decimal((self.0).$method(other.0))
241 }
242 }
243
244 impl<'a> $op<&'a$t> for $t {
245 type Output = $t;
246
247 fn $method(self, other: &'a $t) -> $t {
248 Decimal((self.0).$method(other.0))
249 }
250 }
251
252 impl<'a, 'b> $op<&'a $t> for &'b $t {
253 type Output = $t;
254
255 fn $method(self, other: &'a $t) -> $t {
256 Decimal((self.0).$method(other.0))
257 }
258 }
259 }
260}
261
262binary_op!(impl Add, add, Decimal);
263binary_op!(impl Sub, sub, Decimal);
264binary_op!(impl Mul, mul, Decimal);
265
266macro_rules! guarded_binary_op {
267 ($(#[$attr:meta])* impl $op:ident, $method:ident, $t:ident) => {
268
269
270 $(#[$attr])*
271 impl $op<$t> for $t {
272 type Output = ::std::result::Result<$t, Error>;
273
274 fn $method(self, other: $t) -> ::std::result::Result<$t, Error> {
276 let val = (self.0).$method(other.0);
277 if val.is_finite() {
278 Ok(Decimal(val))
279 }else{
280 Err(Error::new("Only finite value are supported"))
281 }
282 }
283 }
284
285 impl<'a> $op<$t> for &'a $t {
286 type Output = ::std::result::Result<$t, Error>;
287
288 fn $method(self, other: $t) -> ::std::result::Result<$t, Error> {
290 let val = (self.0).$method(other.0);
291 if val.is_finite() {
292 Ok(Decimal(val))
293 }else{
294 Err(Error::new("Only finite value are supported"))
295 }
296 }
297 }
298
299 impl<'a> $op<&'a$t> for $t {
300 type Output = ::std::result::Result<$t, Error>;
301
302 fn $method(self, other: &'a $t) -> ::std::result::Result<$t, Error> {
304 let val = (self.0).$method(other.0);
305 if val.is_finite() {
306 Ok(Decimal(val))
307 }else{
308 Err(Error::new("Only finite value are supported"))
309 }
310 }
311 }
312
313 impl<'a, 'b> $op<&'a $t> for &'b $t {
314 type Output = ::std::result::Result<$t, Error>;
315
316 fn $method(self, other: &'a $t) -> ::std::result::Result<$t, Error> {
318 let val = (self.0).$method(other.0);
319 if val.is_finite() {
320 Ok(Decimal(val))
321 }else{
322 Err(Error::new("Only finite value are supported"))
323 }
324 }
325 }
326 }
327}
328
329guarded_binary_op!(impl Div, div, Decimal);
330guarded_binary_op!(impl Rem, rem, Decimal);
331
332
333macro_rules! unary_assign_op {
334 ($(#[$attr:meta])* impl $op:ident, $method:ident, $t:ident) => {
335 $(#[$attr])*
336 impl $op<$t> for $t {
337 fn $method(&mut self, other: $t) {
338 (self.0).$method(other.0);
339 }
340 }
341 }
342}
343
344unary_assign_op!(impl AddAssign, add_assign, Decimal);
345unary_assign_op!(impl SubAssign, sub_assign, Decimal);
346unary_assign_op!(impl MulAssign, mul_assign, Decimal);
347
348
349impl<T> Sum<T> for Decimal where T: Borrow<Decimal> {
350 fn sum<I: IntoIterator<Item=T>>(iter: I) -> Decimal {
351 iter.into_iter()
352 .fold(Decimal::zero(), |acc, val| acc + val.borrow())
353 }
354}
355
356
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361
362 #[test]
363 fn default() {
364 use std::str::FromStr;
365
366 assert_eq!(Decimal::zero(), Decimal::default());
367 assert_eq!(Decimal::zero(), Default::default());
368 assert_eq!(Decimal::zero(), Decimal::from_str("0").unwrap());
369 assert_eq!(Decimal::zero(), Decimal::from_str("0.0").unwrap());
370 }
371
372 #[test]
373 fn unary_op() {
374 assert_eq!(dec!(-1.1), -dec!(1.1));
375 assert_eq!(dec!(-1.1), -&dec!(1.1));
376 }
377
378 #[test]
379 fn utility_functions() {
380 assert!(dec!(0.0).is_zero());
381 assert_ne!(true,dec!(0.0).is_negative());
382 assert_ne!(true,dec!(0.0).is_positive());
383
384 assert_ne!(true,dec!(0.1).is_zero());
385 assert_ne!(true,dec!(0.1).is_negative());
386 assert!(dec!(0.1).is_positive());
387
388 assert_ne!(true,dec!(-0.1).is_zero());
389 assert!(dec!(-0.1).is_negative());
390 assert_ne!(true,dec!(-0.1).is_positive());
391
392 }
393
394 #[test]
395 fn binary_op() {
396 assert_eq!(dec!(3.33), dec!(1.11) + dec!(2.22));
397 assert_eq!(dec!(3.33), &dec!(1.11) + dec!(2.22));
398 assert_eq!(dec!(3.33), dec!(1.11) + &dec!(2.22));
399 assert_eq!(dec!(3.33), &dec!(1.11) + &dec!(2.22));
400 }
403
404 #[test]
405 fn as_ref_operand() {
406 assert_eq!(dec!(1.1), dec!(1.1).min(dec!(2.2)));
407 assert_eq!(dec!(1.1), dec!(1.1).min(&dec!(2.2)));
408 }
409
410
411 #[test]
412 fn assign_op() {
413 let mut x = dec!(1);
414 x += dec!(2);
415 assert_eq!(x, dec!(3));
416 x *= dec!(3);
417 assert_eq!(x, dec!(9));
418 x -= dec!(1);
419 assert_eq!(x, dec!(8));
420 }
421
422 #[test]
423 fn test_sum() {
424 let decimals = vec![dec!(1), dec!(2), dec!(3), dec!(4)];
425 assert_eq!(dec!(10), decimals.iter().sum());
426 assert_eq!(dec!(10), decimals.into_iter().sum());
427 }
428}