Merge #41
41: Various improvements to FloatCore r=vks a=cuviper - New macros simplify forwarding method implementations. - `Float` and `Real` use this to compact their implementations. - `FloatCore` now forwards `std` implementations when possible. - `FloatCore` now requires `NumCast`, like `Float does. - New additions to `FloatCore`: - Constants like `min_value()` -> `f64::MIN` - Rounding methods `floor`, `ceil`, `round`, `trunc`, `fract` - `integer_decode` matching `Float`'s - Fix NAN sign handling in `FloatCore` (rust-num/num#312, rust-lang/rust#42425) - Fix overflow in `FloatCore::powi` exponent negation. - Add doctests to all `FloatCore` methods.
This commit is contained in:
commit
5f906234bc
|
@ -1,4 +1,3 @@
|
|||
use core::f64;
|
||||
use core::mem::size_of;
|
||||
use core::num::Wrapping;
|
||||
|
||||
|
|
1089
src/float.rs
1089
src/float.rs
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// 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 {
|
||||
($( 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 ),* )
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
macro_rules! constant {
|
||||
($( $method:ident () -> $ret:expr ; )*)
|
||||
=> {$(
|
||||
#[inline]
|
||||
fn $method() -> Self {
|
||||
$ret
|
||||
}
|
||||
)*};
|
||||
}
|
188
src/real.rs
188
src/real.rs
|
@ -782,145 +782,55 @@ pub trait Real
|
|||
}
|
||||
|
||||
impl<T: Float> Real for T {
|
||||
fn min_value() -> Self {
|
||||
Self::min_value()
|
||||
forward! {
|
||||
Float::min_value() -> Self;
|
||||
Float::min_positive_value() -> Self;
|
||||
Float::epsilon() -> Self;
|
||||
Float::max_value() -> Self;
|
||||
}
|
||||
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::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;
|
||||
}
|
||||
}
|
||||
|
|
15
src/sign.rs
15
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.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue