add div and checked_div to Fixed64 (#4136)

* add div and checked_div to Fixed64

* add more tests

* div by zero is div by zero
This commit is contained in:
Xiliang Chen
2019-11-20 10:33:29 +13:00
committed by Kian Paimani
parent 4e8b68dd14
commit 3d4bee6cd6
@@ -22,7 +22,7 @@ use codec::{Encode, Decode};
use crate::{
Perbill,
traits::{
SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating
SaturatedConversion, CheckedSub, CheckedAdd, CheckedDiv, Bounded, UniqueSaturatedInto, Saturating
}
};
@@ -138,6 +138,25 @@ impl ops::Sub for Fixed64 {
}
}
/// Note that this is a standard, _potentially-panicking_, implementation. Use `CheckedDiv` trait
/// for safe division.
impl ops::Div for Fixed64 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
if rhs.0 == 0 {
let zero = 0;
return Fixed64::from_parts( self.0 / zero);
}
let (n, d) = if rhs.0 < 0 {
(-self.0, rhs.0.abs() as u64)
} else {
(self.0, rhs.0 as u64)
};
Fixed64::from_rational(n, d)
}
}
impl CheckedSub for Fixed64 {
fn checked_sub(&self, rhs: &Self) -> Option<Self> {
self.0.checked_sub(rhs.0).map(Self)
@@ -150,6 +169,16 @@ impl CheckedAdd for Fixed64 {
}
}
impl CheckedDiv for Fixed64 {
fn checked_div(&self, rhs: &Self) -> Option<Self> {
if rhs.0 == 0 {
None
} else {
Some(*self / *rhs)
}
}
}
impl rstd::fmt::Debug for Fixed64 {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result {
@@ -241,4 +270,57 @@ mod tests {
saturating_mul_acc_test!(u64);
saturating_mul_acc_test!(u128);
}
#[test]
fn div_works() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 100));
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a / b, Fixed64::from_rational(120, 1));
let a = Fixed64::from_rational(12, 100);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 1000));
let a = Fixed64::from_rational(12, 100);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a / b, Fixed64::from_rational(12, 1));
let a = Fixed64::from_rational(-12, 10);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(-12, 100));
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(-10, 1);
assert_eq!(a / b, Fixed64::from_rational(-12, 100));
let a = Fixed64::from_rational(-12, 10);
let b = Fixed64::from_rational(-10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 100));
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn div_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_natural(0);
let _ = a / b;
}
#[test]
fn checked_div_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_natural(0);
assert_eq!(a.checked_div(&b), None);
}
#[test]
fn checked_div_non_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1)));
}
}