2021-01-10 16:57:21 -05:00
|
|
|
|
//! Constants specific to the `f64` double-precision floating point type.
|
2017-12-21 20:29:14 -05:00
|
|
|
|
//!
|
|
|
|
|
//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
|
2018-05-09 18:03:56 -04:00
|
|
|
|
//!
|
|
|
|
|
//! Mathematically significant numbers are provided in the `consts` sub-module.
|
2020-02-10 19:45:44 +01:00
|
|
|
|
//!
|
2021-01-10 16:57:21 -05:00
|
|
|
|
//! For the constants defined directly in this module
|
|
|
|
|
//! (as distinct from those defined in the `consts` sub-module),
|
|
|
|
|
//! new code should instead use the associated constants
|
|
|
|
|
//! defined directly on the `f64` type.
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
2014-11-15 22:03:34 -08:00
|
|
|
|
|
2019-11-28 15:24:26 +01:00
|
|
|
|
use crate::convert::FloatToInt;
|
2019-06-06 21:27:23 +01:00
|
|
|
|
#[cfg(not(test))]
|
|
|
|
|
use crate::intrinsics;
|
2019-04-15 11:23:21 +09:00
|
|
|
|
use crate::mem;
|
|
|
|
|
use crate::num::FpCategory;
|
2014-05-01 18:06:59 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// The radix or base of the internal representation of `f64`.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::RADIX`](../../std/primitive.f64.html#associatedconstant.RADIX) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let r = std::f64::RADIX;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let r = f64::RADIX;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(since = "TBD", reason = "replaced by the `RADIX` associated constant on `f64`")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const RADIX: u32 = f64::RADIX;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Number of significant digits in base 2.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MANTISSA_DIGITS`](../../std/primitive.f64.html#associatedconstant.MANTISSA_DIGITS) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let d = std::f64::MANTISSA_DIGITS;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let d = f64::MANTISSA_DIGITS;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MANTISSA_DIGITS` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Approximate number of significant digits in base 10.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::DIGITS`](../../std/primitive.f64.html#associatedconstant.DIGITS) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let d = std::f64::DIGITS;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let d = f64::DIGITS;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(since = "TBD", reason = "replaced by the `DIGITS` associated constant on `f64`")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const DIGITS: u32 = f64::DIGITS;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2018-05-20 12:39:13 -04:00
|
|
|
|
/// [Machine epsilon] value for `f64`.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::EPSILON`](../../std/primitive.f64.html#associatedconstant.EPSILON) instead.
|
2018-05-20 12:39:13 -04:00
|
|
|
|
///
|
2019-11-28 13:49:58 +01:00
|
|
|
|
/// This is the difference between `1.0` and the next larger representable number.
|
2018-05-20 12:39:13 -04:00
|
|
|
|
///
|
|
|
|
|
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let e = std::f64::EPSILON;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let e = f64::EPSILON;
|
|
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `EPSILON` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const EPSILON: f64 = f64::EPSILON;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Smallest finite `f64` value.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MIN`](../../std/primitive.f64.html#associatedconstant.MIN) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let min = std::f64::MIN;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let min = f64::MIN;
|
|
|
|
|
/// ```
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(since = "TBD", reason = "replaced by the `MIN` associated constant on `f64`")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN: f64 = f64::MIN;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Smallest positive normal `f64` value.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MIN_POSITIVE`](../../std/primitive.f64.html#associatedconstant.MIN_POSITIVE) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let min = std::f64::MIN_POSITIVE;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let min = f64::MIN_POSITIVE;
|
|
|
|
|
/// ```
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MIN_POSITIVE` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Largest finite `f64` value.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MAX`](../../std/primitive.f64.html#associatedconstant.MAX) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let max = std::f64::MAX;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let max = f64::MAX;
|
|
|
|
|
/// ```
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(since = "TBD", reason = "replaced by the `MAX` associated constant on `f64`")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX: f64 = f64::MAX;
|
2015-02-13 14:40:57 +11:00
|
|
|
|
|
2016-06-30 08:30:30 +01:00
|
|
|
|
/// One greater than the minimum possible normal power of 2 exponent.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MIN_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_EXP) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let min = std::f64::MIN_EXP;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let min = f64::MIN_EXP;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MIN_EXP` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_EXP: i32 = f64::MIN_EXP;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Maximum possible power of 2 exponent.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MAX_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_EXP) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let max = std::f64::MAX_EXP;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let max = f64::MAX_EXP;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MAX_EXP` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX_EXP: i32 = f64::MAX_EXP;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Minimum possible normal power of 10 exponent.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MIN_10_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_10_EXP) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let min = std::f64::MIN_10_EXP;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let min = f64::MIN_10_EXP;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MIN_10_EXP` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Maximum possible power of 10 exponent.
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::MAX_10_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_10_EXP) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let max = std::f64::MAX_10_EXP;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let max = f64::MAX_10_EXP;
|
|
|
|
|
/// ```
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `MAX_10_EXP` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX_10_EXP: i32 = f64::MAX_10_EXP;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Not a Number (NaN).
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::NAN`](../../std/primitive.f64.html#associatedconstant.NAN) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let nan = std::f64::NAN;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let nan = f64::NAN;
|
|
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(since = "TBD", reason = "replaced by the `NAN` associated constant on `f64`")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const NAN: f64 = f64::NAN;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Infinity (∞).
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::INFINITY`](../../std/primitive.f64.html#associatedconstant.INFINITY) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let inf = std::f64::INFINITY;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let inf = f64::INFINITY;
|
|
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `INFINITY` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const INFINITY: f64 = f64::INFINITY;
|
2020-05-04 08:14:38 -05:00
|
|
|
|
|
2019-12-19 17:57:08 +01:00
|
|
|
|
/// Negative infinity (−∞).
|
2020-02-08 12:15:22 +01:00
|
|
|
|
/// Use [`f64::NEG_INFINITY`](../../std/primitive.f64.html#associatedconstant.NEG_INFINITY) instead.
|
2020-05-04 08:14:38 -05:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// // deprecated way
|
2021-01-10 16:57:21 -05:00
|
|
|
|
/// # #[allow(deprecated, deprecated_in_future)]
|
2020-05-04 08:14:38 -05:00
|
|
|
|
/// let ninf = std::f64::NEG_INFINITY;
|
|
|
|
|
///
|
|
|
|
|
/// // intended way
|
|
|
|
|
/// let ninf = f64::NEG_INFINITY;
|
|
|
|
|
/// ```
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2021-01-10 16:57:21 -05:00
|
|
|
|
#[rustc_deprecated(
|
|
|
|
|
since = "TBD",
|
|
|
|
|
reason = "replaced by the `NEG_INFINITY` associated constant on `f64`"
|
|
|
|
|
)]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const NEG_INFINITY: f64 = f64::NEG_INFINITY;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2015-10-05 16:51:43 -07:00
|
|
|
|
/// Basic mathematical constants.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-04-30 22:23:26 -07:00
|
|
|
|
pub mod consts {
|
|
|
|
|
// FIXME: replace with mathematical constants from cmath.
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Archimedes' constant (π)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const PI: f64 = 3.14159265358979323846264338327950288_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2019-11-26 10:47:52 +01:00
|
|
|
|
/// The full circle constant (τ)
|
|
|
|
|
///
|
|
|
|
|
/// Equal to 2π.
|
2020-07-10 12:08:32 +02:00
|
|
|
|
#[stable(feature = "tau_constant", since = "1.47.0")]
|
2019-11-26 10:47:52 +01:00
|
|
|
|
pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// π/2
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// π/3
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// π/4
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// π/6
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// π/8
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// 1/π
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// 2/π
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// 2/sqrt(π)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// sqrt(2)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// 1/sqrt(2)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// Euler's number (e)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2018-05-08 12:05:07 -04:00
|
|
|
|
/// log<sub>2</sub>(10)
|
2020-02-16 18:53:02 +01:00
|
|
|
|
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
2018-05-08 12:05:07 -04:00
|
|
|
|
pub const LOG2_10: f64 = 3.32192809488736234787031942948939018_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// log<sub>2</sub>(e)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2018-05-08 12:05:07 -04:00
|
|
|
|
/// log<sub>10</sub>(2)
|
2020-02-16 18:53:02 +01:00
|
|
|
|
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
2018-05-08 12:05:07 -04:00
|
|
|
|
pub const LOG10_2: f64 = 0.301029995663981195213738894724493027_f64;
|
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// log<sub>10</sub>(e)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// ln(2)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const LN_2: f64 = 0.693147180559945309417232121458176568_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
|
2016-06-14 21:23:21 +01:00
|
|
|
|
/// ln(10)
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2014-10-06 16:14:00 -07:00
|
|
|
|
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
|
2014-04-30 22:23:26 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-21 10:45:11 +02:00
|
|
|
|
#[lang = "f64"]
|
|
|
|
|
#[cfg(not(test))]
|
|
|
|
|
impl f64 {
|
2020-01-17 20:39:15 +01:00
|
|
|
|
/// The radix or base of the internal representation of `f64`.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const RADIX: u32 = 2;
|
|
|
|
|
|
|
|
|
|
/// Number of significant digits in base 2.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MANTISSA_DIGITS: u32 = 53;
|
|
|
|
|
/// Approximate number of significant digits in base 10.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const DIGITS: u32 = 15;
|
|
|
|
|
|
|
|
|
|
/// [Machine epsilon] value for `f64`.
|
|
|
|
|
///
|
|
|
|
|
/// This is the difference between `1.0` and the next larger representable number.
|
|
|
|
|
///
|
|
|
|
|
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
|
|
|
|
|
|
|
|
|
/// Smallest finite `f64` value.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN: f64 = -1.7976931348623157e+308_f64;
|
|
|
|
|
/// Smallest positive normal `f64` value.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
|
|
|
|
|
/// Largest finite `f64` value.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX: f64 = 1.7976931348623157e+308_f64;
|
|
|
|
|
|
|
|
|
|
/// One greater than the minimum possible normal power of 2 exponent.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_EXP: i32 = -1021;
|
|
|
|
|
/// Maximum possible power of 2 exponent.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX_EXP: i32 = 1024;
|
|
|
|
|
|
|
|
|
|
/// Minimum possible normal power of 10 exponent.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_10_EXP: i32 = -307;
|
|
|
|
|
/// Maximum possible power of 10 exponent.
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MAX_10_EXP: i32 = 308;
|
|
|
|
|
|
|
|
|
|
/// Not a Number (NaN).
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const NAN: f64 = 0.0_f64 / 0.0_f64;
|
|
|
|
|
/// Infinity (∞).
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const INFINITY: f64 = 1.0_f64 / 0.0_f64;
|
2020-05-10 11:24:06 +02:00
|
|
|
|
/// Negative infinity (−∞).
|
2020-02-04 18:01:11 +01:00
|
|
|
|
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
|
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Returns `true` if this value is `NaN`.
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let nan = f64::NAN;
|
|
|
|
|
/// let f = 7.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(nan.is_nan());
|
|
|
|
|
/// assert!(!f.is_nan());
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_nan(self) -> bool {
|
2018-05-21 10:45:11 +02:00
|
|
|
|
self != self
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x).
These can both rely on IEEE754 semantics to be made faster, by folding
away the sign with an abs (left private for now), and then comparing
to infinity, letting the NaN semantics of a direct float comparison
handle NaN input properly.
The `abs` bit-fiddling is simple (a single and), and so these new
forms compile down to a few instructions, without branches, e.g. for
f32:
```asm
is_infinite:
andps xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
ucomiss xmm0, dword ptr [rip + .LCPI2_1] ; 0x7F80_0000
setae al
ret
is_finite:
andps xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
movss xmm1, dword ptr [rip + .LCPI1_1] ; 0x7F80_0000
ucomiss xmm1, xmm0
seta al
ret
```
When used in loops/repeatedly, they get even better: the memory
operations (loading the mask 0x7FFFFFFF for abs, and infinity
0x7F80_0000) are likely to be hoisted out of the individual calls, to
be shared, and the `seta`/`setae` are likely to be collapsed into
conditional jumps or moves (or similar).
The old `is_infinite` did two comparisons, and the old `is_finite` did
three (with a branch), and both of them had to check the flags after
every one of those comparison. These functions have had that old
implementation since they were added in
https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
7 years ago.
Benchmark (`abs` is the new form, `std` is the old):
```
test f32_is_finite_abs ... bench: 55 ns/iter (+/- 10)
test f32_is_finite_std ... bench: 118 ns/iter (+/- 5)
test f32_is_infinite_abs ... bench: 53 ns/iter (+/- 1)
test f32_is_infinite_std ... bench: 84 ns/iter (+/- 6)
test f64_is_finite_abs ... bench: 52 ns/iter (+/- 12)
test f64_is_finite_std ... bench: 128 ns/iter (+/- 25)
test f64_is_infinite_abs ... bench: 54 ns/iter (+/- 5)
test f64_is_infinite_std ... bench: 93 ns/iter (+/- 23)
```
```rust
#![feature(test)]
extern crate test;
use std::{f32, f64};
use test::Bencher;
const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f32_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f32_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
}
#[bench]
fn f32_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
}
#[bench]
fn f32_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
}
const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f64_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f64_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
}
#[bench]
fn f64_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
}
#[bench]
fn f64_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
}
```
2019-01-06 01:02:55 +11:00
|
|
|
|
// FIXME(#50145): `abs` is publicly unavailable in libcore due to
|
|
|
|
|
// concerns about portability, so this implementation is for
|
|
|
|
|
// private use internally.
|
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
|
|
|
|
const fn abs_private(self) -> f64 {
|
Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x).
These can both rely on IEEE754 semantics to be made faster, by folding
away the sign with an abs (left private for now), and then comparing
to infinity, letting the NaN semantics of a direct float comparison
handle NaN input properly.
The `abs` bit-fiddling is simple (a single and), and so these new
forms compile down to a few instructions, without branches, e.g. for
f32:
```asm
is_infinite:
andps xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
ucomiss xmm0, dword ptr [rip + .LCPI2_1] ; 0x7F80_0000
setae al
ret
is_finite:
andps xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
movss xmm1, dword ptr [rip + .LCPI1_1] ; 0x7F80_0000
ucomiss xmm1, xmm0
seta al
ret
```
When used in loops/repeatedly, they get even better: the memory
operations (loading the mask 0x7FFFFFFF for abs, and infinity
0x7F80_0000) are likely to be hoisted out of the individual calls, to
be shared, and the `seta`/`setae` are likely to be collapsed into
conditional jumps or moves (or similar).
The old `is_infinite` did two comparisons, and the old `is_finite` did
three (with a branch), and both of them had to check the flags after
every one of those comparison. These functions have had that old
implementation since they were added in
https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
7 years ago.
Benchmark (`abs` is the new form, `std` is the old):
```
test f32_is_finite_abs ... bench: 55 ns/iter (+/- 10)
test f32_is_finite_std ... bench: 118 ns/iter (+/- 5)
test f32_is_infinite_abs ... bench: 53 ns/iter (+/- 1)
test f32_is_infinite_std ... bench: 84 ns/iter (+/- 6)
test f64_is_finite_abs ... bench: 52 ns/iter (+/- 12)
test f64_is_finite_std ... bench: 128 ns/iter (+/- 25)
test f64_is_infinite_abs ... bench: 54 ns/iter (+/- 5)
test f64_is_infinite_std ... bench: 93 ns/iter (+/- 23)
```
```rust
#![feature(test)]
extern crate test;
use std::{f32, f64};
use test::Bencher;
const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f32_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f32_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
}
#[bench]
fn f32_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
}
#[bench]
fn f32_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
}
const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f64_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f64_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
}
#[bench]
fn f64_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
}
#[bench]
fn f64_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
}
```
2019-01-06 01:02:55 +11:00
|
|
|
|
f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Returns `true` if this value is positive infinity or negative infinity, and
|
|
|
|
|
/// `false` otherwise.
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let f = 7.0f64;
|
|
|
|
|
/// let inf = f64::INFINITY;
|
|
|
|
|
/// let neg_inf = f64::NEG_INFINITY;
|
|
|
|
|
/// let nan = f64::NAN;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!f.is_infinite());
|
|
|
|
|
/// assert!(!nan.is_infinite());
|
|
|
|
|
///
|
|
|
|
|
/// assert!(inf.is_infinite());
|
|
|
|
|
/// assert!(neg_inf.is_infinite());
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_infinite(self) -> bool {
|
2020-04-17 01:38:42 +02:00
|
|
|
|
self.abs_private() == Self::INFINITY
|
2018-05-21 10:45:11 +02:00
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Returns `true` if this number is neither infinite nor `NaN`.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let f = 7.0f64;
|
|
|
|
|
/// let inf: f64 = f64::INFINITY;
|
|
|
|
|
/// let neg_inf: f64 = f64::NEG_INFINITY;
|
|
|
|
|
/// let nan: f64 = f64::NAN;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(f.is_finite());
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!nan.is_finite());
|
|
|
|
|
/// assert!(!inf.is_finite());
|
|
|
|
|
/// assert!(!neg_inf.is_finite());
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_finite(self) -> bool {
|
Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x).
These can both rely on IEEE754 semantics to be made faster, by folding
away the sign with an abs (left private for now), and then comparing
to infinity, letting the NaN semantics of a direct float comparison
handle NaN input properly.
The `abs` bit-fiddling is simple (a single and), and so these new
forms compile down to a few instructions, without branches, e.g. for
f32:
```asm
is_infinite:
andps xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
ucomiss xmm0, dword ptr [rip + .LCPI2_1] ; 0x7F80_0000
setae al
ret
is_finite:
andps xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
movss xmm1, dword ptr [rip + .LCPI1_1] ; 0x7F80_0000
ucomiss xmm1, xmm0
seta al
ret
```
When used in loops/repeatedly, they get even better: the memory
operations (loading the mask 0x7FFFFFFF for abs, and infinity
0x7F80_0000) are likely to be hoisted out of the individual calls, to
be shared, and the `seta`/`setae` are likely to be collapsed into
conditional jumps or moves (or similar).
The old `is_infinite` did two comparisons, and the old `is_finite` did
three (with a branch), and both of them had to check the flags after
every one of those comparison. These functions have had that old
implementation since they were added in
https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
7 years ago.
Benchmark (`abs` is the new form, `std` is the old):
```
test f32_is_finite_abs ... bench: 55 ns/iter (+/- 10)
test f32_is_finite_std ... bench: 118 ns/iter (+/- 5)
test f32_is_infinite_abs ... bench: 53 ns/iter (+/- 1)
test f32_is_infinite_std ... bench: 84 ns/iter (+/- 6)
test f64_is_finite_abs ... bench: 52 ns/iter (+/- 12)
test f64_is_finite_std ... bench: 128 ns/iter (+/- 25)
test f64_is_infinite_abs ... bench: 54 ns/iter (+/- 5)
test f64_is_infinite_std ... bench: 93 ns/iter (+/- 23)
```
```rust
#![feature(test)]
extern crate test;
use std::{f32, f64};
use test::Bencher;
const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f32_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f32_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
}
#[bench]
fn f32_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
}
#[bench]
fn f32_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
}
const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f64_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f64_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
}
#[bench]
fn f64_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
}
#[bench]
fn f64_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
}
```
2019-01-06 01:02:55 +11:00
|
|
|
|
// There's no need to handle NaN separately: if self is NaN,
|
|
|
|
|
// the comparison is not true, exactly as desired.
|
2020-04-17 01:38:42 +02:00
|
|
|
|
self.abs_private() < Self::INFINITY
|
2018-05-21 10:45:11 +02:00
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
2020-09-19 16:31:47 -04:00
|
|
|
|
/// Returns `true` if the number is [subnormal].
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(is_subnormal)]
|
|
|
|
|
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
|
|
|
|
|
/// let max = f64::MAX;
|
|
|
|
|
/// let lower_than_min = 1.0e-308_f64;
|
|
|
|
|
/// let zero = 0.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!min.is_subnormal());
|
|
|
|
|
/// assert!(!max.is_subnormal());
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!zero.is_subnormal());
|
|
|
|
|
/// assert!(!f64::NAN.is_subnormal());
|
|
|
|
|
/// assert!(!f64::INFINITY.is_subnormal());
|
|
|
|
|
/// // Values between `0` and `min` are Subnormal.
|
|
|
|
|
/// assert!(lower_than_min.is_subnormal());
|
|
|
|
|
/// ```
|
|
|
|
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
|
|
|
|
#[unstable(feature = "is_subnormal", issue = "79288")]
|
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub const fn is_subnormal(self) -> bool {
|
|
|
|
|
matches!(self.classify(), FpCategory::Subnormal)
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// Returns `true` if the number is neither zero, infinite,
|
2019-12-26 05:04:46 -08:00
|
|
|
|
/// [subnormal], or `NaN`.
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
|
|
|
|
|
/// let max = f64::MAX;
|
|
|
|
|
/// let lower_than_min = 1.0e-308_f64;
|
|
|
|
|
/// let zero = 0.0f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(min.is_normal());
|
|
|
|
|
/// assert!(max.is_normal());
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!zero.is_normal());
|
|
|
|
|
/// assert!(!f64::NAN.is_normal());
|
|
|
|
|
/// assert!(!f64::INFINITY.is_normal());
|
|
|
|
|
/// // Values between `0` and `min` are Subnormal.
|
|
|
|
|
/// assert!(!lower_than_min.is_normal());
|
|
|
|
|
/// ```
|
|
|
|
|
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_normal(self) -> bool {
|
|
|
|
|
matches!(self.classify(), FpCategory::Normal)
|
2018-05-21 10:45:11 +02:00
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Returns the floating point category of the number. If only one property
|
|
|
|
|
/// is going to be tested, it is generally faster to use the specific
|
|
|
|
|
/// predicate instead.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::num::FpCategory;
|
|
|
|
|
///
|
|
|
|
|
/// let num = 12.4_f64;
|
|
|
|
|
/// let inf = f64::INFINITY;
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(num.classify(), FpCategory::Normal);
|
|
|
|
|
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
|
|
|
|
pub const fn classify(self) -> FpCategory {
|
2018-05-21 10:45:11 +02:00
|
|
|
|
const EXP_MASK: u64 = 0x7ff0000000000000;
|
|
|
|
|
const MAN_MASK: u64 = 0x000fffffffffffff;
|
|
|
|
|
|
|
|
|
|
let bits = self.to_bits();
|
|
|
|
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
|
|
|
|
(0, 0) => FpCategory::Zero,
|
|
|
|
|
(_, 0) => FpCategory::Subnormal,
|
|
|
|
|
(0, EXP_MASK) => FpCategory::Infinite,
|
|
|
|
|
(_, EXP_MASK) => FpCategory::Nan,
|
|
|
|
|
_ => FpCategory::Normal,
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// positive sign bit and positive infinity.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let f = 7.0_f64;
|
|
|
|
|
/// let g = -7.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(f.is_sign_positive());
|
|
|
|
|
/// assert!(!g.is_sign_positive());
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_sign_positive(self) -> bool {
|
2018-05-21 10:45:11 +02:00
|
|
|
|
!self.is_sign_negative()
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
|
|
|
|
|
#[inline]
|
|
|
|
|
#[doc(hidden)]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_positive(self) -> bool {
|
|
|
|
|
self.is_sign_positive()
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// negative sign bit and negative infinity.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let f = 7.0_f64;
|
|
|
|
|
/// let g = -7.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert!(!f.is_sign_negative());
|
|
|
|
|
/// assert!(g.is_sign_negative());
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:25:39 -07:00
|
|
|
|
pub const fn is_sign_negative(self) -> bool {
|
2018-05-21 10:45:11 +02:00
|
|
|
|
self.to_bits() & 0x8000_0000_0000_0000 != 0
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
|
|
|
|
|
#[inline]
|
|
|
|
|
#[doc(hidden)]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_negative(self) -> bool {
|
|
|
|
|
self.is_sign_negative()
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Takes the reciprocal (inverse) of a number, `1/x`.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let x = 2.0_f64;
|
2019-08-22 14:27:51 +02:00
|
|
|
|
/// let abs_difference = (x.recip() - (1.0 / x)).abs();
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// assert!(abs_difference < 1e-10);
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn recip(self) -> f64 {
|
|
|
|
|
1.0 / self
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Converts radians to degrees.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2020-04-05 11:44:25 +02:00
|
|
|
|
/// let angle = std::f64::consts::PI;
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
|
|
|
|
|
///
|
|
|
|
|
/// assert!(abs_difference < 1e-10);
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn to_degrees(self) -> f64 {
|
|
|
|
|
// The division here is correctly rounded with respect to the true
|
|
|
|
|
// value of 180/π. (This differs from f32, where a constant must be
|
|
|
|
|
// used to ensure a correctly rounded result.)
|
|
|
|
|
self * (180.0f64 / consts::PI)
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Converts degrees to radians.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let angle = 180.0_f64;
|
|
|
|
|
///
|
2020-04-05 11:44:25 +02:00
|
|
|
|
/// let abs_difference = (angle.to_radians() - std::f64::consts::PI).abs();
|
2018-04-08 10:09:52 +02:00
|
|
|
|
///
|
|
|
|
|
/// assert!(abs_difference < 1e-10);
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn to_radians(self) -> f64 {
|
|
|
|
|
let value: f64 = consts::PI;
|
|
|
|
|
self * (value / 180.0)
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
|
|
|
|
|
/// Returns the maximum of the two numbers.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let x = 1.0_f64;
|
|
|
|
|
/// let y = 2.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(x.max(y), y);
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// If one of the arguments is NaN, then the other argument is returned.
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn max(self, other: f64) -> f64 {
|
2019-06-06 21:27:23 +01:00
|
|
|
|
intrinsics::maxnumf64(self, other)
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the minimum of the two numbers.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let x = 1.0_f64;
|
|
|
|
|
/// let y = 2.0_f64;
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(x.min(y), x);
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// If one of the arguments is NaN, then the other argument is returned.
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn min(self, other: f64) -> f64 {
|
2019-06-06 21:27:23 +01:00
|
|
|
|
intrinsics::minnumf64(self, other)
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 15:24:26 +01:00
|
|
|
|
/// Rounds toward zero and converts to any primitive integer type,
|
|
|
|
|
/// assuming that the value is finite and fits in that type.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2020-05-04 08:28:53 -05:00
|
|
|
|
/// let value = 4.6_f64;
|
2020-03-27 19:18:52 -04:00
|
|
|
|
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
2019-11-28 15:24:26 +01:00
|
|
|
|
/// assert_eq!(rounded, 4);
|
|
|
|
|
///
|
2020-05-04 08:28:53 -05:00
|
|
|
|
/// let value = -128.9_f64;
|
2020-03-27 19:18:52 -04:00
|
|
|
|
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
|
2020-03-27 22:43:28 +01:00
|
|
|
|
/// assert_eq!(rounded, i8::MIN);
|
2019-11-28 15:24:26 +01:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Safety
|
|
|
|
|
///
|
|
|
|
|
/// The value must:
|
|
|
|
|
///
|
|
|
|
|
/// * Not be `NaN`
|
|
|
|
|
/// * Not be infinite
|
|
|
|
|
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
2020-03-27 19:18:52 -04:00
|
|
|
|
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
|
2019-11-28 15:24:26 +01:00
|
|
|
|
#[inline]
|
2020-03-27 19:18:52 -04:00
|
|
|
|
pub unsafe fn to_int_unchecked<Int>(self) -> Int
|
2019-12-06 20:18:12 -08:00
|
|
|
|
where
|
|
|
|
|
Self: FloatToInt<Int>,
|
|
|
|
|
{
|
2020-06-24 13:15:37 +02:00
|
|
|
|
// SAFETY: the caller must uphold the safety contract for
|
|
|
|
|
// `FloatToInt::to_int_unchecked`.
|
|
|
|
|
unsafe { FloatToInt::<Int>::to_int_unchecked(self) }
|
2019-11-28 15:24:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// Raw transmutation to `u64`.
|
|
|
|
|
///
|
|
|
|
|
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
|
|
|
|
|
///
|
|
|
|
|
/// See `from_bits` for some discussion of the portability of this operation
|
|
|
|
|
/// (there are almost no issues).
|
|
|
|
|
///
|
|
|
|
|
/// Note that this function is distinct from `as` casting, which attempts to
|
|
|
|
|
/// preserve the *numeric* value, and not the bitwise value.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
|
|
|
|
|
/// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn to_bits(self) -> u64 {
|
2019-08-21 19:56:46 +02:00
|
|
|
|
// SAFETY: `u64` is a plain old datatype so we can always transmute to it
|
2018-05-21 10:45:11 +02:00
|
|
|
|
unsafe { mem::transmute(self) }
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Raw transmutation from `u64`.
|
|
|
|
|
///
|
|
|
|
|
/// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
|
|
|
|
|
/// It turns out this is incredibly portable, for two reasons:
|
|
|
|
|
///
|
|
|
|
|
/// * Floats and Ints have the same endianness on all supported platforms.
|
|
|
|
|
/// * IEEE-754 very precisely specifies the bit layout of floats.
|
|
|
|
|
///
|
|
|
|
|
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
|
|
|
|
|
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
|
|
|
|
|
/// (notably x86 and ARM) picked the interpretation that was ultimately
|
|
|
|
|
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
|
|
|
|
|
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
|
|
|
|
|
///
|
|
|
|
|
/// Rather than trying to preserve signaling-ness cross-platform, this
|
2020-07-07 20:48:15 -04:00
|
|
|
|
/// implementation favors preserving the exact bits. This means that
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// any payloads encoded in NaNs will be preserved even if the result of
|
|
|
|
|
/// this method is sent over the network from an x86 machine to a MIPS one.
|
|
|
|
|
///
|
|
|
|
|
/// If the results of this method are only manipulated by the same
|
|
|
|
|
/// architecture that produced them, then there is no portability concern.
|
|
|
|
|
///
|
|
|
|
|
/// If the input isn't NaN, then there is no portability concern.
|
|
|
|
|
///
|
2020-07-07 20:48:15 -04:00
|
|
|
|
/// If you don't care about signaling-ness (very likely), then there is no
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// portability concern.
|
|
|
|
|
///
|
|
|
|
|
/// Note that this function is distinct from `as` casting, which attempts to
|
|
|
|
|
/// preserve the *numeric* value, and not the bitwise value.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let v = f64::from_bits(0x4029000000000000);
|
2019-07-04 09:11:15 +00:00
|
|
|
|
/// assert_eq!(v, 12.5);
|
2018-04-08 10:09:52 +02:00
|
|
|
|
/// ```
|
|
|
|
|
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2018-04-08 10:09:52 +02:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn from_bits(v: u64) -> Self {
|
2019-08-21 19:56:46 +02:00
|
|
|
|
// SAFETY: `u64` is a plain old datatype so we can always transmute from it
|
2018-05-21 10:45:11 +02:00
|
|
|
|
// It turns out the safety issues with sNaN were overblown! Hooray!
|
|
|
|
|
unsafe { mem::transmute(v) }
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|
2019-02-26 16:47:33 +01:00
|
|
|
|
|
2019-07-04 09:11:15 +00:00
|
|
|
|
/// Return the memory representation of this floating point number as a byte array in
|
|
|
|
|
/// big-endian (network) byte order.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let bytes = 12.5f64.to_be_bytes();
|
|
|
|
|
/// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn to_be_bytes(self) -> [u8; 8] {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
self.to_bits().to_be_bytes()
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-04 09:11:15 +00:00
|
|
|
|
/// Return the memory representation of this floating point number as a byte array in
|
|
|
|
|
/// little-endian byte order.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let bytes = 12.5f64.to_le_bytes();
|
|
|
|
|
/// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn to_le_bytes(self) -> [u8; 8] {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
self.to_bits().to_le_bytes()
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-04 09:11:15 +00:00
|
|
|
|
/// Return the memory representation of this floating point number as a byte array in
|
|
|
|
|
/// native byte order.
|
|
|
|
|
///
|
|
|
|
|
/// As the target platform's native endianness is used, portable code
|
|
|
|
|
/// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
|
|
|
|
|
///
|
2020-08-22 11:00:40 -04:00
|
|
|
|
/// [`to_be_bytes`]: f64::to_be_bytes
|
|
|
|
|
/// [`to_le_bytes`]: f64::to_le_bytes
|
2019-07-04 09:11:15 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let bytes = 12.5f64.to_ne_bytes();
|
|
|
|
|
/// assert_eq!(
|
|
|
|
|
/// bytes,
|
|
|
|
|
/// if cfg!(target_endian = "big") {
|
|
|
|
|
/// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
|
|
|
/// } else {
|
|
|
|
|
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
|
|
|
|
/// }
|
|
|
|
|
/// );
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn to_ne_bytes(self) -> [u8; 8] {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
self.to_bits().to_ne_bytes()
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-20 15:49:43 +08:00
|
|
|
|
/// Return the memory representation of this floating point number as a byte array in
|
|
|
|
|
/// native byte order.
|
|
|
|
|
///
|
|
|
|
|
/// [`to_ne_bytes`] should be preferred over this whenever possible.
|
|
|
|
|
///
|
2020-08-22 11:00:40 -04:00
|
|
|
|
/// [`to_ne_bytes`]: f64::to_ne_bytes
|
2020-09-20 15:49:43 +08:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(num_as_ne_bytes)]
|
|
|
|
|
/// let num = 12.5f64;
|
|
|
|
|
/// let bytes = num.as_ne_bytes();
|
|
|
|
|
/// assert_eq!(
|
|
|
|
|
/// bytes,
|
|
|
|
|
/// if cfg!(target_endian = "big") {
|
|
|
|
|
/// &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
|
|
|
/// } else {
|
|
|
|
|
/// &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
|
|
|
|
/// }
|
|
|
|
|
/// );
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "num_as_ne_bytes", issue = "76976")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn as_ne_bytes(&self) -> &[u8; 8] {
|
|
|
|
|
// SAFETY: `f64` is a plain old datatype so we can always transmute to it
|
|
|
|
|
unsafe { &*(self as *const Self as *const _) }
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-04 09:11:15 +00:00
|
|
|
|
/// Create a floating point value from its representation as a byte array in big endian.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
|
|
|
/// assert_eq!(value, 12.5);
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
Self::from_bits(u64::from_be_bytes(bytes))
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-08 01:53:30 +00:00
|
|
|
|
/// Create a floating point value from its representation as a byte array in little endian.
|
2019-07-04 09:11:15 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
|
|
|
|
|
/// assert_eq!(value, 12.5);
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
Self::from_bits(u64::from_le_bytes(bytes))
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-08 01:53:30 +00:00
|
|
|
|
/// Create a floating point value from its representation as a byte array in native endian.
|
2019-07-04 09:11:15 +00:00
|
|
|
|
///
|
|
|
|
|
/// As the target platform's native endianness is used, portable code
|
|
|
|
|
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
|
|
|
|
|
/// appropriate instead.
|
|
|
|
|
///
|
2020-08-22 11:00:40 -04:00
|
|
|
|
/// [`from_be_bytes`]: f64::from_be_bytes
|
|
|
|
|
/// [`from_le_bytes`]: f64::from_le_bytes
|
2019-07-04 09:11:15 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") {
|
|
|
|
|
/// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
|
|
|
/// } else {
|
|
|
|
|
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
|
|
|
|
/// });
|
|
|
|
|
/// assert_eq!(value, 12.5);
|
|
|
|
|
/// ```
|
2019-10-31 16:13:28 +00:00
|
|
|
|
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
2020-08-22 12:24:35 -07:00
|
|
|
|
pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self {
|
2019-02-26 16:47:33 +01:00
|
|
|
|
Self::from_bits(u64::from_ne_bytes(bytes))
|
|
|
|
|
}
|
2020-05-23 04:41:24 +09:00
|
|
|
|
|
|
|
|
|
/// Returns an ordering between self and other values.
|
|
|
|
|
/// Unlike the standard partial comparison between floating point numbers,
|
|
|
|
|
/// this comparison always produces an ordering in accordance to
|
|
|
|
|
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
|
|
|
|
|
/// floating point standard. The values are ordered in following order:
|
|
|
|
|
/// - Negative quiet NaN
|
|
|
|
|
/// - Negative signaling NaN
|
|
|
|
|
/// - Negative infinity
|
|
|
|
|
/// - Negative numbers
|
|
|
|
|
/// - Negative subnormal numbers
|
|
|
|
|
/// - Negative zero
|
|
|
|
|
/// - Positive zero
|
|
|
|
|
/// - Positive subnormal numbers
|
|
|
|
|
/// - Positive numbers
|
|
|
|
|
/// - Positive infinity
|
|
|
|
|
/// - Positive signaling NaN
|
|
|
|
|
/// - Positive quiet NaN
|
|
|
|
|
///
|
2020-11-01 14:27:36 +01:00
|
|
|
|
/// Note that this function does not always agree with the [`PartialOrd`]
|
|
|
|
|
/// and [`PartialEq`] implementations of `f64`. In particular, they regard
|
|
|
|
|
/// negative and positive zero as equal, while `total_cmp` doesn't.
|
|
|
|
|
///
|
2020-05-23 04:41:24 +09:00
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(total_cmp)]
|
|
|
|
|
/// struct GoodBoy {
|
|
|
|
|
/// name: String,
|
|
|
|
|
/// weight: f64,
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// let mut bois = vec![
|
|
|
|
|
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
|
|
|
|
|
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
|
|
|
|
|
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
|
|
|
|
|
/// GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY },
|
|
|
|
|
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN },
|
|
|
|
|
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
|
|
|
|
|
/// ];
|
|
|
|
|
///
|
|
|
|
|
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
|
|
|
|
|
/// # assert!(bois.into_iter().map(|b| b.weight)
|
|
|
|
|
/// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter())
|
|
|
|
|
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
|
|
|
|
|
/// ```
|
2020-05-26 11:59:23 +09:00
|
|
|
|
#[unstable(feature = "total_cmp", issue = "72599")]
|
2020-05-23 04:41:24 +09:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
|
|
|
|
let mut left = self.to_bits() as i64;
|
|
|
|
|
let mut right = other.to_bits() as i64;
|
|
|
|
|
|
2020-05-26 04:54:50 +09:00
|
|
|
|
// In case of negatives, flip all the bits except the sign
|
2020-05-23 04:41:24 +09:00
|
|
|
|
// to achieve a similar layout as two's complement integers
|
|
|
|
|
//
|
|
|
|
|
// Why does this work? IEEE 754 floats consist of three fields:
|
|
|
|
|
// Sign bit, exponent and mantissa. The set of exponent and mantissa
|
|
|
|
|
// fields as a whole have the property that their bitwise order is
|
|
|
|
|
// equal to the numeric magnitude where the magnitude is defined.
|
|
|
|
|
// The magnitude is not normally defined on NaN values, but
|
|
|
|
|
// IEEE 754 totalOrder defines the NaN values also to follow the
|
|
|
|
|
// bitwise order. This leads to order explained in the doc comment.
|
|
|
|
|
// However, the representation of magnitude is the same for negative
|
|
|
|
|
// and positive numbers – only the sign bit is different.
|
|
|
|
|
// To easily compare the floats as signed integers, we need to
|
|
|
|
|
// flip the exponent and mantissa bits in case of negative numbers.
|
|
|
|
|
// We effectively convert the numbers to "two's complement" form.
|
2020-05-26 04:50:53 +09:00
|
|
|
|
//
|
|
|
|
|
// To do the flipping, we construct a mask and XOR against it.
|
2020-05-26 04:54:50 +09:00
|
|
|
|
// We branchlessly calculate an "all-ones except for the sign bit"
|
2020-05-26 04:50:53 +09:00
|
|
|
|
// mask from negative-signed values: right shifting sign-extends
|
|
|
|
|
// the integer, so we "fill" the mask with sign bits, and then
|
|
|
|
|
// convert to unsigned to push one more zero bit.
|
|
|
|
|
// On positive values, the mask is all zeros, so it's a no-op.
|
|
|
|
|
left ^= (((left >> 63) as u64) >> 1) as i64;
|
|
|
|
|
right ^= (((right >> 63) as u64) >> 1) as i64;
|
2020-05-23 04:41:24 +09:00
|
|
|
|
|
|
|
|
|
left.cmp(&right)
|
|
|
|
|
}
|
2020-11-27 19:15:51 +01:00
|
|
|
|
|
|
|
|
|
/// Restrict a value to a certain interval unless it is NaN.
|
|
|
|
|
///
|
|
|
|
|
/// Returns `max` if `self` is greater than `max`, and `min` if `self` is
|
|
|
|
|
/// less than `min`. Otherwise this returns `self`.
|
|
|
|
|
///
|
|
|
|
|
/// Note that this function returns NaN if the initial value was NaN as
|
|
|
|
|
/// well.
|
|
|
|
|
///
|
|
|
|
|
/// # Panics
|
|
|
|
|
///
|
|
|
|
|
/// Panics if `min > max`, `min` is NaN, or `max` is NaN.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
|
|
|
|
|
/// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
|
|
|
|
|
/// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
|
|
|
|
|
/// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
|
|
|
|
|
/// ```
|
|
|
|
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
|
|
|
|
#[stable(feature = "clamp", since = "1.50.0")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn clamp(self, min: f64, max: f64) -> f64 {
|
|
|
|
|
assert!(min <= max);
|
|
|
|
|
let mut x = self;
|
|
|
|
|
if x < min {
|
|
|
|
|
x = min;
|
|
|
|
|
}
|
|
|
|
|
if x > max {
|
|
|
|
|
x = max;
|
|
|
|
|
}
|
|
|
|
|
x
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|