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