diff --git a/src/lib.rs b/src/lib.rs index 661b67b..07b5b0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,10 @@ use core::str::FromStr; #[cfg(feature = "std")] use std::error::Error; -use num_traits::{ConstOne, ConstZero, Inv, MulAdd, Num, One, Pow, Signed, Zero}; +use num_traits::{ + CheckedAdd, CheckedDiv, CheckedMul, CheckedRem, CheckedSub, ConstOne, ConstZero, Inv, MulAdd, + Num, One, Pow, Signed, Zero, +}; use num_traits::float::FloatCore; #[cfg(any(feature = "std", feature = "libm"))] @@ -761,6 +764,16 @@ impl Add> for Complex { } } +impl CheckedAdd for Complex { + #[inline] + fn checked_add(&self, other: &Self) -> Option { + Some(Self::new( + self.re.checked_add(&other.re)?, + self.im.checked_add(&other.im)?, + )) + } +} + forward_all_binop!(impl Sub, sub); // (a + i b) - (c + i d) == (a - c) + i (b - d) @@ -773,6 +786,16 @@ impl Sub> for Complex { } } +impl CheckedSub for Complex { + #[inline] + fn checked_sub(&self, other: &Self) -> Option { + Some(Self::new( + self.re.checked_sub(&other.re)?, + self.im.checked_sub(&other.im)?, + )) + } +} + forward_all_binop!(impl Mul, mul); // (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) @@ -787,6 +810,23 @@ impl Mul> for Complex { } } +impl CheckedMul for Complex { + #[inline] + fn checked_mul(&self, other: &Self) -> Option { + let re = self + .re + .checked_mul(&other.re)? + .checked_sub(&self.im.checked_mul(&other.im)?)?; + + let im = self + .re + .checked_mul(&other.im)? + .checked_add(&self.im.checked_mul(&other.re)?)?; + + Some(Self::new(re, im)) + } +} + // (a + i b) * (c + i d) + (e + i f) == ((a*c + e) - b*d) + i (a*d + (b*c + f)) impl> MulAdd> for Complex { type Output = Complex; @@ -799,6 +839,7 @@ impl> MulAdd> for Complex { Complex::new(re, im) } } + impl<'a, 'b, T: Clone + Num + MulAdd> MulAdd<&'b Complex> for &'a Complex { type Output = Complex; @@ -824,6 +865,30 @@ impl Div> for Complex { } } +impl CheckedDiv for Complex { + #[inline] + fn checked_div(&self, other: &Self) -> Option { + let norm_sqr = other + .re + .checked_mul(&other.re)? + .checked_add(&other.im.checked_mul(&other.im)?)?; + + let re = self + .re + .checked_mul(&other.re)? + .checked_add(&self.im.checked_mul(&other.im)?)?; + + let im = self + .im + .checked_mul(&other.re)? + .checked_sub(&self.re.checked_mul(&other.im)?)?; + Some(Self::new( + re.checked_div(&norm_sqr)?, + im.checked_div(&norm_sqr)?, + )) + } +} + forward_all_binop!(impl Rem, rem); impl Complex { @@ -834,6 +899,16 @@ impl Complex { } } +impl Complex { + fn checked_div_trunc(&self, divisor: &Self) -> Option { + let Complex { re, im } = self.checked_div(divisor)?; + let re = re.checked_sub(&re.checked_rem(&T::one())?)?; + let im = im.checked_sub(&im.checked_rem(&T::one())?)?; + + Some(Self::new(re, im)) + } +} + impl Rem> for Complex { type Output = Self; @@ -844,6 +919,17 @@ impl Rem> for Complex { } } +impl CheckedRem + for Complex +{ + #[inline] + fn checked_rem(&self, modulus: &Self) -> Option { + let gaussian = self.checked_div_trunc(modulus)?; + + self.checked_sub(&modulus.checked_mul(&gaussian)?) + } +} + // Op Assign mod opassign {