Browse Source

libm fallback for Pow, factorize MulAdd

Yoan Lecoq 6 years ago
parent
commit
4234eb76aa
3 changed files with 25 additions and 62 deletions
  1. 2 2
      README.md
  2. 8 46
      src/ops/mul_add.rs
  3. 15 14
      src/pow.rs

+ 2 - 2
README.md

@@ -31,13 +31,13 @@ the default `std` feature. Use this in `Cargo.toml`:
 [dependencies.num-traits]
 version = "0.2"
 default-features = false
-# features = ["libm"]    # <--- Uncomment if you wish to use `Float` and `Real`
+# features = ["libm"]    # <--- Uncomment if you wish to use `Float` and `Real` without `std`
 ```
 
 The `Float` and `Real` traits are only available when either `std` or `libm` is enabled.
 
 The `FloatCore` trait is always available.  `MulAdd` and `MulAddAssign` for `f32`
-and `f64` also require `std`, as do implementations of signed and floating-
+and `f64` also require `std` or `libm`, as do implementations of signed and floating-
 point exponents in `Pow`.
 
 Implementations for `i128` and `u128` are only available with Rust 1.26 and

+ 8 - 46
src/ops/mul_add.rs

@@ -34,47 +34,26 @@ pub trait MulAddAssign<A = Self, B = Self> {
     fn mul_add_assign(&mut self, a: A, b: B);
 }
 
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
 impl MulAdd<f32, f32> for f32 {
     type Output = Self;
 
     #[inline]
     fn mul_add(self, a: Self, b: Self) -> Self::Output {
-        f32::mul_add(self, a, b)
+        <Self as ::Float>::mul_add(self, a, b)
     }
 }
 
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
 impl MulAdd<f64, f64> for f64 {
     type Output = Self;
 
     #[inline]
     fn mul_add(self, a: Self, b: Self) -> Self::Output {
-        f64::mul_add(self, a, b)
+        <Self as ::Float>::mul_add(self, a, b)
     }
 }
 
-#[cfg(all(not(feature = "std"), feature = "libm"))]
-impl MulAdd<f32, f32> for f32 {
-    type Output = Self;
-
-    #[inline]
-    fn mul_add(self, a: Self, b: Self) -> Self::Output {
-        <f32 as ::libm::F32Ext>::mul_add(self, a, b)
-    }
-}
-
-#[cfg(all(not(feature = "std"), feature = "libm"))]
-impl MulAdd<f64, f64> for f64 {
-    type Output = Self;
-
-    #[inline]
-    fn mul_add(self, a: Self, b: Self) -> Self::Output {
-        <f64 as ::libm::F64Ext>::mul_add(self, a, b)
-    }
-}
-
-
 macro_rules! mul_add_impl {
     ($trait_name:ident for $($t:ty)*) => {$(
         impl $trait_name for $t {
@@ -92,39 +71,22 @@ mul_add_impl!(MulAdd for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
 #[cfg(has_i128)]
 mul_add_impl!(MulAdd for i128 u128);
 
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
 impl MulAddAssign<f32, f32> for f32 {
     #[inline]
     fn mul_add_assign(&mut self, a: Self, b: Self) {
-        *self = f32::mul_add(*self, a, b)
+        *self = <Self as ::Float>::mul_add(*self, a, b)
     }
 }
 
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
 impl MulAddAssign<f64, f64> for f64 {
     #[inline]
     fn mul_add_assign(&mut self, a: Self, b: Self) {
-        *self = f64::mul_add(*self, a, b)
-    }
-}
-
-#[cfg(all(not(feature = "std"), feature = "libm"))]
-impl MulAddAssign<f32, f32> for f32 {
-    #[inline]
-    fn mul_add_assign(&mut self, a: Self, b: Self) {
-        *self = <f32 as ::libm::F32Ext>::mul_add(*self, a, b)
+        *self = <Self as ::Float>::mul_add(*self, a, b)
     }
 }
 
-#[cfg(all(not(feature = "std"), feature = "libm"))]
-impl MulAddAssign<f64, f64> for f64 {
-    #[inline]
-    fn mul_add_assign(&mut self, a: Self, b: Self) {
-        *self = <f64 as ::libm::F64Ext>::mul_add(*self, a, b)
-    }
-}
-
-
 macro_rules! mul_add_assign_impl {
     ($trait_name:ident for $($t:ty)*) => {$(
         impl $trait_name for $t {

+ 15 - 14
src/pow.rs

@@ -152,23 +152,24 @@ pow_impl!(Wrapping<isize>);
 // pow_impl!(usize, u64);
 // pow_impl!(isize, u64);
 
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
 mod float_impls {
     use super::Pow;
+    use ::Float;
 
-    pow_impl!(f32, i8, i32, f32::powi);
-    pow_impl!(f32, u8, i32, f32::powi);
-    pow_impl!(f32, i16, i32, f32::powi);
-    pow_impl!(f32, u16, i32, f32::powi);
-    pow_impl!(f32, i32, i32, f32::powi);
-    pow_impl!(f64, i8, i32, f64::powi);
-    pow_impl!(f64, u8, i32, f64::powi);
-    pow_impl!(f64, i16, i32, f64::powi);
-    pow_impl!(f64, u16, i32, f64::powi);
-    pow_impl!(f64, i32, i32, f64::powi);
-    pow_impl!(f32, f32, f32, f32::powf);
-    pow_impl!(f64, f32, f64, f64::powf);
-    pow_impl!(f64, f64, f64, f64::powf);
+    pow_impl!(f32, i8, i32,  <f32 as Float>::powi);
+    pow_impl!(f32, u8, i32,  <f32 as Float>::powi);
+    pow_impl!(f32, i16, i32, <f32 as Float>::powi);
+    pow_impl!(f32, u16, i32, <f32 as Float>::powi);
+    pow_impl!(f32, i32, i32, <f32 as Float>::powi);
+    pow_impl!(f64, i8, i32,  <f64 as Float>::powi);
+    pow_impl!(f64, u8, i32,  <f64 as Float>::powi);
+    pow_impl!(f64, i16, i32, <f64 as Float>::powi);
+    pow_impl!(f64, u16, i32, <f64 as Float>::powi);
+    pow_impl!(f64, i32, i32, <f64 as Float>::powi);
+    pow_impl!(f32, f32, f32, <f32 as Float>::powf);
+    pow_impl!(f64, f32, f64, <f64 as Float>::powf);
+    pow_impl!(f64, f64, f64, <f64 as Float>::powf);
 }
 
 /// Raises a value to the power of exp, using exponentiation by squaring.