f16.rs - source
Description: Source of the Rust file `library/std/src/num/f16.rs`.

#
std/num/
f16.rs

    1//! Constants for the `f16` half-precision floating point type.
    2//!
    3//! *[See also the `f16` primitive type](primitive@f16).*
    4//!
    5//! Mathematically significant numbers are provided in the `consts` sub-module.
    6
    7#![unstable(feature = "f16", issue = "116909")]
    8#![doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))]
    9
    10#[unstable(feature = "f16", issue = "116909")]
    11pub use core::f16::consts;
    12
    13#[cfg(not(test))]
    14use crate::intrinsics;
    15#[cfg(not(test))]
    16use crate::sys::cmath;
    17
    18#[cfg(not(test))]
    19impl f16 {
    20    /// Raises a number to a floating point power.
    21    ///
    22    /// Note that this function is special in that it can return non-NaN results for NaN inputs. For
    23    /// example, `f16::powf(f16::NAN, 0.0)` returns `1.0`. However, if an input is a *signaling*
    24    /// NaN, then the result is non-deterministically either a NaN or the result that the
    25    /// corresponding quiet NaN would produce.
    26    ///
    27    /// # Unspecified precision
    28    ///
    29    /// The precision of this function is non-deterministic. This means it varies by platform,
    30    /// Rust version, and can even differ within the same execution from one invocation to the next.
    31    ///
    32    /// # Examples
    33    ///
    34    /// ```
    35    /// #![feature(f16)]
    36    /// # #[cfg(not(miri))]
    37    /// # #[cfg(target_has_reliable_f16_math)] {
    38    ///
    39    /// let x = 2.0_f16;
    40    /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
    41    /// assert!(abs_difference <= f16::EPSILON);
    42    ///
    43    /// assert_eq!(f16::powf(1.0, f16::NAN), 1.0);
    44    /// assert_eq!(f16::powf(f16::NAN, 0.0), 1.0);
    45    /// assert_eq!(f16::powf(0.0, 0.0), 1.0);
    46    /// # }
    47    /// ```
    48    #[inline]
    49    #[rustc_allow_incoherent_impl]
    50    #[unstable(feature = "f16", issue = "116909")]
    51    #[must_use = "method returns a new number and does not mutate the original value"]
    52    pub fn powf(self, n: f16) -> f16 {
    53        intrinsics::powf16(self, n)
    54    }
    55
    56    /// Returns `e^(self)`, (the exponential function).
    57    ///
    58    /// # Unspecified precision
    59    ///
    60    /// The precision of this function is non-deterministic. This means it varies by platform,
    61    /// Rust version, and can even differ within the same execution from one invocation to the next.
    62    ///
    63    /// # Examples
    64    ///
    65    /// ```
    66    /// #![feature(f16)]
    67    /// # #[cfg(not(miri))]
    68    /// # #[cfg(target_has_reliable_f16_math)] {
    69    ///
    70    /// let one = 1.0f16;
    71    /// // e^1
    72    /// let e = one.exp();
    73    ///
    74    /// // ln(e) - 1 == 0
    75    /// let abs_difference = (e.ln() - 1.0).abs();
    76    ///
    77    /// assert!(abs_difference <= f16::EPSILON);
    78    /// # }
    79    /// ```
    80    #[inline]
    81    #[rustc_allow_incoherent_impl]
    82    #[unstable(feature = "f16", issue = "116909")]
    83    #[must_use = "method returns a new number and does not mutate the original value"]
    84    pub fn exp(self) -> f16 {
    85        intrinsics::expf16(self)
    86    }
    87
    88    /// Returns `2^(self)`.
    89    ///
    90    /// # Unspecified precision
    91    ///
    92    /// The precision of this function is non-deterministic. This means it varies by platform,
    93    /// Rust version, and can even differ within the same execution from one invocation to the next.
    94    ///
    95    /// # Examples
    96    ///
    97    /// ```
    98    /// #![feature(f16)]
    99    /// # #[cfg(not(miri))]
    100    /// # #[cfg(target_has_reliable_f16_math)] {
    101    ///
    102    /// let f = 2.0f16;
    103    ///
    104    /// // 2^2 - 4 == 0
    105    /// let abs_difference = (f.exp2() - 4.0).abs();
    106    ///
    107    /// assert!(abs_difference <= f16::EPSILON);
    108    /// # }
    109    /// ```
    110    #[inline]
    111    #[rustc_allow_incoherent_impl]
    112    #[unstable(feature = "f16", issue = "116909")]
    113    #[must_use = "method returns a new number and does not mutate the original value"]
    114    pub fn exp2(self) -> f16 {
    115        intrinsics::exp2f16(self)
    116    }
    117
    118    /// Returns the natural logarithm of the number.
    119    ///
    120    /// This returns NaN when the number is negative, and negative infinity when number is zero.
    121    ///
    122    /// # Unspecified precision
    123    ///
    124    /// The precision of this function is non-deterministic. This means it varies by platform,
    125    /// Rust version, and can even differ within the same execution from one invocation to the next.
    126    ///
    127    /// # Examples
    128    ///
    129    /// ```
    130    /// #![feature(f16)]
    131    /// # #[cfg(not(miri))]
    132    /// # #[cfg(target_has_reliable_f16_math)] {
    133    ///
    134    /// let one = 1.0f16;
    135    /// // e^1
    136    /// let e = one.exp();
    137    ///
    138    /// // ln(e) - 1 == 0
    139    /// let abs_difference = (e.ln() - 1.0).abs();
    140    ///
    141    /// assert!(abs_difference <= f16::EPSILON);
    142    /// # }
    143    /// ```
    144    ///
    145    /// Non-positive values:
    146    /// ```
    147    /// #![feature(f16)]
    148    /// # #[cfg(not(miri))]
    149    /// # #[cfg(target_has_reliable_f16_math)] {
    150    ///
    151    /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY);
    152    /// assert!((-42_f16).ln().is_nan());
    153    /// # }
    154    /// ```
    155    #[inline]
    156    #[rustc_allow_incoherent_impl]
    157    #[unstable(feature = "f16", issue = "116909")]
    158    #[must_use = "method returns a new number and does not mutate the original value"]
    159    pub fn ln(self) -> f16 {
    160        intrinsics::logf16(self)
    161    }
    162
    163    /// Returns the logarithm of the number with respect to an arbitrary base.
    164    ///
    165    /// This returns NaN when the number is negative, and negative infinity when number is zero.
    166    ///
    167    /// The result might not be correctly rounded owing to implementation details;
    168    /// `self.log2()` can produce more accurate results for base 2, and
    169    /// `self.log10()` can produce more accurate results for base 10.
    170    ///
    171    /// # Unspecified precision
    172    ///
    173    /// The precision of this function is non-deterministic. This means it varies by platform,
    174    /// Rust version, and can even differ within the same execution from one invocation to the next.
    175    ///
    176    /// # Examples
    177    ///
    178    /// ```
    179    /// #![feature(f16)]
    180    /// # #[cfg(not(miri))]
    181    /// # #[cfg(target_has_reliable_f16_math)] {
    182    ///
    183    /// let five = 5.0f16;
    184    ///
    185    /// // log5(5) - 1 == 0
    186    /// let abs_difference = (five.log(5.0) - 1.0).abs();
    187    ///
    188    /// assert!(abs_difference <= f16::EPSILON);
    189    /// # }
    190    /// ```
    191    ///
    192    /// Non-positive values:
    193    /// ```
    194    /// #![feature(f16)]
    195    /// # #[cfg(not(miri))]
    196    /// # #[cfg(target_has_reliable_f16_math)] {
    197    ///
    198    /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY);
    199    /// assert!((-42_f16).log(10.0).is_nan());
    200    /// # }
    201    /// ```
    202    #[inline]
    203    #[rustc_allow_incoherent_impl]
    204    #[unstable(feature = "f16", issue = "116909")]
    205    #[must_use = "method returns a new number and does not mutate the original value"]
    206    pub fn log(self, base: f16) -> f16 {
    207        self.ln() / base.ln()
    208    }
    209
    210    /// Returns the base 2 logarithm of the number.
    211    ///
    212    /// This returns NaN when the number is negative, and negative infinity when number is zero.
    213    ///
    214    /// # Unspecified precision
    215    ///
    216    /// The precision of this function is non-deterministic. This means it varies by platform,
    217    /// Rust version, and can even differ within the same execution from one invocation to the next.
    218    ///
    219    /// # Examples
    220    ///
    221    /// ```
    222    /// #![feature(f16)]
    223    /// # #[cfg(not(miri))]
    224    /// # #[cfg(target_has_reliable_f16_math)] {
    225    ///
    226    /// let two = 2.0f16;
    227    ///
    228    /// // log2(2) - 1 == 0
    229    /// let abs_difference = (two.log2() - 1.0).abs();
    230    ///
    231    /// assert!(abs_difference <= f16::EPSILON);
    232    /// # }
    233    /// ```
    234    ///
    235    /// Non-positive values:
    236    /// ```
    237    /// #![feature(f16)]
    238    /// # #[cfg(not(miri))]
    239    /// # #[cfg(target_has_reliable_f16_math)] {
    240    ///
    241    /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY);
    242    /// assert!((-42_f16).log2().is_nan());
    243    /// # }
    244    /// ```
    245    #[inline]
    246    #[rustc_allow_incoherent_impl]
    247    #[unstable(feature = "f16", issue = "116909")]
    248    #[must_use = "method returns a new number and does not mutate the original value"]
    249    pub fn log2(self) -> f16 {
    250        intrinsics::log2f16(self)
    251    }
    252
    253    /// Returns the base 10 logarithm of the number.
    254    ///
    255    /// This returns NaN when the number is negative, and negative infinity when number is zero.
    256    ///
    257    /// # Unspecified precision
    258    ///
    259    /// The precision of this function is non-deterministic. This means it varies by platform,
    260    /// Rust version, and can even differ within the same execution from one invocation to the next.
    261    ///
    262    /// # Examples
    263    ///
    264    /// ```
    265    /// #![feature(f16)]
    266    /// # #[cfg(not(miri))]
    267    /// # #[cfg(target_has_reliable_f16_math)] {
    268    ///
    269    /// let ten = 10.0f16;
    270    ///
    271    /// // log10(10) - 1 == 0
    272    /// let abs_difference = (ten.log10() - 1.0).abs();
    273    ///
    274    /// assert!(abs_difference <= f16::EPSILON);
    275    /// # }
    276    /// ```
    277    ///
    278    /// Non-positive values:
    279    /// ```
    280    /// #![feature(f16)]
    281    /// # #[cfg(not(miri))]
    282    /// # #[cfg(target_has_reliable_f16_math)] {
    283    ///
    284    /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY);
    285    /// assert!((-42_f16).log10().is_nan());
    286    /// # }
    287    /// ```
    288    #[inline]
    289    #[rustc_allow_incoherent_impl]
    290    #[unstable(feature = "f16", issue = "116909")]
    291    #[must_use = "method returns a new number and does not mutate the original value"]
    292    pub fn log10(self) -> f16 {
    293        intrinsics::log10f16(self)
    294    }
    295
    296    /// Compute the distance between the origin and a point (`x`, `y`) on the
    297    /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
    298    /// right-angle triangle with other sides having length `x.abs()` and
    299    /// `y.abs()`.
    300    ///
    301    /// # Unspecified precision
    302    ///
    303    /// The precision of this function is non-deterministic. This means it varies by platform,
    304    /// Rust version, and can even differ within the same execution from one invocation to the next.
    305    ///
    306    /// This function currently corresponds to the `hypotf` from libc on Unix
    307    /// and Windows. Note that this might change in the future.
    308    ///
    309    /// # Examples
    310    ///
    311    /// ```
    312    /// #![feature(f16)]
    313    /// # #[cfg(not(miri))]
    314    /// # #[cfg(target_has_reliable_f16_math)] {
    315    ///
    316    /// let x = 2.0f16;
    317    /// let y = 3.0f16;
    318    ///
    319    /// // sqrt(x^2 + y^2)
    320    /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
    321    ///
    322    /// assert!(abs_difference <= f16::EPSILON);
    323    /// # }
    324    /// ```
    325    #[inline]
    326    #[rustc_allow_incoherent_impl]
    327    #[unstable(feature = "f16", issue = "116909")]
    328    #[must_use = "method returns a new number and does not mutate the original value"]
    329    pub fn hypot(self, other: f16) -> f16 {
    330        cmath::hypotf(self as f32, other as f32) as f16
    331    }
    332
    333    /// Computes the sine of a number (in radians).
    334    ///
    335    /// # Unspecified precision
    336    ///
    337    /// The precision of this function is non-deterministic. This means it varies by platform,
    338    /// Rust version, and can even differ within the same execution from one invocation to the next.
    339    ///
    340    /// # Examples
    341    ///
    342    /// ```
    343    /// #![feature(f16)]
    344    /// # #[cfg(not(miri))]
    345    /// # #[cfg(target_has_reliable_f16_math)] {
    346    ///
    347    /// let x = std::f16::consts::FRAC_PI_2;
    348    ///
    349    /// let abs_difference = (x.sin() - 1.0).abs();
    350    ///
    351    /// assert!(abs_difference <= f16::EPSILON);
    352    /// # }
    353    /// ```
    354    #[inline]
    355    #[rustc_allow_incoherent_impl]
    356    #[unstable(feature = "f16", issue = "116909")]
    357    #[must_use = "method returns a new number and does not mutate the original value"]
    358    pub fn sin(self) -> f16 {
    359        intrinsics::sinf16(self)
    360    }
    361
    362    /// Computes the cosine of a number (in radians).
    363    ///
    364    /// # Unspecified precision
    365    ///
    366    /// The precision of this function is non-deterministic. This means it varies by platform,
    367    /// Rust version, and can even differ within the same execution from one invocation to the next.
    368    ///
    369    /// # Examples
    370    ///
    371    /// ```
    372    /// #![feature(f16)]
    373    /// # #[cfg(not(miri))]
    374    /// # #[cfg(target_has_reliable_f16_math)] {
    375    ///
    376    /// let x = 2.0 * std::f16::consts::PI;
    377    ///
    378    /// let abs_difference = (x.cos() - 1.0).abs();
    379    ///
    380    /// assert!(abs_difference <= f16::EPSILON);
    381    /// # }
    382    /// ```
    383    #[inline]
    384    #[rustc_allow_incoherent_impl]
    385    #[unstable(feature = "f16", issue = "116909")]
    386    #[must_use = "method returns a new number and does not mutate the original value"]
    387    pub fn cos(self) -> f16 {
    388        intrinsics::cosf16(self)
    389    }
    390
    391    /// Computes the tangent of a number (in radians).
    392    ///
    393    /// # Unspecified precision
    394    ///
    395    /// The precision of this function is non-deterministic. This means it varies by platform,
    396    /// Rust version, and can even differ within the same execution from one invocation to the next.
    397    ///
    398    /// This function currently corresponds to the `tanf` from libc on Unix and
    399    /// Windows. Note that this might change in the future.
    400    ///
    401    /// # Examples
    402    ///
    403    /// ```
    404    /// #![feature(f16)]
    405    /// # #[cfg(not(miri))]
    406    /// # #[cfg(target_has_reliable_f16_math)] {
    407    ///
    408    /// let x = std::f16::consts::FRAC_PI_4;
    409    /// let abs_difference = (x.tan() - 1.0).abs();
    410    ///
    411    /// assert!(abs_difference <= f16::EPSILON);
    412    /// # }
    413    /// ```
    414    #[inline]
    415    #[rustc_allow_incoherent_impl]
    416    #[unstable(feature = "f16", issue = "116909")]
    417    #[must_use = "method returns a new number and does not mutate the original value"]
    418    pub fn tan(self) -> f16 {
    419        cmath::tanf(self as f32) as f16
    420    }
    421
    422    /// Computes the arcsine of a number. Return value is in radians in
    423    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
    424    /// [-1, 1].
    425    ///
    426    /// # Unspecified precision
    427    ///
    428    /// The precision of this function is non-deterministic. This means it varies by platform,
    429    /// Rust version, and can even differ within the same execution from one invocation to the next.
    430    ///
    431    /// This function currently corresponds to the `asinf` from libc on Unix
    432    /// and Windows. Note that this might change in the future.
    433    ///
    434    /// # Examples
    435    ///
    436    /// ```
    437    /// #![feature(f16)]
    438    /// # #[cfg(not(miri))]
    439    /// # #[cfg(target_has_reliable_f16_math)] {
    440    ///
    441    /// let f = std::f16::consts::FRAC_PI_4;
    442    ///
    443    /// // asin(sin(pi/2))
    444    /// let abs_difference = (f.sin().asin() - f).abs();
    445    ///
    446    /// assert!(abs_difference <= f16::EPSILON);
    447    /// # }
    448    /// ```
    449    #[inline]
    450    #[doc(alias = "arcsin")]
    451    #[rustc_allow_incoherent_impl]
    452    #[unstable(feature = "f16", issue = "116909")]
    453    #[must_use = "method returns a new number and does not mutate the original value"]
    454    pub fn asin(self) -> f16 {
    455        cmath::asinf(self as f32) as f16
    456    }
    457
    458    /// Computes the arccosine of a number. Return value is in radians in
    459    /// the range [0, pi] or NaN if the number is outside the range
    460    /// [-1, 1].
    461    ///
    462    /// # Unspecified precision
    463    ///
    464    /// The precision of this function is non-deterministic. This means it varies by platform,
    465    /// Rust version, and can even differ within the same execution from one invocation to the next.
    466    ///
    467    /// This function currently corresponds to the `acosf` from libc on Unix
    468    /// and Windows. Note that this might change in the future.
    469    ///
    470    /// # Examples
    471    ///
    472    /// ```
    473    /// #![feature(f16)]
    474    /// # #[cfg(not(miri))]
    475    /// # #[cfg(target_has_reliable_f16_math)] {
    476    ///
    477    /// let f = std::f16::consts::FRAC_PI_4;
    478    ///
    479    /// // acos(cos(pi/4))
    480    /// let abs_difference = (f.cos().acos() - std::f16::consts::FRAC_PI_4).abs();
    481    ///
    482    /// assert!(abs_difference <= f16::EPSILON);
    483    /// # }
    484    /// ```
    485    #[inline]
    486    #[doc(alias = "arccos")]
    487    #[rustc_allow_incoherent_impl]
    488    #[unstable(feature = "f16", issue = "116909")]
    489    #[must_use = "method returns a new number and does not mutate the original value"]
    490    pub fn acos(self) -> f16 {
    491        cmath::acosf(self as f32) as f16
    492    }
    493
    494    /// Computes the arctangent of a number. Return value is in radians in the
    495    /// range [-pi/2, pi/2];
    496    ///
    497    /// # Unspecified precision
    498    ///
    499    /// The precision of this function is non-deterministic. This means it varies by platform,
    500    /// Rust version, and can even differ within the same execution from one invocation to the next.
    501    ///
    502    /// This function currently corresponds to the `atanf` from libc on Unix
    503    /// and Windows. Note that this might change in the future.
    504    ///
    505    /// # Examples
    506    ///
    507    /// ```
    508    /// #![feature(f16)]
    509    /// # #[cfg(not(miri))]
    510    /// # #[cfg(target_has_reliable_f16_math)] {
    511    ///
    512    /// let f = 1.0f16;
    513    ///
    514    /// // atan(tan(1))
    515    /// let abs_difference = (f.tan().atan() - 1.0).abs();
    516    ///
    517    /// assert!(abs_difference <= f16::EPSILON);
    518    /// # }
    519    /// ```
    520    #[inline]
    521    #[doc(alias = "arctan")]
    522    #[rustc_allow_incoherent_impl]
    523    #[unstable(feature = "f16", issue = "116909")]
    524    #[must_use = "method returns a new number and does not mutate the original value"]
    525    pub fn atan(self) -> f16 {
    526        cmath::atanf(self as f32) as f16
    527    }
    528
    529    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
    530    ///
    531    ///  | `x`     | `y`     | Piecewise Definition | Range         |
    532    ///  |---------|---------|----------------------|---------------|
    533    ///  | `>= +0` | `>= +0` | `arctan(y/x)`        | `[+0, +pi/2]` |
    534    ///  | `>= +0` | `<= -0` | `arctan(y/x)`        | `[-pi/2, -0]` |
    535    ///  | `<= -0` | `>= +0` | `arctan(y/x) + pi`   | `[+pi/2, +pi]`|
    536    ///  | `<= -0` | `<= -0` | `arctan(y/x) - pi`   | `[-pi, -pi/2]`|
    537    ///
    538    /// # Unspecified precision
    539    ///
    540    /// The precision of this function is non-deterministic. This means it varies by platform,
    541    /// Rust version, and can even differ within the same execution from one invocation to the next.
    542    ///
    543    /// This function currently corresponds to the `atan2f` from libc on Unix
    544    /// and Windows. Note that this might change in the future.
    545    ///
    546    /// # Examples
    547    ///
    548    /// ```
    549    /// #![feature(f16)]
    550    /// # #[cfg(not(miri))]
    551    /// # #[cfg(target_has_reliable_f16_math)] {
    552    ///
    553    /// // Positive angles measured counter-clockwise
    554    /// // from positive x axis
    555    /// // -pi/4 radians (45 deg clockwise)
    556    /// let x1 = 3.0f16;
    557    /// let y1 = -3.0f16;
    558    ///
    559    /// // 3pi/4 radians (135 deg counter-clockwise)
    560    /// let x2 = -3.0f16;
    561    /// let y2 = 3.0f16;
    562    ///
    563    /// let abs_difference_1 = (y1.atan2(x1) - (-std::f16::consts::FRAC_PI_4)).abs();
    564    /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f16::consts::FRAC_PI_4)).abs();
    565    ///
    566    /// assert!(abs_difference_1 <= f16::EPSILON);
    567    /// assert!(abs_difference_2 <= f16::EPSILON);
    568    /// # }
    569    /// ```
    570    #[inline]
    571    #[rustc_allow_incoherent_impl]
    572    #[unstable(feature = "f16", issue = "116909")]
    573    #[must_use = "method returns a new number and does not mutate the original value"]
    574    pub fn atan2(self, other: f16) -> f16 {
    575        cmath::atan2f(self as f32, other as f32) as f16
    576    }
    577
    578    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
    579    /// `(sin(x), cos(x))`.
    580    ///
    581    /// # Unspecified precision
    582    ///
    583    /// The precision of this function is non-deterministic. This means it varies by platform,
    584    /// Rust version, and can even differ within the same execution from one invocation to the next.
    585    ///
    586    /// This function currently corresponds to the `(f16::sin(x),
    587    /// f16::cos(x))`. Note that this might change in the future.
    588    ///
    589    /// # Examples
    590    ///
    591    /// ```
    592    /// #![feature(f16)]
    593    /// # #[cfg(not(miri))]
    594    /// # #[cfg(target_has_reliable_f16_math)] {
    595    ///
    596    /// let x = std::f16::consts::FRAC_PI_4;
    597    /// let f = x.sin_cos();
    598    ///
    599    /// let abs_difference_0 = (f.0 - x.sin()).abs();
    600    /// let abs_difference_1 = (f.1 - x.cos()).abs();
    601    ///
    602    /// assert!(abs_difference_0 <= f16::EPSILON);
    603    /// assert!(abs_difference_1 <= f16::EPSILON);
    604    /// # }
    605    /// ```
    606    #[inline]
    607    #[doc(alias = "sincos")]
    608    #[rustc_allow_incoherent_impl]
    609    #[unstable(feature = "f16", issue = "116909")]
    610    pub fn sin_cos(self) -> (f16, f16) {
    611        (self.sin(), self.cos())
    612    }
    613
    614    /// Returns `e^(self) - 1` in a way that is accurate even if the
    615    /// number is close to zero.
    616    ///
    617    /// # Unspecified precision
    618    ///
    619    /// The precision of this function is non-deterministic. This means it varies by platform,
    620    /// Rust version, and can even differ within the same execution from one invocation to the next.
    621    ///
    622    /// This function currently corresponds to the `expm1f` from libc on Unix
    623    /// and Windows. Note that this might change in the future.
    624    ///
    625    /// # Examples
    626    ///
    627    /// ```
    628    /// #![feature(f16)]
    629    /// # #[cfg(not(miri))]
    630    /// # #[cfg(target_has_reliable_f16_math)] {
    631    ///
    632    /// let x = 1e-4_f16;
    633    ///
    634    /// // for very small x, e^x is approximately 1 + x + x^2 / 2
    635    /// let approx = x + x * x / 2.0;
    636    /// let abs_difference = (x.exp_m1() - approx).abs();
    637    ///
    638    /// assert!(abs_difference < 1e-4);
    639    /// # }
    640    /// ```
    641    #[inline]
    642    #[rustc_allow_incoherent_impl]
    643    #[unstable(feature = "f16", issue = "116909")]
    644    #[must_use = "method returns a new number and does not mutate the original value"]
    645    pub fn exp_m1(self) -> f16 {
    646        cmath::expm1f(self as f32) as f16
    647    }
    648
    649    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
    650    /// the operations were performed separately.
    651    ///
    652    /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`.
    653    ///
    654    /// # Unspecified precision
    655    ///
    656    /// The precision of this function is non-deterministic. This means it varies by platform,
    657    /// Rust version, and can even differ within the same execution from one invocation to the next.
    658    ///
    659    /// This function currently corresponds to the `log1pf` from libc on Unix
    660    /// and Windows. Note that this might change in the future.
    661    ///
    662    /// # Examples
    663    ///
    664    /// ```
    665    /// #![feature(f16)]
    666    /// # #[cfg(not(miri))]
    667    /// # #[cfg(target_has_reliable_f16_math)] {
    668    ///
    669    /// let x = 1e-4_f16;
    670    ///
    671    /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
    672    /// let approx = x - x * x / 2.0;
    673    /// let abs_difference = (x.ln_1p() - approx).abs();
    674    ///
    675    /// assert!(abs_difference < 1e-4);
    676    /// # }
    677    /// ```
    678    ///
    679    /// Out-of-range values:
    680    /// ```
    681    /// #![feature(f16)]
    682    /// # #[cfg(not(miri))]
    683    /// # #[cfg(target_has_reliable_f16_math)] {
    684    ///
    685    /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
    686    /// assert!((-2.0_f16).ln_1p().is_nan());
    687    /// # }
    688    /// ```
    689    #[inline]
    690    #[doc(alias = "log1p")]
    691    #[rustc_allow_incoherent_impl]
    692    #[unstable(feature = "f16", issue = "116909")]
    693    #[must_use = "method returns a new number and does not mutate the original value"]
    694    pub fn ln_1p(self) -> f16 {
    695        cmath::log1pf(self as f32) as f16
    696    }
    697
    698    /// Hyperbolic sine function.
    699    ///
    700    /// # Unspecified precision
    701    ///
    702    /// The precision of this function is non-deterministic. This means it varies by platform,
    703    /// Rust version, and can even differ within the same execution from one invocation to the next.
    704    ///
    705    /// This function currently corresponds to the `sinhf` from libc on Unix
    706    /// and Windows. Note that this might change in the future.
    707    ///
    708    /// # Examples
    709    ///
    710    /// ```
    711    /// #![feature(f16)]
    712    /// # #[cfg(not(miri))]
    713    /// # #[cfg(target_has_reliable_f16_math)] {
    714    ///
    715    /// let e = std::f16::consts::E;
    716    /// let x = 1.0f16;
    717    ///
    718    /// let f = x.sinh();
    719    /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
    720    /// let g = ((e * e) - 1.0) / (2.0 * e);
    721    /// let abs_difference = (f - g).abs();
    722    ///
    723    /// assert!(abs_difference <= f16::EPSILON);
    724    /// # }
    725    /// ```
    726    #[inline]
    727    #[rustc_allow_incoherent_impl]
    728    #[unstable(feature = "f16", issue = "116909")]
    729    #[must_use = "method returns a new number and does not mutate the original value"]
    730    pub fn sinh(self) -> f16 {
    731        cmath::sinhf(self as f32) as f16
    732    }
    733
    734    /// Hyperbolic cosine function.
    735    ///
    736    /// # Unspecified precision
    737    ///
    738    /// The precision of this function is non-deterministic. This means it varies by platform,
    739    /// Rust version, and can even differ within the same execution from one invocation to the next.
    740    ///
    741    /// This function currently corresponds to the `coshf` from libc on Unix
    742    /// and Windows. Note that this might change in the future.
    743    ///
    744    /// # Examples
    745    ///
    746    /// ```
    747    /// #![feature(f16)]
    748    /// # #[cfg(not(miri))]
    749    /// # #[cfg(target_has_reliable_f16_math)] {
    750    ///
    751    /// let e = std::f16::consts::E;
    752    /// let x = 1.0f16;
    753    /// let f = x.cosh();
    754    /// // Solving cosh() at 1 gives this result
    755    /// let g = ((e * e) + 1.0) / (2.0 * e);
    756    /// let abs_difference = (f - g).abs();
    757    ///
    758    /// // Same result
    759    /// assert!(abs_difference <= f16::EPSILON);
    760    /// # }
    761    /// ```
    762    #[inline]
    763    #[rustc_allow_incoherent_impl]
    764    #[unstable(feature = "f16", issue = "116909")]
    765    #[must_use = "method returns a new number and does not mutate the original value"]
    766    pub fn cosh(self) -> f16 {
    767        cmath::coshf(self as f32) as f16
    768    }
    769
    770    /// Hyperbolic tangent function.
    771    ///
    772    /// # Unspecified precision
    773    ///
    774    /// The precision of this function is non-deterministic. This means it varies by platform,
    775    /// Rust version, and can even differ within the same execution from one invocation to the next.
    776    ///
    777    /// This function currently corresponds to the `tanhf` from libc on Unix
    778    /// and Windows. Note that this might change in the future.
    779    ///
    780    /// # Examples
    781    ///
    782    /// ```
    783    /// #![feature(f16)]
    784    /// # #[cfg(not(miri))]
    785    /// # #[cfg(target_has_reliable_f16_math)] {
    786    ///
    787    /// let e = std::f16::consts::E;
    788    /// let x = 1.0f16;
    789    ///
    790    /// let f = x.tanh();
    791    /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
    792    /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
    793    /// let abs_difference = (f - g).abs();
    794    ///
    795    /// assert!(abs_difference <= f16::EPSILON);
    796    /// # }
    797    /// ```
    798    #[inline]
    799    #[rustc_allow_incoherent_impl]
    800    #[unstable(feature = "f16", issue = "116909")]
    801    #[must_use = "method returns a new number and does not mutate the original value"]
    802    pub fn tanh(self) -> f16 {
    803        cmath::tanhf(self as f32) as f16
    804    }
    805
    806    /// Inverse hyperbolic sine function.
    807    ///
    808    /// # Unspecified precision
    809    ///
    810    /// The precision of this function is non-deterministic. This means it varies by platform,
    811    /// Rust version, and can even differ within the same execution from one invocation to the next.
    812    ///
    813    /// # Examples
    814    ///
    815    /// ```
    816    /// #![feature(f16)]
    817    /// # #[cfg(not(miri))]
    818    /// # #[cfg(target_has_reliable_f16_math)] {
    819    ///
    820    /// let x = 1.0f16;
    821    /// let f = x.sinh().asinh();
    822    ///
    823    /// let abs_difference = (f - x).abs();
    824    ///
    825    /// assert!(abs_difference <= f16::EPSILON);
    826    /// # }
    827    /// ```
    828    #[inline]
    829    #[doc(alias = "arcsinh")]
    830    #[rustc_allow_incoherent_impl]
    831    #[unstable(feature = "f16", issue = "116909")]
    832    #[must_use = "method returns a new number and does not mutate the original value"]
    833    pub fn asinh(self) -> f16 {
    834        let ax = self.abs();
    835        let ix = 1.0 / ax;
    836        (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
    837    }
    838
    839    /// Inverse hyperbolic cosine function.
    840    ///
    841    /// # Unspecified precision
    842    ///
    843    /// The precision of this function is non-deterministic. This means it varies by platform,
    844    /// Rust version, and can even differ within the same execution from one invocation to the next.
    845    ///
    846    /// # Examples
    847    ///
    848    /// ```
    849    /// #![feature(f16)]
    850    /// # #[cfg(not(miri))]
    851    /// # #[cfg(target_has_reliable_f16_math)] {
    852    ///
    853    /// let x = 1.0f16;
    854    /// let f = x.cosh().acosh();
    855    ///
    856    /// let abs_difference = (f - x).abs();
    857    ///
    858    /// assert!(abs_difference <= f16::EPSILON);
    859    /// # }
    860    /// ```
    861    #[inline]
    862    #[doc(alias = "arccosh")]
    863    #[rustc_allow_incoherent_impl]
    864    #[unstable(feature = "f16", issue = "116909")]
    865    #[must_use = "method returns a new number and does not mutate the original value"]
    866    pub fn acosh(self) -> f16 {
    867        if self < 1.0 {
    868            Self::NAN
    869        } else {
    870            (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
    871        }
    872    }
    873
    874    /// Inverse hyperbolic tangent function.
    875    ///
    876    /// # Unspecified precision
    877    ///
    878    /// The precision of this function is non-deterministic. This means it varies by platform,
    879    /// Rust version, and can even differ within the same execution from one invocation to the next.
    880    ///
    881    /// # Examples
    882    ///
    883    /// ```
    884    /// #![feature(f16)]
    885    /// # #[cfg(not(miri))]
    886    /// # #[cfg(target_has_reliable_f16_math)] {
    887    ///
    888    /// let x = std::f16::consts::FRAC_PI_6;
    889    /// let f = x.tanh().atanh();
    890    ///
    891    /// let abs_difference = (f - x).abs();
    892    ///
    893    /// assert!(abs_difference <= 0.01);
    894    /// # }
    895    /// ```
    896    #[inline]
    897    #[doc(alias = "arctanh")]
    898    #[rustc_allow_incoherent_impl]
    899    #[unstable(feature = "f16", issue = "116909")]
    900    #[must_use = "method returns a new number and does not mutate the original value"]
    901    pub fn atanh(self) -> f16 {
    902        0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
    903    }
    904
    905    /// Gamma function.
    906    ///
    907    /// # Unspecified precision
    908    ///
    909    /// The precision of this function is non-deterministic. This means it varies by platform,
    910    /// Rust version, and can even differ within the same execution from one invocation to the next.
    911    ///
    912    /// This function currently corresponds to the `tgammaf` from libc on Unix
    913    /// and Windows. Note that this might change in the future.
    914    ///
    915    /// # Examples
    916    ///
    917    /// ```
    918    /// #![feature(f16)]
    919    /// #![feature(float_gamma)]
    920    /// # #[cfg(not(miri))]
    921    /// # #[cfg(target_has_reliable_f16_math)] {
    922    ///
    923    /// let x = 5.0f16;
    924    ///
    925    /// let abs_difference = (x.gamma() - 24.0).abs();
    926    ///
    927    /// assert!(abs_difference <= f16::EPSILON);
    928    /// # }
    929    /// ```
    930    #[inline]
    931    #[rustc_allow_incoherent_impl]
    932    #[unstable(feature = "f16", issue = "116909")]
    933    // #[unstable(feature = "float_gamma", issue = "99842")]
    934    #[must_use = "method returns a new number and does not mutate the original value"]
    935    pub fn gamma(self) -> f16 {
    936        cmath::tgammaf(self as f32) as f16
    937    }
    938
    939    /// Natural logarithm of the absolute value of the gamma function
    940    ///
    941    /// The integer part of the tuple indicates the sign of the gamma function.
    942    ///
    943    /// # Unspecified precision
    944    ///
    945    /// The precision of this function is non-deterministic. This means it varies by platform,
    946    /// Rust version, and can even differ within the same execution from one invocation to the next.
    947    ///
    948    /// This function currently corresponds to the `lgamma_r` from libc on Unix
    949    /// and Windows. Note that this might change in the future.
    950    ///
    951    /// # Examples
    952    ///
    953    /// ```
    954    /// #![feature(f16)]
    955    /// #![feature(float_gamma)]
    956    /// # #[cfg(not(miri))]
    957    /// # #[cfg(target_has_reliable_f16_math)] {
    958    ///
    959    /// let x = 2.0f16;
    960    ///
    961    /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
    962    ///
    963    /// assert!(abs_difference <= f16::EPSILON);
    964    /// # }
    965    /// ```
    966    #[inline]
    967    #[rustc_allow_incoherent_impl]
    968    #[unstable(feature = "f16", issue = "116909")]
    969    // #[unstable(feature = "float_gamma", issue = "99842")]
    970    #[must_use = "method returns a new number and does not mutate the original value"]
    971    pub fn ln_gamma(self) -> (f16, i32) {
    972        let mut signgamp: i32 = 0;
    973        let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16;
    974        (x, signgamp)
    975    }
    976
    977    /// Error function.
    978    ///
    979    /// # Unspecified precision
    980    ///
    981    /// The precision of this function is non-deterministic. This means it varies by platform,
    982    /// Rust version, and can even differ within the same execution from one invocation to the next.
    983    ///
    984    /// This function currently corresponds to the `erff` from libc on Unix
    985    /// and Windows. Note that this might change in the future.
    986    ///
    987    /// # Examples
    988    ///
    989    /// ```
    990    /// #![feature(f16)]
    991    /// #![feature(float_erf)]
    992    /// # #[cfg(not(miri))]
    993    /// # #[cfg(target_has_reliable_f16_math)] {
    994    /// /// The error function relates what percent of a normal distribution lies
    995    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
    996    /// fn within_standard_deviations(x: f16) -> f16 {
    997    ///     (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
    998    /// }
    999    ///
    1000    /// // 68% of a normal distribution is within one standard deviation
    1001    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
    1002    /// // 95% of a normal distribution is within two standard deviations
    1003    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
    1004    /// // 99.7% of a normal distribution is within three standard deviations
    1005    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
    1006    /// # }
    1007    /// ```
    1008    #[rustc_allow_incoherent_impl]
    1009    #[must_use = "method returns a new number and does not mutate the original value"]
    1010    #[unstable(feature = "f16", issue = "116909")]
    1011    // #[unstable(feature = "float_erf", issue = "136321")]
    1012    #[inline]
    1013    pub fn erf(self) -> f16 {
    1014        cmath::erff(self as f32) as f16
    1015    }
    1016
    1017    /// Complementary error function.
    1018    ///
    1019    /// # Unspecified precision
    1020    ///
    1021    /// The precision of this function is non-deterministic. This means it varies by platform,
    1022    /// Rust version, and can even differ within the same execution from one invocation to the next.
    1023    ///
    1024    /// This function currently corresponds to the `erfcf` from libc on Unix
    1025    /// and Windows. Note that this might change in the future.
    1026    ///
    1027    /// # Examples
    1028    ///
    1029    /// ```
    1030    /// #![feature(f16)]
    1031    /// #![feature(float_erf)]
    1032    /// # #[cfg(not(miri))]
    1033    /// # #[cfg(target_has_reliable_f16_math)] {
    1034    /// let x: f16 = 0.123;
    1035    ///
    1036    /// let one = x.erf() + x.erfc();
    1037    /// let abs_difference = (one - 1.0).abs();
    1038    ///
    1039    /// assert!(abs_difference <= f16::EPSILON);
    1040    /// # }
    1041    /// ```
    1042    #[rustc_allow_incoherent_impl]
    1043    #[must_use = "method returns a new number and does not mutate the original value"]
    1044    #[unstable(feature = "f16", issue = "116909")]
    1045    // #[unstable(feature = "float_erf", issue = "136321")]
    1046    #[inline]
    1047    pub fn erfc(self) -> f16 {
    1048        cmath::erfcf(self as f32) as f16
    1049    }
    1050}