Merge #30
30: Re-introduce the std feature r=vks a=cuviper This is a port of @vks's rust-num/num#296, but without the feature-toggled changes to `Float`. Now `Float` and the newer `Real` are completely dependent on having `std` enabled. In the future we can consider adding separate more-limited float/real traits that can work without `std`, like the `BaseFloat` that was originally proposed in the former PR. This is a breaking change with a bump to 0.2, since anyone currently using `default-features = false` will lose functionality. The actual API is otherwise unchanged, so my plan is to employ the "semver trick" -- publishing a new num-traits-0.1 that re-exports everything from 0.2 (with `std`). Thus all `num-traits` users should remain compatible even if they mix 0.1 and 0.2. Closes #16.
This commit is contained in:
commit
afa81f80e4
|
@ -8,7 +8,11 @@ categories = [ "algorithms", "science" ]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
repository = "https://github.com/rust-num/num-traits"
|
repository = "https://github.com/rust-num/num-traits"
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.1.42"
|
version = "0.2.0-pre"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = []
|
||||||
|
|
15
README.md
15
README.md
|
@ -12,7 +12,7 @@ Add this to your `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "0.1"
|
num-traits = "0.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
and this to your crate root:
|
||||||
|
@ -21,6 +21,19 @@ and this to your crate root:
|
||||||
extern crate num_traits;
|
extern crate num_traits;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
This crate can be used without the standard library (`#![no_std]`) by disabling
|
||||||
|
the default `std` feature. Use this in `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies.num-traits]
|
||||||
|
version = "0.2"
|
||||||
|
default-features = false
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Float` and `Real` traits are only available when `std` is enabled.
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
Release notes are available in [RELEASES.md](RELEASES.md).
|
Release notes are available in [RELEASES.md](RELEASES.md).
|
||||||
|
|
|
@ -4,8 +4,10 @@ set -ex
|
||||||
|
|
||||||
echo Testing num-traits on rustc ${TRAVIS_RUST_VERSION}
|
echo Testing num-traits on rustc ${TRAVIS_RUST_VERSION}
|
||||||
|
|
||||||
# num-integer should build and test everywhere.
|
# num-traits should build and test everywhere.
|
||||||
cargo build --verbose
|
cargo build --verbose
|
||||||
cargo test --verbose
|
cargo test --verbose
|
||||||
|
|
||||||
# We have no features to test...
|
# test `no_std`
|
||||||
|
cargo build --verbose --no-default-features
|
||||||
|
cargo test --verbose --no-default-features
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{usize, u8, u16, u32, u64};
|
use core::{usize, u8, u16, u32, u64};
|
||||||
use std::{isize, i8, i16, i32, i64};
|
use core::{isize, i8, i16, i32, i64};
|
||||||
use std::{f32, f64};
|
use core::{f32, f64};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
/// Numbers which have upper and lower bounds
|
/// Numbers which have upper and lower bounds
|
||||||
pub trait Bounded {
|
pub trait Bounded {
|
||||||
|
|
15
src/cast.rs
15
src/cast.rs
|
@ -1,5 +1,6 @@
|
||||||
use std::mem::size_of;
|
use core::f64;
|
||||||
use std::num::Wrapping;
|
use core::mem::size_of;
|
||||||
|
use core::num::Wrapping;
|
||||||
|
|
||||||
use identities::Zero;
|
use identities::Zero;
|
||||||
use bounds::Bounded;
|
use bounds::Bounded;
|
||||||
|
@ -226,8 +227,10 @@ macro_rules! impl_to_primitive_float_to_float {
|
||||||
// Make sure the value is in range for the cast.
|
// Make sure the value is in range for the cast.
|
||||||
// NaN and +-inf are cast as they are.
|
// NaN and +-inf are cast as they are.
|
||||||
let n = $slf as f64;
|
let n = $slf as f64;
|
||||||
let max_value: $DstT = ::std::$DstT::MAX;
|
let max_value: $DstT = ::core::$DstT::MAX;
|
||||||
if !n.is_finite() || (-max_value as f64 <= n && n <= max_value as f64) {
|
if n != n || n == f64::INFINITY || n == f64::NEG_INFINITY
|
||||||
|
|| (-max_value as f64 <= n && n <= max_value as f64)
|
||||||
|
{
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -522,8 +525,8 @@ impl_as_primitive!(bool => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_primitive_float() {
|
fn to_primitive_float() {
|
||||||
use std::f32;
|
use core::f32;
|
||||||
use std::f64;
|
use core::f64;
|
||||||
|
|
||||||
let f32_toolarge = 1e39f64;
|
let f32_toolarge = 1e39f64;
|
||||||
assert_eq!(f32_toolarge.to_f32(), None);
|
assert_eq!(f32_toolarge.to_f32(), None);
|
||||||
|
|
20
src/float.rs
20
src/float.rs
|
@ -1,15 +1,24 @@
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::num::FpCategory;
|
use std::num::FpCategory;
|
||||||
|
|
||||||
// Used for default implementation of `epsilon`
|
// Used for default implementation of `epsilon`
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::f32;
|
use std::f32;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use {Num, NumCast};
|
use {Num, NumCast};
|
||||||
|
|
||||||
// FIXME: these doctests aren't actually helpful, because they're using and
|
// FIXME: these doctests aren't actually helpful, because they're using and
|
||||||
// testing the inherent methods directly, not going through `Float`.
|
// testing the inherent methods directly, not going through `Float`.
|
||||||
|
|
||||||
|
/// Generic trait for floating point numbers
|
||||||
|
///
|
||||||
|
/// This trait is only available with the `std` feature.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub trait Float
|
pub trait Float
|
||||||
: Num
|
: Num
|
||||||
+ Copy
|
+ Copy
|
||||||
|
@ -923,6 +932,7 @@ pub trait Float
|
||||||
fn integer_decode(self) -> (u64, i16, i8);
|
fn integer_decode(self) -> (u64, i16, i8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
macro_rules! float_impl {
|
macro_rules! float_impl {
|
||||||
($T:ident $decode:ident) => (
|
($T:ident $decode:ident) => (
|
||||||
impl Float for $T {
|
impl Float for $T {
|
||||||
|
@ -1219,6 +1229,7 @@ macro_rules! float_impl {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
let bits: u32 = unsafe { mem::transmute(f) };
|
let bits: u32 = unsafe { mem::transmute(f) };
|
||||||
let sign: i8 = if bits >> 31 == 0 {
|
let sign: i8 = if bits >> 31 == 0 {
|
||||||
|
@ -1237,6 +1248,7 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
(mantissa as u64, exponent, sign)
|
(mantissa as u64, exponent, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
let bits: u64 = unsafe { mem::transmute(f) };
|
let bits: u64 = unsafe { mem::transmute(f) };
|
||||||
let sign: i8 = if bits >> 63 == 0 {
|
let sign: i8 = if bits >> 63 == 0 {
|
||||||
|
@ -1255,7 +1267,9 @@ fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
(mantissa, exponent, sign)
|
(mantissa, exponent, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
float_impl!(f32 integer_decode_f32);
|
float_impl!(f32 integer_decode_f32);
|
||||||
|
#[cfg(feature = "std")]
|
||||||
float_impl!(f64 integer_decode_f64);
|
float_impl!(f64 integer_decode_f64);
|
||||||
|
|
||||||
macro_rules! float_const_impl {
|
macro_rules! float_const_impl {
|
||||||
|
@ -1272,7 +1286,7 @@ macro_rules! float_const_impl {
|
||||||
$(
|
$(
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $constant() -> Self {
|
fn $constant() -> Self {
|
||||||
::std::$T::consts::$constant
|
::core::$T::consts::$constant
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
@ -1314,13 +1328,13 @@ float_const_impl! {
|
||||||
SQRT_2,
|
SQRT_2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(all(test, feature = "std"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use Float;
|
use Float;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_deg_rad() {
|
fn convert_deg_rad() {
|
||||||
use std::f64::consts;
|
use core::f64::consts;
|
||||||
|
|
||||||
const DEG_RAD_PAIRS: [(f64, f64); 7] = [
|
const DEG_RAD_PAIRS: [(f64, f64); 7] = [
|
||||||
(0.0, 0.),
|
(0.0, 0.),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ops::{Add, Mul};
|
use core::ops::{Add, Mul};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
/// Defines an additive identity element for `Self`.
|
/// Defines an additive identity element for `Self`.
|
||||||
pub trait Zero: Sized + Add<Self, Output = Self> {
|
pub trait Zero: Sized + Add<Self, Output = Self> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||||
|
|
||||||
use {Num, NumCast};
|
use {Num, NumCast};
|
||||||
use bounds::Bounded;
|
use bounds::Bounded;
|
||||||
|
|
63
src/lib.rs
63
src/lib.rs
|
@ -10,22 +10,30 @@
|
||||||
|
|
||||||
//! Numeric traits for generic mathematics
|
//! Numeric traits for generic mathematics
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/num-traits/0.1")]
|
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
|
||||||
|
|
||||||
use std::ops::{Add, Sub, Mul, Div, Rem};
|
#![deny(unconditional_recursion)]
|
||||||
use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
|
||||||
use std::num::Wrapping;
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
use std::fmt;
|
#[cfg(feature = "std")]
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
|
use core::ops::{Add, Sub, Mul, Div, Rem};
|
||||||
|
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||||
|
use core::num::Wrapping;
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
pub use bounds::Bounded;
|
pub use bounds::Bounded;
|
||||||
pub use float::{Float, FloatConst};
|
#[cfg(feature = "std")]
|
||||||
|
pub use float::Float;
|
||||||
|
pub use float::FloatConst;
|
||||||
// pub use real::Real; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
// pub use real::Real; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
||||||
pub use identities::{Zero, One, zero, one};
|
pub use identities::{Zero, One, zero, one};
|
||||||
pub use ops::checked::*;
|
pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr};
|
||||||
pub use ops::wrapping::*;
|
pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub};
|
||||||
pub use ops::saturating::Saturating;
|
pub use ops::saturating::Saturating;
|
||||||
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
|
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
|
||||||
pub use cast::*;
|
pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
|
||||||
pub use int::PrimInt;
|
pub use int::PrimInt;
|
||||||
pub use pow::{pow, checked_pow};
|
pub use pow::{pow, checked_pow};
|
||||||
|
|
||||||
|
@ -34,6 +42,7 @@ pub mod sign;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
pub mod bounds;
|
pub mod bounds;
|
||||||
pub mod float;
|
pub mod float;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub mod real;
|
pub mod real;
|
||||||
pub mod cast;
|
pub mod cast;
|
||||||
pub mod int;
|
pub mod int;
|
||||||
|
@ -130,10 +139,10 @@ impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
|
||||||
macro_rules! int_trait_impl {
|
macro_rules! int_trait_impl {
|
||||||
($name:ident for $($t:ty)*) => ($(
|
($name:ident for $($t:ty)*) => ($(
|
||||||
impl $name for $t {
|
impl $name for $t {
|
||||||
type FromStrRadixErr = ::std::num::ParseIntError;
|
type FromStrRadixErr = ::core::num::ParseIntError;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str_radix(s: &str, radix: u32)
|
fn from_str_radix(s: &str, radix: u32)
|
||||||
-> Result<Self, ::std::num::ParseIntError>
|
-> Result<Self, ::core::num::ParseIntError>
|
||||||
{
|
{
|
||||||
<$t>::from_str_radix(s, radix)
|
<$t>::from_str_radix(s, radix)
|
||||||
}
|
}
|
||||||
|
@ -159,7 +168,7 @@ pub enum FloatErrorKind {
|
||||||
Empty,
|
Empty,
|
||||||
Invalid,
|
Invalid,
|
||||||
}
|
}
|
||||||
// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
|
// FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
|
||||||
// so there's not really any way for us to reuse it.
|
// so there's not really any way for us to reuse it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseFloatError {
|
pub struct ParseFloatError {
|
||||||
|
@ -181,7 +190,7 @@ impl fmt::Display for ParseFloatError {
|
||||||
// with this implementation ourselves until we want to make a breaking change.
|
// with this implementation ourselves until we want to make a breaking change.
|
||||||
// (would have to drop it from `Num` though)
|
// (would have to drop it from `Num` though)
|
||||||
macro_rules! float_trait_impl {
|
macro_rules! float_trait_impl {
|
||||||
($name:ident for $($t:ty)*) => ($(
|
($name:ident for $($t:ident)*) => ($(
|
||||||
impl $name for $t {
|
impl $name for $t {
|
||||||
type FromStrRadixErr = ParseFloatError;
|
type FromStrRadixErr = ParseFloatError;
|
||||||
|
|
||||||
|
@ -193,9 +202,9 @@ macro_rules! float_trait_impl {
|
||||||
|
|
||||||
// Special values
|
// Special values
|
||||||
match src {
|
match src {
|
||||||
"inf" => return Ok(Float::infinity()),
|
"inf" => return Ok(core::$t::INFINITY),
|
||||||
"-inf" => return Ok(Float::neg_infinity()),
|
"-inf" => return Ok(core::$t::NEG_INFINITY),
|
||||||
"NaN" => return Ok(Float::nan()),
|
"NaN" => return Ok(core::$t::NAN),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,15 +245,15 @@ macro_rules! float_trait_impl {
|
||||||
// if we've not seen any non-zero digits.
|
// if we've not seen any non-zero digits.
|
||||||
if prev_sig != 0.0 {
|
if prev_sig != 0.0 {
|
||||||
if is_positive && sig <= prev_sig
|
if is_positive && sig <= prev_sig
|
||||||
{ return Ok(Float::infinity()); }
|
{ return Ok(core::$t::INFINITY); }
|
||||||
if !is_positive && sig >= prev_sig
|
if !is_positive && sig >= prev_sig
|
||||||
{ return Ok(Float::neg_infinity()); }
|
{ return Ok(core::$t::NEG_INFINITY); }
|
||||||
|
|
||||||
// Detect overflow by reversing the shift-and-add process
|
// Detect overflow by reversing the shift-and-add process
|
||||||
if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
|
if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
|
||||||
{ return Ok(Float::infinity()); }
|
{ return Ok(core::$t::INFINITY); }
|
||||||
if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
|
if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
|
||||||
{ return Ok(Float::neg_infinity()); }
|
{ return Ok(core::$t::NEG_INFINITY); }
|
||||||
}
|
}
|
||||||
prev_sig = sig;
|
prev_sig = sig;
|
||||||
},
|
},
|
||||||
|
@ -280,9 +289,9 @@ macro_rules! float_trait_impl {
|
||||||
};
|
};
|
||||||
// Detect overflow by comparing to last value
|
// Detect overflow by comparing to last value
|
||||||
if is_positive && sig < prev_sig
|
if is_positive && sig < prev_sig
|
||||||
{ return Ok(Float::infinity()); }
|
{ return Ok(core::$t::INFINITY); }
|
||||||
if !is_positive && sig > prev_sig
|
if !is_positive && sig > prev_sig
|
||||||
{ return Ok(Float::neg_infinity()); }
|
{ return Ok(core::$t::NEG_INFINITY); }
|
||||||
prev_sig = sig;
|
prev_sig = sig;
|
||||||
},
|
},
|
||||||
None => match c {
|
None => match c {
|
||||||
|
@ -316,9 +325,15 @@ macro_rules! float_trait_impl {
|
||||||
None => return Err(PFE { kind: Invalid }),
|
None => return Err(PFE { kind: Invalid }),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn pow(base: $t, exp: usize) -> $t {
|
||||||
|
Float::powi(base, exp as i32)
|
||||||
|
}
|
||||||
|
// otherwise uses the generic `pow` from the root
|
||||||
|
|
||||||
match (is_positive, exp) {
|
match (is_positive, exp) {
|
||||||
(true, Ok(exp)) => base.powi(exp as i32),
|
(true, Ok(exp)) => pow(base, exp),
|
||||||
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
|
(false, Ok(exp)) => 1.0 / pow(base, exp),
|
||||||
(_, Err(_)) => return Err(PFE { kind: Invalid }),
|
(_, Err(_)) => return Err(PFE { kind: Invalid }),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::{Add, Sub, Mul, Div, Shl, Shr};
|
use core::ops::{Add, Sub, Mul, Div, Shl, Shr};
|
||||||
|
|
||||||
/// Performs addition that returns `None` instead of wrapping around on
|
/// Performs addition that returns `None` instead of wrapping around on
|
||||||
/// overflow.
|
/// overflow.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ops::{Add, Sub, Mul};
|
use core::ops::{Add, Sub, Mul};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
macro_rules! wrapping_impl {
|
macro_rules! wrapping_impl {
|
||||||
($trait_name:ident, $method:ident, $t:ty) => {
|
($trait_name:ident, $method:ident, $t:ty) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::ops::Mul;
|
use core::ops::Mul;
|
||||||
use {One, CheckedMul};
|
use {One, CheckedMul};
|
||||||
|
|
||||||
/// Raises a value to the power of exp, using exponentiation by squaring.
|
/// Raises a value to the power of exp, using exponentiation by squaring.
|
||||||
|
|
|
@ -10,6 +10,8 @@ use {Num, NumCast, Float};
|
||||||
///
|
///
|
||||||
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
|
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
|
||||||
/// for a list of data types that could meaningfully implement this trait.
|
/// for a list of data types that could meaningfully implement this trait.
|
||||||
|
///
|
||||||
|
/// This trait is only available with the `std` feature.
|
||||||
pub trait Real
|
pub trait Real
|
||||||
: Num
|
: Num
|
||||||
+ Copy
|
+ Copy
|
||||||
|
|
46
src/sign.rs
46
src/sign.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Neg;
|
use core::ops::Neg;
|
||||||
use std::{f32, f64};
|
use core::{f32, f64};
|
||||||
use std::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
|
|
||||||
use Num;
|
use Num;
|
||||||
|
|
||||||
|
@ -103,17 +103,30 @@ macro_rules! signed_float_impl {
|
||||||
impl Signed for $t {
|
impl Signed for $t {
|
||||||
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn abs(&self) -> $t {
|
fn abs(&self) -> $t {
|
||||||
<$t>::abs(*self)
|
(*self).abs()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
fn abs(&self) -> $t {
|
||||||
|
if self.is_positive() {
|
||||||
|
*self
|
||||||
|
} else if self.is_negative() {
|
||||||
|
-*self
|
||||||
|
} else {
|
||||||
|
$nan
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The positive difference of two numbers. Returns `0.0` if the number is
|
/// The positive difference of two numbers. Returns `0.0` if the number is
|
||||||
/// less than or equal to `other`, otherwise the difference between`self`
|
/// less than or equal to `other`, otherwise the difference between`self`
|
||||||
/// and `other` is returned.
|
/// and `other` is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(deprecated)]
|
|
||||||
fn abs_sub(&self, other: &$t) -> $t {
|
fn abs_sub(&self, other: &$t) -> $t {
|
||||||
<$t>::abs_sub(*self, *other)
|
if *self <= *other { 0. } else { *self - *other }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -122,8 +135,27 @@ macro_rules! signed_float_impl {
|
||||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||||
/// - `NAN` if the number is NaN
|
/// - `NAN` if the number is NaN
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn signum(&self) -> $t {
|
fn signum(&self) -> $t {
|
||||||
<$t>::signum(*self)
|
use Float;
|
||||||
|
Float::signum(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||||
|
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||||
|
/// - `NAN` if the number is NaN
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
fn signum(&self) -> $t {
|
||||||
|
if self.is_positive() {
|
||||||
|
1.0
|
||||||
|
} else if self.is_negative() {
|
||||||
|
-1.0
|
||||||
|
} else {
|
||||||
|
$nan
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
||||||
|
|
Loading…
Reference in New Issue