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;
16use crate::panic::const_assert;
17use crate::{intrinsics, mem};
18
19/// Basic mathematical constants.
20#[unstable(feature = "f16", issue = "116909")]
21pub mod consts {
22 // FIXME: replace with mathematical constants from cmath.
23
24 /// Archimedes' constant (π)
25 #[unstable(feature = "f16", issue = "116909")]
26 pub const PI: f16 = 3.14159265358979323846264338327950288_f16;
27
28 /// The full circle constant (τ)
29 ///
30 /// Equal to 2π.
31 #[unstable(feature = "f16", issue = "116909")]
32 pub const TAU: f16 = 6.28318530717958647692528676655900577_f16;
33
34 /// The golden ratio (φ)
35 #[unstable(feature = "f16", issue = "116909")]
36 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
37 pub const PHI: f16 = 1.618033988749894848204586834365638118_f16;
38
39 /// The Euler-Mascheroni constant (γ)
40 #[unstable(feature = "f16", issue = "116909")]
41 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
42 pub const EGAMMA: f16 = 0.577215664901532860606512090082402431_f16;
43
44 /// π/2
45 #[unstable(feature = "f16", issue = "116909")]
46 pub const FRAC_PI_2: f16 = 1.57079632679489661923132169163975144_f16;
47
48 /// π/3
49 #[unstable(feature = "f16", issue = "116909")]
50 pub const FRAC_PI_3: f16 = 1.04719755119659774615421446109316763_f16;
51
52 /// π/4
53 #[unstable(feature = "f16", issue = "116909")]
54 pub const FRAC_PI_4: f16 = 0.785398163397448309615660845819875721_f16;
55
56 /// π/6
57 #[unstable(feature = "f16", issue = "116909")]
58 pub const FRAC_PI_6: f16 = 0.52359877559829887307710723054658381_f16;
59
60 /// π/8
61 #[unstable(feature = "f16", issue = "116909")]
62 pub const FRAC_PI_8: f16 = 0.39269908169872415480783042290993786_f16;
63
64 /// 1/π
65 #[unstable(feature = "f16", issue = "116909")]
66 pub const FRAC_1_PI: f16 = 0.318309886183790671537767526745028724_f16;
67
68 /// 1/sqrt(π)
69 #[unstable(feature = "f16", issue = "116909")]
70 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
71 pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16;
72
73 /// 1/sqrt(2π)
74 #[doc(alias = "FRAC_1_SQRT_TAU")]
75 #[unstable(feature = "f16", issue = "116909")]
76 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
77 pub const FRAC_1_SQRT_2PI: f16 = 0.398942280401432677939946059934381868_f16;
78
79 /// 2/π
80 #[unstable(feature = "f16", issue = "116909")]
81 pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16;
82
83 /// 2/sqrt(π)
84 #[unstable(feature = "f16", issue = "116909")]
85 pub const FRAC_2_SQRT_PI: f16 = 1.12837916709551257389615890312154517_f16;
86
87 /// sqrt(2)
88 #[unstable(feature = "f16", issue = "116909")]
89 pub const SQRT_2: f16 = 1.41421356237309504880168872420969808_f16;
90
91 /// 1/sqrt(2)
92 #[unstable(feature = "f16", issue = "116909")]
93 pub const FRAC_1_SQRT_2: f16 = 0.707106781186547524400844362104849039_f16;
94
95 /// sqrt(3)
96 #[unstable(feature = "f16", issue = "116909")]
97 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
98 pub const SQRT_3: f16 = 1.732050807568877293527446341505872367_f16;
99
100 /// 1/sqrt(3)
101 #[unstable(feature = "f16", issue = "116909")]
102 // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
103 pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16;
104
105 /// Euler's number (e)
106 #[unstable(feature = "f16", issue = "116909")]
107 pub const E: f16 = 2.71828182845904523536028747135266250_f16;
108
109 /// log<sub>2</sub>(10)
110 #[unstable(feature = "f16", issue = "116909")]
111 pub const LOG2_10: f16 = 3.32192809488736234787031942948939018_f16;
112
113 /// log<sub>2</sub>(e)
114 #[unstable(feature = "f16", issue = "116909")]
115 pub const LOG2_E: f16 = 1.44269504088896340735992468100189214_f16;
116
117 /// log<sub>10</sub>(2)
118 #[unstable(feature = "f16", issue = "116909")]
119 pub const LOG10_2: f16 = 0.301029995663981195213738894724493027_f16;
120
121 /// log<sub>10</sub>(e)
122 #[unstable(feature = "f16", issue = "116909")]
123 pub const LOG10_E: f16 = 0.434294481903251827651128918916605082_f16;
124
125 /// ln(2)
126 #[unstable(feature = "f16", issue = "116909")]
127 pub const LN_2: f16 = 0.693147180559945309417232121458176568_f16;
128
129 /// ln(10)
130 #[unstable(feature = "f16", issue = "116909")]
131 pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16;
132}
133
134impl f16 {
135 // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
136 // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
137
138 /// The radix or base of the internal representation of `f16`.
139 #[unstable(feature = "f16", issue = "116909")]
140 pub const RADIX: u32 = 2;
141
142 /// Number of significant digits in base 2.
143 #[unstable(feature = "f16", issue = "116909")]
144 pub const MANTISSA_DIGITS: u32 = 11;
145
146 /// Approximate number of significant digits in base 10.
147 ///
148 /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
149 /// significant digits can be converted to `f16` and back without loss.
150 ///
151 /// Equal to floor(log<sub>10</sub> 2<sup>[`MANTISSA_DIGITS`] − 1</sup>).
152 ///
153 /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
154 #[unstable(feature = "f16", issue = "116909")]
155 pub const DIGITS: u32 = 3;
156
157 /// [Machine epsilon] value for `f16`.
158 ///
159 /// This is the difference between `1.0` and the next larger representable number.
160 ///
161 /// Equal to 2<sup>1 − [`MANTISSA_DIGITS`]</sup>.
162 ///
163 /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
164 /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
165 #[unstable(feature = "f16", issue = "116909")]
166 pub const EPSILON: f16 = 9.7656e-4_f16;
167
168 /// Smallest finite `f16` value.
169 ///
170 /// Equal to −[`MAX`].
171 ///
172 /// [`MAX`]: f16::MAX
173 #[unstable(feature = "f16", issue = "116909")]
174 pub const MIN: f16 = -6.5504e+4_f16;
175 /// Smallest positive normal `f16` value.
176 ///
177 /// Equal to 2<sup>[`MIN_EXP`] − 1</sup>.
178 ///
179 /// [`MIN_EXP`]: f16::MIN_EXP
180 #[unstable(feature = "f16", issue = "116909")]
181 pub const MIN_POSITIVE: f16 = 6.1035e-5_f16;
182 /// Largest finite `f16` value.
183 ///
184 /// Equal to
185 /// (1 − 2<sup>−[`MANTISSA_DIGITS`]</sup>) 2<sup>[`MAX_EXP`]</sup>.
186 ///
187 /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
188 /// [`MAX_EXP`]: f16::MAX_EXP
189 #[unstable(feature = "f16", issue = "116909")]
190 pub const MAX: f16 = 6.5504e+4_f16;
191
192 /// One greater than the minimum possible normal power of 2 exponent.
193 ///
194 /// If <i>x</i> = `MIN_EXP`, then normal numbers
195 /// ≥ 0.5 × 2<sup><i>x</i></sup>.
196 #[unstable(feature = "f16", issue = "116909")]
197 pub const MIN_EXP: i32 = -13;
198 /// Maximum possible power of 2 exponent.
199 ///
200 /// If <i>x</i> = `MAX_EXP`, then normal numbers
201 /// < 1 × 2<sup><i>x</i></sup>.
202 #[unstable(feature = "f16", issue = "116909")]
203 pub const MAX_EXP: i32 = 16;
204
205 /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
206 ///
207 /// Equal to ceil(log<sub>10</sub> [`MIN_POSITIVE`]).
208 ///
209 /// [`MIN_POSITIVE`]: f16::MIN_POSITIVE
210 #[unstable(feature = "f16", issue = "116909")]
211 pub const MIN_10_EXP: i32 = -4;
212 /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
213 ///
214 /// Equal to floor(log<sub>10</sub> [`MAX`]).
215 ///
216 /// [`MAX`]: f16::MAX
217 #[unstable(feature = "f16", issue = "116909")]
218 pub const MAX_10_EXP: i32 = 4;
219
220 /// Not a Number (NaN).
221 ///
222 /// Note that IEEE 754 doesn't define just a single NaN value;
223 /// a plethora of bit patterns are considered to be NaN.
224 /// Furthermore, the standard makes a difference
225 /// between a "signaling" and a "quiet" NaN,
226 /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
227 /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
228 /// and the stability of its representation over Rust versions
229 /// and target platforms isn't guaranteed.
230 #[allow(clippy::eq_op)]
231 #[rustc_diagnostic_item = "f16_nan"]
232 #[unstable(feature = "f16", issue = "116909")]
233 pub const NAN: f16 = 0.0_f16 / 0.0_f16;
234
235 /// Infinity (∞).
236 #[unstable(feature = "f16", issue = "116909")]
237 pub const INFINITY: f16 = 1.0_f16 / 0.0_f16;
238
239 /// Negative infinity (−∞).
240 #[unstable(feature = "f16", issue = "116909")]
241 pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
242
243 /// Sign bit
244 pub(crate) const SIGN_MASK: u16 = 0x8000;
245
246 /// Exponent mask
247 pub(crate) const EXP_MASK: u16 = 0x7c00;
248
249 /// Mantissa mask
250 pub(crate) const MAN_MASK: u16 = 0x03ff;
251
252 /// Minimum representable positive value (min subnormal)
253 const TINY_BITS: u16 = 0x1;
254
255 /// Minimum representable negative value (min negative subnormal)
256 const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK;
257
258 /// Returns `true` if this value is NaN.
259 ///
260 /// ```
261 /// #![feature(f16)]
262 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
263 ///
264 /// let nan = f16::NAN;
265 /// let f = 7.0_f16;
266 ///
267 /// assert!(nan.is_nan());
268 /// assert!(!f.is_nan());
269 /// # }
270 /// ```
271 #[inline]
272 #[must_use]
273 #[unstable(feature = "f16", issue = "116909")]
274 #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
275 pub const fn is_nan(self) -> bool {
276 self != self
277 }
278
279 /// Returns `true` if this value is positive infinity or negative infinity, and
280 /// `false` otherwise.
281 ///
282 /// ```
283 /// #![feature(f16)]
284 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
285 ///
286 /// let f = 7.0f16;
287 /// let inf = f16::INFINITY;
288 /// let neg_inf = f16::NEG_INFINITY;
289 /// let nan = f16::NAN;
290 ///
291 /// assert!(!f.is_infinite());
292 /// assert!(!nan.is_infinite());
293 ///
294 /// assert!(inf.is_infinite());
295 /// assert!(neg_inf.is_infinite());
296 /// # }
297 /// ```
298 #[inline]
299 #[must_use]
300 #[unstable(feature = "f16", issue = "116909")]
301 pub const fn is_infinite(self) -> bool {
302 (self == f16::INFINITY) | (self == f16::NEG_INFINITY)
303 }
304
305 /// Returns `true` if this number is neither infinite nor NaN.
306 ///
307 /// ```
308 /// #![feature(f16)]
309 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
310 ///
311 /// let f = 7.0f16;
312 /// let inf: f16 = f16::INFINITY;
313 /// let neg_inf: f16 = f16::NEG_INFINITY;
314 /// let nan: f16 = f16::NAN;
315 ///
316 /// assert!(f.is_finite());
317 ///
318 /// assert!(!nan.is_finite());
319 /// assert!(!inf.is_finite());
320 /// assert!(!neg_inf.is_finite());
321 /// # }
322 /// ```
323 #[inline]
324 #[must_use]
325 #[unstable(feature = "f16", issue = "116909")]
326 #[rustc_const_unstable(feature = "f16", issue = "116909")]
327 pub const fn is_finite(self) -> bool {
328 // There's no need to handle NaN separately: if self is NaN,
329 // the comparison is not true, exactly as desired.
330 self.abs() < Self::INFINITY
331 }
332
333 /// Returns `true` if the number is [subnormal].
334 ///
335 /// ```
336 /// #![feature(f16)]
337 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
338 ///
339 /// let min = f16::MIN_POSITIVE; // 6.1035e-5
340 /// let max = f16::MAX;
341 /// let lower_than_min = 1.0e-7_f16;
342 /// let zero = 0.0_f16;
343 ///
344 /// assert!(!min.is_subnormal());
345 /// assert!(!max.is_subnormal());
346 ///
347 /// assert!(!zero.is_subnormal());
348 /// assert!(!f16::NAN.is_subnormal());
349 /// assert!(!f16::INFINITY.is_subnormal());
350 /// // Values between `0` and `min` are Subnormal.
351 /// assert!(lower_than_min.is_subnormal());
352 /// # }
353 /// ```
354 /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
355 #[inline]
356 #[must_use]
357 #[unstable(feature = "f16", issue = "116909")]
358 pub const fn is_subnormal(self) -> bool {
359 matches!(self.classify(), FpCategory::Subnormal)
360 }
361
362 /// Returns `true` if the number is neither zero, infinite, [subnormal], or NaN.
363 ///
364 /// ```
365 /// #![feature(f16)]
366 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
367 ///
368 /// let min = f16::MIN_POSITIVE; // 6.1035e-5
369 /// let max = f16::MAX;
370 /// let lower_than_min = 1.0e-7_f16;
371 /// let zero = 0.0_f16;
372 ///
373 /// assert!(min.is_normal());
374 /// assert!(max.is_normal());
375 ///
376 /// assert!(!zero.is_normal());
377 /// assert!(!f16::NAN.is_normal());
378 /// assert!(!f16::INFINITY.is_normal());
379 /// // Values between `0` and `min` are Subnormal.
380 /// assert!(!lower_than_min.is_normal());
381 /// # }
382 /// ```
383 /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
384 #[inline]
385 #[must_use]
386 #[unstable(feature = "f16", issue = "116909")]
387 pub const fn is_normal(self) -> bool {
388 matches!(self.classify(), FpCategory::Normal)
389 }
390
391 /// Returns the floating point category of the number. If only one property
392 /// is going to be tested, it is generally faster to use the specific
393 /// predicate instead.
394 ///
395 /// ```
396 /// #![feature(f16)]
397 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
398 ///
399 /// use std::num::FpCategory;
400 ///
401 /// let num = 12.4_f16;
402 /// let inf = f16::INFINITY;
403 ///
404 /// assert_eq!(num.classify(), FpCategory::Normal);
405 /// assert_eq!(inf.classify(), FpCategory::Infinite);
406 /// # }
407 /// ```
408 #[inline]
409 #[unstable(feature = "f16", issue = "116909")]
410 pub const fn classify(self) -> FpCategory {
411 let b = self.to_bits();
412 match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
413 (0, Self::EXP_MASK) => FpCategory::Infinite,
414 (_, Self::EXP_MASK) => FpCategory::Nan,
415 (0, 0) => FpCategory::Zero,
416 (_, 0) => FpCategory::Subnormal,
417 _ => FpCategory::Normal,
418 }
419 }
420
421 /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
422 /// positive sign bit and positive infinity.
423 ///
424 /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
425 /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
426 /// conserved over arithmetic operations, the result of `is_sign_positive` on
427 /// a NaN might produce an unexpected or non-portable result. See the [specification
428 /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0`
429 /// if you need fully portable behavior (will return `false` for all NaNs).
430 ///
431 /// ```
432 /// #![feature(f16)]
433 /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
434 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
435 ///
436 /// let f = 7.0_f16;
437 /// let g = -7.0_f16;
438 ///
439 /// assert!(f.is_sign_positive());
440 /// assert!(!g.is_sign_positive());
441 /// # }
442 /// ```
443 #[inline]
444 #[must_use]
445 #[unstable(feature = "f16", issue = "116909")]
446 pub const fn is_sign_positive(self) -> bool {
447 !self.is_sign_negative()
448 }
449
450 /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
451 /// negative sign bit and negative infinity.
452 ///
453 /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
454 /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
455 /// conserved over arithmetic operations, the result of `is_sign_negative` on
456 /// a NaN might produce an unexpected or non-portable result. See the [specification
457 /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0`
458 /// if you need fully portable behavior (will return `false` for all NaNs).
459 ///
460 /// ```
461 /// #![feature(f16)]
462 /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
463 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
464 ///
465 /// let f = 7.0_f16;
466 /// let g = -7.0_f16;
467 ///
468 /// assert!(!f.is_sign_negative());
469 /// assert!(g.is_sign_negative());
470 /// # }
471 /// ```
472 #[inline]
473 #[must_use]
474 #[unstable(feature = "f16", issue = "116909")]
475 pub const fn is_sign_negative(self) -> bool {
476 // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
477 // applies to zeros and NaNs as well.
478 // SAFETY: This is just transmuting to get the sign bit, it's fine.
479 (self.to_bits() & (1 << 15)) != 0
480 }
481
482 /// Returns the least number greater than `self`.
483 ///
484 /// Let `TINY` be the smallest representable positive `f16`. Then,
485 /// - if `self.is_nan()`, this returns `self`;
486 /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`];
487 /// - if `self` is `-TINY`, this returns -0.0;
488 /// - if `self` is -0.0 or +0.0, this returns `TINY`;
489 /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`];
490 /// - otherwise the unique least value greater than `self` is returned.
491 ///
492 /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x`
493 /// is finite `x == x.next_up().next_down()` also holds.
494 ///
495 /// ```rust
496 /// #![feature(f16)]
497 /// # // FIXME(f16_f128): ABI issues on MSVC
498 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
499 ///
500 /// // f16::EPSILON is the difference between 1.0 and the next number up.
501 /// assert_eq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
502 /// // But not for most numbers.
503 /// assert!(0.1f16.next_up() < 0.1 + f16::EPSILON);
504 /// assert_eq!(4356f16.next_up(), 4360.0);
505 /// # }
506 /// ```
507 ///
508 /// This operation corresponds to IEEE-754 `nextUp`.
509 ///
510 /// [`NEG_INFINITY`]: Self::NEG_INFINITY
511 /// [`INFINITY`]: Self::INFINITY
512 /// [`MIN`]: Self::MIN
513 /// [`MAX`]: Self::MAX
514 #[inline]
515 #[doc(alias = "nextUp")]
516 #[unstable(feature = "f16", issue = "116909")]
517 pub const fn next_up(self) -> Self {
518 // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
519 // denormals to zero. This is in general unsound and unsupported, but here
520 // we do our best to still produce the correct result on such targets.
521 let bits = self.to_bits();
522 if self.is_nan() || bits == Self::INFINITY.to_bits() {
523 return self;
524 }
525
526 let abs = bits & !Self::SIGN_MASK;
527 let next_bits = if abs == 0 {
528 Self::TINY_BITS
529 } else if bits == abs {
530 bits + 1
531 } else {
532 bits - 1
533 };
534 Self::from_bits(next_bits)
535 }
536
537 /// Returns the greatest number less than `self`.
538 ///
539 /// Let `TINY` be the smallest representable positive `f16`. Then,
540 /// - if `self.is_nan()`, this returns `self`;
541 /// - if `self` is [`INFINITY`], this returns [`MAX`];
542 /// - if `self` is `TINY`, this returns 0.0;
543 /// - if `self` is -0.0 or +0.0, this returns `-TINY`;
544 /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`];
545 /// - otherwise the unique greatest value less than `self` is returned.
546 ///
547 /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x`
548 /// is finite `x == x.next_down().next_up()` also holds.
549 ///
550 /// ```rust
551 /// #![feature(f16)]
552 /// # // FIXME(f16_f128): ABI issues on MSVC
553 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
554 ///
555 /// let x = 1.0f16;
556 /// // Clamp value into range [0, 1).
557 /// let clamped = x.clamp(0.0, 1.0f16.next_down());
558 /// assert!(clamped < 1.0);
559 /// assert_eq!(clamped.next_up(), 1.0);
560 /// # }
561 /// ```
562 ///
563 /// This operation corresponds to IEEE-754 `nextDown`.
564 ///
565 /// [`NEG_INFINITY`]: Self::NEG_INFINITY
566 /// [`INFINITY`]: Self::INFINITY
567 /// [`MIN`]: Self::MIN
568 /// [`MAX`]: Self::MAX
569 #[inline]
570 #[doc(alias = "nextDown")]
571 #[unstable(feature = "f16", issue = "116909")]
572 pub const fn next_down(self) -> Self {
573 // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
574 // denormals to zero. This is in general unsound and unsupported, but here
575 // we do our best to still produce the correct result on such targets.
576 let bits = self.to_bits();
577 if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
578 return self;
579 }
580
581 let abs = bits & !Self::SIGN_MASK;
582 let next_bits = if abs == 0 {
583 Self::NEG_TINY_BITS
584 } else if bits == abs {
585 bits - 1
586 } else {
587 bits + 1
588 };
589 Self::from_bits(next_bits)
590 }
591
592 /// Takes the reciprocal (inverse) of a number, `1/x`.
593 ///
594 /// ```
595 /// #![feature(f16)]
596 /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
597 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
598 ///
599 /// let x = 2.0_f16;
600 /// let abs_difference = (x.recip() - (1.0 / x)).abs();
601 ///
602 /// assert!(abs_difference <= f16::EPSILON);
603 /// # }
604 /// ```
605 #[inline]
606 #[unstable(feature = "f16", issue = "116909")]
607 #[must_use = "this returns the result of the operation, without modifying the original"]
608 pub const fn recip(self) -> Self {
609 1.0 / self
610 }
611
612 /// Converts radians to degrees.
613 ///
614 /// ```
615 /// #![feature(f16)]
616 /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
617 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
618 ///
619 /// let angle = std::f16::consts::PI;
620 ///
621 /// let abs_difference = (angle.to_degrees() - 180.0).abs();
622 /// assert!(abs_difference <= 0.5);
623 /// # }
624 /// ```
625 #[inline]
626 #[unstable(feature = "f16", issue = "116909")]
627 #[must_use = "this returns the result of the operation, without modifying the original"]
628 pub const fn to_degrees(self) -> Self {
629 // Use a literal for better precision.
630 const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
631 self * PIS_IN_180
632 }
633
634 /// Converts degrees to radians.
635 ///
636 /// ```
637 /// #![feature(f16)]
638 /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
639 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
640 ///
641 /// let angle = 180.0f16;
642 ///
643 /// let abs_difference = (angle.to_radians() - std::f16::consts::PI).abs();
644 ///
645 /// assert!(abs_difference <= 0.01);
646 /// # }
647 /// ```
648 #[inline]
649 #[unstable(feature = "f16", issue = "116909")]
650 #[must_use = "this returns the result of the operation, without modifying the original"]
651 pub const fn to_radians(self) -> f16 {
652 // Use a literal for better precision.
653 const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
654 self * RADS_PER_DEG
655 }
656
657 /// Returns the maximum of the two numbers, ignoring NaN.
658 ///
659 /// If one of the arguments is NaN, then the other argument is returned.
660 /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
661 /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
662 /// This also matches the behavior of libm’s fmax. In particular, if the inputs compare equal
663 /// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
664 ///
665 /// ```
666 /// #![feature(f16)]
667 /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
668 ///
669 /// let x = 1.0f16;
670 /// let y = 2.0f16;
671 ///
672 /// assert_eq!(x.max(y), y);
673 /// # }
674 /// ```
675 #[inline]
676 #[unstable(feature = "f16", issue = "116909")]
677 #[rustc_const_unstable(feature = "f16", issue = "116909")]
678 #[must_use = "this returns the result of the comparison, without modifying either input"]
679 pub const fn max(self, other: f16) -> f16 {
680 intrinsics::maxnumf16(self, other)
681 }
682
683 /// Returns the minimum of the two numbers, ignoring NaN.
684 ///
685 /// If one of the arguments is NaN, then the other argument is returned.
686 /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
687 /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
688 /// This also matches the behavior of libm’s fmin. In particular, if the inputs compare equal
689 /// (such as for the case of `+0.0` and `-0.0`), either input may be returned non-deterministically.
690 ///
691 /// ```
692 /// #![feature(f16)]
693 /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
694 ///
695 /// let x = 1.0f16;
696 /// let y = 2.0f16;
697 ///
698 /// assert_eq!(x.min(y), x);
699 /// # }
700 /// ```
701 #[inline]
702 #[unstable(feature = "f16", issue = "116909")]
703 #[rustc_const_unstable(feature = "f16", issue = "116909")]
704 #[must_use = "this returns the result of the comparison, without modifying either input"]
705 pub const fn min(self, other: f16) -> f16 {
706 intrinsics::minnumf16(self, other)
707 }
708
709 /// Returns the maximum of the two numbers, propagating NaN.
710 ///
711 /// This returns NaN when *either* argument is NaN, as opposed to
712 /// [`f16::max`] which only returns NaN when *both* arguments are NaN.
713 ///
714 /// ```
715 /// #![feature(f16)]
716 /// #![feature(float_minimum_maximum)]
717 /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
718 ///
719 /// let x = 1.0f16;
720 /// let y = 2.0f16;
721 ///
722 /// assert_eq!(x.maximum(y), y);
723 /// assert!(x.maximum(f16::NAN).is_nan());
724 /// # }
725 /// ```
726 ///
727 /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
728 /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
729 /// Note that this follows the semantics specified in IEEE 754-2019.
730 ///
731 /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
732 /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
733 #[inline]
734 #[unstable(feature = "f16", issue = "116909")]
735 // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
736 #[must_use = "this returns the result of the comparison, without modifying either input"]
737 pub const fn maximum(self, other: f16) -> f16 {
738 if self > other {
739 self
740 } else if other > self {
741 other
742 } else if self == other {
743 if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
744 } else {
745 self + other
746 }
747 }
748
749 /// Returns the minimum of the two numbers, propagating NaN.
750 ///
751 /// This returns NaN when *either* argument is NaN, as opposed to
752 /// [`f16::min`] which only returns NaN when *both* arguments are NaN.
753 ///
754 /// ```
755 /// #![feature(f16)]
756 /// #![feature(float_minimum_maximum)]
757 /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
758 ///
759 /// let x = 1.0f16;
760 /// let y = 2.0f16;
761 ///
762 /// assert_eq!(x.minimum(y), x);
763 /// assert!(x.minimum(f16::NAN).is_nan());
764 /// # }
765 /// ```
766 ///
767 /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
768 /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
769 /// Note that this follows the semantics specified in IEEE 754-2019.
770 ///
771 /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
772 /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
773 #[inline]
774 #[unstable(feature = "f16", issue = "116909")]
775 // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
776 #[must_use = "this returns the result of the comparison, without modifying either input"]
777 pub const fn minimum(self, other: f16) -> f16 {
778 if self < other {
779 self
780 } else if other < self {
781 other
782 } else if self == other {
783 if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
784 } else {
785 // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
786 self + other
787 }
788 }
789
790 /// Calculates the middle point of `self` and `rhs`.
791 ///
792 /// This returns NaN when *either* argument is NaN or if a combination of
793 /// +inf and -inf is provided as arguments.
794 ///
795 /// # Examples
796 ///
797 /// ```
798 /// #![feature(f16)]
799 /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
800 ///
801 /// assert_eq!(1f16.midpoint(4.0), 2.5);
802 /// assert_eq!((-5.5f16).midpoint(8.0), 1.25);
803 /// # }
804 /// ```
805 #[inline]
806 #[unstable(feature = "f16", issue = "116909")]
807 #[rustc_const_unstable(feature = "f16", issue = "116909")]
808 pub const fn midpoint(self, other: f16) -> f16 {
809 const LO: f16 = f16::MIN_POSITIVE * 2.;
810 const HI: f16 = f16::MAX / 2.;
811
812 let (a, b) = (self, other);
813 let abs_a = a.abs();
814 let abs_b = b.abs();
815
816 if abs_a <= HI && abs_b <= HI {
817 // Overflow is impossible
818 (a + b) / 2.
819 } else if abs_a < LO {
820 // Not safe to halve `a` (would underflow)
821 a + (b / 2.)
822 } else if abs_b < LO {
823 // Not safe to halve `b` (would underflow)
824 (a / 2.) + b
825 } else {
826 // Safe to halve `a` and `b`
827 (a / 2.) + (b / 2.)
828 }
829 }
830
831 /// Rounds toward zero and converts to any primitive integer type,
832 /// assuming that the value is finite and fits in that type.
833 ///
834 /// ```
835 /// #![feature(f16)]
836 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
837 ///
838 /// let value = 4.6_f16;
839 /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
840 /// assert_eq!(rounded, 4);
841 ///
842 /// let value = -128.9_f16;
843 /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
844 /// assert_eq!(rounded, i8::MIN);
845 /// # }
846 /// ```
847 ///
848 /// # Safety
849 ///
850 /// The value must:
851 ///
852 /// * Not be `NaN`
853 /// * Not be infinite
854 /// * Be representable in the return type `Int`, after truncating off its fractional part
855 #[inline]
856 #[unstable(feature = "f16", issue = "116909")]
857 #[must_use = "this returns the result of the operation, without modifying the original"]
858 pub unsafe fn to_int_unchecked<Int>(self) -> Int
859 where
860 Self: FloatToInt<Int>,
861 {
862 // SAFETY: the caller must uphold the safety contract for
863 // `FloatToInt::to_int_unchecked`.
864 unsafe { FloatToInt::<Int>::to_int_unchecked(self) }
865 }
866
867 /// Raw transmutation to `u16`.
868 ///
869 /// This is currently identical to `transmute::<f16, u16>(self)` on all platforms.
870 ///
871 /// See [`from_bits`](#method.from_bits) for some discussion of the
872 /// portability of this operation (there are almost no issues).
873 ///
874 /// Note that this function is distinct from `as` casting, which attempts to
875 /// preserve the *numeric* value, and not the bitwise value.
876 ///
877 /// ```
878 /// #![feature(f16)]
879 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
880 ///
881 /// # // FIXME(f16_f128): enable this once const casting works
882 /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting!
883 /// assert_eq!((12.5f16).to_bits(), 0x4a40);
884 /// # }
885 /// ```
886 #[inline]
887 #[unstable(feature = "f16", issue = "116909")]
888 #[must_use = "this returns the result of the operation, without modifying the original"]
889 pub const fn to_bits(self) -> u16 {
890 // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
891 unsafe { mem::transmute(self) }
892 }
893
894 /// Raw transmutation from `u16`.
895 ///
896 /// This is currently identical to `transmute::<u16, f16>(v)` on all platforms.
897 /// It turns out this is incredibly portable, for two reasons:
898 ///
899 /// * Floats and Ints have the same endianness on all supported platforms.
900 /// * IEEE 754 very precisely specifies the bit layout of floats.
901 ///
902 /// However there is one caveat: prior to the 2008 version of IEEE 754, how
903 /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
904 /// (notably x86 and ARM) picked the interpretation that was ultimately
905 /// standardized in 2008, but some didn't (notably MIPS). As a result, all
906 /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
907 ///
908 /// Rather than trying to preserve signaling-ness cross-platform, this
909 /// implementation favors preserving the exact bits. This means that
910 /// any payloads encoded in NaNs will be preserved even if the result of
911 /// this method is sent over the network from an x86 machine to a MIPS one.
912 ///
913 /// If the results of this method are only manipulated by the same
914 /// architecture that produced them, then there is no portability concern.
915 ///
916 /// If the input isn't NaN, then there is no portability concern.
917 ///
918 /// If you don't care about signalingness (very likely), then there is no
919 /// portability concern.
920 ///
921 /// Note that this function is distinct from `as` casting, which attempts to
922 /// preserve the *numeric* value, and not the bitwise value.
923 ///
924 /// ```
925 /// #![feature(f16)]
926 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
927 ///
928 /// let v = f16::from_bits(0x4a40);
929 /// assert_eq!(v, 12.5);
930 /// # }
931 /// ```
932 #[inline]
933 #[must_use]
934 #[unstable(feature = "f16", issue = "116909")]
935 pub const fn from_bits(v: u16) -> Self {
936 // It turns out the safety issues with sNaN were overblown! Hooray!
937 // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
938 unsafe { mem::transmute(v) }
939 }
940
941 /// Returns the memory representation of this floating point number as a byte array in
942 /// big-endian (network) byte order.
943 ///
944 /// See [`from_bits`](Self::from_bits) for some discussion of the
945 /// portability of this operation (there are almost no issues).
946 ///
947 /// # Examples
948 ///
949 /// ```
950 /// #![feature(f16)]
951 /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
952 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
953 ///
954 /// let bytes = 12.5f16.to_be_bytes();
955 /// assert_eq!(bytes, [0x4a, 0x40]);
956 /// # }
957 /// ```
958 #[inline]
959 #[unstable(feature = "f16", issue = "116909")]
960 #[must_use = "this returns the result of the operation, without modifying the original"]
961 pub const fn to_be_bytes(self) -> [u8; 2] {
962 self.to_bits().to_be_bytes()
963 }
964
965 /// Returns the memory representation of this floating point number as a byte array in
966 /// little-endian byte order.
967 ///
968 /// See [`from_bits`](Self::from_bits) for some discussion of the
969 /// portability of this operation (there are almost no issues).
970 ///
971 /// # Examples
972 ///
973 /// ```
974 /// #![feature(f16)]
975 /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
976 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
977 ///
978 /// let bytes = 12.5f16.to_le_bytes();
979 /// assert_eq!(bytes, [0x40, 0x4a]);
980 /// # }
981 /// ```
982 #[inline]
983 #[unstable(feature = "f16", issue = "116909")]
984 #[must_use = "this returns the result of the operation, without modifying the original"]
985 pub const fn to_le_bytes(self) -> [u8; 2] {
986 self.to_bits().to_le_bytes()
987 }
988
989 /// Returns the memory representation of this floating point number as a byte array in
990 /// native byte order.
991 ///
992 /// As the target platform's native endianness is used, portable code
993 /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
994 ///
995 /// [`to_be_bytes`]: f16::to_be_bytes
996 /// [`to_le_bytes`]: f16::to_le_bytes
997 ///
998 /// See [`from_bits`](Self::from_bits) for some discussion of the
999 /// portability of this operation (there are almost no issues).
1000 ///
1001 /// # Examples
1002 ///
1003 /// ```
1004 /// #![feature(f16)]
1005 /// # // FIXME(f16_f128): LLVM crashes on s390x, llvm/llvm-project#50374
1006 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1007 ///
1008 /// let bytes = 12.5f16.to_ne_bytes();
1009 /// assert_eq!(
1010 /// bytes,
1011 /// if cfg!(target_endian = "big") {
1012 /// [0x4a, 0x40]
1013 /// } else {
1014 /// [0x40, 0x4a]
1015 /// }
1016 /// );
1017 /// # }
1018 /// ```
1019 #[inline]
1020 #[unstable(feature = "f16", issue = "116909")]
1021 #[must_use = "this returns the result of the operation, without modifying the original"]
1022 pub const fn to_ne_bytes(self) -> [u8; 2] {
1023 self.to_bits().to_ne_bytes()
1024 }
1025
1026 /// Creates a floating point value from its representation as a byte array in big endian.
1027 ///
1028 /// See [`from_bits`](Self::from_bits) for some discussion of the
1029 /// portability of this operation (there are almost no issues).
1030 ///
1031 /// # Examples
1032 ///
1033 /// ```
1034 /// #![feature(f16)]
1035 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1036 ///
1037 /// let value = f16::from_be_bytes([0x4a, 0x40]);
1038 /// assert_eq!(value, 12.5);
1039 /// # }
1040 /// ```
1041 #[inline]
1042 #[must_use]
1043 #[unstable(feature = "f16", issue = "116909")]
1044 pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
1045 Self::from_bits(u16::from_be_bytes(bytes))
1046 }
1047
1048 /// Creates a floating point value from its representation as a byte array in little endian.
1049 ///
1050 /// See [`from_bits`](Self::from_bits) for some discussion of the
1051 /// portability of this operation (there are almost no issues).
1052 ///
1053 /// # Examples
1054 ///
1055 /// ```
1056 /// #![feature(f16)]
1057 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1058 ///
1059 /// let value = f16::from_le_bytes([0x40, 0x4a]);
1060 /// assert_eq!(value, 12.5);
1061 /// # }
1062 /// ```
1063 #[inline]
1064 #[must_use]
1065 #[unstable(feature = "f16", issue = "116909")]
1066 pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
1067 Self::from_bits(u16::from_le_bytes(bytes))
1068 }
1069
1070 /// Creates a floating point value from its representation as a byte array in native endian.
1071 ///
1072 /// As the target platform's native endianness is used, portable code
1073 /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
1074 /// appropriate instead.
1075 ///
1076 /// [`from_be_bytes`]: f16::from_be_bytes
1077 /// [`from_le_bytes`]: f16::from_le_bytes
1078 ///
1079 /// See [`from_bits`](Self::from_bits) for some discussion of the
1080 /// portability of this operation (there are almost no issues).
1081 ///
1082 /// # Examples
1083 ///
1084 /// ```
1085 /// #![feature(f16)]
1086 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1087 ///
1088 /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") {
1089 /// [0x4a, 0x40]
1090 /// } else {
1091 /// [0x40, 0x4a]
1092 /// });
1093 /// assert_eq!(value, 12.5);
1094 /// # }
1095 /// ```
1096 #[inline]
1097 #[must_use]
1098 #[unstable(feature = "f16", issue = "116909")]
1099 pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
1100 Self::from_bits(u16::from_ne_bytes(bytes))
1101 }
1102
1103 /// Returns the ordering between `self` and `other`.
1104 ///
1105 /// Unlike the standard partial comparison between floating point numbers,
1106 /// this comparison always produces an ordering in accordance to
1107 /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision)
1108 /// floating point standard. The values are ordered in the following sequence:
1109 ///
1110 /// - negative quiet NaN
1111 /// - negative signaling NaN
1112 /// - negative infinity
1113 /// - negative numbers
1114 /// - negative subnormal numbers
1115 /// - negative zero
1116 /// - positive zero
1117 /// - positive subnormal numbers
1118 /// - positive numbers
1119 /// - positive infinity
1120 /// - positive signaling NaN
1121 /// - positive quiet NaN.
1122 ///
1123 /// The ordering established by this function does not always agree with the
1124 /// [`PartialOrd`] and [`PartialEq`] implementations of `f16`. For example,
1125 /// they consider negative and positive zero equal, while `total_cmp`
1126 /// doesn't.
1127 ///
1128 /// The interpretation of the signaling NaN bit follows the definition in
1129 /// the IEEE 754 standard, which may not match the interpretation by some of
1130 /// the older, non-conformant (e.g. MIPS) hardware implementations.
1131 ///
1132 /// # Example
1133 ///
1134 /// ```
1135 /// #![feature(f16)]
1136 /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
1137 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1138 ///
1139 /// struct GoodBoy {
1140 /// name: &'static str,
1141 /// weight: f16,
1142 /// }
1143 ///
1144 /// let mut bois = vec![
1145 /// GoodBoy { name: "Pucci", weight: 0.1 },
1146 /// GoodBoy { name: "Woofer", weight: 99.0 },
1147 /// GoodBoy { name: "Yapper", weight: 10.0 },
1148 /// GoodBoy { name: "Chonk", weight: f16::INFINITY },
1149 /// GoodBoy { name: "Abs. Unit", weight: f16::NAN },
1150 /// GoodBoy { name: "Floaty", weight: -5.0 },
1151 /// ];
1152 ///
1153 /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
1154 ///
1155 /// // `f16::NAN` could be positive or negative, which will affect the sort order.
1156 /// if f16::NAN.is_sign_negative() {
1157 /// bois.into_iter().map(|b| b.weight)
1158 /// .zip([f16::NAN, -5.0, 0.1, 10.0, 99.0, f16::INFINITY].iter())
1159 /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
1160 /// } else {
1161 /// bois.into_iter().map(|b| b.weight)
1162 /// .zip([-5.0, 0.1, 10.0, 99.0, f16::INFINITY, f16::NAN].iter())
1163 /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits()))
1164 /// }
1165 /// # }
1166 /// ```
1167 #[inline]
1168 #[must_use]
1169 #[unstable(feature = "f16", issue = "116909")]
1170 pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
1171 let mut left = self.to_bits() as i16;
1172 let mut right = other.to_bits() as i16;
1173
1174 // In case of negatives, flip all the bits except the sign
1175 // to achieve a similar layout as two's complement integers
1176 //
1177 // Why does this work? IEEE 754 floats consist of three fields:
1178 // Sign bit, exponent and mantissa. The set of exponent and mantissa
1179 // fields as a whole have the property that their bitwise order is
1180 // equal to the numeric magnitude where the magnitude is defined.
1181 // The magnitude is not normally defined on NaN values, but
1182 // IEEE 754 totalOrder defines the NaN values also to follow the
1183 // bitwise order. This leads to order explained in the doc comment.
1184 // However, the representation of magnitude is the same for negative
1185 // and positive numbers – only the sign bit is different.
1186 // To easily compare the floats as signed integers, we need to
1187 // flip the exponent and mantissa bits in case of negative numbers.
1188 // We effectively convert the numbers to "two's complement" form.
1189 //
1190 // To do the flipping, we construct a mask and XOR against it.
1191 // We branchlessly calculate an "all-ones except for the sign bit"
1192 // mask from negative-signed values: right shifting sign-extends
1193 // the integer, so we "fill" the mask with sign bits, and then
1194 // convert to unsigned to push one more zero bit.
1195 // On positive values, the mask is all zeros, so it's a no-op.
1196 left ^= (((left >> 15) as u16) >> 1) as i16;
1197 right ^= (((right >> 15) as u16) >> 1) as i16;
1198
1199 left.cmp(&right)
1200 }
1201
1202 /// Restrict a value to a certain interval unless it is NaN.
1203 ///
1204 /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
1205 /// less than `min`. Otherwise this returns `self`.
1206 ///
1207 /// Note that this function returns NaN if the initial value was NaN as
1208 /// well.
1209 ///
1210 /// # Panics
1211 ///
1212 /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
1213 ///
1214 /// # Examples
1215 ///
1216 /// ```
1217 /// #![feature(f16)]
1218 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1219 ///
1220 /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0);
1221 /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0);
1222 /// assert!((2.0f16).clamp(-2.0, 1.0) == 1.0);
1223 /// assert!((f16::NAN).clamp(-2.0, 1.0).is_nan());
1224 /// # }
1225 /// ```
1226 #[inline]
1227 #[unstable(feature = "f16", issue = "116909")]
1228 #[must_use = "method returns a new number and does not mutate the original value"]
1229 pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
1230 const_assert!(
1231 min <= max,
1232 "min > max, or either was NaN",
1233 "min > max, or either was NaN. min = {min:?}, max = {max:?}",
1234 min: f16,
1235 max: f16,
1236 );
1237
1238 if self < min {
1239 self = min;
1240 }
1241 if self > max {
1242 self = max;
1243 }
1244 self
1245 }
1246
1247 /// Computes the absolute value of `self`.
1248 ///
1249 /// This function always returns the precise result.
1250 ///
1251 /// # Examples
1252 ///
1253 /// ```
1254 /// #![feature(f16)]
1255 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1256 ///
1257 /// let x = 3.5_f16;
1258 /// let y = -3.5_f16;
1259 ///
1260 /// assert_eq!(x.abs(), x);
1261 /// assert_eq!(y.abs(), -y);
1262 ///
1263 /// assert!(f16::NAN.abs().is_nan());
1264 /// # }
1265 /// ```
1266 #[inline]
1267 #[unstable(feature = "f16", issue = "116909")]
1268 #[rustc_const_unstable(feature = "f16", issue = "116909")]
1269 #[must_use = "method returns a new number and does not mutate the original value"]
1270 pub const fn abs(self) -> Self {
1271 // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
1272 Self::from_bits(self.to_bits() & !(1 << 15))
1273 }
1274
1275 /// Returns a number that represents the sign of `self`.
1276 ///
1277 /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
1278 /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
1279 /// - NaN if the number is NaN
1280 ///
1281 /// # Examples
1282 ///
1283 /// ```
1284 /// #![feature(f16)]
1285 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1286 ///
1287 /// let f = 3.5_f16;
1288 ///
1289 /// assert_eq!(f.signum(), 1.0);
1290 /// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
1291 ///
1292 /// assert!(f16::NAN.signum().is_nan());
1293 /// # }
1294 /// ```
1295 #[inline]
1296 #[unstable(feature = "f16", issue = "116909")]
1297 #[rustc_const_unstable(feature = "f16", issue = "116909")]
1298 #[must_use = "method returns a new number and does not mutate the original value"]
1299 pub const fn signum(self) -> f16 {
1300 if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
1301 }
1302
1303 /// Returns a number composed of the magnitude of `self` and the sign of
1304 /// `sign`.
1305 ///
1306 /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
1307 /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
1308 /// returned.
1309 ///
1310 /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
1311 /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
1312 /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
1313 /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
1314 /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
1315 /// info.
1316 ///
1317 /// # Examples
1318 ///
1319 /// ```
1320 /// #![feature(f16)]
1321 /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
1322 ///
1323 /// let f = 3.5_f16;
1324 ///
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 /// assert_eq!((-f).copysign(-0.42), -3.5_f16);
1329 ///
1330 /// assert!(f16::NAN.copysign(1.0).is_nan());
1331 /// # }
1332 /// ```
1333 #[inline]
1334 #[unstable(feature = "f16", issue = "116909")]
1335 #[rustc_const_unstable(feature = "f16", issue = "116909")]
1336 #[must_use = "method returns a new number and does not mutate the original value"]
1337 pub const fn copysign(self, sign: f16) -> f16 {
1338 // SAFETY: this is actually a safe intrinsic
1339 unsafe { intrinsics::copysignf16(self, sign) }
1340 }
1341}