core/num/
f16.rs

1//! Constants for the `f16` half-precision floating point type.
2//!
3//! *[See also the `f16` primitive type][f16].*
4//!
5//! Mathematically significant numbers are provided in the `consts` sub-module.
6//!
7//! For the constants defined directly in this module
8//! (as distinct from those defined in the `consts` sub-module),
9//! new code should instead use the associated constants
10//! defined directly on the `f16` type.
11
12#![unstable(feature = "f16", issue = "116909")]
13
14use crate::convert::FloatToInt;
15use crate::num::FpCategory;
16#[cfg(not(test))]
17use crate::num::libm;
18use crate::panic::const_assert;
19use crate::{intrinsics, mem};
20
21/// Basic mathematical constants.
22#[unstable(feature = "f16", issue = "116909")]
23pub mod consts {
24    // FIXME: replace with mathematical constants from cmath.
25
26    /// Archimedes' constant (π)
27    #[unstable(feature = "f16", issue = "116909")]
28    pub const PI: f16 = 3.14159265358979323846264338327950288_f16;
29
30    /// The full circle constant (τ)
31    ///
32    /// Equal to 2π.
33    #[unstable(feature = "f16", issue = "116909")]
34    pub const TAU: f16 = 6.28318530717958647692528676655900577_f16;
35
36    /// The golden ratio (φ)
37    #[unstable(feature = "f16", issue = "116909")]
38    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
39    pub const PHI: f16 = 1.618033988749894848204586834365638118_f16;
40
41    /// The Euler-Mascheroni constant (γ)
42    #[unstable(feature = "f16", issue = "116909")]
43    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
44    pub const EGAMMA: f16 = 0.577215664901532860606512090082402431_f16;
45
46    /// π/2
47    #[unstable(feature = "f16", issue = "116909")]
48    pub const FRAC_PI_2: f16 = 1.57079632679489661923132169163975144_f16;
49
50    /// π/3
51    #[unstable(feature = "f16", issue = "116909")]
52    pub const FRAC_PI_3: f16 = 1.04719755119659774615421446109316763_f16;
53
54    /// π/4
55    #[unstable(feature = "f16", issue = "116909")]
56    pub const FRAC_PI_4: f16 = 0.785398163397448309615660845819875721_f16;
57
58    /// π/6
59    #[unstable(feature = "f16", issue = "116909")]
60    pub const FRAC_PI_6: f16 = 0.52359877559829887307710723054658381_f16;
61
62    /// π/8
63    #[unstable(feature = "f16", issue = "116909")]
64    pub const FRAC_PI_8: f16 = 0.39269908169872415480783042290993786_f16;
65
66    /// 1/π
67    #[unstable(feature = "f16", issue = "116909")]
68    pub const FRAC_1_PI: f16 = 0.318309886183790671537767526745028724_f16;
69
70    /// 1/sqrt(π)
71    #[unstable(feature = "f16", issue = "116909")]
72    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
73    pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16;
74
75    /// 1/sqrt(2π)
76    #[doc(alias = "FRAC_1_SQRT_TAU")]
77    #[unstable(feature = "f16", issue = "116909")]
78    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
79    pub const FRAC_1_SQRT_2PI: f16 = 0.398942280401432677939946059934381868_f16;
80
81    /// 2/π
82    #[unstable(feature = "f16", issue = "116909")]
83    pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16;
84
85    /// 2/sqrt(π)
86    #[unstable(feature = "f16", issue = "116909")]
87    pub const FRAC_2_SQRT_PI: f16 = 1.12837916709551257389615890312154517_f16;
88
89    /// sqrt(2)
90    #[unstable(feature = "f16", issue = "116909")]
91    pub const SQRT_2: f16 = 1.41421356237309504880168872420969808_f16;
92
93    /// 1/sqrt(2)
94    #[unstable(feature = "f16", issue = "116909")]
95    pub const FRAC_1_SQRT_2: f16 = 0.707106781186547524400844362104849039_f16;
96
97    /// sqrt(3)
98    #[unstable(feature = "f16", issue = "116909")]
99    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
100    pub const SQRT_3: f16 = 1.732050807568877293527446341505872367_f16;
101
102    /// 1/sqrt(3)
103    #[unstable(feature = "f16", issue = "116909")]
104    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
105    pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16;
106
107    /// Euler's number (e)
108    #[unstable(feature = "f16", issue = "116909")]
109    pub const E: f16 = 2.71828182845904523536028747135266250_f16;
110
111    /// log<sub>2</sub>(10)
112    #[unstable(feature = "f16", issue = "116909")]
113    pub const LOG2_10: f16 = 3.32192809488736234787031942948939018_f16;
114
115    /// log<sub>2</sub>(e)
116    #[unstable(feature = "f16", issue = "116909")]
117    pub const LOG2_E: f16 = 1.44269504088896340735992468100189214_f16;
118
119    /// log<sub>10</sub>(2)
120    #[unstable(feature = "f16", issue = "116909")]
121    pub const LOG10_2: f16 = 0.301029995663981195213738894724493027_f16;
122
123    /// log<sub>10</sub>(e)
124    #[unstable(feature = "f16", issue = "116909")]
125    pub const LOG10_E: f16 = 0.434294481903251827651128918916605082_f16;
126
127    /// ln(2)
128    #[unstable(feature = "f16", issue = "116909")]
129    pub const LN_2: f16 = 0.693147180559945309417232121458176568_f16;
130
131    /// ln(10)
132    #[unstable(feature = "f16", issue = "116909")]
133    pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16;
134}
135
136impl f16 {
137    // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
138    // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
139
140    /// The radix or base of the internal representation of `f16`.
141    #[unstable(feature = "f16", issue = "116909")]
142    pub const RADIX: u32 = 2;
143
144    /// Number of significant digits in base 2.
145    ///
146    /// Note that the size of the mantissa in the bitwise representation is one
147    /// smaller than this since the leading 1 is not stored explicitly.
148    #[unstable(feature = "f16", issue = "116909")]
149    pub const MANTISSA_DIGITS: u32 = 11;
150
151    /// Approximate number of significant digits in base 10.
152    ///
153    /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
154    /// significant digits can be converted to `f16` and back without loss.
155    ///
156    /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
157    ///
158    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
159    #[unstable(feature = "f16", issue = "116909")]
160    pub const DIGITS: u32 = 3;
161
162    /// [Machine epsilon] value for `f16`.
163    ///
164    /// This is the difference between `1.0` and the next larger representable number.
165    ///
166    /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
167    ///
168    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
169    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
170    #[unstable(feature = "f16", issue = "116909")]
171    pub const EPSILON: f16 = 9.7656e-4_f16;
172
173    /// Smallest finite `f16` value.
174    ///
175    /// Equal to &minus;[`MAX`].
176    ///
177    /// [`MAX`]: f16::MAX
178    #[unstable(feature = "f16", issue = "116909")]
179    pub const MIN: f16 = -6.5504e+4_f16;
180    /// Smallest positive normal `f16` value.
181    ///
182    /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
183    ///
184    /// [`MIN_EXP`]: f16::MIN_EXP
185    #[unstable(feature = "f16", issue = "116909")]
186    pub const MIN_POSITIVE: f16 = 6.1035e-5_f16;
187    /// Largest finite `f16` value.
188    ///
189    /// Equal to
190    /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
191    ///
192    /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
193    /// [`MAX_EXP`]: f16::MAX_EXP
194    #[unstable(feature = "f16", issue = "116909")]
195    pub const MAX: f16 = 6.5504e+4_f16;
196
197    /// One greater than the minimum possible *normal* power of 2 exponent
198    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
199    ///
200    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
201    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
202    /// In other words, all normal numbers representable by this type are
203    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
204    #[unstable(feature = "f16", issue = "116909")]
205    pub const MIN_EXP: i32 = -13;
206    /// One greater than the maximum possible power of 2 exponent
207    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
208    ///
209    /// This corresponds to the exact maximum possible power of 2 exponent
210    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
211    /// In other words, all numbers representable by this type are
212    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
213    #[unstable(feature = "f16", issue = "116909")]
214    pub const MAX_EXP: i32 = 16;
215
216    /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
217    ///
218    /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
219    ///
220    /// [`MIN_POSITIVE`]: f16::MIN_POSITIVE
221    #[unstable(feature = "f16", issue = "116909")]
222    pub const MIN_10_EXP: i32 = -4;
223    /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
224    ///
225    /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
226    ///
227    /// [`MAX`]: f16::MAX
228    #[unstable(feature = "f16", issue = "116909")]
229    pub const MAX_10_EXP: i32 = 4;
230
231    /// Not a Number (NaN).
232    ///
233    /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are
234    /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and
235    /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern)
236    /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more
237    /// info.
238    ///
239    /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions
240    /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is
241    /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary.
242    /// The concrete bit pattern may change across Rust versions and target platforms.
243    #[allow(clippy::eq_op)]
244    #[rustc_diagnostic_item = "f16_nan"]
245    #[unstable(feature = "f16", issue = "116909")]
246    pub const NAN: f16 = 0.0_f16 / 0.0_f16;
247
248    /// Infinity (∞).
249    #[unstable(feature = "f16", issue = "116909")]
250    pub const INFINITY: f16 = 1.0_f16 / 0.0_f16;
251
252    /// Negative infinity (−∞).
253    #[unstable(feature = "f16", issue = "116909")]
254    pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
255
256    /// Sign bit
257    pub(crate) const SIGN_MASK: u16 = 0x8000;
258
259    /// Exponent mask
260    pub(crate) const EXP_MASK: u16 = 0x7c00;
261
262    /// Mantissa mask
263    pub(crate) const MAN_MASK: u16 = 0x03ff;
264
265    /// Minimum representable positive value (min subnormal)
266    const TINY_BITS: u16 = 0x1;
267
268    /// Minimum representable negative value (min negative subnormal)
269    const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK;
270
271    /// Returns `true` if this value is NaN.
272    ///
273    /// ```
274    /// #![feature(f16)]
275    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
276    ///
277    /// let nan = f16::NAN;
278    /// let f = 7.0_f16;
279    ///
280    /// assert!(nan.is_nan());
281    /// assert!(!f.is_nan());
282    /// # }
283    /// ```
284    #[inline]
285    #[must_use]
286    #[unstable(feature = "f16", issue = "116909")]
287    #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
288    pub const fn is_nan(self) -> bool {
289        self != self
290    }
291
292    /// Returns `true` if this value is positive infinity or negative infinity, and
293    /// `false` otherwise.
294    ///
295    /// ```
296    /// #![feature(f16)]
297    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
298    ///
299    /// let f = 7.0f16;
300    /// let inf = f16::INFINITY;
301    /// let neg_inf = f16::NEG_INFINITY;
302    /// let nan = f16::NAN;
303    ///
304    /// assert!(!f.is_infinite());
305    /// assert!(!nan.is_infinite());
306    ///
307    /// assert!(inf.is_infinite());
308    /// assert!(neg_inf.is_infinite());
309    /// # }
310    /// ```
311    #[inline]
312    #[must_use]
313    #[unstable(feature = "f16", issue = "116909")]
314    pub const fn is_infinite(self) -> bool {
315        (self == f16::INFINITY) | (self == f16::NEG_INFINITY)
316    }
317
318    /// Returns `true` if this number is neither infinite nor NaN.
319    ///
320    /// ```
321    /// #![feature(f16)]
322    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
323    ///
324    /// let f = 7.0f16;
325    /// let inf: f16 = f16::INFINITY;
326    /// let neg_inf: f16 = f16::NEG_INFINITY;
327    /// let nan: f16 = f16::NAN;
328    ///
329    /// assert!(f.is_finite());
330    ///
331    /// assert!(!nan.is_finite());
332    /// assert!(!inf.is_finite());
333    /// assert!(!neg_inf.is_finite());
334    /// # }
335    /// ```
336    #[inline]
337    #[must_use]
338    #[unstable(feature = "f16", issue = "116909")]
339    #[rustc_const_unstable(feature = "f16", issue = "116909")]
340    pub const fn is_finite(self) -> bool {
341        // There's no need to handle NaN separately: if self is NaN,
342        // the comparison is not true, exactly as desired.
343        self.abs() < Self::INFINITY
344    }
345
346    /// Returns `true` if the number is [subnormal].
347    ///
348    /// ```
349    /// #![feature(f16)]
350    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
351    ///
352    /// let min = f16::MIN_POSITIVE; // 6.1035e-5
353    /// let max = f16::MAX;
354    /// let lower_than_min = 1.0e-7_f16;
355    /// let zero = 0.0_f16;
356    ///
357    /// assert!(!min.is_subnormal());
358    /// assert!(!max.is_subnormal());
359    ///
360    /// assert!(!zero.is_subnormal());
361    /// assert!(!f16::NAN.is_subnormal());
362    /// assert!(!f16::INFINITY.is_subnormal());
363    /// // Values between `0` and `min` are Subnormal.
364    /// assert!(lower_than_min.is_subnormal());
365    /// # }
366    /// ```
367    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
368    #[inline]
369    #[must_use]
370    #[unstable(feature = "f16", issue = "116909")]
371    pub const fn is_subnormal(self) -> bool {
372        matches!(self.classify(), FpCategory::Subnormal)
373    }
374
375    /// Returns `true` if the number is neither zero, infinite, [subnormal], or NaN.
376    ///
377    /// ```
378    /// #![feature(f16)]
379    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
380    ///
381    /// let min = f16::MIN_POSITIVE; // 6.1035e-5
382    /// let max = f16::MAX;
383    /// let lower_than_min = 1.0e-7_f16;
384    /// let zero = 0.0_f16;
385    ///
386    /// assert!(min.is_normal());
387    /// assert!(max.is_normal());
388    ///
389    /// assert!(!zero.is_normal());
390    /// assert!(!f16::NAN.is_normal());
391    /// assert!(!f16::INFINITY.is_normal());
392    /// // Values between `0` and `min` are Subnormal.
393    /// assert!(!lower_than_min.is_normal());
394    /// # }
395    /// ```
396    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
397    #[inline]
398    #[must_use]
399    #[unstable(feature = "f16", issue = "116909")]
400    pub const fn is_normal(self) -> bool {
401        matches!(self.classify(), FpCategory::Normal)
402    }
403
404    /// Returns the floating point category of the number. If only one property
405    /// is going to be tested, it is generally faster to use the specific
406    /// predicate instead.
407    ///
408    /// ```
409    /// #![feature(f16)]
410    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
411    ///
412    /// use std::num::FpCategory;
413    ///
414    /// let num = 12.4_f16;
415    /// let inf = f16::INFINITY;
416    ///
417    /// assert_eq!(num.classify(), FpCategory::Normal);
418    /// assert_eq!(inf.classify(), FpCategory::Infinite);
419    /// # }
420    /// ```
421    #[inline]
422    #[unstable(feature = "f16", issue = "116909")]
423    pub const fn classify(self) -> FpCategory {
424        let b = self.to_bits();
425        match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
426            (0, Self::EXP_MASK) => FpCategory::Infinite,
427            (_, Self::EXP_MASK) => FpCategory::Nan,
428            (0, 0) => FpCategory::Zero,
429            (_, 0) => FpCategory::Subnormal,
430            _ => FpCategory::Normal,
431        }
432    }
433
434    /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
435    /// positive sign bit and positive infinity.
436    ///
437    /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
438    /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
439    /// conserved over arithmetic operations, the result of `is_sign_positive` on
440    /// a NaN might produce an unexpected or non-portable result. See the [specification
441    /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0`
442    /// if you need fully portable behavior (will return `false` for all NaNs).
443    ///
444    /// ```
445    /// #![feature(f16)]
446    /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
447    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
448    ///
449    /// let f = 7.0_f16;
450    /// let g = -7.0_f16;
451    ///
452    /// assert!(f.is_sign_positive());
453    /// assert!(!g.is_sign_positive());
454    /// # }
455    /// ```
456    #[inline]
457    #[must_use]
458    #[unstable(feature = "f16", issue = "116909")]
459    pub const fn is_sign_positive(self) -> bool {
460        !self.is_sign_negative()
461    }
462
463    /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
464    /// negative sign bit and negative infinity.
465    ///
466    /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
467    /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
468    /// conserved over arithmetic operations, the result of `is_sign_negative` on
469    /// a NaN might produce an unexpected or non-portable result. See the [specification
470    /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0`
471    /// if you need fully portable behavior (will return `false` for all NaNs).
472    ///
473    /// ```
474    /// #![feature(f16)]
475    /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
476    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
477    ///
478    /// let f = 7.0_f16;
479    /// let g = -7.0_f16;
480    ///
481    /// assert!(!f.is_sign_negative());
482    /// assert!(g.is_sign_negative());
483    /// # }
484    /// ```
485    #[inline]
486    #[must_use]
487    #[unstable(feature = "f16", issue = "116909")]
488    pub const fn is_sign_negative(self) -> bool {
489        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
490        // applies to zeros and NaNs as well.
491        // SAFETY: This is just transmuting to get the sign bit, it's fine.
492        (self.to_bits() & (1 << 15)) != 0
493    }
494
495    /// Returns the least number greater than `self`.
496    ///
497    /// Let `TINY` be the smallest representable positive `f16`. Then,
498    ///  - if `self.is_nan()`, this returns `self`;
499    ///  - if `self` is [`NEG_INFINITY`], this returns [`MIN`];
500    ///  - if `self` is `-TINY`, this returns -0.0;
501    ///  - if `self` is -0.0 or +0.0, this returns `TINY`;
502    ///  - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`];
503    ///  - otherwise the unique least value greater than `self` is returned.
504    ///
505    /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x`
506    /// is finite `x == x.next_up().next_down()` also holds.
507    ///
508    /// ```rust
509    /// #![feature(f16)]
510    /// # // FIXME(f16_f128): ABI issues on MSVC
511    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
512    ///
513    /// // f16::EPSILON is the difference between 1.0 and the next number up.
514    /// assert_eq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
515    /// // But not for most numbers.
516    /// assert!(0.1f16.next_up() < 0.1 + f16::EPSILON);
517    /// assert_eq!(4356f16.next_up(), 4360.0);
518    /// # }
519    /// ```
520    ///
521    /// This operation corresponds to IEEE-754 `nextUp`.
522    ///
523    /// [`NEG_INFINITY`]: Self::NEG_INFINITY
524    /// [`INFINITY`]: Self::INFINITY
525    /// [`MIN`]: Self::MIN
526    /// [`MAX`]: Self::MAX
527    #[inline]
528    #[doc(alias = "nextUp")]
529    #[unstable(feature = "f16", issue = "116909")]
530    pub const fn next_up(self) -> Self {
531        // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
532        // denormals to zero. This is in general unsound and unsupported, but here
533        // we do our best to still produce the correct result on such targets.
534        let bits = self.to_bits();
535        if self.is_nan() || bits == Self::INFINITY.to_bits() {
536            return self;
537        }
538
539        let abs = bits & !Self::SIGN_MASK;
540        let next_bits = if abs == 0 {
541            Self::TINY_BITS
542        } else if bits == abs {
543            bits + 1
544        } else {
545            bits - 1
546        };
547        Self::from_bits(next_bits)
548    }
549
550    /// Returns the greatest number less than `self`.
551    ///
552    /// Let `TINY` be the smallest representable positive `f16`. Then,
553    ///  - if `self.is_nan()`, this returns `self`;
554    ///  - if `self` is [`INFINITY`], this returns [`MAX`];
555    ///  - if `self` is `TINY`, this returns 0.0;
556    ///  - if `self` is -0.0 or +0.0, this returns `-TINY`;
557    ///  - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`];
558    ///  - otherwise the unique greatest value less than `self` is returned.
559    ///
560    /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x`
561    /// is finite `x == x.next_down().next_up()` also holds.
562    ///
563    /// ```rust
564    /// #![feature(f16)]
565    /// # // FIXME(f16_f128): ABI issues on MSVC
566    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
567    ///
568    /// let x = 1.0f16;
569    /// // Clamp value into range [0, 1).
570    /// let clamped = x.clamp(0.0, 1.0f16.next_down());
571    /// assert!(clamped < 1.0);
572    /// assert_eq!(clamped.next_up(), 1.0);
573    /// # }
574    /// ```
575    ///
576    /// This operation corresponds to IEEE-754 `nextDown`.
577    ///
578    /// [`NEG_INFINITY`]: Self::NEG_INFINITY
579    /// [`INFINITY`]: Self::INFINITY
580    /// [`MIN`]: Self::MIN
581    /// [`MAX`]: Self::MAX
582    #[inline]
583    #[doc(alias = "nextDown")]
584    #[unstable(feature = "f16", issue = "116909")]
585    pub const fn next_down(self) -> Self {
586        // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
587        // denormals to zero. This is in general unsound and unsupported, but here
588        // we do our best to still produce the correct result on such targets.
589        let bits = self.to_bits();
590        if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
591            return self;
592        }
593
594        let abs = bits & !Self::SIGN_MASK;
595        let next_bits = if abs == 0 {
596            Self::NEG_TINY_BITS
597        } else if bits == abs {
598            bits - 1
599        } else {
600            bits + 1
601        };
602        Self::from_bits(next_bits)
603    }
604
605    /// Takes the reciprocal (inverse) of a number, `1/x`.
606    ///
607    /// ```
608    /// #![feature(f16)]
609    /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
610    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
611    ///
612    /// let x = 2.0_f16;
613    /// let abs_difference = (x.recip() - (1.0 / x)).abs();
614    ///
615    /// assert!(abs_difference <= f16::EPSILON);
616    /// # }
617    /// ```
618    #[inline]
619    #[unstable(feature = "f16", issue = "116909")]
620    #[must_use = "this returns the result of the operation, without modifying the original"]
621    pub const fn recip(self) -> Self {
622        1.0 / self
623    }
624
625    /// Converts radians to degrees.
626    ///
627    /// ```
628    /// #![feature(f16)]
629    /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
630    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
631    ///
632    /// let angle = std::f16::consts::PI;
633    ///
634    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
635    /// assert!(abs_difference <= 0.5);
636    /// # }
637    /// ```
638    #[inline]
639    #[unstable(feature = "f16", issue = "116909")]
640    #[must_use = "this returns the result of the operation, without modifying the original"]
641    pub const fn to_degrees(self) -> Self {
642        // Use a literal for better precision.
643        const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
644        self * PIS_IN_180
645    }
646
647    /// Converts degrees to radians.
648    ///
649    /// ```
650    /// #![feature(f16)]
651    /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
652    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
653    ///
654    /// let angle = 180.0f16;
655    ///
656    /// let abs_difference = (angle.to_radians() - std::f16::consts::PI).abs();
657    ///
658    /// assert!(abs_difference <= 0.01);
659    /// # }
660    /// ```
661    #[inline]
662    #[unstable(feature = "f16", issue = "116909")]
663    #[must_use = "this returns the result of the operation, without modifying the original"]
664    pub const fn to_radians(self) -> f16 {
665        // Use a literal for better precision.
666        const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
667        self * RADS_PER_DEG
668    }
669
670    /// Returns the maximum of the two numbers, ignoring NaN.
671    ///
672    /// If one of the arguments is NaN, then the other argument is returned.
673    /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
674    /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
675    /// This also matches the behavior of libm’s fmax. In particular, if the inputs compare equal
676    /// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
677    ///
678    /// ```
679    /// #![feature(f16)]
680    /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
681    ///
682    /// let x = 1.0f16;
683    /// let y = 2.0f16;
684    ///
685    /// assert_eq!(x.max(y), y);
686    /// # }
687    /// ```
688    #[inline]
689    #[unstable(feature = "f16", issue = "116909")]
690    #[rustc_const_unstable(feature = "f16", issue = "116909")]
691    #[must_use = "this returns the result of the comparison, without modifying either input"]
692    pub const fn max(self, other: f16) -> f16 {
693        intrinsics::maxnumf16(self, other)
694    }
695
696    /// Returns the minimum of the two numbers, ignoring NaN.
697    ///
698    /// If one of the arguments is NaN, then the other argument is returned.
699    /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
700    /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
701    /// This also matches the behavior of libm’s fmin. In particular, if the inputs compare equal
702    /// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
703    ///
704    /// ```
705    /// #![feature(f16)]
706    /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
707    ///
708    /// let x = 1.0f16;
709    /// let y = 2.0f16;
710    ///
711    /// assert_eq!(x.min(y), x);
712    /// # }
713    /// ```
714    #[inline]
715    #[unstable(feature = "f16", issue = "116909")]
716    #[rustc_const_unstable(feature = "f16", issue = "116909")]
717    #[must_use = "this returns the result of the comparison, without modifying either input"]
718    pub const fn min(self, other: f16) -> f16 {
719        intrinsics::minnumf16(self, other)
720    }
721
722    /// Returns the maximum of the two numbers, propagating NaN.
723    ///
724    /// This returns NaN when *either* argument is NaN, as opposed to
725    /// [`f16::max`] which only returns NaN when *both* arguments are NaN.
726    ///
727    /// ```
728    /// #![feature(f16)]
729    /// #![feature(float_minimum_maximum)]
730    /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
731    ///
732    /// let x = 1.0f16;
733    /// let y = 2.0f16;
734    ///
735    /// assert_eq!(x.maximum(y), y);
736    /// assert!(x.maximum(f16::NAN).is_nan());
737    /// # }
738    /// ```
739    ///
740    /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
741    /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
742    /// Note that this follows the semantics specified in IEEE 754-2019.
743    ///
744    /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
745    /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
746    #[inline]
747    #[unstable(feature = "f16", issue = "116909")]
748    // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
749    #[must_use = "this returns the result of the comparison, without modifying either input"]
750    pub const fn maximum(self, other: f16) -> f16 {
751        intrinsics::maximumf16(self, other)
752    }
753
754    /// Returns the minimum of the two numbers, propagating NaN.
755    ///
756    /// This returns NaN when *either* argument is NaN, as opposed to
757    /// [`f16::min`] which only returns NaN when *both* arguments are NaN.
758    ///
759    /// ```
760    /// #![feature(f16)]
761    /// #![feature(float_minimum_maximum)]
762    /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
763    ///
764    /// let x = 1.0f16;
765    /// let y = 2.0f16;
766    ///
767    /// assert_eq!(x.minimum(y), x);
768    /// assert!(x.minimum(f16::NAN).is_nan());
769    /// # }
770    /// ```
771    ///
772    /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
773    /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
774    /// Note that this follows the semantics specified in IEEE 754-2019.
775    ///
776    /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
777    /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
778    #[inline]
779    #[unstable(feature = "f16", issue = "116909")]
780    // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
781    #[must_use = "this returns the result of the comparison, without modifying either input"]
782    pub const fn minimum(self, other: f16) -> f16 {
783        intrinsics::minimumf16(self, other)
784    }
785
786    /// Calculates the midpoint (average) between `self` and `rhs`.
787    ///
788    /// This returns NaN when *either* argument is NaN or if a combination of
789    /// +inf and -inf is provided as arguments.
790    ///
791    /// # Examples
792    ///
793    /// ```
794    /// #![feature(f16)]
795    /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
796    ///
797    /// assert_eq!(1f16.midpoint(4.0), 2.5);
798    /// assert_eq!((-5.5f16).midpoint(8.0), 1.25);
799    /// # }
800    /// ```
801    #[inline]
802    #[doc(alias = "average")]
803    #[unstable(feature = "f16", issue = "116909")]
804    #[rustc_const_unstable(feature = "f16", issue = "116909")]
805    pub const fn midpoint(self, other: f16) -> f16 {
806        const LO: f16 = f16::MIN_POSITIVE * 2.;
807        const HI: f16 = f16::MAX / 2.;
808
809        let (a, b) = (self, other);
810        let abs_a = a.abs();
811        let abs_b = b.abs();
812
813        if abs_a <= HI && abs_b <= HI {
814            // Overflow is impossible
815            (a + b) / 2.
816        } else if abs_a < LO {
817            // Not safe to halve `a` (would underflow)
818            a + (b / 2.)
819        } else if abs_b < LO {
820            // Not safe to halve `b` (would underflow)
821            (a / 2.) + b
822        } else {
823            // Safe to halve `a` and `b`
824            (a / 2.) + (b / 2.)
825        }
826    }
827
828    /// Rounds toward zero and converts to any primitive integer type,
829    /// assuming that the value is finite and fits in that type.
830    ///
831    /// ```
832    /// #![feature(f16)]
833    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
834    ///
835    /// let value = 4.6_f16;
836    /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
837    /// assert_eq!(rounded, 4);
838    ///
839    /// let value = -128.9_f16;
840    /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
841    /// assert_eq!(rounded, i8::MIN);
842    /// # }
843    /// ```
844    ///
845    /// # Safety
846    ///
847    /// The value must:
848    ///
849    /// * Not be `NaN`
850    /// * Not be infinite
851    /// * Be representable in the return type `Int`, after truncating off its fractional part
852    #[inline]
853    #[unstable(feature = "f16", issue = "116909")]
854    #[must_use = "this returns the result of the operation, without modifying the original"]
855    pub unsafe fn to_int_unchecked<Int>(self) -> Int
856    where
857        Self: FloatToInt<Int>,
858    {
859        // SAFETY: the caller must uphold the safety contract for
860        // `FloatToInt::to_int_unchecked`.
861        unsafe { FloatToInt::<Int>::to_int_unchecked(self) }
862    }
863
864    /// Raw transmutation to `u16`.
865    ///
866    /// This is currently identical to `transmute::<f16, u16>(self)` on all platforms.
867    ///
868    /// See [`from_bits`](#method.from_bits) for some discussion of the
869    /// portability of this operation (there are almost no issues).
870    ///
871    /// Note that this function is distinct from `as` casting, which attempts to
872    /// preserve the *numeric* value, and not the bitwise value.
873    ///
874    /// ```
875    /// #![feature(f16)]
876    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
877    ///
878    /// # // FIXME(f16_f128): enable this once const casting works
879    /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting!
880    /// assert_eq!((12.5f16).to_bits(), 0x4a40);
881    /// # }
882    /// ```
883    #[inline]
884    #[unstable(feature = "f16", issue = "116909")]
885    #[must_use = "this returns the result of the operation, without modifying the original"]
886    #[allow(unnecessary_transmutes)]
887    pub const fn to_bits(self) -> u16 {
888        // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
889        unsafe { mem::transmute(self) }
890    }
891
892    /// Raw transmutation from `u16`.
893    ///
894    /// This is currently identical to `transmute::<u16, f16>(v)` on all platforms.
895    /// It turns out this is incredibly portable, for two reasons:
896    ///
897    /// * Floats and Ints have the same endianness on all supported platforms.
898    /// * IEEE 754 very precisely specifies the bit layout of floats.
899    ///
900    /// However there is one caveat: prior to the 2008 version of IEEE 754, how
901    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
902    /// (notably x86 and ARM) picked the interpretation that was ultimately
903    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
904    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
905    ///
906    /// Rather than trying to preserve signaling-ness cross-platform, this
907    /// implementation favors preserving the exact bits. This means that
908    /// any payloads encoded in NaNs will be preserved even if the result of
909    /// this method is sent over the network from an x86 machine to a MIPS one.
910    ///
911    /// If the results of this method are only manipulated by the same
912    /// architecture that produced them, then there is no portability concern.
913    ///
914    /// If the input isn't NaN, then there is no portability concern.
915    ///
916    /// If you don't care about signalingness (very likely), then there is no
917    /// portability concern.
918    ///
919    /// Note that this function is distinct from `as` casting, which attempts to
920    /// preserve the *numeric* value, and not the bitwise value.
921    ///
922    /// ```
923    /// #![feature(f16)]
924    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
925    ///
926    /// let v = f16::from_bits(0x4a40);
927    /// assert_eq!(v, 12.5);
928    /// # }
929    /// ```
930    #[inline]
931    #[must_use]
932    #[unstable(feature = "f16", issue = "116909")]
933    #[allow(unnecessary_transmutes)]
934    pub const fn from_bits(v: u16) -> Self {
935        // It turns out the safety issues with sNaN were overblown! Hooray!
936        // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
937        unsafe { mem::transmute(v) }
938    }
939
940    /// Returns the memory representation of this floating point number as a byte array in
941    /// big-endian (network) byte order.
942    ///
943    /// See [`from_bits`](Self::from_bits) for some discussion of the
944    /// portability of this operation (there are almost no issues).
945    ///
946    /// # Examples
947    ///
948    /// ```
949    /// #![feature(f16)]
950    /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
951    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
952    ///
953    /// let bytes = 12.5f16.to_be_bytes();
954    /// assert_eq!(bytes, [0x4a, 0x40]);
955    /// # }
956    /// ```
957    #[inline]
958    #[unstable(feature = "f16", issue = "116909")]
959    #[must_use = "this returns the result of the operation, without modifying the original"]
960    pub const fn to_be_bytes(self) -> [u8; 2] {
961        self.to_bits().to_be_bytes()
962    }
963
964    /// Returns the memory representation of this floating point number as a byte array in
965    /// little-endian byte order.
966    ///
967    /// See [`from_bits`](Self::from_bits) for some discussion of the
968    /// portability of this operation (there are almost no issues).
969    ///
970    /// # Examples
971    ///
972    /// ```
973    /// #![feature(f16)]
974    /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
975    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
976    ///
977    /// let bytes = 12.5f16.to_le_bytes();
978    /// assert_eq!(bytes, [0x40, 0x4a]);
979    /// # }
980    /// ```
981    #[inline]
982    #[unstable(feature = "f16", issue = "116909")]
983    #[must_use = "this returns the result of the operation, without modifying the original"]
984    pub const fn to_le_bytes(self) -> [u8; 2] {
985        self.to_bits().to_le_bytes()
986    }
987
988    /// Returns the memory representation of this floating point number as a byte array in
989    /// native byte order.
990    ///
991    /// As the target platform's native endianness is used, portable code
992    /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
993    ///
994    /// [`to_be_bytes`]: f16::to_be_bytes
995    /// [`to_le_bytes`]: f16::to_le_bytes
996    ///
997    /// See [`from_bits`](Self::from_bits) for some discussion of the
998    /// portability of this operation (there are almost no issues).
999    ///
1000    /// # Examples
1001    ///
1002    /// ```
1003    /// #![feature(f16)]
1004    /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
1005    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1006    ///
1007    /// let bytes = 12.5f16.to_ne_bytes();
1008    /// assert_eq!(
1009    ///     bytes,
1010    ///     if cfg!(target_endian = "big") {
1011    ///         [0x4a, 0x40]
1012    ///     } else {
1013    ///         [0x40, 0x4a]
1014    ///     }
1015    /// );
1016    /// # }
1017    /// ```
1018    #[inline]
1019    #[unstable(feature = "f16", issue = "116909")]
1020    #[must_use = "this returns the result of the operation, without modifying the original"]
1021    pub const fn to_ne_bytes(self) -> [u8; 2] {
1022        self.to_bits().to_ne_bytes()
1023    }
1024
1025    /// Creates a floating point value from its representation as a byte array in big endian.
1026    ///
1027    /// See [`from_bits`](Self::from_bits) for some discussion of the
1028    /// portability of this operation (there are almost no issues).
1029    ///
1030    /// # Examples
1031    ///
1032    /// ```
1033    /// #![feature(f16)]
1034    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1035    ///
1036    /// let value = f16::from_be_bytes([0x4a, 0x40]);
1037    /// assert_eq!(value, 12.5);
1038    /// # }
1039    /// ```
1040    #[inline]
1041    #[must_use]
1042    #[unstable(feature = "f16", issue = "116909")]
1043    pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
1044        Self::from_bits(u16::from_be_bytes(bytes))
1045    }
1046
1047    /// Creates a floating point value from its representation as a byte array in little endian.
1048    ///
1049    /// See [`from_bits`](Self::from_bits) for some discussion of the
1050    /// portability of this operation (there are almost no issues).
1051    ///
1052    /// # Examples
1053    ///
1054    /// ```
1055    /// #![feature(f16)]
1056    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1057    ///
1058    /// let value = f16::from_le_bytes([0x40, 0x4a]);
1059    /// assert_eq!(value, 12.5);
1060    /// # }
1061    /// ```
1062    #[inline]
1063    #[must_use]
1064    #[unstable(feature = "f16", issue = "116909")]
1065    pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
1066        Self::from_bits(u16::from_le_bytes(bytes))
1067    }
1068
1069    /// Creates a floating point value from its representation as a byte array in native endian.
1070    ///
1071    /// As the target platform's native endianness is used, portable code
1072    /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
1073    /// appropriate instead.
1074    ///
1075    /// [`from_be_bytes`]: f16::from_be_bytes
1076    /// [`from_le_bytes`]: f16::from_le_bytes
1077    ///
1078    /// See [`from_bits`](Self::from_bits) for some discussion of the
1079    /// portability of this operation (there are almost no issues).
1080    ///
1081    /// # Examples
1082    ///
1083    /// ```
1084    /// #![feature(f16)]
1085    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1086    ///
1087    /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") {
1088    ///     [0x4a, 0x40]
1089    /// } else {
1090    ///     [0x40, 0x4a]
1091    /// });
1092    /// assert_eq!(value, 12.5);
1093    /// # }
1094    /// ```
1095    #[inline]
1096    #[must_use]
1097    #[unstable(feature = "f16", issue = "116909")]
1098    pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
1099        Self::from_bits(u16::from_ne_bytes(bytes))
1100    }
1101
1102    /// Returns the ordering between `self` and `other`.
1103    ///
1104    /// Unlike the standard partial comparison between floating point numbers,
1105    /// this comparison always produces an ordering in accordance to
1106    /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision)
1107    /// floating point standard. The values are ordered in the following sequence:
1108    ///
1109    /// - negative quiet NaN
1110    /// - negative signaling NaN
1111    /// - negative infinity
1112    /// - negative numbers
1113    /// - negative subnormal numbers
1114    /// - negative zero
1115    /// - positive zero
1116    /// - positive subnormal numbers
1117    /// - positive numbers
1118    /// - positive infinity
1119    /// - positive signaling NaN
1120    /// - positive quiet NaN.
1121    ///
1122    /// The ordering established by this function does not always agree with the
1123    /// [`PartialOrd`] and [`PartialEq`] implementations of `f16`. For example,
1124    /// they consider negative and positive zero equal, while `total_cmp`
1125    /// doesn't.
1126    ///
1127    /// The interpretation of the signaling NaN bit follows the definition in
1128    /// the IEEE 754 standard, which may not match the interpretation by some of
1129    /// the older, non-conformant (e.g. MIPS) hardware implementations.
1130    ///
1131    /// # Example
1132    ///
1133    /// ```
1134    /// #![feature(f16)]
1135    /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
1136    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1137    ///
1138    /// struct GoodBoy {
1139    ///     name: &'static str,
1140    ///     weight: f16,
1141    /// }
1142    ///
1143    /// let mut bois = vec![
1144    ///     GoodBoy { name: "Pucci", weight: 0.1 },
1145    ///     GoodBoy { name: "Woofer", weight: 99.0 },
1146    ///     GoodBoy { name: "Yapper", weight: 10.0 },
1147    ///     GoodBoy { name: "Chonk", weight: f16::INFINITY },
1148    ///     GoodBoy { name: "Abs. Unit", weight: f16::NAN },
1149    ///     GoodBoy { name: "Floaty", weight: -5.0 },
1150    /// ];
1151    ///
1152    /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
1153    ///
1154    /// // `f16::NAN` could be positive or negative, which will affect the sort order.
1155    /// if f16::NAN.is_sign_negative() {
1156    ///     bois.into_iter().map(|b| b.weight)
1157    ///         .zip([f16::NAN, -5.0, 0.1, 10.0, 99.0, f16::INFINITY].iter())
1158    ///         .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
1159    /// } else {
1160    ///     bois.into_iter().map(|b| b.weight)
1161    ///         .zip([-5.0, 0.1, 10.0, 99.0, f16::INFINITY, f16::NAN].iter())
1162    ///         .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
1163    /// }
1164    /// # }
1165    /// ```
1166    #[inline]
1167    #[must_use]
1168    #[unstable(feature = "f16", issue = "116909")]
1169    pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
1170        let mut left = self.to_bits() as i16;
1171        let mut right = other.to_bits() as i16;
1172
1173        // In case of negatives, flip all the bits except the sign
1174        // to achieve a similar layout as two's complement integers
1175        //
1176        // Why does this work? IEEE 754 floats consist of three fields:
1177        // Sign bit, exponent and mantissa. The set of exponent and mantissa
1178        // fields as a whole have the property that their bitwise order is
1179        // equal to the numeric magnitude where the magnitude is defined.
1180        // The magnitude is not normally defined on NaN values, but
1181        // IEEE 754 totalOrder defines the NaN values also to follow the
1182        // bitwise order. This leads to order explained in the doc comment.
1183        // However, the representation of magnitude is the same for negative
1184        // and positive numbers – only the sign bit is different.
1185        // To easily compare the floats as signed integers, we need to
1186        // flip the exponent and mantissa bits in case of negative numbers.
1187        // We effectively convert the numbers to "two's complement" form.
1188        //
1189        // To do the flipping, we construct a mask and XOR against it.
1190        // We branchlessly calculate an "all-ones except for the sign bit"
1191        // mask from negative-signed values: right shifting sign-extends
1192        // the integer, so we "fill" the mask with sign bits, and then
1193        // convert to unsigned to push one more zero bit.
1194        // On positive values, the mask is all zeros, so it's a no-op.
1195        left ^= (((left >> 15) as u16) >> 1) as i16;
1196        right ^= (((right >> 15) as u16) >> 1) as i16;
1197
1198        left.cmp(&right)
1199    }
1200
1201    /// Restrict a value to a certain interval unless it is NaN.
1202    ///
1203    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
1204    /// less than `min`. Otherwise this returns `self`.
1205    ///
1206    /// Note that this function returns NaN if the initial value was NaN as
1207    /// well.
1208    ///
1209    /// # Panics
1210    ///
1211    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
1212    ///
1213    /// # Examples
1214    ///
1215    /// ```
1216    /// #![feature(f16)]
1217    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1218    ///
1219    /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0);
1220    /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0);
1221    /// assert!((2.0f16).clamp(-2.0, 1.0) == 1.0);
1222    /// assert!((f16::NAN).clamp(-2.0, 1.0).is_nan());
1223    /// # }
1224    /// ```
1225    #[inline]
1226    #[unstable(feature = "f16", issue = "116909")]
1227    #[must_use = "method returns a new number and does not mutate the original value"]
1228    pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
1229        const_assert!(
1230            min <= max,
1231            "min > max, or either was NaN",
1232            "min > max, or either was NaN. min = {min:?}, max = {max:?}",
1233            min: f16,
1234            max: f16,
1235        );
1236
1237        if self < min {
1238            self = min;
1239        }
1240        if self > max {
1241            self = max;
1242        }
1243        self
1244    }
1245
1246    /// Computes the absolute value of `self`.
1247    ///
1248    /// This function always returns the precise result.
1249    ///
1250    /// # Examples
1251    ///
1252    /// ```
1253    /// #![feature(f16)]
1254    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1255    ///
1256    /// let x = 3.5_f16;
1257    /// let y = -3.5_f16;
1258    ///
1259    /// assert_eq!(x.abs(), x);
1260    /// assert_eq!(y.abs(), -y);
1261    ///
1262    /// assert!(f16::NAN.abs().is_nan());
1263    /// # }
1264    /// ```
1265    #[inline]
1266    #[unstable(feature = "f16", issue = "116909")]
1267    #[rustc_const_unstable(feature = "f16", issue = "116909")]
1268    #[must_use = "method returns a new number and does not mutate the original value"]
1269    pub const fn abs(self) -> Self {
1270        // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
1271        Self::from_bits(self.to_bits() & !(1 << 15))
1272    }
1273
1274    /// Returns a number that represents the sign of `self`.
1275    ///
1276    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1277    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1278    /// - NaN if the number is NaN
1279    ///
1280    /// # Examples
1281    ///
1282    /// ```
1283    /// #![feature(f16)]
1284    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1285    ///
1286    /// let f = 3.5_f16;
1287    ///
1288    /// assert_eq!(f.signum(), 1.0);
1289    /// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
1290    ///
1291    /// assert!(f16::NAN.signum().is_nan());
1292    /// # }
1293    /// ```
1294    #[inline]
1295    #[unstable(feature = "f16", issue = "116909")]
1296    #[rustc_const_unstable(feature = "f16", issue = "116909")]
1297    #[must_use = "method returns a new number and does not mutate the original value"]
1298    pub const fn signum(self) -> f16 {
1299        if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
1300    }
1301
1302    /// Returns a number composed of the magnitude of `self` and the sign of
1303    /// `sign`.
1304    ///
1305    /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1306    /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1307    /// returned.
1308    ///
1309    /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1310    /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1311    /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1312    /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1313    /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1314    /// info.
1315    ///
1316    /// # Examples
1317    ///
1318    /// ```
1319    /// #![feature(f16)]
1320    /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1321    ///
1322    /// let f = 3.5_f16;
1323    ///
1324    /// assert_eq!(f.copysign(0.42), 3.5_f16);
1325    /// assert_eq!(f.copysign(-0.42), -3.5_f16);
1326    /// assert_eq!((-f).copysign(0.42), 3.5_f16);
1327    /// assert_eq!((-f).copysign(-0.42), -3.5_f16);
1328    ///
1329    /// assert!(f16::NAN.copysign(1.0).is_nan());
1330    /// # }
1331    /// ```
1332    #[inline]
1333    #[unstable(feature = "f16", issue = "116909")]
1334    #[rustc_const_unstable(feature = "f16", issue = "116909")]
1335    #[must_use = "method returns a new number and does not mutate the original value"]
1336    pub const fn copysign(self, sign: f16) -> f16 {
1337        // SAFETY: this is actually a safe intrinsic
1338        unsafe { intrinsics::copysignf16(self, sign) }
1339    }
1340
1341    /// Float addition that allows optimizations based on algebraic rules.
1342    ///
1343    /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
1344    #[must_use = "method returns a new number and does not mutate the original value"]
1345    #[unstable(feature = "float_algebraic", issue = "136469")]
1346    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
1347    #[inline]
1348    pub const fn algebraic_add(self, rhs: f16) -> f16 {
1349        intrinsics::fadd_algebraic(self, rhs)
1350    }
1351
1352    /// Float subtraction that allows optimizations based on algebraic rules.
1353    ///
1354    /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
1355    #[must_use = "method returns a new number and does not mutate the original value"]
1356    #[unstable(feature = "float_algebraic", issue = "136469")]
1357    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
1358    #[inline]
1359    pub const fn algebraic_sub(self, rhs: f16) -> f16 {
1360        intrinsics::fsub_algebraic(self, rhs)
1361    }
1362
1363    /// Float multiplication that allows optimizations based on algebraic rules.
1364    ///
1365    /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
1366    #[must_use = "method returns a new number and does not mutate the original value"]
1367    #[unstable(feature = "float_algebraic", issue = "136469")]
1368    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
1369    #[inline]
1370    pub const fn algebraic_mul(self, rhs: f16) -> f16 {
1371        intrinsics::fmul_algebraic(self, rhs)
1372    }
1373
1374    /// Float division that allows optimizations based on algebraic rules.
1375    ///
1376    /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
1377    #[must_use = "method returns a new number and does not mutate the original value"]
1378    #[unstable(feature = "float_algebraic", issue = "136469")]
1379    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
1380    #[inline]
1381    pub const fn algebraic_div(self, rhs: f16) -> f16 {
1382        intrinsics::fdiv_algebraic(self, rhs)
1383    }
1384
1385    /// Float remainder that allows optimizations based on algebraic rules.
1386    ///
1387    /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
1388    #[must_use = "method returns a new number and does not mutate the original value"]
1389    #[unstable(feature = "float_algebraic", issue = "136469")]
1390    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
1391    #[inline]
1392    pub const fn algebraic_rem(self, rhs: f16) -> f16 {
1393        intrinsics::frem_algebraic(self, rhs)
1394    }
1395}
1396
1397// Functions in this module fall into `core_float_math`
1398// #[unstable(feature = "core_float_math", issue = "137578")]
1399#[cfg(not(test))]
1400impl f16 {
1401    /// Returns the largest integer less than or equal to `self`.
1402    ///
1403    /// This function always returns the precise result.
1404    ///
1405    /// # Examples
1406    ///
1407    /// ```
1408    /// #![feature(f16)]
1409    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1410    /// # #![expect(internal_features)]
1411    /// # #[cfg(not(miri))]
1412    /// # #[cfg(target_has_reliable_f16_math)] {
1413    ///
1414    /// let f = 3.7_f16;
1415    /// let g = 3.0_f16;
1416    /// let h = -3.7_f16;
1417    ///
1418    /// assert_eq!(f.floor(), 3.0);
1419    /// assert_eq!(g.floor(), 3.0);
1420    /// assert_eq!(h.floor(), -4.0);
1421    /// # }
1422    /// ```
1423    #[inline]
1424    #[rustc_allow_incoherent_impl]
1425    #[unstable(feature = "f16", issue = "116909")]
1426    #[must_use = "method returns a new number and does not mutate the original value"]
1427    pub fn floor(self) -> f16 {
1428        // SAFETY: intrinsic with no preconditions
1429        unsafe { intrinsics::floorf16(self) }
1430    }
1431
1432    /// Returns the smallest integer greater than or equal to `self`.
1433    ///
1434    /// This function always returns the precise result.
1435    ///
1436    /// # Examples
1437    ///
1438    /// ```
1439    /// #![feature(f16)]
1440    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1441    /// # #![expect(internal_features)]
1442    /// # #[cfg(not(miri))]
1443    /// # #[cfg(target_has_reliable_f16_math)] {
1444    ///
1445    /// let f = 3.01_f16;
1446    /// let g = 4.0_f16;
1447    ///
1448    /// assert_eq!(f.ceil(), 4.0);
1449    /// assert_eq!(g.ceil(), 4.0);
1450    /// # }
1451    /// ```
1452    #[inline]
1453    #[doc(alias = "ceiling")]
1454    #[rustc_allow_incoherent_impl]
1455    #[unstable(feature = "f16", issue = "116909")]
1456    #[must_use = "method returns a new number and does not mutate the original value"]
1457    pub fn ceil(self) -> f16 {
1458        // SAFETY: intrinsic with no preconditions
1459        unsafe { intrinsics::ceilf16(self) }
1460    }
1461
1462    /// Returns the nearest integer to `self`. If a value is half-way between two
1463    /// integers, round away from `0.0`.
1464    ///
1465    /// This function always returns the precise result.
1466    ///
1467    /// # Examples
1468    ///
1469    /// ```
1470    /// #![feature(f16)]
1471    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1472    /// # #![expect(internal_features)]
1473    /// # #[cfg(not(miri))]
1474    /// # #[cfg(target_has_reliable_f16_math)] {
1475    ///
1476    /// let f = 3.3_f16;
1477    /// let g = -3.3_f16;
1478    /// let h = -3.7_f16;
1479    /// let i = 3.5_f16;
1480    /// let j = 4.5_f16;
1481    ///
1482    /// assert_eq!(f.round(), 3.0);
1483    /// assert_eq!(g.round(), -3.0);
1484    /// assert_eq!(h.round(), -4.0);
1485    /// assert_eq!(i.round(), 4.0);
1486    /// assert_eq!(j.round(), 5.0);
1487    /// # }
1488    /// ```
1489    #[inline]
1490    #[rustc_allow_incoherent_impl]
1491    #[unstable(feature = "f16", issue = "116909")]
1492    #[must_use = "method returns a new number and does not mutate the original value"]
1493    pub fn round(self) -> f16 {
1494        // SAFETY: intrinsic with no preconditions
1495        unsafe { intrinsics::roundf16(self) }
1496    }
1497
1498    /// Returns the nearest integer to a number. Rounds half-way cases to the number
1499    /// with an even least significant digit.
1500    ///
1501    /// This function always returns the precise result.
1502    ///
1503    /// # Examples
1504    ///
1505    /// ```
1506    /// #![feature(f16)]
1507    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1508    /// # #![expect(internal_features)]
1509    /// # #[cfg(not(miri))]
1510    /// # #[cfg(target_has_reliable_f16_math)] {
1511    ///
1512    /// let f = 3.3_f16;
1513    /// let g = -3.3_f16;
1514    /// let h = 3.5_f16;
1515    /// let i = 4.5_f16;
1516    ///
1517    /// assert_eq!(f.round_ties_even(), 3.0);
1518    /// assert_eq!(g.round_ties_even(), -3.0);
1519    /// assert_eq!(h.round_ties_even(), 4.0);
1520    /// assert_eq!(i.round_ties_even(), 4.0);
1521    /// # }
1522    /// ```
1523    #[inline]
1524    #[rustc_allow_incoherent_impl]
1525    #[unstable(feature = "f16", issue = "116909")]
1526    #[must_use = "method returns a new number and does not mutate the original value"]
1527    pub fn round_ties_even(self) -> f16 {
1528        intrinsics::round_ties_even_f16(self)
1529    }
1530
1531    /// Returns the integer part of `self`.
1532    /// This means that non-integer numbers are always truncated towards zero.
1533    ///
1534    /// This function always returns the precise result.
1535    ///
1536    /// # Examples
1537    ///
1538    /// ```
1539    /// #![feature(f16)]
1540    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1541    /// # #![expect(internal_features)]
1542    /// # #[cfg(not(miri))]
1543    /// # #[cfg(target_has_reliable_f16_math)] {
1544    ///
1545    /// let f = 3.7_f16;
1546    /// let g = 3.0_f16;
1547    /// let h = -3.7_f16;
1548    ///
1549    /// assert_eq!(f.trunc(), 3.0);
1550    /// assert_eq!(g.trunc(), 3.0);
1551    /// assert_eq!(h.trunc(), -3.0);
1552    /// # }
1553    /// ```
1554    #[inline]
1555    #[doc(alias = "truncate")]
1556    #[rustc_allow_incoherent_impl]
1557    #[unstable(feature = "f16", issue = "116909")]
1558    #[must_use = "method returns a new number and does not mutate the original value"]
1559    pub fn trunc(self) -> f16 {
1560        // SAFETY: intrinsic with no preconditions
1561        unsafe { intrinsics::truncf16(self) }
1562    }
1563
1564    /// Returns the fractional part of `self`.
1565    ///
1566    /// This function always returns the precise result.
1567    ///
1568    /// # Examples
1569    ///
1570    /// ```
1571    /// #![feature(f16)]
1572    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1573    /// # #![expect(internal_features)]
1574    /// # #[cfg(not(miri))]
1575    /// # #[cfg(target_has_reliable_f16_math)] {
1576    ///
1577    /// let x = 3.6_f16;
1578    /// let y = -3.6_f16;
1579    /// let abs_difference_x = (x.fract() - 0.6).abs();
1580    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
1581    ///
1582    /// assert!(abs_difference_x <= f16::EPSILON);
1583    /// assert!(abs_difference_y <= f16::EPSILON);
1584    /// # }
1585    /// ```
1586    #[inline]
1587    #[rustc_allow_incoherent_impl]
1588    #[unstable(feature = "f16", issue = "116909")]
1589    #[must_use = "method returns a new number and does not mutate the original value"]
1590    pub fn fract(self) -> f16 {
1591        self - self.trunc()
1592    }
1593
1594    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
1595    /// error, yielding a more accurate result than an unfused multiply-add.
1596    ///
1597    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
1598    /// the target architecture has a dedicated `fma` CPU instruction. However,
1599    /// this is not always true, and will be heavily dependant on designing
1600    /// algorithms with specific target hardware in mind.
1601    ///
1602    /// # Precision
1603    ///
1604    /// The result of this operation is guaranteed to be the rounded
1605    /// infinite-precision result. It is specified by IEEE 754 as
1606    /// `fusedMultiplyAdd` and guaranteed not to change.
1607    ///
1608    /// # Examples
1609    ///
1610    /// ```
1611    /// #![feature(f16)]
1612    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1613    /// # #![expect(internal_features)]
1614    /// # #[cfg(not(miri))]
1615    /// # #[cfg(target_has_reliable_f16_math)] {
1616    ///
1617    /// let m = 10.0_f16;
1618    /// let x = 4.0_f16;
1619    /// let b = 60.0_f16;
1620    ///
1621    /// assert_eq!(m.mul_add(x, b), 100.0);
1622    /// assert_eq!(m * x + b, 100.0);
1623    ///
1624    /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
1625    /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
1626    /// let minus_one = -1.0_f16;
1627    ///
1628    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
1629    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
1630    /// // Different rounding with the non-fused multiply and add.
1631    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
1632    /// # }
1633    /// ```
1634    #[inline]
1635    #[rustc_allow_incoherent_impl]
1636    #[unstable(feature = "f16", issue = "116909")]
1637    #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")]
1638    #[must_use = "method returns a new number and does not mutate the original value"]
1639    pub fn mul_add(self, a: f16, b: f16) -> f16 {
1640        // SAFETY: intrinsic with no preconditions
1641        unsafe { intrinsics::fmaf16(self, a, b) }
1642    }
1643
1644    /// Calculates Euclidean division, the matching method for `rem_euclid`.
1645    ///
1646    /// This computes the integer `n` such that
1647    /// `self = n * rhs + self.rem_euclid(rhs)`.
1648    /// In other words, the result is `self / rhs` rounded to the integer `n`
1649    /// such that `self >= n * rhs`.
1650    ///
1651    /// # Precision
1652    ///
1653    /// The result of this operation is guaranteed to be the rounded
1654    /// infinite-precision result.
1655    ///
1656    /// # Examples
1657    ///
1658    /// ```
1659    /// #![feature(f16)]
1660    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1661    /// # #![expect(internal_features)]
1662    /// # #[cfg(not(miri))]
1663    /// # #[cfg(target_has_reliable_f16_math)] {
1664    ///
1665    /// let a: f16 = 7.0;
1666    /// let b = 4.0;
1667    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
1668    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
1669    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
1670    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
1671    /// # }
1672    /// ```
1673    #[inline]
1674    #[rustc_allow_incoherent_impl]
1675    #[unstable(feature = "f16", issue = "116909")]
1676    #[must_use = "method returns a new number and does not mutate the original value"]
1677    pub fn div_euclid(self, rhs: f16) -> f16 {
1678        let q = (self / rhs).trunc();
1679        if self % rhs < 0.0 {
1680            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
1681        }
1682        q
1683    }
1684
1685    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
1686    ///
1687    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
1688    /// most cases. However, due to a floating point round-off error it can
1689    /// result in `r == rhs.abs()`, violating the mathematical definition, if
1690    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
1691    /// This result is not an element of the function's codomain, but it is the
1692    /// closest floating point number in the real numbers and thus fulfills the
1693    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
1694    /// approximately.
1695    ///
1696    /// # Precision
1697    ///
1698    /// The result of this operation is guaranteed to be the rounded
1699    /// infinite-precision result.
1700    ///
1701    /// # Examples
1702    ///
1703    /// ```
1704    /// #![feature(f16)]
1705    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1706    /// # #![expect(internal_features)]
1707    /// # #[cfg(not(miri))]
1708    /// # #[cfg(target_has_reliable_f16_math)] {
1709    ///
1710    /// let a: f16 = 7.0;
1711    /// let b = 4.0;
1712    /// assert_eq!(a.rem_euclid(b), 3.0);
1713    /// assert_eq!((-a).rem_euclid(b), 1.0);
1714    /// assert_eq!(a.rem_euclid(-b), 3.0);
1715    /// assert_eq!((-a).rem_euclid(-b), 1.0);
1716    /// // limitation due to round-off error
1717    /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
1718    /// # }
1719    /// ```
1720    #[inline]
1721    #[rustc_allow_incoherent_impl]
1722    #[doc(alias = "modulo", alias = "mod")]
1723    #[unstable(feature = "f16", issue = "116909")]
1724    #[must_use = "method returns a new number and does not mutate the original value"]
1725    pub fn rem_euclid(self, rhs: f16) -> f16 {
1726        let r = self % rhs;
1727        if r < 0.0 { r + rhs.abs() } else { r }
1728    }
1729
1730    /// Raises a number to an integer power.
1731    ///
1732    /// Using this function is generally faster than using `powf`.
1733    /// It might have a different sequence of rounding operations than `powf`,
1734    /// so the results are not guaranteed to agree.
1735    ///
1736    /// # Unspecified precision
1737    ///
1738    /// The precision of this function is non-deterministic. This means it varies by platform,
1739    /// Rust version, and can even differ within the same execution from one invocation to the next.
1740    ///
1741    /// # Examples
1742    ///
1743    /// ```
1744    /// #![feature(f16)]
1745    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1746    /// # #![expect(internal_features)]
1747    /// # #[cfg(not(miri))]
1748    /// # #[cfg(target_has_reliable_f16_math)] {
1749    ///
1750    /// let x = 2.0_f16;
1751    /// let abs_difference = (x.powi(2) - (x * x)).abs();
1752    /// assert!(abs_difference <= f16::EPSILON);
1753    ///
1754    /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
1755    /// # }
1756    /// ```
1757    #[inline]
1758    #[rustc_allow_incoherent_impl]
1759    #[unstable(feature = "f16", issue = "116909")]
1760    #[must_use = "method returns a new number and does not mutate the original value"]
1761    pub fn powi(self, n: i32) -> f16 {
1762        // SAFETY: intrinsic with no preconditions
1763        unsafe { intrinsics::powif16(self, n) }
1764    }
1765
1766    /// Returns the square root of a number.
1767    ///
1768    /// Returns NaN if `self` is a negative number other than `-0.0`.
1769    ///
1770    /// # Precision
1771    ///
1772    /// The result of this operation is guaranteed to be the rounded
1773    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
1774    /// and guaranteed not to change.
1775    ///
1776    /// # Examples
1777    ///
1778    /// ```
1779    /// #![feature(f16)]
1780    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1781    /// # #![expect(internal_features)]
1782    /// # #[cfg(not(miri))]
1783    /// # #[cfg(target_has_reliable_f16_math)] {
1784    ///
1785    /// let positive = 4.0_f16;
1786    /// let negative = -4.0_f16;
1787    /// let negative_zero = -0.0_f16;
1788    ///
1789    /// assert_eq!(positive.sqrt(), 2.0);
1790    /// assert!(negative.sqrt().is_nan());
1791    /// assert!(negative_zero.sqrt() == negative_zero);
1792    /// # }
1793    /// ```
1794    #[inline]
1795    #[doc(alias = "squareRoot")]
1796    #[rustc_allow_incoherent_impl]
1797    #[unstable(feature = "f16", issue = "116909")]
1798    #[must_use = "method returns a new number and does not mutate the original value"]
1799    pub fn sqrt(self) -> f16 {
1800        // SAFETY: intrinsic with no preconditions
1801        unsafe { intrinsics::sqrtf16(self) }
1802    }
1803
1804    /// Returns the cube root of a number.
1805    ///
1806    /// # Unspecified precision
1807    ///
1808    /// The precision of this function is non-deterministic. This means it varies by platform,
1809    /// Rust version, and can even differ within the same execution from one invocation to the next.
1810    ///
1811    /// This function currently corresponds to the `cbrtf` from libc on Unix
1812    /// and Windows. Note that this might change in the future.
1813    ///
1814    /// # Examples
1815    ///
1816    /// ```
1817    /// #![feature(f16)]
1818    /// # #![feature(cfg_target_has_reliable_f16_f128)]
1819    /// # #![expect(internal_features)]
1820    /// # #[cfg(not(miri))]
1821    /// # #[cfg(target_has_reliable_f16_math)] {
1822    ///
1823    /// let x = 8.0f16;
1824    ///
1825    /// // x^(1/3) - 2 == 0
1826    /// let abs_difference = (x.cbrt() - 2.0).abs();
1827    ///
1828    /// assert!(abs_difference <= f16::EPSILON);
1829    /// # }
1830    /// ```
1831    #[inline]
1832    #[rustc_allow_incoherent_impl]
1833    #[unstable(feature = "f16", issue = "116909")]
1834    #[must_use = "method returns a new number and does not mutate the original value"]
1835    pub fn cbrt(self) -> f16 {
1836        libm::cbrtf(self as f32) as f16
1837    }
1838}