From a077ad3bc920e31abf9611a3c67fa6d4057aecea Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 10 Aug 2018 10:44:25 +0200 Subject: [PATCH] implement Sum and Product --- src/lib.rs | 19 +++++++++++++++++++ src/traits.rs | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 668408f..ae1c520 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ mod traits; use std::f32; use std::f64; +use std::iter::{Product, Sum}; use std::mem; use std::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, @@ -290,6 +291,24 @@ macro_rules! fixed_unsigned { pass_assign! { impl BitOrAssign for $Fixed($Inner) { bitor_assign } } pass! { impl BitXor for $Fixed($Inner) { bitxor } } pass_assign! { impl BitXorAssign for $Fixed($Inner) { bitxor_assign } } + + impl Product<$Fixed> for $Fixed { + fn product>(mut iter: I) -> $Fixed { + match iter.next() { + None => <$Fixed as FixedNum>::one().expect("overflow"), + Some(first) => iter.fold(first, Mul::mul), + } + } + } + + impl<'a> Product<&'a $Fixed> for $Fixed { + fn product>(mut iter: I) -> $Fixed { + match iter.next() { + None => <$Fixed as FixedNum>::one().expect("overflow"), + Some(first) => iter.fold(*first, Mul::mul), + } + } + } }; } diff --git a/src/traits.rs b/src/traits.rs index eba714b..bc6c754 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -8,6 +8,7 @@ use { pub(crate) trait FixedNum: Copy { type Part; + fn one() -> Option; fn parts(self) -> (bool, Self::Part, Self::Part); #[inline(always)] fn int_bits() -> u32 { @@ -82,6 +83,18 @@ macro_rules! fixed_num_unsigned { ($Fixed:ident($Part:ty)) => { fixed_num_common! { $Fixed($Part); + + #[inline] + fn one() -> Option { + let int_bits = <$Fixed as FixedNum>::int_bits(); + let frac_bits = <$Fixed as FixedNum>::frac_bits(); + if int_bits < 1 { + None + } else { + Some($Fixed::from_bits(1 << frac_bits)) + } + } + #[inline] fn parts(self) -> (bool, $Part, $Part) { let bits = self.to_bits(); @@ -99,6 +112,18 @@ macro_rules! fixed_num_signed { ($Fixed:ident($Part:ty)) => { fixed_num_common! { $Fixed($Part); + + #[inline] + fn one() -> Option { + let int_bits = <$Fixed as FixedNum>::int_bits(); + let frac_bits = <$Fixed as FixedNum>::frac_bits(); + if int_bits < 2 { + None + } else { + Some($Fixed::from_bits(1 << frac_bits)) + } + } + #[inline] fn parts(self) -> (bool, $Part, $Part) { let bits = self.to_bits().wrapping_abs() as $Part;