Upgrade num-traits to 0.2.15

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update rust/crates/num-traits
For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md

Test: TreeHugger
Change-Id: Ib712393e1371ed920552a4194b6aae0c0acd22d3
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 4988b82..1ec548f 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "e8da6fe581f0e14a6322c5d51f57bec641772dac"
-  }
-}
+    "sha1": "1597c1c4d1b3e33548e4661c519b7246a5fc1c28"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 2f7d557..83aa668 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@
     host_supported: true,
     crate_name: "num_traits",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.2.14",
+    cargo_pkg_version: "0.2.15",
     srcs: ["src/lib.rs"],
     edition: "2015",
     features: [
@@ -50,7 +50,12 @@
         "std",
     ],
     cfgs: [
+        "has_copysign",
+        "has_div_euclid",
         "has_i128",
+        "has_int_assignop_ref",
+        "has_leading_trailing_ones",
+        "has_reverse_bits",
         "has_to_int_unchecked",
     ],
     apex_available: [
@@ -69,7 +74,7 @@
     host_supported: true,
     crate_name: "num_traits",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.2.14",
+    cargo_pkg_version: "0.2.15",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -82,7 +87,12 @@
         "std",
     ],
     cfgs: [
+        "has_copysign",
+        "has_div_euclid",
         "has_i128",
+        "has_int_assignop_ref",
+        "has_leading_trailing_ones",
+        "has_reverse_bits",
         "has_to_int_unchecked",
     ],
 }
@@ -92,7 +102,7 @@
     host_supported: true,
     crate_name: "cast",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.2.14",
+    cargo_pkg_version: "0.2.15",
     srcs: ["tests/cast.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -105,7 +115,12 @@
         "std",
     ],
     cfgs: [
+        "has_copysign",
+        "has_div_euclid",
         "has_i128",
+        "has_int_assignop_ref",
+        "has_leading_trailing_ones",
+        "has_reverse_bits",
         "has_to_int_unchecked",
     ],
     rustlibs: [
diff --git a/Cargo.toml b/Cargo.toml
index 685a784..b30fca3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,32 +3,45 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 name = "num-traits"
-version = "0.2.14"
+version = "0.2.15"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
-exclude = ["/bors.toml", "/ci/*", "/.github/*"]
+exclude = [
+    "/bors.toml",
+    "/ci/*",
+    "/.github/*",
+]
 description = "Numeric traits for generic mathematics"
 homepage = "https://github.com/rust-num/num-traits"
 documentation = "https://docs.rs/num-traits"
 readme = "README.md"
-keywords = ["mathematics", "numerics"]
-categories = ["algorithms", "science", "no-std"]
+keywords = [
+    "mathematics",
+    "numerics",
+]
+categories = [
+    "algorithms",
+    "science",
+    "no-std",
+]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-num/num-traits"
+
 [package.metadata.docs.rs]
 features = ["std"]
+
 [dependencies.libm]
 version = "0.2.0"
 optional = true
+
 [build-dependencies.autocfg]
 version = "1"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 8d88bf4..340ac21 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -8,7 +8,7 @@
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-num/num-traits"
 name = "num-traits"
-version = "0.2.14"
+version = "0.2.15"
 readme = "README.md"
 build = "build.rs"
 exclude = ["/bors.toml", "/ci/*", "/.github/*"]
diff --git a/METADATA b/METADATA
index d984688..0740892 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/num-traits
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "num-traits"
 description: "Numeric traits for generic mathematics"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/num-traits/num-traits-0.2.14.crate"
+    value: "https://static.crates.io/crates/num-traits/num-traits-0.2.15.crate"
   }
-  version: "0.2.14"
+  version: "0.2.15"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
-    month: 10
-    day: 29
+    year: 2022
+    month: 12
+    day: 13
   }
 }
diff --git a/README.md b/README.md
index 1ee1e1e..3633962 100644
--- a/README.md
+++ b/README.md
@@ -16,12 +16,6 @@
 num-traits = "0.2"
 ```
 
-and this to your crate root:
-
-```rust
-extern crate num_traits;
-```
-
 ## Features
 
 This crate can be used without the standard library (`#![no_std]`) by disabling
diff --git a/RELEASES.md b/RELEASES.md
index 94449d6..cd33c04 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,31 @@
+# Release 0.2.15 (2022-05-02)
+
+- [The new `Euclid` trait calculates Euclidean division][195], where the
+  remainder is always positive or zero.
+- [The new `LowerBounded` and `UpperBounded` traits][210] separately describe
+  types with lower and upper bounds. These traits are automatically implemented
+  for all fully-`Bounded` types.
+- [The new `Float::copysign` method copies the sign of the argument][207] to
+  to the magnitude of `self`.
+- [The new `PrimInt::leading_ones` and `trailing_ones` methods][205] are the
+  complement of the existing methods that count zero bits.
+- [The new `PrimInt::reverse_bits` method reverses the order of all bits][202]
+  of a primitive integer.
+- [Improved `Num::from_str_radix` for floats][201], also [ignoring case][214].
+- [`Float` and `FloatCore` use more from `libm`][196] when that is enabled.
+
+**Contributors**: @alion02, @clarfonthey, @cuviper, @ElectronicRU,
+@ibraheemdev, @SparrowLii, @sshilovsky, @tspiteri, @XAMPPRocky, @Xiretza
+
+[195]: https://github.com/rust-num/num-traits/pull/195
+[196]: https://github.com/rust-num/num-traits/pull/196
+[201]: https://github.com/rust-num/num-traits/pull/201
+[202]: https://github.com/rust-num/num-traits/pull/202
+[205]: https://github.com/rust-num/num-traits/pull/205
+[207]: https://github.com/rust-num/num-traits/pull/207
+[210]: https://github.com/rust-num/num-traits/pull/210
+[214]: https://github.com/rust-num/num-traits/pull/214
+
 # Release 0.2.14 (2020-10-29)
 
 - Clarify the license specification as "MIT OR Apache-2.0".
diff --git a/build.rs b/build.rs
index 816ddad..c7bf364 100644
--- a/build.rs
+++ b/build.rs
@@ -16,5 +16,14 @@
         "has_to_int_unchecked",
     );
 
+    ac.emit_expression_cfg("1u32.reverse_bits()", "has_reverse_bits");
+    ac.emit_expression_cfg("1u32.trailing_ones()", "has_leading_trailing_ones");
+    ac.emit_expression_cfg("{ let mut x = 1; x += &2; }", "has_int_assignop_ref");
+    ac.emit_expression_cfg("1u32.div_euclid(1u32)", "has_div_euclid");
+
+    if env::var_os("CARGO_FEATURE_STD").is_some() {
+        ac.emit_expression_cfg("1f64.copysign(-1f64)", "has_copysign");
+    }
+
     autocfg::rerun_path("build.rs");
 }
diff --git a/src/bounds.rs b/src/bounds.rs
index c9ff749..36e1bbd 100644
--- a/src/bounds.rs
+++ b/src/bounds.rs
@@ -8,12 +8,38 @@
 /// Numbers which have upper and lower bounds
 pub trait Bounded {
     // FIXME (#5527): These should be associated constants
-    /// returns the smallest finite number this type can represent
+    /// Returns the smallest finite number this type can represent
     fn min_value() -> Self;
-    /// returns the largest finite number this type can represent
+    /// Returns the largest finite number this type can represent
     fn max_value() -> Self;
 }
 
+/// Numbers which have lower bounds
+pub trait LowerBounded {
+    /// Returns the smallest finite number this type can represent
+    fn min_value() -> Self;
+}
+
+// FIXME: With a major version bump, this should be a supertrait instead
+impl<T: Bounded> LowerBounded for T {
+    fn min_value() -> T {
+        Bounded::min_value()
+    }
+}
+
+/// Numbers which have upper bounds
+pub trait UpperBounded {
+    /// Returns the largest finite number this type can represent
+    fn max_value() -> Self;
+}
+
+// FIXME: With a major version bump, this should be a supertrait instead
+impl<T: Bounded> UpperBounded for T {
+    fn max_value() -> T {
+        Bounded::max_value()
+    }
+}
+
 macro_rules! bounded_impl {
     ($t:ty, $min:expr, $max:expr) => {
         impl Bounded for $t {
diff --git a/src/float.rs b/src/float.rs
index 0e7b9db..47bd654 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -783,6 +783,17 @@
 
     #[inline]
     #[cfg(not(feature = "std"))]
+    fn is_sign_negative(self) -> bool {
+        const SIGN_MASK: u32 = 0x80000000;
+
+        // Safety: this identical to the implementation of f32::to_bits(),
+        // which is only available starting at Rust 1.20
+        let bits: u32 = unsafe { mem::transmute(self) };
+        bits & SIGN_MASK != 0
+    }
+
+    #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
         // Use a constant for better precision.
         const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
@@ -818,6 +829,23 @@
         Self::to_degrees(self) -> Self;
         Self::to_radians(self) -> Self;
     }
+
+    #[cfg(all(not(feature = "std"), feature = "libm"))]
+    forward! {
+        libm::floorf as floor(self) -> Self;
+        libm::ceilf as ceil(self) -> Self;
+        libm::roundf as round(self) -> Self;
+        libm::truncf as trunc(self) -> Self;
+        libm::fabsf as abs(self) -> Self;
+        libm::fminf as min(self, other: Self) -> Self;
+        libm::fmaxf as max(self, other: Self) -> Self;
+    }
+
+    #[cfg(all(not(feature = "std"), feature = "libm"))]
+    #[inline]
+    fn fract(self) -> Self {
+        self - libm::truncf(self)
+    }
 }
 
 impl FloatCore for f64 {
@@ -857,6 +885,17 @@
 
     #[inline]
     #[cfg(not(feature = "std"))]
+    fn is_sign_negative(self) -> bool {
+        const SIGN_MASK: u64 = 0x8000000000000000;
+
+        // Safety: this identical to the implementation of f64::to_bits(),
+        // which is only available starting at Rust 1.20
+        let bits: u64 = unsafe { mem::transmute(self) };
+        bits & SIGN_MASK != 0
+    }
+
+    #[inline]
+    #[cfg(not(feature = "std"))]
     fn to_degrees(self) -> Self {
         // The division here is correctly rounded with respect to the true
         // value of 180/π. (This differs from f32, where a constant must be
@@ -893,6 +932,23 @@
         Self::to_degrees(self) -> Self;
         Self::to_radians(self) -> Self;
     }
+
+    #[cfg(all(not(feature = "std"), feature = "libm"))]
+    forward! {
+        libm::floor as floor(self) -> Self;
+        libm::ceil as ceil(self) -> Self;
+        libm::round as round(self) -> Self;
+        libm::trunc as trunc(self) -> Self;
+        libm::fabs as abs(self) -> Self;
+        libm::fmin as min(self, other: Self) -> Self;
+        libm::fmax as max(self, other: Self) -> Self;
+    }
+
+    #[cfg(all(not(feature = "std"), feature = "libm"))]
+    #[inline]
+    fn fract(self) -> Self {
+        self - libm::trunc(self)
+    }
 }
 
 // FIXME: these doctests aren't actually helpful, because they're using and
@@ -1806,6 +1862,35 @@
     /// assert!(abs_difference < 1e-10);
     /// ```
     fn integer_decode(self) -> (u64, i16, i8);
+
+    /// Returns a number composed of the magnitude of `self` and the sign of
+    /// `sign`.
+    ///
+    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
+    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
+    /// `sign` is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::Float;
+    ///
+    /// let f = 3.5_f32;
+    ///
+    /// assert_eq!(f.copysign(0.42), 3.5_f32);
+    /// assert_eq!(f.copysign(-0.42), -3.5_f32);
+    /// assert_eq!((-f).copysign(0.42), 3.5_f32);
+    /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
+    ///
+    /// assert!(f32::nan().copysign(1.0).is_nan());
+    /// ```
+    fn copysign(self, sign: Self) -> Self {
+        if self.is_sign_negative() == sign.is_sign_negative() {
+            self
+        } else {
+            self.neg()
+        }
+    }
 }
 
 #[cfg(feature = "std")]
@@ -1883,6 +1968,12 @@
                 Self::acosh(self) -> Self;
                 Self::atanh(self) -> Self;
             }
+
+            #[cfg(has_copysign)]
+            #[inline]
+            fn copysign(self, sign: Self) -> Self {
+                Self::copysign(self, sign)
+            }
         }
     };
 }
@@ -1908,7 +1999,7 @@
 
         #[inline]
         fn fract(self) -> Self {
-            self - FloatCore::trunc(self)
+            self - Float::trunc(self)
         }
 
         #[inline]
@@ -1929,8 +2020,6 @@
             FloatCore::powi(self, n: i32) -> Self;
             FloatCore::to_degrees(self) -> Self;
             FloatCore::to_radians(self) -> Self;
-            FloatCore::max(self, other: Self) -> Self;
-            FloatCore::min(self, other: Self) -> Self;
         }
     };
 }
@@ -1981,129 +2070,42 @@
     fn abs_sub(self, other: Self) -> Self {
         libm::fdimf(self, other)
     }
-    #[inline]
-    fn floor(self) -> Self {
-        libm::floorf(self)
-    }
-    #[inline]
-    fn ceil(self) -> Self {
-        libm::ceilf(self)
-    }
-    #[inline]
-    fn round(self) -> Self {
-        libm::roundf(self)
-    }
-    #[inline]
-    fn trunc(self) -> Self {
-        libm::truncf(self)
-    }
-    #[inline]
-    fn abs(self) -> Self {
-        libm::fabsf(self)
-    }
-    #[inline]
-    fn mul_add(self, a: Self, b: Self) -> Self {
-        libm::fmaf(self, a, b)
-    }
-    #[inline]
-    fn powf(self, n: Self) -> Self {
-        libm::powf(self, n)
-    }
-    #[inline]
-    fn sqrt(self) -> Self {
-        libm::sqrtf(self)
-    }
-    #[inline]
-    fn exp(self) -> Self {
-        libm::expf(self)
-    }
-    #[inline]
-    fn exp2(self) -> Self {
-        libm::exp2f(self)
-    }
-    #[inline]
-    fn ln(self) -> Self {
-        libm::logf(self)
-    }
-    #[inline]
-    fn log2(self) -> Self {
-        libm::log2f(self)
-    }
-    #[inline]
-    fn log10(self) -> Self {
-        libm::log10f(self)
-    }
-    #[inline]
-    fn cbrt(self) -> Self {
-        libm::cbrtf(self)
-    }
-    #[inline]
-    fn hypot(self, other: Self) -> Self {
-        libm::hypotf(self, other)
-    }
-    #[inline]
-    fn sin(self) -> Self {
-        libm::sinf(self)
-    }
-    #[inline]
-    fn cos(self) -> Self {
-        libm::cosf(self)
-    }
-    #[inline]
-    fn tan(self) -> Self {
-        libm::tanf(self)
-    }
-    #[inline]
-    fn asin(self) -> Self {
-        libm::asinf(self)
-    }
-    #[inline]
-    fn acos(self) -> Self {
-        libm::acosf(self)
-    }
-    #[inline]
-    fn atan(self) -> Self {
-        libm::atanf(self)
-    }
-    #[inline]
-    fn atan2(self, other: Self) -> Self {
-        libm::atan2f(self, other)
-    }
-    #[inline]
-    fn sin_cos(self) -> (Self, Self) {
-        libm::sincosf(self)
-    }
-    #[inline]
-    fn exp_m1(self) -> Self {
-        libm::expm1f(self)
-    }
-    #[inline]
-    fn ln_1p(self) -> Self {
-        libm::log1pf(self)
-    }
-    #[inline]
-    fn sinh(self) -> Self {
-        libm::sinhf(self)
-    }
-    #[inline]
-    fn cosh(self) -> Self {
-        libm::coshf(self)
-    }
-    #[inline]
-    fn tanh(self) -> Self {
-        libm::tanhf(self)
-    }
-    #[inline]
-    fn asinh(self) -> Self {
-        libm::asinhf(self)
-    }
-    #[inline]
-    fn acosh(self) -> Self {
-        libm::acoshf(self)
-    }
-    #[inline]
-    fn atanh(self) -> Self {
-        libm::atanhf(self)
+
+    forward! {
+        libm::floorf as floor(self) -> Self;
+        libm::ceilf as ceil(self) -> Self;
+        libm::roundf as round(self) -> Self;
+        libm::truncf as trunc(self) -> Self;
+        libm::fabsf as abs(self) -> Self;
+        libm::fmaf as mul_add(self, a: Self, b: Self) -> Self;
+        libm::powf as powf(self, n: Self) -> Self;
+        libm::sqrtf as sqrt(self) -> Self;
+        libm::expf as exp(self) -> Self;
+        libm::exp2f as exp2(self) -> Self;
+        libm::logf as ln(self) -> Self;
+        libm::log2f as log2(self) -> Self;
+        libm::log10f as log10(self) -> Self;
+        libm::cbrtf as cbrt(self) -> Self;
+        libm::hypotf as hypot(self, other: Self) -> Self;
+        libm::sinf as sin(self) -> Self;
+        libm::cosf as cos(self) -> Self;
+        libm::tanf as tan(self) -> Self;
+        libm::asinf as asin(self) -> Self;
+        libm::acosf as acos(self) -> Self;
+        libm::atanf as atan(self) -> Self;
+        libm::atan2f as atan2(self, other: Self) -> Self;
+        libm::sincosf as sin_cos(self) -> (Self, Self);
+        libm::expm1f as exp_m1(self) -> Self;
+        libm::log1pf as ln_1p(self) -> Self;
+        libm::sinhf as sinh(self) -> Self;
+        libm::coshf as cosh(self) -> Self;
+        libm::tanhf as tanh(self) -> Self;
+        libm::asinhf as asinh(self) -> Self;
+        libm::acoshf as acosh(self) -> Self;
+        libm::atanhf as atanh(self) -> Self;
+        libm::fmaxf as max(self, other: Self) -> Self;
+        libm::fminf as min(self, other: Self) -> Self;
+        libm::copysignf as copysign(self, other: Self) -> Self;
     }
 }
 
@@ -2116,129 +2118,42 @@
     fn abs_sub(self, other: Self) -> Self {
         libm::fdim(self, other)
     }
-    #[inline]
-    fn floor(self) -> Self {
-        libm::floor(self)
-    }
-    #[inline]
-    fn ceil(self) -> Self {
-        libm::ceil(self)
-    }
-    #[inline]
-    fn round(self) -> Self {
-        libm::round(self)
-    }
-    #[inline]
-    fn trunc(self) -> Self {
-        libm::trunc(self)
-    }
-    #[inline]
-    fn abs(self) -> Self {
-        libm::fabs(self)
-    }
-    #[inline]
-    fn mul_add(self, a: Self, b: Self) -> Self {
-        libm::fma(self, a, b)
-    }
-    #[inline]
-    fn powf(self, n: Self) -> Self {
-        libm::pow(self, n)
-    }
-    #[inline]
-    fn sqrt(self) -> Self {
-        libm::sqrt(self)
-    }
-    #[inline]
-    fn exp(self) -> Self {
-        libm::exp(self)
-    }
-    #[inline]
-    fn exp2(self) -> Self {
-        libm::exp2(self)
-    }
-    #[inline]
-    fn ln(self) -> Self {
-        libm::log(self)
-    }
-    #[inline]
-    fn log2(self) -> Self {
-        libm::log2(self)
-    }
-    #[inline]
-    fn log10(self) -> Self {
-        libm::log10(self)
-    }
-    #[inline]
-    fn cbrt(self) -> Self {
-        libm::cbrt(self)
-    }
-    #[inline]
-    fn hypot(self, other: Self) -> Self {
-        libm::hypot(self, other)
-    }
-    #[inline]
-    fn sin(self) -> Self {
-        libm::sin(self)
-    }
-    #[inline]
-    fn cos(self) -> Self {
-        libm::cos(self)
-    }
-    #[inline]
-    fn tan(self) -> Self {
-        libm::tan(self)
-    }
-    #[inline]
-    fn asin(self) -> Self {
-        libm::asin(self)
-    }
-    #[inline]
-    fn acos(self) -> Self {
-        libm::acos(self)
-    }
-    #[inline]
-    fn atan(self) -> Self {
-        libm::atan(self)
-    }
-    #[inline]
-    fn atan2(self, other: Self) -> Self {
-        libm::atan2(self, other)
-    }
-    #[inline]
-    fn sin_cos(self) -> (Self, Self) {
-        libm::sincos(self)
-    }
-    #[inline]
-    fn exp_m1(self) -> Self {
-        libm::expm1(self)
-    }
-    #[inline]
-    fn ln_1p(self) -> Self {
-        libm::log1p(self)
-    }
-    #[inline]
-    fn sinh(self) -> Self {
-        libm::sinh(self)
-    }
-    #[inline]
-    fn cosh(self) -> Self {
-        libm::cosh(self)
-    }
-    #[inline]
-    fn tanh(self) -> Self {
-        libm::tanh(self)
-    }
-    #[inline]
-    fn asinh(self) -> Self {
-        libm::asinh(self)
-    }
-    #[inline]
-    fn acosh(self) -> Self {
-        libm::acosh(self)
-    }
-    #[inline]
-    fn atanh(self) -> Self {
-        libm::atanh(self)
+
+    forward! {
+        libm::floor as floor(self) -> Self;
+        libm::ceil as ceil(self) -> Self;
+        libm::round as round(self) -> Self;
+        libm::trunc as trunc(self) -> Self;
+        libm::fabs as abs(self) -> Self;
+        libm::fma as mul_add(self, a: Self, b: Self) -> Self;
+        libm::pow as powf(self, n: Self) -> Self;
+        libm::sqrt as sqrt(self) -> Self;
+        libm::exp as exp(self) -> Self;
+        libm::exp2 as exp2(self) -> Self;
+        libm::log as ln(self) -> Self;
+        libm::log2 as log2(self) -> Self;
+        libm::log10 as log10(self) -> Self;
+        libm::cbrt as cbrt(self) -> Self;
+        libm::hypot as hypot(self, other: Self) -> Self;
+        libm::sin as sin(self) -> Self;
+        libm::cos as cos(self) -> Self;
+        libm::tan as tan(self) -> Self;
+        libm::asin as asin(self) -> Self;
+        libm::acos as acos(self) -> Self;
+        libm::atan as atan(self) -> Self;
+        libm::atan2 as atan2(self, other: Self) -> Self;
+        libm::sincos as sin_cos(self) -> (Self, Self);
+        libm::expm1 as exp_m1(self) -> Self;
+        libm::log1p as ln_1p(self) -> Self;
+        libm::sinh as sinh(self) -> Self;
+        libm::cosh as cosh(self) -> Self;
+        libm::tanh as tanh(self) -> Self;
+        libm::asinh as asinh(self) -> Self;
+        libm::acosh as acosh(self) -> Self;
+        libm::atanh as atanh(self) -> Self;
+        libm::fmax as max(self, other: Self) -> Self;
+        libm::fmin as min(self, other: Self) -> Self;
+        libm::copysign as copysign(self, sign: Self) -> Self;
     }
 }
 
@@ -2387,4 +2302,50 @@
         check::<f32>(1e-6);
         check::<f64>(1e-12);
     }
+
+    #[test]
+    #[cfg(any(feature = "std", feature = "libm"))]
+    fn copysign() {
+        use float::Float;
+        test_copysign_generic(2.0_f32, -2.0_f32, f32::nan());
+        test_copysign_generic(2.0_f64, -2.0_f64, f64::nan());
+        test_copysignf(2.0_f32, -2.0_f32, f32::nan());
+    }
+
+    #[cfg(any(feature = "std", feature = "libm"))]
+    fn test_copysignf(p: f32, n: f32, nan: f32) {
+        use core::ops::Neg;
+        use float::Float;
+
+        assert!(p.is_sign_positive());
+        assert!(n.is_sign_negative());
+        assert!(nan.is_nan());
+
+        assert_eq!(p, Float::copysign(p, p));
+        assert_eq!(p.neg(), Float::copysign(p, n));
+
+        assert_eq!(n, Float::copysign(n, n));
+        assert_eq!(n.neg(), Float::copysign(n, p));
+
+        // FIXME: is_sign... only works on NaN starting in Rust 1.20
+        // assert!(Float::copysign(nan, p).is_sign_positive());
+        // assert!(Float::copysign(nan, n).is_sign_negative());
+    }
+
+    #[cfg(any(feature = "std", feature = "libm"))]
+    fn test_copysign_generic<F: ::float::Float + ::core::fmt::Debug>(p: F, n: F, nan: F) {
+        assert!(p.is_sign_positive());
+        assert!(n.is_sign_negative());
+        assert!(nan.is_nan());
+
+        assert_eq!(p, p.copysign(p));
+        assert_eq!(p.neg(), p.copysign(n));
+
+        assert_eq!(n, n.copysign(n));
+        assert_eq!(n.neg(), n.copysign(p));
+
+        // FIXME: is_sign... only works on NaN starting in Rust 1.20
+        // assert!(nan.copysign(p).is_sign_positive());
+        // assert!(nan.copysign(n).is_sign_negative());
+    }
 }
diff --git a/src/int.rs b/src/int.rs
index 10e751a..c7dbf12 100644
--- a/src/int.rs
+++ b/src/int.rs
@@ -78,6 +78,22 @@
     /// ```
     fn count_zeros(self) -> u32;
 
+    /// Returns the number of leading ones in the binary representation
+    /// of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::PrimInt;
+    ///
+    /// let n = 0xF00Du16;
+    ///
+    /// assert_eq!(n.leading_ones(), 4);
+    /// ```
+    fn leading_ones(self) -> u32 {
+        (!self).leading_zeros()
+    }
+
     /// Returns the number of leading zeros in the binary representation
     /// of `self`.
     ///
@@ -92,6 +108,22 @@
     /// ```
     fn leading_zeros(self) -> u32;
 
+    /// Returns the number of trailing ones in the binary representation
+    /// of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::PrimInt;
+    ///
+    /// let n = 0xBEEFu16;
+    ///
+    /// assert_eq!(n.trailing_ones(), 4);
+    /// ```
+    fn trailing_ones(self) -> u32 {
+        (!self).trailing_zeros()
+    }
+
     /// Returns the number of trailing zeros in the binary representation
     /// of `self`.
     ///
@@ -218,6 +250,26 @@
     /// ```
     fn swap_bytes(self) -> Self;
 
+    /// Reverses the order of bits in the integer.
+    ///
+    /// The least significant bit becomes the most significant bit, second least-significant bit
+    /// becomes second most-significant bit, etc.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::PrimInt;
+    ///
+    /// let n = 0x12345678u32;
+    /// let m = 0x1e6a2c48u32;
+    ///
+    /// assert_eq!(n.reverse_bits(), m);
+    /// assert_eq!(0u32.reverse_bits(), 0);
+    /// ```
+    fn reverse_bits(self) -> Self {
+        reverse_bits_fallback(self)
+    }
+
     /// Convert an integer from big endian to the target's endianness.
     ///
     /// On big endian this is a no-op. On little endian the bytes are swapped.
@@ -306,6 +358,39 @@
     fn pow(self, exp: u32) -> Self;
 }
 
+fn one_per_byte<P: PrimInt>() -> P {
+    // i8, u8: return 0x01
+    // i16, u16: return 0x0101 = (0x01 << 8) | 0x01
+    // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101
+    // ...
+    let mut ret = P::one();
+    let mut shift = 8;
+    let mut b = ret.count_zeros() >> 3;
+    while b != 0 {
+        ret = (ret << shift) | ret;
+        shift <<= 1;
+        b >>= 1;
+    }
+    ret
+}
+
+fn reverse_bits_fallback<P: PrimInt>(i: P) -> P {
+    let rep_01: P = one_per_byte();
+    let rep_03 = (rep_01 << 1) | rep_01;
+    let rep_05 = (rep_01 << 2) | rep_01;
+    let rep_0f = (rep_03 << 2) | rep_03;
+    let rep_33 = (rep_03 << 4) | rep_03;
+    let rep_55 = (rep_05 << 4) | rep_05;
+
+    // code above only used to determine rep_0f, rep_33, rep_55;
+    // optimizer should be able to do it in compile time
+    let mut ret = i.swap_bytes();
+    ret = ((ret & rep_0f) << 4) | ((ret >> 4) & rep_0f);
+    ret = ((ret & rep_33) << 2) | ((ret >> 2) & rep_33);
+    ret = ((ret & rep_55) << 1) | ((ret >> 1) & rep_55);
+    ret
+}
+
 macro_rules! prim_int_impl {
     ($T:ty, $S:ty, $U:ty) => {
         impl PrimInt for $T {
@@ -319,11 +404,23 @@
                 <$T>::count_zeros(self)
             }
 
+            #[cfg(has_leading_trailing_ones)]
+            #[inline]
+            fn leading_ones(self) -> u32 {
+                <$T>::leading_ones(self)
+            }
+
             #[inline]
             fn leading_zeros(self) -> u32 {
                 <$T>::leading_zeros(self)
             }
 
+            #[cfg(has_leading_trailing_ones)]
+            #[inline]
+            fn trailing_ones(self) -> u32 {
+                <$T>::trailing_ones(self)
+            }
+
             #[inline]
             fn trailing_zeros(self) -> u32 {
                 <$T>::trailing_zeros(self)
@@ -364,6 +461,12 @@
                 <$T>::swap_bytes(self)
             }
 
+            #[cfg(has_reverse_bits)]
+            #[inline]
+            fn reverse_bits(self) -> Self {
+                <$T>::reverse_bits(self)
+            }
+
             #[inline]
             fn from_be(x: Self) -> Self {
                 <$T>::from_be(x)
@@ -407,3 +510,59 @@
 #[cfg(has_i128)]
 prim_int_impl!(i128, i128, u128);
 prim_int_impl!(isize, isize, usize);
+
+#[cfg(test)]
+mod tests {
+    use int::PrimInt;
+
+    #[test]
+    pub fn reverse_bits() {
+        use core::{i16, i32, i64, i8};
+
+        assert_eq!(
+            PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64),
+            0xf7b3_d591_e6a2_c480
+        );
+
+        assert_eq!(PrimInt::reverse_bits(0i8), 0);
+        assert_eq!(PrimInt::reverse_bits(-1i8), -1);
+        assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN);
+        assert_eq!(PrimInt::reverse_bits(i8::MIN), 1);
+        assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX);
+        assert_eq!(PrimInt::reverse_bits(i8::MAX), -2);
+
+        assert_eq!(PrimInt::reverse_bits(0i16), 0);
+        assert_eq!(PrimInt::reverse_bits(-1i16), -1);
+        assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN);
+        assert_eq!(PrimInt::reverse_bits(i16::MIN), 1);
+        assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX);
+        assert_eq!(PrimInt::reverse_bits(i16::MAX), -2);
+
+        assert_eq!(PrimInt::reverse_bits(0i32), 0);
+        assert_eq!(PrimInt::reverse_bits(-1i32), -1);
+        assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN);
+        assert_eq!(PrimInt::reverse_bits(i32::MIN), 1);
+        assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX);
+        assert_eq!(PrimInt::reverse_bits(i32::MAX), -2);
+
+        assert_eq!(PrimInt::reverse_bits(0i64), 0);
+        assert_eq!(PrimInt::reverse_bits(-1i64), -1);
+        assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN);
+        assert_eq!(PrimInt::reverse_bits(i64::MIN), 1);
+        assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX);
+        assert_eq!(PrimInt::reverse_bits(i64::MAX), -2);
+    }
+
+    #[test]
+    #[cfg(has_i128)]
+    pub fn reverse_bits_i128() {
+        use core::i128;
+
+        assert_eq!(PrimInt::reverse_bits(0i128), 0);
+        assert_eq!(PrimInt::reverse_bits(-1i128), -1);
+        assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN);
+        assert_eq!(PrimInt::reverse_bits(i128::MIN), 1);
+        assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX);
+        assert_eq!(PrimInt::reverse_bits(i128::MAX), -2);
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index a6c202c..bed87f3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,6 +40,7 @@
 pub use ops::checked::{
     CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
 };
+pub use ops::euclid::{CheckedEuclid, Euclid};
 pub use ops::inv::Inv;
 pub use ops::mul_add::{MulAdd, MulAddAssign};
 pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub};
@@ -95,7 +96,7 @@
     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
 }
 
-/// The trait for types implementing basic numeric operations
+/// Generic trait for types implementing basic numeric operations
 ///
 /// This is automatically implemented for types which implement the operators.
 pub trait NumOps<Rhs = Self, Output = Self>:
@@ -123,14 +124,16 @@
 pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
 impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
 
-/// The trait for references which implement numeric operations, taking the
+/// The trait for `Num` references which implement numeric operations, taking the
 /// second operand either by value or by reference.
 ///
-/// This is automatically implemented for types which implement the operators.
+/// This is automatically implemented for all types which implement the operators. It covers
+/// every type implementing the operations though, regardless of it being a reference or
+/// related to `Num`.
 pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
 impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
 
-/// The trait for types implementing numeric assignment operators (like `+=`).
+/// Generic trait for types implementing numeric assignment operators (like `+=`).
 ///
 /// This is automatically implemented for types which implement the operators.
 pub trait NumAssignOps<Rhs = Self>:
@@ -175,11 +178,7 @@
 
 impl<T: Num> Num for Wrapping<T>
 where
-    Wrapping<T>: Add<Output = Wrapping<T>>
-        + Sub<Output = Wrapping<T>>
-        + Mul<Output = Wrapping<T>>
-        + Div<Output = Wrapping<T>>
-        + Rem<Output = Wrapping<T>>,
+    Wrapping<T>: NumOps,
 {
     type FromStrRadixErr = T::FromStrRadixErr;
     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
@@ -210,6 +209,14 @@
     }
 }
 
+fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool {
+    a.len() == b.len()
+        && a.bytes().zip(b.bytes()).all(|(a, b)| {
+            let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5);
+            a_to_ascii_lower == b
+        })
+}
+
 // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
 // with this implementation ourselves until we want to make a breaking change.
 // (would have to drop it from `Num` though)
@@ -224,12 +231,26 @@
                 use self::FloatErrorKind::*;
                 use self::ParseFloatError as PFE;
 
+                // Special case radix 10 to use more accurate standard library implementation
+                if radix == 10 {
+                    return src.parse().map_err(|_| PFE {
+                        kind: if src.is_empty() { Empty } else { Invalid },
+                    });
+                }
+
                 // Special values
-                match src {
-                    "inf"   => return Ok(core::$t::INFINITY),
-                    "-inf"  => return Ok(core::$t::NEG_INFINITY),
-                    "NaN"   => return Ok(core::$t::NAN),
-                    _       => {},
+                if str_to_ascii_lower_eq_str(src, "inf")
+                    || str_to_ascii_lower_eq_str(src, "infinity")
+                {
+                    return Ok(core::$t::INFINITY);
+                } else if str_to_ascii_lower_eq_str(src, "-inf")
+                    || str_to_ascii_lower_eq_str(src, "-infinity")
+                {
+                    return Ok(core::$t::NEG_INFINITY);
+                } else if str_to_ascii_lower_eq_str(src, "nan") {
+                    return Ok(core::$t::NAN);
+                } else if str_to_ascii_lower_eq_str(src, "-nan") {
+                    return Ok(-core::$t::NAN);
                 }
 
                 fn slice_shift_char(src: &str) -> Option<(char, &str)> {
@@ -509,6 +530,28 @@
 }
 
 #[test]
+fn from_str_radix_ignore_case() {
+    assert_eq!(
+        f32::from_str_radix("InF", 16).unwrap(),
+        ::core::f32::INFINITY
+    );
+    assert_eq!(
+        f32::from_str_radix("InfinitY", 16).unwrap(),
+        ::core::f32::INFINITY
+    );
+    assert_eq!(
+        f32::from_str_radix("-InF", 8).unwrap(),
+        ::core::f32::NEG_INFINITY
+    );
+    assert_eq!(
+        f32::from_str_radix("-InfinitY", 8).unwrap(),
+        ::core::f32::NEG_INFINITY
+    );
+    assert!(f32::from_str_radix("nAn", 4).unwrap().is_nan());
+    assert!(f32::from_str_radix("-nAn", 4).unwrap().is_nan());
+}
+
+#[test]
 fn wrapping_is_num() {
     fn require_num<T: Num>(_: &T) {}
     require_num(&Wrapping(42_u32));
@@ -582,5 +625,16 @@
     assert_eq!(compute(1, 2), 1)
 }
 
-// TODO test `NumAssignRef`, but even the standard numeric types don't
-// implement this yet. (see rust pr41336)
+#[cfg(has_int_assignop_ref)]
+#[test]
+fn check_numassignref_ops() {
+    fn compute<T: NumAssignRef + Copy>(mut x: T, y: &T) -> T {
+        x *= y;
+        x /= y;
+        x %= y;
+        x += y;
+        x -= y;
+        x
+    }
+    assert_eq!(compute(1, &2), 1)
+}
diff --git a/src/macros.rs b/src/macros.rs
index 4330cdf..b97758e 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -23,7 +23,14 @@
             fn $method( $( $arg : $ty ),* ) -> $ret {
                 <Self as $base>::$method( $( $arg ),* )
             }
-        )*}
+        )*};
+    ($( $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+        => {$(
+            #[inline]
+            fn $method(self $( , $arg : $ty )* ) -> $ret {
+                $imp(self $( , $arg )* )
+            }
+        )*};
 }
 
 macro_rules! constant {
diff --git a/src/ops/euclid.rs b/src/ops/euclid.rs
new file mode 100644
index 0000000..99b5127
--- /dev/null
+++ b/src/ops/euclid.rs
@@ -0,0 +1,347 @@
+use core::ops::{Div, Rem};
+
+pub trait Euclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
+    /// Calculates Euclidean division, the matching method for `rem_euclid`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * v + self.rem_euclid(v)`.
+    /// In other words, the result is `self / v` rounded to the integer `n`
+    /// such that `self >= n * v`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::Euclid;
+    ///
+    /// let a: i32 = 7;
+    /// let b: i32 = 4;
+    /// assert_eq!(Euclid::div_euclid(&a, &b), 1); // 7 > 4 * 1
+    /// assert_eq!(Euclid::div_euclid(&-a, &b), -2); // -7 >= 4 * -2
+    /// assert_eq!(Euclid::div_euclid(&a, &-b), -1); // 7 >= -4 * -1
+    /// assert_eq!(Euclid::div_euclid(&-a, &-b), 2); // -7 >= -4 * 2
+    /// ```
+    fn div_euclid(&self, v: &Self) -> Self;
+
+    /// Calculates the least nonnegative remainder of `self (mod v)`.
+    ///
+    /// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in
+    /// most cases. However, due to a floating point round-off error it can
+    /// result in `r == v.abs()`, violating the mathematical definition, if
+    /// `self` is much smaller than `v.abs()` in magnitude and `self < 0.0`.
+    /// This result is not an element of the function's codomain, but it is the
+    /// closest floating point number in the real numbers and thus fulfills the
+    /// property `self == self.div_euclid(v) * v + self.rem_euclid(v)`
+    /// approximatively.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use num_traits::Euclid;
+    ///
+    /// let a: i32 = 7;
+    /// let b: i32 = 4;
+    /// assert_eq!(Euclid::rem_euclid(&a, &b), 3);
+    /// assert_eq!(Euclid::rem_euclid(&-a, &b), 1);
+    /// assert_eq!(Euclid::rem_euclid(&a, &-b), 3);
+    /// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1);
+    /// ```
+    fn rem_euclid(&self, v: &Self) -> Self;
+}
+
+macro_rules! euclid_forward_impl {
+    ($($t:ty)*) => {$(
+        #[cfg(has_div_euclid)]
+        impl Euclid for $t {
+            #[inline]
+            fn div_euclid(&self, v: &$t) -> Self {
+                <$t>::div_euclid(*self, *v)
+            }
+
+            #[inline]
+            fn rem_euclid(&self, v: &$t) -> Self {
+                <$t>::rem_euclid(*self, *v)
+            }
+        }
+    )*}
+}
+
+macro_rules! euclid_int_impl {
+    ($($t:ty)*) => {$(
+        euclid_forward_impl!($t);
+
+        #[cfg(not(has_div_euclid))]
+        impl Euclid for $t {
+            #[inline]
+            fn div_euclid(&self, v: &$t) -> Self {
+                let q = self / v;
+                if self % v < 0 {
+                    return if *v > 0 { q - 1 } else { q + 1 }
+                }
+                q
+            }
+
+            #[inline]
+            fn rem_euclid(&self, v: &$t) -> Self {
+                let r = self % v;
+                if r < 0 {
+                    if *v < 0 {
+                        r - v
+                    } else {
+                        r + v
+                    }
+                } else {
+                    r
+                }
+            }
+        }
+    )*}
+}
+
+macro_rules! euclid_uint_impl {
+    ($($t:ty)*) => {$(
+        euclid_forward_impl!($t);
+
+        #[cfg(not(has_div_euclid))]
+        impl Euclid for $t {
+            #[inline]
+            fn div_euclid(&self, v: &$t) -> Self {
+                self / v
+            }
+
+            #[inline]
+            fn rem_euclid(&self, v: &$t) -> Self {
+                self % v
+            }
+        }
+    )*}
+}
+
+euclid_int_impl!(isize i8 i16 i32 i64);
+euclid_uint_impl!(usize u8 u16 u32 u64);
+#[cfg(has_i128)]
+euclid_int_impl!(i128);
+#[cfg(has_i128)]
+euclid_uint_impl!(u128);
+
+#[cfg(all(has_div_euclid, feature = "std"))]
+euclid_forward_impl!(f32 f64);
+
+#[cfg(not(all(has_div_euclid, feature = "std")))]
+impl Euclid for f32 {
+    #[inline]
+    fn div_euclid(&self, v: &f32) -> f32 {
+        let q = <f32 as ::float::FloatCore>::trunc(self / v);
+        if self % v < 0.0 {
+            return if *v > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    #[inline]
+    fn rem_euclid(&self, v: &f32) -> f32 {
+        let r = self % v;
+        if r < 0.0 {
+            r + <f32 as ::float::FloatCore>::abs(*v)
+        } else {
+            r
+        }
+    }
+}
+
+#[cfg(not(all(has_div_euclid, feature = "std")))]
+impl Euclid for f64 {
+    #[inline]
+    fn div_euclid(&self, v: &f64) -> f64 {
+        let q = <f64 as ::float::FloatCore>::trunc(self / v);
+        if self % v < 0.0 {
+            return if *v > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    #[inline]
+    fn rem_euclid(&self, v: &f64) -> f64 {
+        let r = self % v;
+        if r < 0.0 {
+            r + <f64 as ::float::FloatCore>::abs(*v)
+        } else {
+            r
+        }
+    }
+}
+
+pub trait CheckedEuclid: Euclid {
+    /// Performs euclid division that returns `None` instead of panicking on division by zero
+    /// and instead of wrapping around on underflow and overflow.
+    fn checked_div_euclid(&self, v: &Self) -> Option<Self>;
+
+    /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
+    /// division by zero. If any of that happens, `None` is returned.
+    fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
+}
+
+macro_rules! checked_euclid_forward_impl {
+    ($($t:ty)*) => {$(
+        #[cfg(has_div_euclid)]
+        impl CheckedEuclid for $t {
+            #[inline]
+            fn checked_div_euclid(&self, v: &$t) -> Option<Self> {
+                <$t>::checked_div_euclid(*self, *v)
+            }
+
+            #[inline]
+            fn checked_rem_euclid(&self, v: &$t) -> Option<Self> {
+                <$t>::checked_rem_euclid(*self, *v)
+            }
+        }
+    )*}
+}
+
+macro_rules! checked_euclid_int_impl {
+    ($($t:ty)*) => {$(
+        checked_euclid_forward_impl!($t);
+
+        #[cfg(not(has_div_euclid))]
+        impl CheckedEuclid for $t {
+            #[inline]
+            fn checked_div_euclid(&self, v: &$t) -> Option<$t> {
+                if *v == 0 || (*self == Self::min_value() && *v == -1) {
+                    None
+                } else {
+                    Some(Euclid::div_euclid(self, v))
+                }
+            }
+
+            #[inline]
+            fn checked_rem_euclid(&self, v: &$t) -> Option<$t> {
+                if *v == 0 || (*self == Self::min_value() && *v == -1) {
+                    None
+                } else {
+                    Some(Euclid::rem_euclid(self, v))
+                }
+            }
+        }
+    )*}
+}
+
+macro_rules! checked_euclid_uint_impl {
+    ($($t:ty)*) => {$(
+        checked_euclid_forward_impl!($t);
+
+        #[cfg(not(has_div_euclid))]
+        impl CheckedEuclid for $t {
+            #[inline]
+            fn checked_div_euclid(&self, v: &$t) -> Option<$t> {
+                if *v == 0 {
+                    None
+                } else {
+                    Some(Euclid::div_euclid(self, v))
+                }
+            }
+
+            #[inline]
+            fn checked_rem_euclid(&self, v: &$t) -> Option<$t> {
+                if *v == 0 {
+                    None
+                } else {
+                    Some(Euclid::rem_euclid(self, v))
+                }
+            }
+        }
+    )*}
+}
+
+checked_euclid_int_impl!(isize i8 i16 i32 i64);
+checked_euclid_uint_impl!(usize u8 u16 u32 u64);
+#[cfg(has_i128)]
+checked_euclid_int_impl!(i128);
+#[cfg(has_i128)]
+checked_euclid_uint_impl!(u128);
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn euclid_unsigned() {
+        macro_rules! test_euclid {
+            ($($t:ident)+) => {
+                $(
+                    {
+                        let x: $t = 10;
+                        let y: $t = 3;
+                        assert_eq!(Euclid::div_euclid(&x, &y), 3);
+                        assert_eq!(Euclid::rem_euclid(&x, &y), 1);
+                    }
+                )+
+            };
+        }
+
+        test_euclid!(usize u8 u16 u32 u64);
+    }
+
+    #[test]
+    fn euclid_signed() {
+        macro_rules! test_euclid {
+            ($($t:ident)+) => {
+                $(
+                    {
+                        let x: $t = 10;
+                        let y: $t = -3;
+                        assert_eq!(Euclid::div_euclid(&x, &y), -3);
+                        assert_eq!(Euclid::div_euclid(&-x, &y), 4);
+                        assert_eq!(Euclid::rem_euclid(&x, &y), 1);
+                        assert_eq!(Euclid::rem_euclid(&-x, &y), 2);
+                        let x: $t = $t::min_value() + 1;
+                        let y: $t = -1;
+                        assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value());
+                    }
+                )+
+            };
+        }
+
+        test_euclid!(isize i8 i16 i32 i64);
+    }
+
+    #[test]
+    fn euclid_float() {
+        macro_rules! test_euclid {
+            ($($t:ident)+) => {
+                $(
+                    {
+                        let x: $t = 12.1;
+                        let y: $t = 3.2;
+                        assert!(Euclid::div_euclid(&x, &y) * y + Euclid::rem_euclid(&x, &y) - x
+                        <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+                        assert!(Euclid::div_euclid(&x, &-y) * -y + Euclid::rem_euclid(&x, &-y) - x
+                        <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+                        assert!(Euclid::div_euclid(&-x, &y) * y + Euclid::rem_euclid(&-x, &y) + x
+                        <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+                        assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x
+                        <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+                    }
+                )+
+            };
+        }
+
+        test_euclid!(f32 f64);
+    }
+
+    #[test]
+    fn euclid_checked() {
+        macro_rules! test_euclid_checked {
+            ($($t:ident)+) => {
+                $(
+                    {
+                        assert_eq!(CheckedEuclid::checked_div_euclid(&$t::min_value(), &-1), None);
+                        assert_eq!(CheckedEuclid::checked_rem_euclid(&$t::min_value(), &-1), None);
+                        assert_eq!(CheckedEuclid::checked_div_euclid(&1, &0), None);
+                        assert_eq!(CheckedEuclid::checked_rem_euclid(&1, &0), None);
+                    }
+                )+
+            };
+        }
+
+        test_euclid_checked!(isize i8 i16 i32 i64);
+    }
+}
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 73c4f90..585879f 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -1,4 +1,5 @@
 pub mod checked;
+pub mod euclid;
 pub mod inv;
 pub mod mul_add;
 pub mod overflowing;