Skip to content

Commit

Permalink
Merge pull request #65 from bennofs/master
Browse files Browse the repository at this point in the history
Add Sum/Product impls for NotNan
  • Loading branch information
mbrubeck committed May 20, 2020
2 parents 06afbc9 + eae4033 commit 90f4ca8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/lib.rs
Expand Up @@ -14,6 +14,7 @@ use core::hash::{Hash, Hasher};
use core::fmt;
use core::mem;
use core::hint::unreachable_unchecked;
use core::iter::{Sum, Product};
use core::str::FromStr;

use num_traits::{Bounded, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero};
Expand Down Expand Up @@ -322,6 +323,19 @@ impl<T: Float + AddAssign> AddAssign<T> for NotNan<T> {
}
}


impl<T: Float + Sum> Sum for NotNan<T> {
fn sum<I: Iterator<Item = NotNan<T>>>(iter: I) -> Self {
NotNan::new(iter.map(|v| v.0).sum()).expect("Sum resulted in NaN")
}
}

impl<'a, T: Float + Sum> Sum<&'a NotNan<T>> for NotNan<T> {
fn sum<I: Iterator<Item = &'a NotNan<T>>>(iter: I) -> Self {
iter.map(|v| *v).sum()
}
}

impl<T: Float> Sub for NotNan<T> {
type Output = Self;

Expand Down Expand Up @@ -392,6 +406,18 @@ impl<T: Float + MulAssign> MulAssign<T> for NotNan<T> {
}
}

impl<T: Float + Product> Product for NotNan<T> {
fn product<I: Iterator<Item = NotNan<T>>>(iter: I) -> Self {
NotNan::new(iter.map(|v| v.0).product()).expect("Product resulted in NaN")
}
}

impl<'a, T: Float + Product> Product<&'a NotNan<T>> for NotNan<T> {
fn product<I: Iterator<Item = &'a NotNan<T>>>(iter: I) -> Self {
iter.map(|v| *v).product()
}
}

impl<T: Float> Div for NotNan<T> {
type Output = Self;

Expand Down
34 changes: 34 additions & 0 deletions tests/test.rs
Expand Up @@ -545,3 +545,37 @@ fn ordered_f32_neg() {
fn ordered_f64_neg() {
assert_eq!(OrderedFloat(-7.0f64), -OrderedFloat(7.0f64));
}

#[test]
#[should_panic]
fn test_sum_fails_on_nan() {
let a = NotNan::new(std::f32::INFINITY).unwrap();
let b = NotNan::new(std::f32::NEG_INFINITY).unwrap();
let _c: NotNan<_> = [a,b].iter().sum();
}

#[test]
#[should_panic]
fn test_product_fails_on_nan() {
let a = NotNan::new(std::f32::INFINITY).unwrap();
let b = NotNan::new(0f32).unwrap();
let _c: NotNan<_> = [a,b].iter().product();
}

#[test]
fn not_nan64_sum_product() {
let a = NotNan::new(2138.1237).unwrap();
let b = NotNan::new(132f64).unwrap();
let c = NotNan::new(5.1).unwrap();

assert_eq!(std::iter::empty::<NotNan<f64>>().sum::<NotNan<_>>(), NotNan::new(0f64).unwrap());
assert_eq!([a].iter().sum::<NotNan<_>>(), a);
assert_eq!([a,b].iter().sum::<NotNan<_>>(), a + b);
assert_eq!([a,b,c].iter().sum::<NotNan<_>>(), a + b + c);

assert_eq!(std::iter::empty::<NotNan<f64>>().product::<NotNan<_>>(), NotNan::new(1f64).unwrap());
assert_eq!([a].iter().product::<NotNan<_>>(), a);
assert_eq!([a,b].iter().product::<NotNan<_>>(), a * b);
assert_eq!([a,b,c].iter().product::<NotNan<_>>(), a * b * c);

}

0 comments on commit 90f4ca8

Please sign in to comment.