From 5bdff3f0ff194b2f783fc55f2fffc8b905d457da Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sun, 18 Feb 2018 14:29:21 -0500 Subject: [PATCH 1/7] Add Inv trait. --- src/lib.rs | 1 + src/ops/inv.rs | 29 +++++++++++++++++++++++++++++ src/ops/mod.rs | 1 + 3 files changed, 31 insertions(+) create mode 100644 src/ops/inv.rs diff --git a/src/lib.rs b/src/lib.rs index 83a45f9..2b4844b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ pub use float::Float; pub use float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use identities::{Zero, One, zero, one}; +pub use ops::inv::Inv; pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr}; pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub}; pub use ops::saturating::Saturating; diff --git a/src/ops/inv.rs b/src/ops/inv.rs new file mode 100644 index 0000000..16f3643 --- /dev/null +++ b/src/ops/inv.rs @@ -0,0 +1,29 @@ +/// Unary operator for retrieving the multiplicative inverse, or reciprocal, of a value. +pub trait Inv { + /// The result after applying the operator. + type Output; + + /// Returns the multiplicative inverse of `Self`. + fn inv(self) -> Self::Output; +} + +macro_rules! inv_impl { + ($t:ty, $out:ty, $fn:expr) => { + impl<'a> Inv for $t { + type Output = $out; + + #[inline] + fn inv(self) -> $out { + ($fn)(self) + } + } + } +} + +#[cfg(feature = "std")] +mod float_impls { + inv_impl!(f32, f32, f32::recip); + inv_impl!(f64, f64, f64::recip); + inv_impl!(&'a f32, f32, f32::recip); + inv_impl!(&'a f64, f64, f64::recip); +} diff --git a/src/ops/mod.rs b/src/ops/mod.rs index ec9edeb..b83a2a5 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -1,3 +1,4 @@ pub mod saturating; pub mod checked; pub mod wrapping; +pub mod new; From c1f4118b4e161fcde40be80d979b138c9f62e20b Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Mon, 19 Feb 2018 15:00:36 -0500 Subject: [PATCH 2/7] Fix Inv trait, add Pow trait. --- src/lib.rs | 1 + src/ops/inv.rs | 49 ++++++++++++++++++++-------------- src/ops/mod.rs | 3 ++- src/ops/pow.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 20 deletions(-) create mode 100644 src/ops/pow.rs diff --git a/src/lib.rs b/src/lib.rs index 2b4844b..bf98f2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ pub use float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use identities::{Zero, One, zero, one}; pub use ops::inv::Inv; +pub use ops::pow::Pow; pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr}; pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub}; pub use ops::saturating::Saturating; diff --git a/src/ops/inv.rs b/src/ops/inv.rs index 16f3643..9d04cd2 100644 --- a/src/ops/inv.rs +++ b/src/ops/inv.rs @@ -3,27 +3,38 @@ pub trait Inv { /// The result after applying the operator. type Output; - /// Returns the multiplicative inverse of `Self`. + /// Returns the multiplicative inverse of `self`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::{Inv, One}; + /// + /// let x = 7.0; + /// let y = -0.0; + /// assert_eq!(x.inv() * x, One::one()); + /// assert_eq!(y.inv() * y, One::one()); + /// ``` fn inv(self) -> Self::Output; } -macro_rules! inv_impl { - ($t:ty, $out:ty, $fn:expr) => { - impl<'a> Inv for $t { - type Output = $out; - - #[inline] - fn inv(self) -> $out { - ($fn)(self) - } - } - } +impl Inv for f32 { + type Output = f32; + #[inline] + fn inv(self) -> f32 { 1.0 / self } } - -#[cfg(feature = "std")] -mod float_impls { - inv_impl!(f32, f32, f32::recip); - inv_impl!(f64, f64, f64::recip); - inv_impl!(&'a f32, f32, f32::recip); - inv_impl!(&'a f64, f64, f64::recip); +impl Inv for f64 { + type Output = f64; + #[inline] + fn inv(self) -> f64 { 1.0 / self } +} +impl<'a> Inv for &'a f32 { + type Output = f32; + #[inline] + fn inv(self) -> f32 { 1.0 / *self } +} +impl<'a> Inv for &'a f64 { + type Output = f64; + #[inline] + fn inv(self) -> f64 { 1.0 / *self } } diff --git a/src/ops/mod.rs b/src/ops/mod.rs index b83a2a5..6f7f022 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -1,4 +1,5 @@ pub mod saturating; pub mod checked; pub mod wrapping; -pub mod new; +pub mod inv; +pub mod pow; diff --git a/src/ops/pow.rs b/src/ops/pow.rs new file mode 100644 index 0000000..9f7dd1e --- /dev/null +++ b/src/ops/pow.rs @@ -0,0 +1,71 @@ +/// Binary operator for raising a value to a power. +pub trait Pow { + /// The result after applying the operator. + type Output; + + /// Returns `self` to the power `rhs`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::Pow; + /// assert_eq!(10.pow(2), 100); + /// ``` + fn pow(self, rhs: RHS) -> Self::Output; +} + +macro_rules! pow_impl { + ($t:ty, $rhs:ty, $method:ident) => { + impl Pow<$rhs> for $t { + type Output = $t; + + #[inline] + fn pow(self, rhs: $rhs) -> $t { + <$t>::$method(self, rhs) + } + } + + impl<'a> Pow<&'a $rhs> for $t { + type Output = $t; + #[inline] + fn pow(self, rhs: &'a $rhs) -> $t { + <$t>::$method(self, *rhs) + } + } + + impl<'a> Pow<$rhs> for &'a $t { + type Output = $t; + #[inline] + fn pow(self, rhs: $rhs) -> $t { + <$t>::$method(*self, rhs) + } + } + + impl<'a, 'b> Pow<&'a $rhs> for &'b $t { + type Output = $t; + #[inline] + fn pow(self, rhs: &'a $rhs) -> $t { + <$t>::$method(*self, *rhs) + } + } + } +} + +pow_impl!(u8, u32, pow); +pow_impl!(i8, u32, pow); +pow_impl!(u16, u32, pow); +pow_impl!(i16, u32, pow); +pow_impl!(u32, u32, pow); +pow_impl!(i32, u32, pow); +pow_impl!(u64, u32, pow); +pow_impl!(i64, u32, pow); +pow_impl!(usize, u32, pow); +pow_impl!(isize, u32, pow); + +#[cfg(feature = "std")] +mod float_impls { + pow_impl!(f32, i32, powi); + pow_impl!(f64, i32, powi); + pow_impl!(f32, f32, powf); + pow_impl!(f64, f64, powf); +} From ce3badca570507df4efae6ea1d9b1b4d74746b1f Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Mon, 19 Feb 2018 15:17:41 -0500 Subject: [PATCH 3/7] Move Pow to pow module. --- src/lib.rs | 3 +- src/ops/mod.rs | 1 - src/ops/pow.rs | 71 ----------------------------------------------- src/pow.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 74 deletions(-) delete mode 100644 src/ops/pow.rs diff --git a/src/lib.rs b/src/lib.rs index bf98f2b..14bb3d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,14 +34,13 @@ pub use float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use identities::{Zero, One, zero, one}; pub use ops::inv::Inv; -pub use ops::pow::Pow; pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr}; pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub}; pub use ops::saturating::Saturating; pub use sign::{Signed, Unsigned, abs, abs_sub, signum}; pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast}; pub use int::PrimInt; -pub use pow::{pow, checked_pow}; +pub use pow::{Pow, pow, checked_pow}; pub mod identities; pub mod sign; diff --git a/src/ops/mod.rs b/src/ops/mod.rs index 6f7f022..7b9a7e3 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -2,4 +2,3 @@ pub mod saturating; pub mod checked; pub mod wrapping; pub mod inv; -pub mod pow; diff --git a/src/ops/pow.rs b/src/ops/pow.rs deleted file mode 100644 index 9f7dd1e..0000000 --- a/src/ops/pow.rs +++ /dev/null @@ -1,71 +0,0 @@ -/// Binary operator for raising a value to a power. -pub trait Pow { - /// The result after applying the operator. - type Output; - - /// Returns `self` to the power `rhs`. - /// - /// # Examples - /// - /// ``` - /// use num_traits::Pow; - /// assert_eq!(10.pow(2), 100); - /// ``` - fn pow(self, rhs: RHS) -> Self::Output; -} - -macro_rules! pow_impl { - ($t:ty, $rhs:ty, $method:ident) => { - impl Pow<$rhs> for $t { - type Output = $t; - - #[inline] - fn pow(self, rhs: $rhs) -> $t { - <$t>::$method(self, rhs) - } - } - - impl<'a> Pow<&'a $rhs> for $t { - type Output = $t; - #[inline] - fn pow(self, rhs: &'a $rhs) -> $t { - <$t>::$method(self, *rhs) - } - } - - impl<'a> Pow<$rhs> for &'a $t { - type Output = $t; - #[inline] - fn pow(self, rhs: $rhs) -> $t { - <$t>::$method(*self, rhs) - } - } - - impl<'a, 'b> Pow<&'a $rhs> for &'b $t { - type Output = $t; - #[inline] - fn pow(self, rhs: &'a $rhs) -> $t { - <$t>::$method(*self, *rhs) - } - } - } -} - -pow_impl!(u8, u32, pow); -pow_impl!(i8, u32, pow); -pow_impl!(u16, u32, pow); -pow_impl!(i16, u32, pow); -pow_impl!(u32, u32, pow); -pow_impl!(i32, u32, pow); -pow_impl!(u64, u32, pow); -pow_impl!(i64, u32, pow); -pow_impl!(usize, u32, pow); -pow_impl!(isize, u32, pow); - -#[cfg(feature = "std")] -mod float_impls { - pow_impl!(f32, i32, powi); - pow_impl!(f64, i32, powi); - pow_impl!(f32, f32, powf); - pow_impl!(f64, f64, powf); -} diff --git a/src/pow.rs b/src/pow.rs index 212a1de..352d30c 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -1,6 +1,81 @@ use core::ops::Mul; use {One, CheckedMul}; +/// Binary operator for raising a value to a power. +pub trait Pow { + /// The result after applying the operator. + type Output; + + /// Returns `self` to the power `rhs`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::Pow; + /// assert_eq!(10.pow(2), 100); + /// ``` + fn pow(self, rhs: RHS) -> Self::Output; +} + +macro_rules! pow_impl { + ($t:ty, $rhs:ty, $method:ident) => { + impl Pow<$rhs> for $t { + type Output = $t; + + #[inline] + fn pow(self, rhs: $rhs) -> $t { + <$t>::$method(self, rhs) + } + } + + impl<'a> Pow<&'a $rhs> for $t { + type Output = $t; + #[inline] + fn pow(self, rhs: &'a $rhs) -> $t { + <$t>::$method(self, *rhs) + } + } + + impl<'a> Pow<$rhs> for &'a $t { + type Output = $t; + #[inline] + fn pow(self, rhs: $rhs) -> $t { + <$t>::$method(*self, rhs) + } + } + + impl<'a, 'b> Pow<&'a $rhs> for &'b $t { + type Output = $t; + #[inline] + fn pow(self, rhs: &'a $rhs) -> $t { + <$t>::$method(*self, *rhs) + } + } + } +} + +pow_impl!(u8, u32, pow); +pow_impl!(i8, u32, pow); +pow_impl!(u16, u32, pow); +pow_impl!(i16, u32, pow); +pow_impl!(u32, u32, pow); +pow_impl!(i32, u32, pow); +pow_impl!(u64, u32, pow); +pow_impl!(i64, u32, pow); +pow_impl!(usize, u32, pow); +pow_impl!(isize, u32, pow); + +#[cfg(feature = "std")] +mod float_impls { + use super::Pow; + + pow_impl!(f32, i32, powi); + pow_impl!(f64, i32, powi); + pow_impl!(f32, f32, powf); + pow_impl!(f64, f64, powf); +} + + /// Raises a value to the power of exp, using exponentiation by squaring. /// /// # Example From 5d6933f34a9b3b483affca186691924d9f6d4d3c Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 23 Feb 2018 17:20:08 -0500 Subject: [PATCH 4/7] Fix doc tests. --- src/ops/inv.rs | 9 ++++----- src/pow.rs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ops/inv.rs b/src/ops/inv.rs index 9d04cd2..38e89ea 100644 --- a/src/ops/inv.rs +++ b/src/ops/inv.rs @@ -8,12 +8,11 @@ pub trait Inv { /// # Examples /// /// ``` - /// use num_traits::{Inv, One}; + /// use std::f64::INFINITY; + /// use num_traits::Inv; /// - /// let x = 7.0; - /// let y = -0.0; - /// assert_eq!(x.inv() * x, One::one()); - /// assert_eq!(y.inv() * y, One::one()); + /// assert_eq!(7.0.inv() * 7.0, 1.0); + /// assert_eq!((-0.0).inv(), -INFINITY); /// ``` fn inv(self) -> Self::Output; } diff --git a/src/pow.rs b/src/pow.rs index 352d30c..c51576f 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -12,7 +12,7 @@ pub trait Pow { /// /// ``` /// use num_traits::Pow; - /// assert_eq!(10.pow(2), 100); + /// assert_eq!(Pow::pow(10u32, 2u32), 100); /// ``` fn pow(self, rhs: RHS) -> Self::Output; } From 61a6acc9c2d73c70ef8525286e368dd90d146923 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 23 Feb 2018 17:43:27 -0500 Subject: [PATCH 5/7] Add more Pow implementations. --- src/pow.rs | 101 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 21 deletions(-) diff --git a/src/pow.rs b/src/pow.rs index c51576f..39dcc18 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -1,4 +1,5 @@ use core::ops::Mul; +use core::num::Wrapping; use {One, CheckedMul}; /// Binary operator for raising a value to a power. @@ -18,13 +19,22 @@ pub trait Pow { } macro_rules! pow_impl { - ($t:ty, $rhs:ty, $method:ident) => { + ($t:ty) => { + pow_impl!($t, u8); + pow_impl!($t, u16); + pow_impl!($t, u32); + pow_impl!($t, u64); + pow_impl!($t, usize); + }; + ($t:ty, $rhs:ty) => { + pow_impl!($t, $rhs, |x, p| pow(x, p as usize)); + }; + ($t:ty, $rhs:ty, $method:expr) => { impl Pow<$rhs> for $t { type Output = $t; - #[inline] fn pow(self, rhs: $rhs) -> $t { - <$t>::$method(self, rhs) + ($method)(self, rhs) } } @@ -32,7 +42,7 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: &'a $rhs) -> $t { - <$t>::$method(self, *rhs) + ($method)(self, *rhs) } } @@ -40,7 +50,7 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: $rhs) -> $t { - <$t>::$method(*self, rhs) + ($method)(*self, rhs) } } @@ -48,31 +58,80 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: &'a $rhs) -> $t { - <$t>::$method(*self, *rhs) + ($method)(*self, *rhs) } } - } + }; } -pow_impl!(u8, u32, pow); -pow_impl!(i8, u32, pow); -pow_impl!(u16, u32, pow); -pow_impl!(i16, u32, pow); -pow_impl!(u32, u32, pow); -pow_impl!(i32, u32, pow); -pow_impl!(u64, u32, pow); -pow_impl!(i64, u32, pow); -pow_impl!(usize, u32, pow); -pow_impl!(isize, u32, pow); +pow_impl!(u8, u8, |x: u8, p| x.pow(p as u32)); +pow_impl!(u8, u16, |x: u8, p| x.pow(p as u32)); +pow_impl!(u8, u32, u8::pow); +pow_impl!(u8, usize); +pow_impl!(i8, u8, |x: i8, p| x.pow(p as u32)); +pow_impl!(i8, u16, |x: i8, p| x.pow(p as u32)); +pow_impl!(i8, u32, i8::pow); +pow_impl!(i8, usize); +pow_impl!(u16, u8, |x: u16, p| x.pow(p as u32)); +pow_impl!(u16, u16, |x: u16, p| x.pow(p as u32)); +pow_impl!(u16, u32, u16::pow); +pow_impl!(u16, usize); +pow_impl!(i16, u8, |x: i16, p| x.pow(p as u32)); +pow_impl!(i16, u16, |x: i16, p| x.pow(p as u32)); +pow_impl!(i16, u32, i16::pow); +pow_impl!(i16, usize); +pow_impl!(u32, u8, |x: u32, p| x.pow(p as u32)); +pow_impl!(u32, u16, |x: u32, p| x.pow(p as u32)); +pow_impl!(u32, u32, u32::pow); +pow_impl!(u32, usize); +pow_impl!(i32, u8, |x: i32, p| x.pow(p as u32)); +pow_impl!(i32, u16, |x: i32, p| x.pow(p as u32)); +pow_impl!(i32, u32, i32::pow); +pow_impl!(i32, usize); +pow_impl!(u64, u8, |x: u64, p| x.pow(p as u32)); +pow_impl!(u64, u16, |x: u64, p| x.pow(p as u32)); +pow_impl!(u64, u32, u64::pow); +pow_impl!(u64, usize); +pow_impl!(i64, u8, |x: i64, p| x.pow(p as u32)); +pow_impl!(i64, u16, |x: i64, p| x.pow(p as u32)); +pow_impl!(i64, u32, i64::pow); +pow_impl!(i64, usize); +pow_impl!(usize, u8, |x: usize, p| x.pow(p as u32)); +pow_impl!(usize, u16, |x: usize, p| x.pow(p as u32)); +pow_impl!(usize, u32, usize::pow); +pow_impl!(usize, usize); +pow_impl!(isize, u8, |x: isize, p| x.pow(p as u32)); +pow_impl!(isize, u16, |x: isize, p| x.pow(p as u32)); +pow_impl!(isize, u32, isize::pow); +pow_impl!(isize, usize); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); +pow_impl!(Wrapping); #[cfg(feature = "std")] mod float_impls { use super::Pow; - pow_impl!(f32, i32, powi); - pow_impl!(f64, i32, powi); - pow_impl!(f32, f32, powf); - pow_impl!(f64, f64, powf); + pow_impl!(f32, i8, |x: f32, p| x.powi(p as i32)); + pow_impl!(f32, u8, |x: f32, p| x.powi(p as i32)); + pow_impl!(f32, i16, |x: f32, p| x.powi(p as i32)); + pow_impl!(f32, u16, |x: f32, p| x.powi(p as i32)); + pow_impl!(f32, i32, f32::powi); + pow_impl!(f64, i8, |x: f64, p| x.powi(p as i32)); + pow_impl!(f64, u8, |x: f64, p| x.powi(p as i32)); + pow_impl!(f64, i16, |x: f64, p| x.powi(p as i32)); + pow_impl!(f64, u16, |x: f64, p| x.powi(p as i32)); + pow_impl!(f64, i32, f64::powi); + pow_impl!(f32, f32, f32::powf); + pow_impl!(f64, f32, |x: f64, p| x.powf(p as f64)); + pow_impl!(f64, f64, f64::powf); } From aca8dc8149766250cea238e6590390a467583707 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 23 Feb 2018 18:03:40 -0500 Subject: [PATCH 6/7] Remove Pow (accidentally added). --- src/pow.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pow.rs b/src/pow.rs index 39dcc18..c6fbdfb 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -23,7 +23,6 @@ macro_rules! pow_impl { pow_impl!($t, u8); pow_impl!($t, u16); pow_impl!($t, u32); - pow_impl!($t, u64); pow_impl!($t, usize); }; ($t:ty, $rhs:ty) => { From 79b557f04000a37724f3245040bbc2e43e3d1dd6 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Tue, 27 Feb 2018 14:06:46 -0500 Subject: [PATCH 7/7] Ensure infalliability of conversions, avoid closures. --- src/pow.rs | 118 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/src/pow.rs b/src/pow.rs index c6fbdfb..e2dc740 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -21,19 +21,22 @@ pub trait Pow { macro_rules! pow_impl { ($t:ty) => { pow_impl!($t, u8); - pow_impl!($t, u16); - pow_impl!($t, u32); pow_impl!($t, usize); + + // FIXME: these should be possible + // pow_impl!($t, u16); + // pow_impl!($t, u32); + // pow_impl!($t, u64); }; ($t:ty, $rhs:ty) => { - pow_impl!($t, $rhs, |x, p| pow(x, p as usize)); + pow_impl!($t, $rhs, usize, pow); }; - ($t:ty, $rhs:ty, $method:expr) => { + ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => { impl Pow<$rhs> for $t { type Output = $t; #[inline] fn pow(self, rhs: $rhs) -> $t { - ($method)(self, rhs) + ($method)(self, <$desired_rhs>::from(rhs)) } } @@ -41,7 +44,7 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: &'a $rhs) -> $t { - ($method)(self, *rhs) + ($method)(self, <$desired_rhs>::from(*rhs)) } } @@ -49,7 +52,7 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: $rhs) -> $t { - ($method)(*self, rhs) + ($method)(*self, <$desired_rhs>::from(rhs)) } } @@ -57,51 +60,51 @@ macro_rules! pow_impl { type Output = $t; #[inline] fn pow(self, rhs: &'a $rhs) -> $t { - ($method)(*self, *rhs) + ($method)(*self, <$desired_rhs>::from(*rhs)) } } }; } -pow_impl!(u8, u8, |x: u8, p| x.pow(p as u32)); -pow_impl!(u8, u16, |x: u8, p| x.pow(p as u32)); -pow_impl!(u8, u32, u8::pow); +pow_impl!(u8, u8, u32, u8::pow); +pow_impl!(u8, u16, u32, u8::pow); +pow_impl!(u8, u32, u32, u8::pow); pow_impl!(u8, usize); -pow_impl!(i8, u8, |x: i8, p| x.pow(p as u32)); -pow_impl!(i8, u16, |x: i8, p| x.pow(p as u32)); -pow_impl!(i8, u32, i8::pow); +pow_impl!(i8, u8, u32, i8::pow); +pow_impl!(i8, u16, u32, i8::pow); +pow_impl!(i8, u32, u32, i8::pow); pow_impl!(i8, usize); -pow_impl!(u16, u8, |x: u16, p| x.pow(p as u32)); -pow_impl!(u16, u16, |x: u16, p| x.pow(p as u32)); -pow_impl!(u16, u32, u16::pow); +pow_impl!(u16, u8, u32, u16::pow); +pow_impl!(u16, u16, u32, u16::pow); +pow_impl!(u16, u32, u32, u16::pow); pow_impl!(u16, usize); -pow_impl!(i16, u8, |x: i16, p| x.pow(p as u32)); -pow_impl!(i16, u16, |x: i16, p| x.pow(p as u32)); -pow_impl!(i16, u32, i16::pow); +pow_impl!(i16, u8, u32, i16::pow); +pow_impl!(i16, u16, u32, i16::pow); +pow_impl!(i16, u32, u32, i16::pow); pow_impl!(i16, usize); -pow_impl!(u32, u8, |x: u32, p| x.pow(p as u32)); -pow_impl!(u32, u16, |x: u32, p| x.pow(p as u32)); -pow_impl!(u32, u32, u32::pow); +pow_impl!(u32, u8, u32, u32::pow); +pow_impl!(u32, u16, u32, u32::pow); +pow_impl!(u32, u32, u32, u32::pow); pow_impl!(u32, usize); -pow_impl!(i32, u8, |x: i32, p| x.pow(p as u32)); -pow_impl!(i32, u16, |x: i32, p| x.pow(p as u32)); -pow_impl!(i32, u32, i32::pow); +pow_impl!(i32, u8, u32, i32::pow); +pow_impl!(i32, u16, u32, i32::pow); +pow_impl!(i32, u32, u32, i32::pow); pow_impl!(i32, usize); -pow_impl!(u64, u8, |x: u64, p| x.pow(p as u32)); -pow_impl!(u64, u16, |x: u64, p| x.pow(p as u32)); -pow_impl!(u64, u32, u64::pow); +pow_impl!(u64, u8, u32, u64::pow); +pow_impl!(u64, u16, u32, u64::pow); +pow_impl!(u64, u32, u32, u64::pow); pow_impl!(u64, usize); -pow_impl!(i64, u8, |x: i64, p| x.pow(p as u32)); -pow_impl!(i64, u16, |x: i64, p| x.pow(p as u32)); -pow_impl!(i64, u32, i64::pow); +pow_impl!(i64, u8, u32, i64::pow); +pow_impl!(i64, u16, u32, i64::pow); +pow_impl!(i64, u32, u32, i64::pow); pow_impl!(i64, usize); -pow_impl!(usize, u8, |x: usize, p| x.pow(p as u32)); -pow_impl!(usize, u16, |x: usize, p| x.pow(p as u32)); -pow_impl!(usize, u32, usize::pow); +pow_impl!(usize, u8, u32, usize::pow); +pow_impl!(usize, u16, u32, usize::pow); +pow_impl!(usize, u32, u32, usize::pow); pow_impl!(usize, usize); -pow_impl!(isize, u8, |x: isize, p| x.pow(p as u32)); -pow_impl!(isize, u16, |x: isize, p| x.pow(p as u32)); -pow_impl!(isize, u32, isize::pow); +pow_impl!(isize, u8, u32, isize::pow); +pow_impl!(isize, u16, u32, isize::pow); +pow_impl!(isize, u32, u32, isize::pow); pow_impl!(isize, usize); pow_impl!(Wrapping); pow_impl!(Wrapping); @@ -114,26 +117,37 @@ pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); +// FIXME: these should be possible +// pow_impl!(u8, u64); +// pow_impl!(i16, u64); +// pow_impl!(i8, u64); +// pow_impl!(u16, u64); +// pow_impl!(u32, u64); +// pow_impl!(i32, u64); +// pow_impl!(u64, u64); +// pow_impl!(i64, u64); +// pow_impl!(usize, u64); +// pow_impl!(isize, u64); + #[cfg(feature = "std")] mod float_impls { use super::Pow; - pow_impl!(f32, i8, |x: f32, p| x.powi(p as i32)); - pow_impl!(f32, u8, |x: f32, p| x.powi(p as i32)); - pow_impl!(f32, i16, |x: f32, p| x.powi(p as i32)); - pow_impl!(f32, u16, |x: f32, p| x.powi(p as i32)); - pow_impl!(f32, i32, f32::powi); - pow_impl!(f64, i8, |x: f64, p| x.powi(p as i32)); - pow_impl!(f64, u8, |x: f64, p| x.powi(p as i32)); - pow_impl!(f64, i16, |x: f64, p| x.powi(p as i32)); - pow_impl!(f64, u16, |x: f64, p| x.powi(p as i32)); - pow_impl!(f64, i32, f64::powi); - pow_impl!(f32, f32, f32::powf); - pow_impl!(f64, f32, |x: f64, p| x.powf(p as f64)); - pow_impl!(f64, f64, f64::powf); + 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); } - /// Raises a value to the power of exp, using exponentiation by squaring. /// /// # Example