From c848562fcff82e3a05c2066f9bc0406fdb97bc6c Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 14:31:09 -0800
Subject: [PATCH 01/15] Use forwarding macros to implement Float and Real

---
 src/float.rs  | 289 +++++++++-----------------------------------------
 src/lib.rs    |   3 +
 src/macros.rs |  25 +++++
 src/real.rs   | 190 +++++++++------------------------
 4 files changed, 128 insertions(+), 379 deletions(-)
 create mode 100644 src/macros.rs

diff --git a/src/float.rs b/src/float.rs
index 5ca80d2c..d09bef77 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -1197,255 +1197,66 @@ macro_rules! float_impl {
                 ::std::$T::MAX
             }
 
-            #[inline]
-            fn is_nan(self) -> bool {
-                <$T>::is_nan(self)
-            }
-
-            #[inline]
-            fn is_infinite(self) -> bool {
-                <$T>::is_infinite(self)
-            }
-
-            #[inline]
-            fn is_finite(self) -> bool {
-                <$T>::is_finite(self)
-            }
-
-            #[inline]
-            fn is_normal(self) -> bool {
-                <$T>::is_normal(self)
-            }
-
-            #[inline]
-            fn classify(self) -> FpCategory {
-                <$T>::classify(self)
-            }
-
-            #[inline]
-            fn floor(self) -> Self {
-                <$T>::floor(self)
-            }
-
-            #[inline]
-            fn ceil(self) -> Self {
-                <$T>::ceil(self)
-            }
-
-            #[inline]
-            fn round(self) -> Self {
-                <$T>::round(self)
-            }
-
-            #[inline]
-            fn trunc(self) -> Self {
-                <$T>::trunc(self)
-            }
-
-            #[inline]
-            fn fract(self) -> Self {
-                <$T>::fract(self)
-            }
-
-            #[inline]
-            fn abs(self) -> Self {
-                <$T>::abs(self)
-            }
-
-            #[inline]
-            fn signum(self) -> Self {
-                <$T>::signum(self)
-            }
-
-            #[inline]
-            fn is_sign_positive(self) -> bool {
-                <$T>::is_sign_positive(self)
-            }
-
-            #[inline]
-            fn is_sign_negative(self) -> bool {
-                <$T>::is_sign_negative(self)
-            }
-
-            #[inline]
-            fn mul_add(self, a: Self, b: Self) -> Self {
-                <$T>::mul_add(self, a, b)
-            }
-
-            #[inline]
-            fn recip(self) -> Self {
-                <$T>::recip(self)
-            }
-
-            #[inline]
-            fn powi(self, n: i32) -> Self {
-                <$T>::powi(self, n)
-            }
-
-            #[inline]
-            fn powf(self, n: Self) -> Self {
-                <$T>::powf(self, n)
-            }
-
-            #[inline]
-            fn sqrt(self) -> Self {
-                <$T>::sqrt(self)
-            }
-
-            #[inline]
-            fn exp(self) -> Self {
-                <$T>::exp(self)
-            }
-
-            #[inline]
-            fn exp2(self) -> Self {
-                <$T>::exp2(self)
-            }
-
-            #[inline]
-            fn ln(self) -> Self {
-                <$T>::ln(self)
-            }
-
-            #[inline]
-            fn log(self, base: Self) -> Self {
-                <$T>::log(self, base)
-            }
-
-            #[inline]
-            fn log2(self) -> Self {
-                <$T>::log2(self)
-            }
-
-            #[inline]
-            fn log10(self) -> Self {
-                <$T>::log10(self)
-            }
-
-            #[inline]
-            fn to_degrees(self) -> Self {
-                // NB: `f32` didn't stabilize this until 1.7
-                // <$T>::to_degrees(self)
-                self * (180. / ::std::$T::consts::PI)
-            }
-
-            #[inline]
-            fn to_radians(self) -> Self {
-                // NB: `f32` didn't stabilize this until 1.7
-                // <$T>::to_radians(self)
-                self * (::std::$T::consts::PI / 180.)
-            }
-
-            #[inline]
-            fn max(self, other: Self) -> Self {
-                <$T>::max(self, other)
-            }
-
-            #[inline]
-            fn min(self, other: Self) -> Self {
-                <$T>::min(self, other)
-            }
-
             #[inline]
             #[allow(deprecated)]
             fn abs_sub(self, other: Self) -> Self {
                 <$T>::abs_sub(self, other)
             }
 
-            #[inline]
-            fn cbrt(self) -> Self {
-                <$T>::cbrt(self)
-            }
-
-            #[inline]
-            fn hypot(self, other: Self) -> Self {
-                <$T>::hypot(self, other)
-            }
-
-            #[inline]
-            fn sin(self) -> Self {
-                <$T>::sin(self)
-            }
-
-            #[inline]
-            fn cos(self) -> Self {
-                <$T>::cos(self)
-            }
-
-            #[inline]
-            fn tan(self) -> Self {
-                <$T>::tan(self)
-            }
-
-            #[inline]
-            fn asin(self) -> Self {
-                <$T>::asin(self)
-            }
-
-            #[inline]
-            fn acos(self) -> Self {
-                <$T>::acos(self)
-            }
-
-            #[inline]
-            fn atan(self) -> Self {
-                <$T>::atan(self)
-            }
-
-            #[inline]
-            fn atan2(self, other: Self) -> Self {
-                <$T>::atan2(self, other)
-            }
-
-            #[inline]
-            fn sin_cos(self) -> (Self, Self) {
-                <$T>::sin_cos(self)
-            }
-
-            #[inline]
-            fn exp_m1(self) -> Self {
-                <$T>::exp_m1(self)
-            }
-
-            #[inline]
-            fn ln_1p(self) -> Self {
-                <$T>::ln_1p(self)
-            }
-
-            #[inline]
-            fn sinh(self) -> Self {
-                <$T>::sinh(self)
-            }
-
-            #[inline]
-            fn cosh(self) -> Self {
-                <$T>::cosh(self)
-            }
-
-            #[inline]
-            fn tanh(self) -> Self {
-                <$T>::tanh(self)
-            }
-
-            #[inline]
-            fn asinh(self) -> Self {
-                <$T>::asinh(self)
-            }
-
-            #[inline]
-            fn acosh(self) -> Self {
-                <$T>::acosh(self)
-            }
-
-            #[inline]
-            fn atanh(self) -> Self {
-                <$T>::atanh(self)
-            }
-
             #[inline]
             fn integer_decode(self) -> (u64, i16, i8) {
                 $decode(self)
             }
+
+            forward! {
+                Self::is_nan(self) -> bool;
+                Self::is_infinite(self) -> bool;
+                Self::is_finite(self) -> bool;
+                Self::is_normal(self) -> bool;
+                Self::classify(self) -> FpCategory;
+                Self::floor(self) -> Self;
+                Self::ceil(self) -> Self;
+                Self::round(self) -> Self;
+                Self::trunc(self) -> Self;
+                Self::fract(self) -> Self;
+                Self::abs(self) -> Self;
+                Self::signum(self) -> Self;
+                Self::is_sign_positive(self) -> bool;
+                Self::is_sign_negative(self) -> bool;
+                Self::mul_add(self, a: Self, b: Self) -> Self;
+                Self::recip(self) -> Self;
+                Self::powi(self, n: i32) -> Self;
+                Self::powf(self, n: Self) -> Self;
+                Self::sqrt(self) -> Self;
+                Self::exp(self) -> Self;
+                Self::exp2(self) -> Self;
+                Self::ln(self) -> Self;
+                Self::log(self, base: Self) -> Self;
+                Self::log2(self) -> Self;
+                Self::log10(self) -> Self;
+                Self::to_degrees(self) -> Self;
+                Self::to_radians(self) -> Self;
+                Self::max(self, other: Self) -> Self;
+                Self::min(self, other: Self) -> Self;
+                Self::cbrt(self) -> Self;
+                Self::hypot(self, other: Self) -> Self;
+                Self::sin(self) -> Self;
+                Self::cos(self) -> Self;
+                Self::tan(self) -> Self;
+                Self::asin(self) -> Self;
+                Self::acos(self) -> Self;
+                Self::atan(self) -> Self;
+                Self::atan2(self, other: Self) -> Self;
+                Self::sin_cos(self) -> (Self, Self);
+                Self::exp_m1(self) -> Self;
+                Self::ln_1p(self) -> Self;
+                Self::sinh(self) -> Self;
+                Self::cosh(self) -> Self;
+                Self::tanh(self) -> Self;
+                Self::asinh(self) -> Self;
+                Self::acosh(self) -> Self;
+                Self::atanh(self) -> Self;
+            }
         }
     )
 }
diff --git a/src/lib.rs b/src/lib.rs
index 14bb3d31..3e1c80c0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -42,6 +42,9 @@ pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
 pub use int::PrimInt;
 pub use pow::{Pow, pow, checked_pow};
 
+#[macro_use]
+mod macros;
+
 pub mod identities;
 pub mod sign;
 pub mod ops;
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 00000000..8c7a6f85
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,25 @@
+
+/// Forward a method to an inherent method or a base trait method.
+macro_rules! forward {
+    ($( Self :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+        => {$(
+            #[inline]
+            fn $method(self $( , $arg : $ty )* ) -> $ret {
+                Self::$method(self $( , $arg )* )
+            }
+        )*};
+    ($( $base:ident :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+        => {$(
+            #[inline]
+            fn $method(self $( , $arg : $ty )* ) -> $ret {
+                <Self as $base>::$method(self $( , $arg )* )
+            }
+        )*};
+    ($( $base:ident :: $method:ident ( $( $arg:ident : $ty:ty ),* ) -> $ret:ty ; )*)
+        => {$(
+            #[inline]
+            fn $method( $( $arg : $ty ),* ) -> $ret {
+                <Self as $base>::$method( $( $arg ),* )
+            }
+        )*}
+}
diff --git a/src/real.rs b/src/real.rs
index ab29d450..fb6714a7 100644
--- a/src/real.rs
+++ b/src/real.rs
@@ -782,145 +782,55 @@ pub trait Real
 }
 
 impl<T: Float> Real for T {
-    fn min_value() -> Self {
-        Self::min_value()
-    }
-    fn min_positive_value() -> Self {
-        Self::min_positive_value()
-    }
-    fn epsilon() -> Self {
-        Self::epsilon()
-    }
-    fn max_value() -> Self {
-        Self::max_value()
-    }
-    fn floor(self) -> Self {
-        self.floor()
-    }
-    fn ceil(self) -> Self {
-        self.ceil()
-    }
-    fn round(self) -> Self {
-        self.round()
-    }
-    fn trunc(self) -> Self {
-        self.trunc()
-    }
-    fn fract(self) -> Self {
-        self.fract()
-    }
-    fn abs(self) -> Self {
-        self.abs()
-    }
-    fn signum(self) -> Self {
-        self.signum()
-    }
-    fn is_sign_positive(self) -> bool {
-        self.is_sign_positive()
-    }
-    fn is_sign_negative(self) -> bool {
-        self.is_sign_negative()
-    }
-    fn mul_add(self, a: Self, b: Self) -> Self {
-        self.mul_add(a, b)
-    }
-    fn recip(self) -> Self {
-        self.recip()
-    }
-    fn powi(self, n: i32) -> Self {
-        self.powi(n)
-    }
-    fn powf(self, n: Self) -> Self {
-        self.powf(n)
-    }
-    fn sqrt(self) -> Self {
-        self.sqrt()
-    }
-    fn exp(self) -> Self {
-        self.exp()
-    }
-    fn exp2(self) -> Self {
-        self.exp2()
-    }
-    fn ln(self) -> Self {
-        self.ln()
-    }
-    fn log(self, base: Self) -> Self {
-        self.log(base)
-    }
-    fn log2(self) -> Self {
-        self.log2()
-    }
-    fn log10(self) -> Self {
-        self.log10()
-    }
-    fn to_degrees(self) -> Self {
-        self.to_degrees()
-    }
-    fn to_radians(self) -> Self {
-        self.to_radians()
-    }
-    fn max(self, other: Self) -> Self {
-        self.max(other)
-    }
-    fn min(self, other: Self) -> Self {
-        self.min(other)
-    }
-    fn abs_sub(self, other: Self) -> Self {
-        self.abs_sub(other)
-    }
-    fn cbrt(self) -> Self {
-        self.cbrt()
-    }
-    fn hypot(self, other: Self) -> Self {
-        self.hypot(other)
-    }
-    fn sin(self) -> Self {
-        self.sin()
-    }
-    fn cos(self) -> Self {
-        self.cos()
-    }
-    fn tan(self) -> Self {
-        self.tan()
-    }
-    fn asin(self) -> Self {
-        self.asin()
-    }
-    fn acos(self) -> Self {
-        self.acos()
-    }
-    fn atan(self) -> Self {
-        self.atan()
-    }
-    fn atan2(self, other: Self) -> Self {
-        self.atan2(other)
-    }
-    fn sin_cos(self) -> (Self, Self) {
-        self.sin_cos()
-    }
-    fn exp_m1(self) -> Self {
-        self.exp_m1()
-    }
-    fn ln_1p(self) -> Self {
-        self.ln_1p()
-    }
-    fn sinh(self) -> Self {
-        self.sinh()
-    }
-    fn cosh(self) -> Self {
-        self.cosh()
-    }
-    fn tanh(self) -> Self {
-        self.tanh()
-    }
-    fn asinh(self) -> Self {
-        self.asinh()
-    }
-    fn acosh(self) -> Self {
-        self.acosh()
-    }
-    fn atanh(self) -> Self {
-        self.atanh()
+    forward! {
+        Float::min_value() -> Self;
+        Float::min_positive_value() -> Self;
+        Float::epsilon() -> Self;
+        Float::max_value() -> Self;
+    }
+    forward! {
+        Float::floor(self) -> Self;
+        Float::ceil(self) -> Self;
+        Float::round(self) -> Self;
+        Float::trunc(self) -> Self;
+        Float::fract(self) -> Self;
+        Float::abs(self) -> Self;
+        Float::signum(self) -> Self;
+        Float::is_sign_positive(self) -> bool;
+        Float::is_sign_negative(self) -> bool;
+        Float::mul_add(self, a: Self, b: Self) -> Self;
+        Float::recip(self) -> Self;
+        Float::powi(self, n: i32) -> Self;
+        Float::powf(self, n: Self) -> Self;
+        Float::sqrt(self) -> Self;
+        Float::exp(self) -> Self;
+        Float::exp2(self) -> Self;
+        Float::ln(self) -> Self;
+        Float::log(self, base: Self) -> Self;
+        Float::log2(self) -> Self;
+        Float::log10(self) -> Self;
+        Float::to_degrees(self) -> Self;
+        Float::to_radians(self) -> Self;
+        Float::max(self, other: Self) -> Self;
+        Float::min(self, other: Self) -> Self;
+        Float::abs_sub(self, other: Self) -> Self;
+        Float::cbrt(self) -> Self;
+        Float::hypot(self, other: Self) -> Self;
+        Float::sin(self) -> Self;
+        Float::cos(self) -> Self;
+        Float::tan(self) -> Self;
+        Float::asin(self) -> Self;
+        Float::acos(self) -> Self;
+        Float::atan(self) -> Self;
+        Float::atan2(self, other: Self) -> Self;
+        Float::sin_cos(self) -> (Self, Self);
+        Float::exp_m1(self) -> Self;
+        Float::ln_1p(self) -> Self;
+        Float::sinh(self) -> Self;
+        Float::cosh(self) -> Self;
+        Float::tanh(self) -> Self;
+        Float::asinh(self) -> Self;
+        Float::acosh(self) -> Self;
+        Float::atanh(self) -> Self;
     }
 }

From ac503261ca1d82457a5a3a72332c050cf4eb8369 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 14:41:09 -0800
Subject: [PATCH 02/15] Forward FloatCore to inherent methods when possible

---
 src/cast.rs  |  1 -
 src/float.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/src/cast.rs b/src/cast.rs
index 3d7d0a69..630341f4 100644
--- a/src/cast.rs
+++ b/src/cast.rs
@@ -1,4 +1,3 @@
-use core::f64;
 use core::mem::size_of;
 use core::num::Wrapping;
 
diff --git a/src/float.rs b/src/float.rs
index d09bef77..c2e28d42 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -166,6 +166,7 @@ impl FloatCore for f32 {
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {
         const EXP_MASK: u32 = 0x7f800000;
         const MAN_MASK: u32 = 0x007fffff;
@@ -181,14 +182,35 @@ impl FloatCore for f32 {
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
         self * (180.0 / ::core::f32::consts::PI)
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_radians(self) -> Self {
         self * (::core::f32::consts::PI / 180.0)
     }
+
+    #[cfg(feature = "std")]
+    forward! {
+        Self::is_nan(self) -> bool;
+        Self::is_infinite(self) -> bool;
+        Self::is_finite(self) -> bool;
+        Self::is_normal(self) -> bool;
+        Self::classify(self) -> FpCategory;
+        Self::abs(self) -> Self;
+        Self::signum(self) -> Self;
+        Self::is_sign_positive(self) -> bool;
+        Self::is_sign_negative(self) -> bool;
+        Self::min(self, other: Self) -> Self;
+        Self::max(self, other: Self) -> Self;
+        Self::recip(self) -> Self;
+        Self::powi(self, n: i32) -> Self;
+        Self::to_degrees(self) -> Self;
+        Self::to_radians(self) -> Self;
+    }
 }
 
 impl FloatCore for f64 {
@@ -208,6 +230,7 @@ impl FloatCore for f64 {
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {
         const EXP_MASK: u64 = 0x7ff0000000000000;
         const MAN_MASK: u64 = 0x000fffffffffffff;
@@ -223,14 +246,35 @@ impl FloatCore for f64 {
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
         self * (180.0 / ::core::f64::consts::PI)
     }
 
     #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_radians(self) -> Self {
         self * (::core::f64::consts::PI / 180.0)
     }
+
+    #[cfg(feature = "std")]
+    forward! {
+        Self::is_nan(self) -> bool;
+        Self::is_infinite(self) -> bool;
+        Self::is_finite(self) -> bool;
+        Self::is_normal(self) -> bool;
+        Self::classify(self) -> FpCategory;
+        Self::abs(self) -> Self;
+        Self::signum(self) -> Self;
+        Self::is_sign_positive(self) -> bool;
+        Self::is_sign_negative(self) -> bool;
+        Self::min(self, other: Self) -> Self;
+        Self::max(self, other: Self) -> Self;
+        Self::recip(self) -> Self;
+        Self::powi(self, n: i32) -> Self;
+        Self::to_degrees(self) -> Self;
+        Self::to_radians(self) -> Self;
+    }
 }
 
 // FIXME: these doctests aren't actually helpful, because they're using and

From 7d6575da0fa421d1baa3482a30e6408505316b8e Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 14:43:31 -0800
Subject: [PATCH 03/15] Add NumCast to FloatCore, matching Float

---
 src/float.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index c2e28d42..7952357d 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -6,14 +6,12 @@ use core::num::FpCategory;
 #[cfg(feature = "std")]
 use std::f32;
 
-use {Num, ToPrimitive};
-#[cfg(feature = "std")]
-use NumCast;
+use {Num, NumCast, ToPrimitive};
 
 /// Generic trait for floating point numbers that works with `no_std`.
 ///
 /// This trait implements a subset of the `Float` trait.
-pub trait FloatCore: Num + Neg<Output = Self> + PartialOrd + Copy {
+pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns positive infinity.
     fn infinity() -> Self;
 

From 99c6cc11ba1ba6b7dfc49c7f0866f8b482dc34be Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 16:31:36 -0800
Subject: [PATCH 04/15] Add more constants to FloatCore

---
 src/float.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/src/float.rs b/src/float.rs
index 7952357d..7522d58a 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -21,6 +21,21 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns NaN.
     fn nan() -> Self;
 
+    /// Returns `-0.0`.
+    fn neg_zero() -> Self;
+
+    /// Returns the smallest finite value that this type can represent.
+    fn min_value() -> Self;
+
+    /// Returns the smallest positive, normalized value that this type can represent.
+    fn min_positive_value() -> Self;
+
+    /// Returns epsilon, a small positive value.
+    fn epsilon() -> Self;
+
+    /// Returns the largest finite value that this type can represent.
+    fn max_value() -> Self;
+
     /// Returns `true` if the number is NaN.
     #[inline]
     fn is_nan(self) -> bool {
@@ -163,6 +178,31 @@ impl FloatCore for f32 {
         ::core::f32::NAN
     }
 
+    #[inline]
+    fn neg_zero() -> Self {
+        -0.0
+    }
+
+    #[inline]
+    fn min_value() -> Self {
+        ::core::f32::MIN
+    }
+
+    #[inline]
+    fn min_positive_value() -> Self {
+        ::core::f32::MIN_POSITIVE
+    }
+
+    #[inline]
+    fn epsilon() -> Self {
+        ::core::f32::EPSILON
+    }
+
+    #[inline]
+    fn max_value() -> Self {
+        ::core::f32::MAX
+    }
+
     #[inline]
     #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {
@@ -227,6 +267,31 @@ impl FloatCore for f64 {
         ::core::f64::NAN
     }
 
+    #[inline]
+    fn neg_zero() -> Self {
+        -0.0
+    }
+
+    #[inline]
+    fn min_value() -> Self {
+        ::core::f64::MIN
+    }
+
+    #[inline]
+    fn min_positive_value() -> Self {
+        ::core::f64::MIN_POSITIVE
+    }
+
+    #[inline]
+    fn epsilon() -> Self {
+        ::core::f64::EPSILON
+    }
+
+    #[inline]
+    fn max_value() -> Self {
+        ::core::f64::MAX
+    }
+
     #[inline]
     #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {

From f365a4205f84ff6d33fd95bd71d8b30bc38caaf7 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 16:32:31 -0800
Subject: [PATCH 05/15] Add rounding methods to FloatCore

---
 src/float.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/src/float.rs b/src/float.rs
index 7522d58a..a75d55cd 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -65,6 +65,76 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// predicate instead.
     fn classify(self) -> FpCategory;
 
+    /// Returns the largest integer less than or equal to a number.
+    #[inline]
+    fn floor(self) -> Self {
+        let f = self.fract();
+        if f.is_nan() || f.is_zero() {
+            self
+        } else if self < Self::zero() {
+            self - f - Self::one()
+        } else {
+            self - f
+        }
+    }
+
+    /// Returns the smallest integer greater than or equal to a number.
+    #[inline]
+    fn ceil(self) -> Self {
+        let f = self.fract();
+        if f.is_nan() || f.is_zero() {
+            self
+        } else if self > Self::zero() {
+            self - f + Self::one()
+        } else {
+            self - f
+        }
+    }
+
+    /// Returns the nearest integer to a number. Round half-way cases away from `0.0`.
+    #[inline]
+    fn round(self) -> Self {
+        let one = Self::one();
+        let h = Self::from(0.5).expect("Unable to cast from 0.5");
+        let f = self.fract();
+        if f.is_nan() || f.is_zero() {
+            self
+        } else if self > Self::zero() {
+            if f < h {
+                self - f
+            } else {
+                self - f + one
+            }
+        } else {
+            if -f < h {
+                self - f
+            } else {
+                self - f - one
+            }
+        }
+    }
+
+    /// Return the integer part of a number.
+    #[inline]
+    fn trunc(self) -> Self {
+        let f = self.fract();
+        if f.is_nan() {
+            self
+        } else {
+            self - f
+        }
+    }
+
+    /// Returns the fractional part of a number.
+    #[inline]
+    fn fract(self) -> Self {
+        if self.is_zero() {
+            Self::zero()
+        } else {
+            self % Self::one()
+        }
+    }
+
     /// Computes the absolute value of `self`. Returns `FloatCore::nan()` if the
     /// number is `FloatCore::nan()`.
     #[inline]
@@ -238,6 +308,11 @@ impl FloatCore for f32 {
         Self::is_finite(self) -> bool;
         Self::is_normal(self) -> bool;
         Self::classify(self) -> FpCategory;
+        Self::floor(self) -> Self;
+        Self::ceil(self) -> Self;
+        Self::round(self) -> Self;
+        Self::trunc(self) -> Self;
+        Self::fract(self) -> Self;
         Self::abs(self) -> Self;
         Self::signum(self) -> Self;
         Self::is_sign_positive(self) -> bool;
@@ -327,6 +402,11 @@ impl FloatCore for f64 {
         Self::is_finite(self) -> bool;
         Self::is_normal(self) -> bool;
         Self::classify(self) -> FpCategory;
+        Self::floor(self) -> Self;
+        Self::ceil(self) -> Self;
+        Self::round(self) -> Self;
+        Self::trunc(self) -> Self;
+        Self::fract(self) -> Self;
         Self::abs(self) -> Self;
         Self::signum(self) -> Self;
         Self::is_sign_positive(self) -> bool;

From 83d498d0be8fdb9c82afc8aad7a211965de06a15 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 16:32:48 -0800
Subject: [PATCH 06/15] Add integer_decode to FloatCore

---
 src/float.rs | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index a75d55cd..0caf5617 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -230,6 +230,11 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
 
     /// Converts to radians, assuming the number is in degrees.
     fn to_radians(self) -> Self;
+
+    /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
+    /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
+    /// The floating point encoding is documented in the [Reference][floating-point].
+    fn integer_decode(self) -> (u64, i16, i8);
 }
 
 impl FloatCore for f32 {
@@ -273,6 +278,11 @@ impl FloatCore for f32 {
         ::core::f32::MAX
     }
 
+    #[inline]
+    fn integer_decode(self) -> (u64, i16, i8) {
+        integer_decode_f32(self)
+    }
+
     #[inline]
     #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {
@@ -367,6 +377,11 @@ impl FloatCore for f64 {
         ::core::f64::MAX
     }
 
+    #[inline]
+    fn integer_decode(self) -> (u64, i16, i8) {
+        integer_decode_f64(self)
+    }
+
     #[inline]
     #[cfg(not(feature = "std"))]
     fn classify(self) -> FpCategory {
@@ -1448,7 +1463,6 @@ macro_rules! float_impl {
     )
 }
 
-#[cfg(feature = "std")]
 fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
     let bits: u32 = unsafe { mem::transmute(f) };
     let sign: i8 = if bits >> 31 == 0 {
@@ -1467,7 +1481,6 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
     (mantissa as u64, exponent, sign)
 }
 
-#[cfg(feature = "std")]
 fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
     let bits: u64 = unsafe { mem::transmute(f) };
     let sign: i8 = if bits >> 63 == 0 {

From 6fa29be7c0ccb3d6f12b96fc79358bde01a74f46 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 16:51:30 -0800
Subject: [PATCH 07/15] Use macros for more float constants

---
 src/float.rs  | 163 +++++++++++---------------------------------------
 src/macros.rs |  10 ++++
 2 files changed, 46 insertions(+), 127 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index 0caf5617..ae8df033 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -2,9 +2,8 @@ use core::mem;
 use core::ops::Neg;
 use core::num::FpCategory;
 
-// Used for default implementation of `epsilon`
-#[cfg(feature = "std")]
-use std::f32;
+use core::f32;
+use core::f64;
 
 use {Num, NumCast, ToPrimitive};
 
@@ -238,44 +237,15 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
 }
 
 impl FloatCore for f32 {
-    #[inline]
-    fn infinity() -> Self {
-        ::core::f32::INFINITY
-    }
-
-    #[inline]
-    fn neg_infinity() -> Self {
-        ::core::f32::NEG_INFINITY
-    }
-
-    #[inline]
-    fn nan() -> Self {
-        ::core::f32::NAN
-    }
-
-    #[inline]
-    fn neg_zero() -> Self {
-        -0.0
-    }
-
-    #[inline]
-    fn min_value() -> Self {
-        ::core::f32::MIN
-    }
-
-    #[inline]
-    fn min_positive_value() -> Self {
-        ::core::f32::MIN_POSITIVE
-    }
-
-    #[inline]
-    fn epsilon() -> Self {
-        ::core::f32::EPSILON
-    }
-
-    #[inline]
-    fn max_value() -> Self {
-        ::core::f32::MAX
+    constant! {
+        infinity() -> f32::INFINITY;
+        neg_infinity() -> f32::NEG_INFINITY;
+        nan() -> f32::NAN;
+        neg_zero() -> -0.0;
+        min_value() -> f32::MIN;
+        min_positive_value() -> f32::MIN_POSITIVE;
+        epsilon() -> f32::EPSILON;
+        max_value() -> f32::MAX;
     }
 
     #[inline]
@@ -302,13 +272,13 @@ impl FloatCore for f32 {
     #[inline]
     #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
-        self * (180.0 / ::core::f32::consts::PI)
+        self * (180.0 / f32::consts::PI)
     }
 
     #[inline]
     #[cfg(not(feature = "std"))]
     fn to_radians(self) -> Self {
-        self * (::core::f32::consts::PI / 180.0)
+        self * (f32::consts::PI / 180.0)
     }
 
     #[cfg(feature = "std")]
@@ -337,44 +307,15 @@ impl FloatCore for f32 {
 }
 
 impl FloatCore for f64 {
-    #[inline]
-    fn infinity() -> Self {
-        ::core::f64::INFINITY
-    }
-
-    #[inline]
-    fn neg_infinity() -> Self {
-        ::core::f64::NEG_INFINITY
-    }
-
-    #[inline]
-    fn nan() -> Self {
-        ::core::f64::NAN
-    }
-
-    #[inline]
-    fn neg_zero() -> Self {
-        -0.0
-    }
-
-    #[inline]
-    fn min_value() -> Self {
-        ::core::f64::MIN
-    }
-
-    #[inline]
-    fn min_positive_value() -> Self {
-        ::core::f64::MIN_POSITIVE
-    }
-
-    #[inline]
-    fn epsilon() -> Self {
-        ::core::f64::EPSILON
-    }
-
-    #[inline]
-    fn max_value() -> Self {
-        ::core::f64::MAX
+    constant! {
+        infinity() -> f64::INFINITY;
+        neg_infinity() -> f64::NEG_INFINITY;
+        nan() -> f64::NAN;
+        neg_zero() -> -0.0;
+        min_value() -> f64::MIN;
+        min_positive_value() -> f64::MIN_POSITIVE;
+        epsilon() -> f64::EPSILON;
+        max_value() -> f64::MAX;
     }
 
     #[inline]
@@ -401,13 +342,13 @@ impl FloatCore for f64 {
     #[inline]
     #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
-        self * (180.0 / ::core::f64::consts::PI)
+        self * (180.0 / f64::consts::PI)
     }
 
     #[inline]
     #[cfg(not(feature = "std"))]
     fn to_radians(self) -> Self {
-        self * (::core::f64::consts::PI / 180.0)
+        self * (f64::consts::PI / 180.0)
     }
 
     #[cfg(feature = "std")]
@@ -1359,44 +1300,15 @@ pub trait Float
 macro_rules! float_impl {
     ($T:ident $decode:ident) => (
         impl Float for $T {
-            #[inline]
-            fn nan() -> Self {
-                ::std::$T::NAN
-            }
-
-            #[inline]
-            fn infinity() -> Self {
-                ::std::$T::INFINITY
-            }
-
-            #[inline]
-            fn neg_infinity() -> Self {
-                ::std::$T::NEG_INFINITY
-            }
-
-            #[inline]
-            fn neg_zero() -> Self {
-                -0.0
-            }
-
-            #[inline]
-            fn min_value() -> Self {
-                ::std::$T::MIN
-            }
-
-            #[inline]
-            fn min_positive_value() -> Self {
-                ::std::$T::MIN_POSITIVE
-            }
-
-            #[inline]
-            fn epsilon() -> Self {
-                ::std::$T::EPSILON
-            }
-
-            #[inline]
-            fn max_value() -> Self {
-                ::std::$T::MAX
+            constant! {
+                nan() -> $T::NAN;
+                infinity() -> $T::INFINITY;
+                neg_infinity() -> $T::NEG_INFINITY;
+                neg_zero() -> -0.0;
+                min_value() -> $T::MIN;
+                min_positive_value() -> $T::MIN_POSITIVE;
+                epsilon() -> $T::EPSILON;
+                max_value() -> $T::MAX;
             }
 
             #[inline]
@@ -1515,12 +1427,9 @@ macro_rules! float_const_impl {
     );
     (@float $T:ident, $($constant:ident,)+) => (
         impl FloatConst for $T {
-            $(
-                #[inline]
-                fn $constant() -> Self {
-                    ::core::$T::consts::$constant
-                }
-            )+
+            constant! {
+                $( $constant() -> $T::consts::$constant; )+
+            }
         }
     );
 }
diff --git a/src/macros.rs b/src/macros.rs
index 8c7a6f85..a5f816e5 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -23,3 +23,13 @@ macro_rules! forward {
             }
         )*}
 }
+
+macro_rules! constant {
+    ($( $method:ident () -> $ret:expr ; )*)
+        => {$(
+            #[inline]
+            fn $method() -> Self {
+                $ret
+            }
+        )*};
+}

From 8d16921579a4e09cfb42c41e23cfa965dd00823d Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 17:08:35 -0800
Subject: [PATCH 08/15] allow unused macros

---
 src/macros.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/macros.rs b/src/macros.rs
index a5f816e5..4330cdfd 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -1,3 +1,5 @@
+// not all are used in all features configurations
+#![allow(unused)]
 
 /// Forward a method to an inherent method or a base trait method.
 macro_rules! forward {

From 964a7e52a8437a7613194f10eabe7a6c246501b3 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 21:03:30 -0800
Subject: [PATCH 09/15] Reinstate NAN-sign fixes in FloatCore

Formerly changed on the next branch, part of rust-num/num#319.
---
 src/float.rs | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index ae8df033..6d1fcdc5 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -154,27 +154,28 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// - `FloatCore::nan()` if the number is `FloatCore::nan()`
     #[inline]
     fn signum(self) -> Self {
-        if self.is_sign_positive() {
-            return Self::one();
-        }
-        if self.is_sign_negative() {
-            return -Self::one();
+        if self.is_nan() {
+            Self::nan()
+        } else if self.is_sign_negative() {
+            -Self::one()
+        } else {
+            Self::one()
         }
-        Self::nan()
     }
 
     /// Returns `true` if `self` is positive, including `+0.0` and
     /// `FloatCore::infinity()`.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > Self::zero() || (Self::one() / self) == Self::infinity()
+        !self.is_sign_negative()
     }
 
     /// Returns `true` if `self` is negative, including `-0.0` and
     /// `FloatCore::neg_infinity()`.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < Self::zero() || (Self::one() / self) == Self::neg_infinity()
+        let (_, _, sign) = self.integer_decode();
+        sign < 0
     }
 
     /// Returns the minimum of the two numbers.

From 36c7e324dbdc46e5dd7e42c3b816cd68064cd092 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 21:34:01 -0800
Subject: [PATCH 10/15] Fix FloatCore::powi with i32::MIN exponent

---
 src/float.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index 6d1fcdc5..fdc5f7d7 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -5,7 +5,7 @@ use core::num::FpCategory;
 use core::f32;
 use core::f64;
 
-use {Num, NumCast, ToPrimitive};
+use {Num, NumCast};
 
 /// Generic trait for floating point numbers that works with `no_std`.
 ///
@@ -218,11 +218,11 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     #[inline]
     fn powi(mut self, mut exp: i32) -> Self {
         if exp < 0 {
-            exp = -exp;
+            exp = exp.wrapping_neg();
             self = self.recip();
         }
         // It should always be possible to convert a positive `i32` to a `usize`.
-        super::pow(self, exp.to_usize().unwrap())
+        super::pow(self, exp as u32 as usize)
     }
 
     /// Converts to degrees, assuming the number is in radians.

From ac6eca4b66e4d8dce69c6e2d8c76b7c87c682ab6 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 21:50:44 -0800
Subject: [PATCH 11/15] Use more FloatCore in src/sign.rs

---
 src/sign.rs | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/src/sign.rs b/src/sign.rs
index 437c8bfd..932496a7 100644
--- a/src/sign.rs
+++ b/src/sign.rs
@@ -1,9 +1,7 @@
 use core::ops::Neg;
-use core::{f32, f64};
 use core::num::Wrapping;
 
 use Num;
-#[cfg(not(feature = "std"))]
 use float::FloatCore;
 
 /// Useful functions for signed numbers (i.e. numbers that can be negative).
@@ -101,12 +99,12 @@ impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapp
 }
 
 macro_rules! signed_float_impl {
-    ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
+    ($t:ty) => {
         impl Signed for $t {
             /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
             #[inline]
             fn abs(&self) -> $t {
-                (*self).abs()
+                FloatCore::abs(*self)
             }
 
             /// The positive difference of two numbers. Returns `0.0` if the number is
@@ -124,23 +122,22 @@ macro_rules! signed_float_impl {
             /// - `NAN` if the number is NaN
             #[inline]
             fn signum(&self) -> $t {
-                use float::FloatCore;
                 FloatCore::signum(*self)
             }
 
             /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
             #[inline]
-            fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }
+            fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }
 
             /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
             #[inline]
-            fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
+            fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
         }
     }
 }
 
-signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
-signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);
+signed_float_impl!(f32);
+signed_float_impl!(f64);
 
 /// Computes the absolute value.
 ///

From ec3cd50f3d6feefb8df23906cd55e7eb909885a0 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 22:10:46 -0800
Subject: [PATCH 12/15] Weaken the std f32::to_degrees/to_radians tests

---
 src/float.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index fdc5f7d7..d35b0710 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -1493,8 +1493,8 @@ mod tests {
             assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
 
             let (deg, rad) = (deg as f32, rad as f32);
-            assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
-            assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
+            assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-5);
+            assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-5);
         }
     }
 
@@ -1508,8 +1508,8 @@ mod tests {
             assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
 
             let (deg, rad) = (deg as f32, rad as f32);
-            assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
-            assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
+            assert!((Float::to_degrees(rad) - deg).abs() < 1e-5);
+            assert!((Float::to_radians(deg) - rad).abs() < 1e-5);
         }
     }
 }

From aa9ceba628f495d1b7de190fa564de43d90c8d84 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 27 Feb 2018 22:12:37 -0800
Subject: [PATCH 13/15] Add doctests to FloatCore

---
 src/float.rs | 504 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 499 insertions(+), 5 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index d35b0710..eeeb48b2 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -12,48 +12,230 @@ use {Num, NumCast};
 /// This trait implements a subset of the `Float` trait.
 pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns positive infinity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::infinity() == x);
+    /// }
+    ///
+    /// check(f32::INFINITY);
+    /// check(f64::INFINITY);
+    /// ```
     fn infinity() -> Self;
 
     /// Returns negative infinity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::neg_infinity() == x);
+    /// }
+    ///
+    /// check(f32::NEG_INFINITY);
+    /// check(f64::NEG_INFINITY);
+    /// ```
     fn neg_infinity() -> Self;
 
     /// Returns NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    ///
+    /// fn check<T: FloatCore>() {
+    ///     let n = T::nan();
+    ///     assert!(n != n);
+    /// }
+    ///
+    /// check::<f32>();
+    /// check::<f64>();
+    /// ```
     fn nan() -> Self;
 
     /// Returns `-0.0`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(n: T) {
+    ///     let z = T::neg_zero();
+    ///     assert!(z.is_zero());
+    ///     assert!(T::one() / z == n);
+    /// }
+    ///
+    /// check(f32::NEG_INFINITY);
+    /// check(f64::NEG_INFINITY);
+    /// ```
     fn neg_zero() -> Self;
 
     /// Returns the smallest finite value that this type can represent.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::min_value() == x);
+    /// }
+    ///
+    /// check(f32::MIN);
+    /// check(f64::MIN);
+    /// ```
     fn min_value() -> Self;
 
     /// Returns the smallest positive, normalized value that this type can represent.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::min_positive_value() == x);
+    /// }
+    ///
+    /// check(f32::MIN_POSITIVE);
+    /// check(f64::MIN_POSITIVE);
+    /// ```
     fn min_positive_value() -> Self;
 
     /// Returns epsilon, a small positive value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::epsilon() == x);
+    /// }
+    ///
+    /// check(f32::EPSILON);
+    /// check(f64::EPSILON);
+    /// ```
     fn epsilon() -> Self;
 
     /// Returns the largest finite value that this type can represent.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T) {
+    ///     assert!(T::max_value() == x);
+    /// }
+    ///
+    /// check(f32::MAX);
+    /// check(f64::MAX);
+    /// ```
     fn max_value() -> Self;
 
     /// Returns `true` if the number is NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_nan() == p);
+    /// }
+    ///
+    /// check(f32::NAN, true);
+    /// check(f32::INFINITY, false);
+    /// check(f64::NAN, true);
+    /// check(0.0f64, false);
+    /// ```
     #[inline]
     fn is_nan(self) -> bool {
         self != self
     }
 
     /// Returns `true` if the number is infinite.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_infinite() == p);
+    /// }
+    ///
+    /// check(f32::INFINITY, true);
+    /// check(f32::NEG_INFINITY, true);
+    /// check(f32::NAN, false);
+    /// check(f64::INFINITY, true);
+    /// check(f64::NEG_INFINITY, true);
+    /// check(0.0f64, false);
+    /// ```
     #[inline]
     fn is_infinite(self) -> bool {
         self == Self::infinity() || self == Self::neg_infinity()
     }
 
     /// Returns `true` if the number is neither infinite or NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_finite() == p);
+    /// }
+    ///
+    /// check(f32::INFINITY, false);
+    /// check(f32::MAX, true);
+    /// check(f64::NEG_INFINITY, false);
+    /// check(f64::MIN_POSITIVE, true);
+    /// check(f64::NAN, false);
+    /// ```
     #[inline]
     fn is_finite(self) -> bool {
         !(self.is_nan() || self.is_infinite())
     }
 
     /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_normal() == p);
+    /// }
+    ///
+    /// check(f32::INFINITY, false);
+    /// check(f32::MAX, true);
+    /// check(f64::NEG_INFINITY, false);
+    /// check(f64::MIN_POSITIVE, true);
+    /// check(0.0f64, false);
+    /// ```
     #[inline]
     fn is_normal(self) -> bool {
         self.classify() == FpCategory::Normal
@@ -62,9 +244,49 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns the floating point category of the number. If only one property
     /// is going to be tested, it is generally faster to use the specific
     /// predicate instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    /// use std::num::FpCategory;
+    ///
+    /// fn check<T: FloatCore>(x: T, c: FpCategory) {
+    ///     assert!(x.classify() == c);
+    /// }
+    ///
+    /// check(f32::INFINITY, FpCategory::Infinite);
+    /// check(f32::MAX, FpCategory::Normal);
+    /// check(f64::NAN, FpCategory::Nan);
+    /// check(f64::MIN_POSITIVE, FpCategory::Normal);
+    /// check(f64::MIN_POSITIVE / 2.0, FpCategory::Subnormal);
+    /// check(0.0f64, FpCategory::Zero);
+    /// ```
     fn classify(self) -> FpCategory;
 
     /// Returns the largest integer less than or equal to a number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.floor() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, f32::INFINITY);
+    /// check(0.9f32, 0.0);
+    /// check(1.0f32, 1.0);
+    /// check(1.1f32, 1.0);
+    /// check(-0.0f64, 0.0);
+    /// check(-0.9f64, -1.0);
+    /// check(-1.0f64, -1.0);
+    /// check(-1.1f64, -2.0);
+    /// check(f64::MIN, f64::MIN);
+    /// ```
     #[inline]
     fn floor(self) -> Self {
         let f = self.fract();
@@ -78,6 +300,27 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns the smallest integer greater than or equal to a number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.ceil() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, f32::INFINITY);
+    /// check(0.9f32, 1.0);
+    /// check(1.0f32, 1.0);
+    /// check(1.1f32, 2.0);
+    /// check(-0.0f64, 0.0);
+    /// check(-0.9f64, -0.0);
+    /// check(-1.0f64, -1.0);
+    /// check(-1.1f64, -1.0);
+    /// check(f64::MIN, f64::MIN);
+    /// ```
     #[inline]
     fn ceil(self) -> Self {
         let f = self.fract();
@@ -91,6 +334,26 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns the nearest integer to a number. Round half-way cases away from `0.0`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.round() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, f32::INFINITY);
+    /// check(0.4f32, 0.0);
+    /// check(0.5f32, 1.0);
+    /// check(0.6f32, 1.0);
+    /// check(-0.4f64, 0.0);
+    /// check(-0.5f64, -1.0);
+    /// check(-0.6f64, -1.0);
+    /// check(f64::MIN, f64::MIN);
+    /// ```
     #[inline]
     fn round(self) -> Self {
         let one = Self::one();
@@ -114,6 +377,27 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Return the integer part of a number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.trunc() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, f32::INFINITY);
+    /// check(0.9f32, 0.0);
+    /// check(1.0f32, 1.0);
+    /// check(1.1f32, 1.0);
+    /// check(-0.0f64, 0.0);
+    /// check(-0.9f64, -0.0);
+    /// check(-1.0f64, -1.0);
+    /// check(-1.1f64, -1.0);
+    /// check(f64::MIN, f64::MIN);
+    /// ```
     #[inline]
     fn trunc(self) -> Self {
         let f = self.fract();
@@ -125,6 +409,27 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns the fractional part of a number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.fract() == y);
+    /// }
+    ///
+    /// check(f32::MAX, 0.0);
+    /// check(0.75f32, 0.75);
+    /// check(1.0f32, 0.0);
+    /// check(1.25f32, 0.25);
+    /// check(-0.0f64, 0.0);
+    /// check(-0.75f64, -0.75);
+    /// check(-1.0f64, 0.0);
+    /// check(-1.25f64, -0.25);
+    /// check(f64::MIN, 0.0);
+    /// ```
     #[inline]
     fn fract(self) -> Self {
         if self.is_zero() {
@@ -136,6 +441,24 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
 
     /// Computes the absolute value of `self`. Returns `FloatCore::nan()` if the
     /// number is `FloatCore::nan()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.abs() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, f32::INFINITY);
+    /// check(1.0f32, 1.0);
+    /// check(0.0f64, 0.0);
+    /// check(-0.0f64, 0.0);
+    /// check(-1.0f64, 1.0);
+    /// check(f64::MIN, f64::MAX);
+    /// ```
     #[inline]
     fn abs(self) -> Self {
         if self.is_sign_positive() {
@@ -152,6 +475,24 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// - `1.0` if the number is positive, `+0.0` or `FloatCore::infinity()`
     /// - `-1.0` if the number is negative, `-0.0` or `FloatCore::neg_infinity()`
     /// - `FloatCore::nan()` if the number is `FloatCore::nan()`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.signum() == y);
+    /// }
+    ///
+    /// check(f32::INFINITY, 1.0);
+    /// check(3.0f32, 1.0);
+    /// check(0.0f32, 1.0);
+    /// check(-0.0f64, -1.0);
+    /// check(-3.0f64, -1.0);
+    /// check(f64::MIN, -1.0);
+    /// ```
     #[inline]
     fn signum(self) -> Self {
         if self.is_nan() {
@@ -164,14 +505,54 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `FloatCore::infinity()`.
+    /// `FloatCore::infinity()`, and with newer versions of Rust
+    /// even `FloatCore::nan()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_sign_positive() == p);
+    /// }
+    ///
+    /// check(f32::INFINITY, true);
+    /// check(f32::MAX, true);
+    /// check(0.0f32, true);
+    /// check(-0.0f64, false);
+    /// check(f64::NEG_INFINITY, false);
+    /// check(f64::MIN_POSITIVE, true);
+    /// check(-f64::NAN, false);
+    /// ```
     #[inline]
     fn is_sign_positive(self) -> bool {
         !self.is_sign_negative()
     }
 
     /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `FloatCore::neg_infinity()`.
+    /// `FloatCore::neg_infinity()`, and with newer versions of Rust
+    /// even `-FloatCore::nan()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, p: bool) {
+    ///     assert!(x.is_sign_negative() == p);
+    /// }
+    ///
+    /// check(f32::INFINITY, false);
+    /// check(f32::MAX, false);
+    /// check(0.0f32, false);
+    /// check(-0.0f64, true);
+    /// check(f64::NEG_INFINITY, true);
+    /// check(f64::MIN_POSITIVE, false);
+    /// check(f64::NAN, false);
+    /// ```
     #[inline]
     fn is_sign_negative(self) -> bool {
         let (_, _, sign) = self.integer_decode();
@@ -181,6 +562,22 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns the minimum of the two numbers.
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T, min: T) {
+    ///     assert!(x.min(y) == min);
+    /// }
+    ///
+    /// check(1.0f32, 2.0, 1.0);
+    /// check(f32::NAN, 2.0, 2.0);
+    /// check(1.0f64, -2.0, -2.0);
+    /// check(1.0f64, f64::NAN, 1.0);
+    /// ```
     #[inline]
     fn min(self, other: Self) -> Self {
         if self.is_nan() {
@@ -195,6 +592,22 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Returns the maximum of the two numbers.
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T, min: T) {
+    ///     assert!(x.max(y) == min);
+    /// }
+    ///
+    /// check(1.0f32, 2.0, 2.0);
+    /// check(1.0f32, f32::NAN, 1.0);
+    /// check(-1.0f64, 2.0, 2.0);
+    /// check(-1.0f64, f64::NAN, -1.0);
+    /// ```
     #[inline]
     fn max(self, other: Self) -> Self {
         if self.is_nan() {
@@ -207,6 +620,23 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, y: T) {
+    ///     assert!(x.recip() == y);
+    ///     assert!(y.recip() == x);
+    /// }
+    ///
+    /// check(f32::INFINITY, 0.0);
+    /// check(2.0f32, 0.5);
+    /// check(-0.25f64, -4.0);
+    /// check(-0.0f64, f64::NEG_INFINITY);
+    /// ```
     #[inline]
     fn recip(self) -> Self {
         Self::one() / self
@@ -215,6 +645,22 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// Raise a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    ///
+    /// fn check<T: FloatCore>(x: T, exp: i32, powi: T) {
+    ///     assert!(x.powi(exp) == powi);
+    /// }
+    ///
+    /// check(9.0f32, 2, 81.0);
+    /// check(1.0f32, -2, 1.0);
+    /// check(10.0f64, 20, 1e20);
+    /// check(4.0f64, -2, 0.0625);
+    /// check(-1.0f64, std::i32::MIN, 1.0);
+    /// ```
     #[inline]
     fn powi(mut self, mut exp: i32) -> Self {
         if exp < 0 {
@@ -226,14 +672,64 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Converts to degrees, assuming the number is in radians.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(rad: T, deg: T) {
+    ///     assert!(rad.to_degrees() == deg);
+    /// }
+    ///
+    /// check(0.0f32, 0.0);
+    /// check(f32::consts::PI, 180.0);
+    /// check(f64::consts::FRAC_PI_4, 45.0);
+    /// check(f64::INFINITY, f64::INFINITY);
+    /// ```
     fn to_degrees(self) -> Self;
 
     /// Converts to radians, assuming the number is in degrees.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(deg: T, rad: T) {
+    ///     assert!(deg.to_radians() == rad);
+    /// }
+    ///
+    /// check(0.0f32, 0.0);
+    /// check(180.0, f32::consts::PI);
+    /// check(45.0, f64::consts::FRAC_PI_4);
+    /// check(f64::INFINITY, f64::INFINITY);
+    /// ```
     fn to_radians(self) -> Self;
 
     /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
     /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
-    /// The floating point encoding is documented in the [Reference][floating-point].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::float::FloatCore;
+    /// use std::{f32, f64};
+    ///
+    /// fn check<T: FloatCore>(x: T, m: u64, e: i16, s:i8) {
+    ///     let (mantissa, exponent, sign) = x.integer_decode();
+    ///     assert_eq!(mantissa, m);
+    ///     assert_eq!(exponent, e);
+    ///     assert_eq!(sign, s);
+    /// }
+    ///
+    /// check(2.0f32, 1 << 23, -22, 1);
+    /// check(-2.0f32, 1 << 23, -22, -1);
+    /// check(f32::INFINITY, 1 << 23, 105, 1);
+    /// check(f64::NEG_INFINITY, 1 << 52, 972, -1);
+    /// ```
     fn integer_decode(self) -> (u64, i16, i8);
 }
 
@@ -1275,7 +1771,6 @@ pub trait Float
 
     /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
     /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
-    /// The floating point encoding is documented in the [Reference][floating-point].
     ///
     /// ```
     /// use num_traits::Float;
@@ -1293,7 +1788,6 @@ pub trait Float
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
-    /// [floating-point]: ../../../../../reference.html#machine-types
     fn integer_decode(self) -> (u64, i16, i8);
 }
 

From 080f6f259ef9e4d935640f3d7b461326a31f3e1c Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Wed, 28 Feb 2018 11:33:34 -0800
Subject: [PATCH 14/15] Comment the i32::MIN case for FloatCore::powi

---
 src/float.rs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index eeeb48b2..8f5c7f04 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -5,7 +5,7 @@ use core::num::FpCategory;
 use core::f32;
 use core::f64;
 
-use {Num, NumCast};
+use {Num, NumCast, ToPrimitive};
 
 /// Generic trait for floating point numbers that works with `no_std`.
 ///
@@ -668,7 +668,9 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
             self = self.recip();
         }
         // It should always be possible to convert a positive `i32` to a `usize`.
-        super::pow(self, exp as u32 as usize)
+        // Note, `i32::MIN` will wrap and still be negative, so we need to convert
+        // to `u32` without sign-extension before growing to `usize`.
+        super::pow(self, (exp as u32).to_usize().unwrap())
     }
 
     /// Converts to degrees, assuming the number is in radians.

From 04a3f2a5914bbda644aec7f724a49d4a670d0df0 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Wed, 28 Feb 2018 11:43:55 -0800
Subject: [PATCH 15/15] Comment the Rust version for NAN.is_sign_* behavior

---
 src/float.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/float.rs b/src/float.rs
index 8f5c7f04..072a91b2 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -505,8 +505,8 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `FloatCore::infinity()`, and with newer versions of Rust
-    /// even `FloatCore::nan()`.
+    /// `FloatCore::infinity()`, and since Rust 1.20 also
+    /// `FloatCore::nan()`.
     ///
     /// # Examples
     ///
@@ -532,8 +532,8 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     }
 
     /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `FloatCore::neg_infinity()`, and with newer versions of Rust
-    /// even `-FloatCore::nan()`.
+    /// `FloatCore::neg_infinity()`, and since Rust 1.20 also
+    /// `-FloatCore::nan()`.
     ///
     /// # Examples
     ///
@@ -1196,7 +1196,7 @@ pub trait Float
     fn signum(self) -> Self;
 
     /// Returns `true` if `self` is positive, including `+0.0`,
-    /// `Float::infinity()`, and with newer versions of Rust `f64::NAN`.
+    /// `Float::infinity()`, and since Rust 1.20 also `Float::nan()`.
     ///
     /// ```
     /// use num_traits::Float;
@@ -1214,7 +1214,7 @@ pub trait Float
     fn is_sign_positive(self) -> bool;
 
     /// Returns `true` if `self` is negative, including `-0.0`,
-    /// `Float::neg_infinity()`, and with newer versions of Rust `-f64::NAN`.
+    /// `Float::neg_infinity()`, and since Rust 1.20 also `-Float::nan()`.
     ///
     /// ```
     /// use num_traits::Float;