Skip to content

Commit

Permalink
Decimal / explicit operator implementations, supporting primitive cast
Browse files Browse the repository at this point in the history
  • Loading branch information
dnsl48 committed Oct 18, 2023
1 parent 2b1b0bd commit c26456a
Show file tree
Hide file tree
Showing 18 changed files with 1,724 additions and 123 deletions.
119 changes: 7 additions & 112 deletions src/decimal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ use error;

use num::integer::Integer;
use num::traits::{
Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Signed,
ToPrimitive, Zero,
Bounded, CheckedAdd, CheckedMul, CheckedSub, FromPrimitive, Num, One, Signed, ToPrimitive, Zero,
};

use std::cmp::{self, Eq, Ordering, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::{Product, Sum};
use std::num::FpCategory;
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
use std::ops::{Add, DivAssign, Mul, MulAssign, Neg, SubAssign};
use std::str::FromStr;

use super::{GenericFraction, Sign};
Expand All @@ -34,6 +31,8 @@ mod juniper_support;
#[cfg(feature = "with-approx")]
mod approx;

mod ops;

/// Decimal type implementation
///
/// T is the type for data
Expand Down Expand Up @@ -171,58 +170,6 @@ where
}

macro_rules! dec_impl {
(impl_trait_math; $trait:ident, $fn:ident) => {
impl<T, P> $trait for GenericDecimal<T, P>
where
T: Clone + GenericInteger + $trait,
P: Copy + GenericInteger + Into<usize>
{
type Output = Self;

fn $fn(self, other: Self) -> Self::Output {
match self {
GenericDecimal(sf, sp) => match other {
GenericDecimal(of, op) => GenericDecimal($trait::$fn(sf, of), cmp::max(sp, op))
}
}
}
}


impl<'a, T, P> $trait for &'a GenericDecimal<T, P>
where
T: Clone + GenericInteger + $trait,
P: Copy + GenericInteger + Into<usize>,
&'a T: $trait<Output=T>
{
type Output = GenericDecimal<T, P>;

fn $fn(self, other: Self) -> Self::Output {
match self {
GenericDecimal(sf, sp) => match other {
GenericDecimal(of, op) => GenericDecimal($trait::$fn(sf, of), cmp::max(*sp, *op))
}
}
}
}
};

(impl_trait_math_checked; $trait:ident, $fn:ident) => {
impl<T, P> $trait for GenericDecimal<T, P>
where
T: Clone + GenericInteger + CheckedAdd + CheckedDiv + CheckedMul + CheckedSub + $trait,
P: Copy + GenericInteger + Into<usize>
{
fn $fn(&self, other: &Self) -> Option<Self> {
match *self {
GenericDecimal(ref sf, sp) => match *other {
GenericDecimal(ref of, op) => $trait::$fn(sf, of).map(|val| GenericDecimal(val, cmp::max(sp, op)))
}
}
}
}
};

(impl_trait_math_unary; $trait:ident, $fn:ident) => {
impl<T, P> $trait for GenericDecimal<T, P>
where
Expand Down Expand Up @@ -255,43 +202,6 @@ macro_rules! dec_impl {
}
};


(impl_trait_math_assign; $trait:ident, $fn:ident) => {
impl<T, P> $trait for GenericDecimal<T, P>
where
T: Clone + GenericInteger + DivAssign + SubAssign + MulAssign + $trait,
P: Copy + GenericInteger + Into<usize>
{
fn $fn(&mut self, other: Self) {
match *self {
GenericDecimal(ref mut sf, ref mut sp) => match other {
GenericDecimal(of, op) => {
$trait::$fn(sf, of);
*sp = cmp::max(*sp, op);
}
}
};
}
}

impl<'a, T, P> $trait<&'a Self> for GenericDecimal<T, P>
where
T: Clone + Integer + $trait + $trait<&'a T>,
P: Copy + Integer + Into<usize>
{
fn $fn(&mut self, other: &'a Self) {
match *self {
GenericDecimal(ref mut sf, ref mut sp) => match other {
GenericDecimal(of, op) => {
$trait::$fn(sf, of);
*sp = cmp::max(*sp, *op);
}
}
};
}
}
};

(impl_trait_cmp; $trait:ident; $fn:ident; $return:ty) => {
impl<T, P> $trait for GenericDecimal<T, P>
where
Expand Down Expand Up @@ -373,23 +283,6 @@ where
#[cfg(feature = "with-bigint")]
dec_impl!(impl_trait_from_int; BigUint, BigInt);

dec_impl!(impl_trait_math; Add, add);
dec_impl!(impl_trait_math; Div, div);
dec_impl!(impl_trait_math; Mul, mul);
dec_impl!(impl_trait_math; Sub, sub);
dec_impl!(impl_trait_math; Rem, rem);

dec_impl!(impl_trait_math_assign; AddAssign, add_assign);
dec_impl!(impl_trait_math_assign; DivAssign, div_assign);
dec_impl!(impl_trait_math_assign; MulAssign, mul_assign);
dec_impl!(impl_trait_math_assign; SubAssign, sub_assign);
dec_impl!(impl_trait_math_assign; RemAssign, rem_assign);

dec_impl!(impl_trait_math_checked; CheckedAdd, checked_add);
dec_impl!(impl_trait_math_checked; CheckedDiv, checked_div);
dec_impl!(impl_trait_math_checked; CheckedMul, checked_mul);
dec_impl!(impl_trait_math_checked; CheckedSub, checked_sub);

dec_impl!(impl_trait_math_unary; Neg, neg);

dec_impl!(impl_trait_proxy;
Expand Down Expand Up @@ -1132,7 +1025,9 @@ where

#[cfg(test)]
mod tests {
use super::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, GenericDecimal, One};
use {CheckedAdd, CheckedDiv, CheckedMul, CheckedSub};

use super::{GenericDecimal, One};
use fraction::GenericFraction;
use prelude::Decimal;
use std::hash::{Hash, Hasher};
Expand Down
83 changes: 83 additions & 0 deletions src/decimal/ops/add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::generic::GenericInteger;
use crate::GenericDecimal;
use std::cmp;
use std::ops::Add;

impl<O, T, P> Add<O> for GenericDecimal<T, P>
where
T: Clone + GenericInteger,
P: Copy + GenericInteger + Into<usize>,
O: Into<GenericDecimal<T, P>>,
{
type Output = Self;

fn add(self, other: O) -> Self::Output {
let other: GenericDecimal<T, P> = other.into();

match self {
GenericDecimal(sf, sp) => match other {
GenericDecimal(of, op) => GenericDecimal(Add::add(sf, of), cmp::max(sp, op)),
},
}
}
}

impl<'a, T, P> Add for &'a GenericDecimal<T, P>
where
T: Clone + GenericInteger,
P: Copy + GenericInteger + Into<usize>,
&'a T: Add<Output = T>,
{
type Output = GenericDecimal<T, P>;

fn add(self, other: Self) -> Self::Output {
match self {
GenericDecimal(sf, sp) => match other {
GenericDecimal(of, op) => GenericDecimal(Add::add(sf, of), cmp::max(*sp, *op)),
},
}
}
}

impl<'a, O, T, P> Add<O> for &'a GenericDecimal<T, P>
where
T: Clone + GenericInteger,
P: Copy + GenericInteger + Into<usize>,
&'a T: Add<Output = T>,
O: Into<GenericDecimal<T, P>>,
{
type Output = GenericDecimal<T, P>;

fn add(self, other: O) -> Self::Output {
let other: GenericDecimal<T, P> = other.into();

match self {
GenericDecimal(sf, sp) => match other {
GenericDecimal(of, op) => GenericDecimal(Add::add(sf, of), cmp::max(*sp, op)),
},
}
}
}

#[cfg(test)]
mod tests {
use super::GenericDecimal;
use crate::Zero;

type F = GenericDecimal<u8, u8>;

#[test]
fn add_scalar() {
assert_eq!(F::zero() + 1, F::from(1));
assert_eq!(F::zero() + 1.5, F::from(1.5));

assert_eq!(&F::zero() + 1, F::from(1));
assert_eq!(&F::zero() + 1.5, F::from(1.5));

assert_eq!(F::zero() + F::from(1), F::from(1));
assert_eq!(F::zero() + F::from(1.5), F::from(1.5));

assert_eq!(&F::zero() + F::from(1), F::from(1));
assert_eq!(&F::zero() + F::from(1.5), F::from(1.5));
}
}

0 comments on commit c26456a

Please sign in to comment.