2017-12-21 20:29:14 -05:00
|
|
|
|
//! This module provides constants which are specific to the implementation
|
|
|
|
|
//! of the `f64` floating point data type.
|
|
|
|
|
//!
|
|
|
|
|
//! *[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
|
|
|
|
//!
|
|
|
|
|
//! Although using these constants won’t cause compilation warnings,
|
|
|
|
|
//! new code should use the associated constants directly on the primitive 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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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.
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN: f64 = f64::MIN;
|
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.
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
|
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.
|
2015-02-13 14:40:57 +11:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_EXP: i32 = f64::MIN_EXP;
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
|
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.
|
2015-03-19 23:42:18 -07:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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.
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const NAN: f64 = f64::NAN;
|
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.
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
2020-01-17 20:39:15 +01:00
|
|
|
|
pub const INFINITY: f64 = f64::INFINITY;
|
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.
|
2015-01-23 21:48:20 -08:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
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π.
|
2019-11-26 11:20:54 +01:00
|
|
|
|
#[unstable(feature = "tau_constant", issue = "66770")]
|
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;
|
|
|
|
|
/// 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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_nan(self) -> bool {
|
|
|
|
|
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]
|
|
|
|
|
fn abs_private(self) -> f64 {
|
|
|
|
|
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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_infinite(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
|
|
|
|
self.abs_private() == 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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub 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.
|
|
|
|
|
self.abs_private() < INFINITY
|
2018-05-21 10:45:11 +02:00
|
|
|
|
}
|
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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_normal(self) -> bool {
|
|
|
|
|
self.classify() == FpCategory::Normal
|
|
|
|
|
}
|
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")]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn classify(self) -> FpCategory {
|
|
|
|
|
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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_sign_positive(self) -> bool {
|
|
|
|
|
!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")]
|
|
|
|
|
#[inline]
|
2018-05-21 10:45:11 +02:00
|
|
|
|
pub fn is_sign_negative(self) -> bool {
|
|
|
|
|
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.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let value = 4.6_f32;
|
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);
|
|
|
|
|
///
|
|
|
|
|
/// let value = -128.9_f32;
|
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-03-27 19:18:52 -04:00
|
|
|
|
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")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub 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
|
|
|
|
|
/// implementation favours preserving the exact bits. This means that
|
|
|
|
|
/// 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.
|
|
|
|
|
///
|
|
|
|
|
/// If you don't care about signalingness (very likely), then there is no
|
|
|
|
|
/// 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")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub 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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn to_be_bytes(self) -> [u8; 8] {
|
|
|
|
|
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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn to_le_bytes(self) -> [u8; 8] {
|
|
|
|
|
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.
|
|
|
|
|
///
|
|
|
|
|
/// [`to_be_bytes`]: #method.to_be_bytes
|
|
|
|
|
/// [`to_le_bytes`]: #method.to_le_bytes
|
|
|
|
|
///
|
|
|
|
|
/// # 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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn to_ne_bytes(self) -> [u8; 8] {
|
|
|
|
|
self.to_bits().to_ne_bytes()
|
|
|
|
|
}
|
|
|
|
|
|
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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn from_be_bytes(bytes: [u8; 8]) -> Self {
|
|
|
|
|
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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn from_le_bytes(bytes: [u8; 8]) -> Self {
|
|
|
|
|
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.
|
|
|
|
|
///
|
|
|
|
|
/// [`from_be_bytes`]: #method.from_be_bytes
|
|
|
|
|
/// [`from_le_bytes`]: #method.from_le_bytes
|
|
|
|
|
///
|
|
|
|
|
/// # 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")]
|
2019-02-26 16:47:33 +01:00
|
|
|
|
#[inline]
|
|
|
|
|
pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
|
|
|
|
|
Self::from_bits(u64::from_ne_bytes(bytes))
|
|
|
|
|
}
|
2018-04-08 10:09:52 +02:00
|
|
|
|
}
|