#![no_std] #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] //! Wrappers for total order on Floats. extern crate num_traits; #[cfg(feature = "std")] extern crate std; use core::cmp::Ordering; use core::ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign}; use core::hash::{Hash, Hasher}; use core::fmt; use core::mem; use core::hint::unreachable_unchecked; use num_traits::{Bounded, Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero}; /// A wrapper around Floats providing an implementation of Ord and Hash. /// /// A NaN value cannot be stored in this type. #[deprecated(since = "0.6.0", note = "renamed to `NotNan`")] pub type NotNaN = NotNan; /// An error indicating an attempt to construct NotNan from a NaN #[deprecated(since = "0.6.0", note = "renamed to `FloatIsNan`")] pub type FloatIsNaN = FloatIsNan; // masks for the parts of the IEEE 754 float const SIGN_MASK: u64 = 0x8000000000000000u64; const EXP_MASK: u64 = 0x7ff0000000000000u64; const MAN_MASK: u64 = 0x000fffffffffffffu64; // canonical raw bit patterns (for hashing) const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64; const CANONICAL_ZERO_BITS: u64 = 0x0u64; /// A wrapper around Floats providing an implementation of Ord and Hash. /// /// NaN is sorted as *greater* than all other values and *equal* /// to itself, in contradiction with the IEEE standard. #[derive(Debug, Default, Clone, Copy)] #[repr(transparent)] pub struct OrderedFloat(pub T); impl OrderedFloat { /// Get the value out. pub fn into_inner(self) -> T { let OrderedFloat(val) = self; val } } impl AsRef for OrderedFloat { fn as_ref(&self) -> &T { let OrderedFloat(ref val) = *self; val } } impl AsMut for OrderedFloat { fn as_mut(&mut self) -> &mut T { let OrderedFloat(ref mut val) = *self; val } } impl PartialOrd for OrderedFloat { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for OrderedFloat { fn cmp(&self, other: &Self) -> Ordering { let lhs = self.as_ref(); let rhs = other.as_ref(); match lhs.partial_cmp(&rhs) { Some(ordering) => ordering, None => { if lhs.is_nan() { if rhs.is_nan() { Ordering::Equal } else { Ordering::Greater } } else { Ordering::Less } } } } } impl PartialEq for OrderedFloat { fn eq(&self, other: &OrderedFloat) -> bool { if self.as_ref().is_nan() { other.as_ref().is_nan() } else if other.as_ref().is_nan() { false } else { self.as_ref() == other.as_ref() } } } impl Hash for OrderedFloat { fn hash(&self, state: &mut H) { if self.is_nan() { // normalize to one representation of NaN hash_float(&T::nan(), state) } else { hash_float(self.as_ref(), state) } } } impl fmt::Display for OrderedFloat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_ref().fmt(f) } } impl Into for OrderedFloat { fn into(self) -> f32 { self.into_inner() } } impl Into for OrderedFloat { fn into(self) -> f64 { self.into_inner() } } impl From for OrderedFloat { fn from(val: T) -> Self { OrderedFloat(val) } } impl Deref for OrderedFloat { type Target = T; fn deref(&self) -> &Self::Target { self.as_ref() } } impl DerefMut for OrderedFloat { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } } impl Eq for OrderedFloat {} impl Bounded for OrderedFloat { fn min_value() -> Self { OrderedFloat(T::min_value()) } fn max_value() -> Self { OrderedFloat(T::max_value()) } } /// A wrapper around Floats providing an implementation of Ord and Hash. /// /// A NaN value cannot be stored in this type. #[derive(PartialOrd, PartialEq, Debug, Default, Clone, Copy)] #[repr(transparent)] pub struct NotNan(T); impl NotNan { /// Create a NotNan value. /// /// Returns Err if val is NaN pub fn new(val: T) -> Result { match val { ref val if val.is_nan() => Err(FloatIsNan), val => Ok(NotNan(val)), } } /// Create a NotNan value from a value that is guaranteed to not be NaN /// /// Behaviour is undefined if `val` is NaN pub unsafe fn unchecked_new(val: T) -> Self { debug_assert!(!val.is_nan()); NotNan(val) } /// Get the value out. pub fn into_inner(self) -> T { let NotNan(val) = self; val } } impl AsRef for NotNan { fn as_ref(&self) -> &T { let NotNan(ref val) = *self; val } } impl Ord for NotNan { fn cmp(&self, other: &NotNan) -> Ordering { match self.partial_cmp(&other) { Some(ord) => ord, None => unsafe { unreachable_unchecked() }, } } } impl Hash for NotNan { fn hash(&self, state: &mut H) { hash_float(self.as_ref(), state) } } impl fmt::Display for NotNan { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_ref().fmt(f) } } impl Into for NotNan { fn into(self) -> f32 { self.into_inner() } } impl Into for NotNan { fn into(self) -> f64 { self.into_inner() } } /// Creates a NotNan value from a Float. /// /// Panics if the provided value is NaN or the computation results in NaN impl From for NotNan { fn from(v: T) -> Self { assert!(!v.is_nan()); NotNan(v) } } impl Deref for NotNan { type Target = T; fn deref(&self) -> &Self::Target { self.as_ref() } } impl Eq for NotNan {} /// Adds two NotNans. /// /// Panics if the computation results in NaN impl Add for NotNan { type Output = Self; fn add(self, other: Self) -> Self { NotNan::new(self.0 + other.0).expect("Addition resulted in NaN") } } /// Adds a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl Add for NotNan { type Output = Self; fn add(self, other: T) -> Self { assert!(!other.is_nan()); NotNan::new(self.0 + other).expect("Addition resulted in NaN") } } impl AddAssign for NotNan { fn add_assign(&mut self, other: Self) { self.0 += other.0; assert!(!self.0.is_nan(), "Addition resulted in NaN") } } impl AddAssign for NotNan { fn add_assign(&mut self, other: Self) { self.0 += other.0; assert!(!self.0.is_nan(), "Addition resulted in NaN") } } /// Adds a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl AddAssign for NotNan { fn add_assign(&mut self, other: f64) { assert!(!other.is_nan()); self.0 += other; assert!(!self.0.is_nan(), "Addition resulted in NaN") } } /// Adds a float directly. /// /// Panics if the provided value is NaN. impl AddAssign for NotNan { fn add_assign(&mut self, other: f32) { assert!(!other.is_nan()); self.0 += other; assert!(!self.0.is_nan(), "Addition resulted in NaN") } } impl Sub for NotNan { type Output = Self; fn sub(self, other: Self) -> Self { NotNan::new(self.0 - other.0).expect("Subtraction resulted in NaN") } } /// Subtracts a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl Sub for NotNan { type Output = Self; fn sub(self, other: T) -> Self { assert!(!other.is_nan()); NotNan::new(self.0 - other).expect("Subtraction resulted in NaN") } } impl SubAssign for NotNan { fn sub_assign(&mut self, other: Self) { self.0 -= other.0; assert!(!self.0.is_nan(), "Subtraction resulted in NaN") } } impl SubAssign for NotNan { fn sub_assign(&mut self, other: Self) { self.0 -= other.0; assert!(!self.0.is_nan(), "Subtraction resulted in NaN") } } /// Subtracts a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl SubAssign for NotNan { fn sub_assign(&mut self, other: f64) { assert!(!other.is_nan()); self.0 -= other; assert!(!self.0.is_nan(), "Subtraction resulted in NaN") } } /// Subtracts a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl SubAssign for NotNan { fn sub_assign(&mut self, other: f32) { assert!(!other.is_nan()); self.0 -= other; assert!(!self.0.is_nan(), "Subtraction resulted in NaN") } } impl Mul for NotNan { type Output = Self; fn mul(self, other: Self) -> Self { NotNan::new(self.0 * other.0).expect("Multiplication resulted in NaN") } } /// Multiplies a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl Mul for NotNan { type Output = Self; fn mul(self, other: T) -> Self { assert!(!other.is_nan()); NotNan::new(self.0 * other).expect("Multiplication resulted in NaN") } } impl MulAssign for NotNan { fn mul_assign(&mut self, other: Self) { self.0 *= other.0; assert!(!self.0.is_nan(), "Multiplication resulted in NaN") } } impl MulAssign for NotNan { fn mul_assign(&mut self, other: Self) { self.0 *= other.0; assert!(!self.0.is_nan(), "Multiplication resulted in NaN") } } /// Multiplies a float directly. /// /// Panics if the provided value is NaN. impl MulAssign for NotNan { fn mul_assign(&mut self, other: f64) { assert!(!other.is_nan()); self.0 *= other; } } /// Multiplies a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl MulAssign for NotNan { fn mul_assign(&mut self, other: f32) { assert!(!other.is_nan()); self.0 *= other; assert!(!self.0.is_nan(), "Multiplication resulted in NaN") } } impl Div for NotNan { type Output = Self; fn div(self, other: Self) -> Self { NotNan::new(self.0 / other.0).expect("Division resulted in NaN") } } /// Divides a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl Div for NotNan { type Output = Self; fn div(self, other: T) -> Self { assert!(!other.is_nan()); NotNan::new(self.0 / other).expect("Division resulted in NaN") } } impl DivAssign for NotNan { fn div_assign(&mut self, other: Self) { self.0 /= other.0; assert!(!self.0.is_nan(), "Division resulted in NaN") } } impl DivAssign for NotNan { fn div_assign(&mut self, other: Self) { self.0 /= other.0; assert!(!self.0.is_nan(), "Division resulted in NaN") } } /// Divides a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl DivAssign for NotNan { fn div_assign(&mut self, other: f64) { assert!(!other.is_nan()); self.0 /= other; assert!(!self.0.is_nan(), "Division resulted in NaN") } } /// Divides a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl DivAssign for NotNan { fn div_assign(&mut self, other: f32) { assert!(!other.is_nan()); self.0 /= other; assert!(!self.0.is_nan(), "Division resulted in NaN") } } impl Rem for NotNan { type Output = Self; fn rem(self, other: Self) -> Self { NotNan::new(self.0 % other.0).expect("Rem resulted in NaN") } } /// Calculates `%` with a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl Rem for NotNan { type Output = Self; fn rem(self, other: T) -> Self { assert!(!other.is_nan()); NotNan::new(self.0 % other).expect("Rem resulted in NaN") } } impl RemAssign for NotNan { fn rem_assign(&mut self, other: Self) { self.0 %= other.0; assert!(!self.0.is_nan(), "Rem resulted in NaN") } } impl RemAssign for NotNan { fn rem_assign(&mut self, other: Self) { self.0 %= other.0; assert!(!self.0.is_nan(), "Rem resulted in NaN") } } /// Calculates `%=` with a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl RemAssign for NotNan { fn rem_assign(&mut self, other: f64) { assert!(!other.is_nan()); self.0 %= other; assert!(!self.0.is_nan(), "Rem resulted in NaN") } } /// Calculates `%=` with a float directly. /// /// Panics if the provided value is NaN or the computation results in NaN impl RemAssign for NotNan { fn rem_assign(&mut self, other: f32) { assert!(!other.is_nan()); self.0 %= other; assert!(!self.0.is_nan(), "Rem resulted in NaN") } } impl Neg for NotNan { type Output = Self; fn neg(self) -> Self { NotNan::new(-self.0).expect("Negation resulted in NaN") } } /// An error indicating an attempt to construct NotNan from a NaN #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct FloatIsNan; #[cfg(feature = "std")] impl std::error::Error for FloatIsNan { fn description(&self) -> &str { "NotNan constructed with NaN" } } impl fmt::Display for FloatIsNan { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "NotNan constructed with NaN") } } #[cfg(feature = "std")] impl Into for FloatIsNan { fn into(self) -> std::io::Error { std::io::Error::new(std::io::ErrorKind::InvalidInput, self) } } #[inline] fn hash_float(f: &F, state: &mut H) { raw_double_bits(f).hash(state); } #[inline] fn raw_double_bits(f: &F) -> u64 { if f.is_nan() { return CANONICAL_NAN_BITS; } let (man, exp, sign) = f.integer_decode(); if man == 0 { return CANONICAL_ZERO_BITS; } let exp_u64 = unsafe { mem::transmute::(exp) } as u64; let sign_u64 = if sign > 0 { 1u64 } else { 0u64 }; (man & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK) } impl Zero for NotNan { fn zero() -> Self { NotNan(T::zero()) } fn is_zero(&self) -> bool { self.0.is_zero() } } impl One for NotNan { fn one() -> Self { NotNan(T::one()) } } impl Bounded for NotNan { fn min_value() -> Self { NotNan(T::min_value()) } fn max_value() -> Self { NotNan(T::max_value()) } } impl FromPrimitive for NotNan { fn from_i64(n: i64) -> Option { T::from_i64(n).and_then(|n| NotNan::new(n).ok()) } fn from_u64(n: u64) -> Option { T::from_u64(n).and_then(|n| NotNan::new(n).ok()) } fn from_isize(n: isize) -> Option { T::from_isize(n).and_then(|n| NotNan::new(n).ok()) } fn from_i8(n: i8) -> Option { T::from_i8(n).and_then(|n| NotNan::new(n).ok()) } fn from_i16(n: i16) -> Option { T::from_i16(n).and_then(|n| NotNan::new(n).ok()) } fn from_i32(n: i32) -> Option { T::from_i32(n).and_then(|n| NotNan::new(n).ok()) } fn from_usize(n: usize) -> Option { T::from_usize(n).and_then(|n| NotNan::new(n).ok()) } fn from_u8(n: u8) -> Option { T::from_u8(n).and_then(|n| NotNan::new(n).ok()) } fn from_u16(n: u16) -> Option { T::from_u16(n).and_then(|n| NotNan::new(n).ok()) } fn from_u32(n: u32) -> Option { T::from_u32(n).and_then(|n| NotNan::new(n).ok()) } fn from_f32(n: f32) -> Option { T::from_f32(n).and_then(|n| NotNan::new(n).ok()) } fn from_f64(n: f64) -> Option { T::from_f64(n).and_then(|n| NotNan::new(n).ok()) } } impl ToPrimitive for NotNan { fn to_i64(&self) -> Option { self.0.to_i64() } fn to_u64(&self) -> Option { self.0.to_u64() } fn to_isize(&self) -> Option { self.0.to_isize() } fn to_i8(&self) -> Option { self.0.to_i8() } fn to_i16(&self) -> Option { self.0.to_i16() } fn to_i32(&self) -> Option { self.0.to_i32() } fn to_usize(&self) -> Option { self.0.to_usize() } fn to_u8(&self) -> Option { self.0.to_u8() } fn to_u16(&self) -> Option { self.0.to_u16() } fn to_u32(&self) -> Option { self.0.to_u32() } fn to_f32(&self) -> Option { self.0.to_f32() } fn to_f64(&self) -> Option { self.0.to_f64() } } /// An error indicating a parse error from a string for `NotNan`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ParseNotNanError { /// A plain parse error from the underlying float type. ParseFloatError(E), /// The parsed float value resulted in a NaN. IsNaN, } #[cfg(feature = "std")] impl std::error::Error for ParseNotNanError { fn description(&self) -> &str { return "Error parsing a not-NaN floating point value"; } } impl fmt::Display for ParseNotNanError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ::fmt(self, f) } } impl Num for NotNan { type FromStrRadixErr = ParseNotNanError; fn from_str_radix(src: &str, radix: u32) -> Result { T::from_str_radix(src, radix) .map_err(|err| ParseNotNanError::ParseFloatError(err)) .and_then(|n| NotNan::new(n).map_err(|_| ParseNotNanError::IsNaN)) } } impl Signed for NotNan { fn abs(&self) -> Self { NotNan(self.0.abs()) } fn abs_sub(&self, other: &Self) -> Self { NotNan::new(self.0.abs_sub(other.0)).expect("Subtraction resulted in NaN") } fn signum(&self) -> Self { NotNan(self.0.signum()) } fn is_positive(&self) -> bool { self.0.is_positive() } fn is_negative(&self) -> bool { self.0.is_negative() } } impl NumCast for NotNan { fn from(n: F) -> Option { T::from(n).and_then(|n| NotNan::new(n).ok()) } } #[cfg(feature = "serde")] mod impl_serde { extern crate serde; use self::serde::{Serialize, Serializer, Deserialize, Deserializer}; use self::serde::de::{Error, Unexpected}; use super::{OrderedFloat, NotNan}; use num_traits::Float; use core::f64; #[cfg(test)] extern crate serde_test; #[cfg(test)] use self::serde_test::{Token, assert_tokens, assert_de_tokens_error}; impl Serialize for OrderedFloat { fn serialize(&self, s: S) -> Result { self.0.serialize(s) } } impl<'de, T: Float + Deserialize<'de>> Deserialize<'de> for OrderedFloat { fn deserialize>(d: D) -> Result { T::deserialize(d).map(OrderedFloat) } } impl Serialize for NotNan { fn serialize(&self, s: S) -> Result { self.0.serialize(s) } } impl<'de, T: Float + Deserialize<'de>> Deserialize<'de> for NotNan { fn deserialize>(d: D) -> Result { let float = T::deserialize(d)?; NotNan::new(float).map_err(|_| { Error::invalid_value(Unexpected::Float(f64::NAN), &"float (but not NaN)") }) } } #[test] fn test_ordered_float() { let float = OrderedFloat(1.0f64); assert_tokens(&float, &[Token::F64(1.0)]); } #[test] fn test_not_nan() { let float = NotNan(1.0f64); assert_tokens(&float, &[Token::F64(1.0)]); } #[test] fn test_fail_on_nan() { assert_de_tokens_error::>( &[Token::F64(f64::NAN)], "invalid value: floating point `NaN`, expected float (but not NaN)"); } }