std/
f16.rs

1//! Constants for the `f16` half-precision floating point type.
2//!
3//! *[See also the `f16` primitive type](primitive@f16).*
4//!
5//! Mathematically significant numbers are provided in the `consts` sub-module.
6
7#[unstable(feature = "f16", issue = "116909")]
8pub use core::f16::consts;
9
10#[cfg(not(test))]
11use crate::intrinsics;
12#[cfg(not(test))]
13use crate::sys::cmath;
14
15#[cfg(not(test))]
16impl f16 {
17    /// Returns the largest integer less than or equal to `self`.
18    ///
19    /// This function always returns the precise result.
20    ///
21    /// # Examples
22    ///
23    /// ```
24    /// #![feature(f16)]
25    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
26    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
27    /// # #[cfg(not(miri))]
28    /// # #[cfg(not(bootstrap))]
29    /// # #[cfg(target_has_reliable_f16_math)] {
30    ///
31    /// let f = 3.7_f16;
32    /// let g = 3.0_f16;
33    /// let h = -3.7_f16;
34    ///
35    /// assert_eq!(f.floor(), 3.0);
36    /// assert_eq!(g.floor(), 3.0);
37    /// assert_eq!(h.floor(), -4.0);
38    /// # }
39    /// ```
40    #[inline]
41    #[rustc_allow_incoherent_impl]
42    #[unstable(feature = "f16", issue = "116909")]
43    #[must_use = "method returns a new number and does not mutate the original value"]
44    pub fn floor(self) -> f16 {
45        unsafe { intrinsics::floorf16(self) }
46    }
47
48    /// Returns the smallest integer greater than or equal to `self`.
49    ///
50    /// This function always returns the precise result.
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// #![feature(f16)]
56    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
57    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
58    /// # #[cfg(not(miri))]
59    /// # #[cfg(not(bootstrap))]
60    /// # #[cfg(target_has_reliable_f16_math)] {
61    ///
62    /// let f = 3.01_f16;
63    /// let g = 4.0_f16;
64    ///
65    /// assert_eq!(f.ceil(), 4.0);
66    /// assert_eq!(g.ceil(), 4.0);
67    /// # }
68    /// ```
69    #[inline]
70    #[doc(alias = "ceiling")]
71    #[rustc_allow_incoherent_impl]
72    #[unstable(feature = "f16", issue = "116909")]
73    #[must_use = "method returns a new number and does not mutate the original value"]
74    pub fn ceil(self) -> f16 {
75        unsafe { intrinsics::ceilf16(self) }
76    }
77
78    /// Returns the nearest integer to `self`. If a value is half-way between two
79    /// integers, round away from `0.0`.
80    ///
81    /// This function always returns the precise result.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// #![feature(f16)]
87    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
88    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
89    /// # #[cfg(not(miri))]
90    /// # #[cfg(not(bootstrap))]
91    /// # #[cfg(target_has_reliable_f16_math)] {
92    ///
93    /// let f = 3.3_f16;
94    /// let g = -3.3_f16;
95    /// let h = -3.7_f16;
96    /// let i = 3.5_f16;
97    /// let j = 4.5_f16;
98    ///
99    /// assert_eq!(f.round(), 3.0);
100    /// assert_eq!(g.round(), -3.0);
101    /// assert_eq!(h.round(), -4.0);
102    /// assert_eq!(i.round(), 4.0);
103    /// assert_eq!(j.round(), 5.0);
104    /// # }
105    /// ```
106    #[inline]
107    #[rustc_allow_incoherent_impl]
108    #[unstable(feature = "f16", issue = "116909")]
109    #[must_use = "method returns a new number and does not mutate the original value"]
110    pub fn round(self) -> f16 {
111        unsafe { intrinsics::roundf16(self) }
112    }
113
114    /// Returns the nearest integer to a number. Rounds half-way cases to the number
115    /// with an even least significant digit.
116    ///
117    /// This function always returns the precise result.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// #![feature(f16)]
123    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
124    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
125    /// # #[cfg(not(miri))]
126    /// # #[cfg(not(bootstrap))]
127    /// # #[cfg(target_has_reliable_f16_math)] {
128    ///
129    /// let f = 3.3_f16;
130    /// let g = -3.3_f16;
131    /// let h = 3.5_f16;
132    /// let i = 4.5_f16;
133    ///
134    /// assert_eq!(f.round_ties_even(), 3.0);
135    /// assert_eq!(g.round_ties_even(), -3.0);
136    /// assert_eq!(h.round_ties_even(), 4.0);
137    /// assert_eq!(i.round_ties_even(), 4.0);
138    /// # }
139    /// ```
140    #[inline]
141    #[rustc_allow_incoherent_impl]
142    #[unstable(feature = "f16", issue = "116909")]
143    #[must_use = "method returns a new number and does not mutate the original value"]
144    pub fn round_ties_even(self) -> f16 {
145        intrinsics::round_ties_even_f16(self)
146    }
147
148    /// Returns the integer part of `self`.
149    /// This means that non-integer numbers are always truncated towards zero.
150    ///
151    /// This function always returns the precise result.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// #![feature(f16)]
157    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
158    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
159    /// # #[cfg(not(miri))]
160    /// # #[cfg(not(bootstrap))]
161    /// # #[cfg(target_has_reliable_f16_math)] {
162    ///
163    /// let f = 3.7_f16;
164    /// let g = 3.0_f16;
165    /// let h = -3.7_f16;
166    ///
167    /// assert_eq!(f.trunc(), 3.0);
168    /// assert_eq!(g.trunc(), 3.0);
169    /// assert_eq!(h.trunc(), -3.0);
170    /// # }
171    /// ```
172    #[inline]
173    #[doc(alias = "truncate")]
174    #[rustc_allow_incoherent_impl]
175    #[unstable(feature = "f16", issue = "116909")]
176    #[must_use = "method returns a new number and does not mutate the original value"]
177    pub fn trunc(self) -> f16 {
178        unsafe { intrinsics::truncf16(self) }
179    }
180
181    /// Returns the fractional part of `self`.
182    ///
183    /// This function always returns the precise result.
184    ///
185    /// # Examples
186    ///
187    /// ```
188    /// #![feature(f16)]
189    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
190    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
191    /// # #[cfg(not(miri))]
192    /// # #[cfg(not(bootstrap))]
193    /// # #[cfg(target_has_reliable_f16_math)] {
194    ///
195    /// let x = 3.6_f16;
196    /// let y = -3.6_f16;
197    /// let abs_difference_x = (x.fract() - 0.6).abs();
198    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
199    ///
200    /// assert!(abs_difference_x <= f16::EPSILON);
201    /// assert!(abs_difference_y <= f16::EPSILON);
202    /// # }
203    /// ```
204    #[inline]
205    #[rustc_allow_incoherent_impl]
206    #[unstable(feature = "f16", issue = "116909")]
207    #[must_use = "method returns a new number and does not mutate the original value"]
208    pub fn fract(self) -> f16 {
209        self - self.trunc()
210    }
211
212    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
213    /// error, yielding a more accurate result than an unfused multiply-add.
214    ///
215    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
216    /// the target architecture has a dedicated `fma` CPU instruction. However,
217    /// this is not always true, and will be heavily dependant on designing
218    /// algorithms with specific target hardware in mind.
219    ///
220    /// # Precision
221    ///
222    /// The result of this operation is guaranteed to be the rounded
223    /// infinite-precision result. It is specified by IEEE 754 as
224    /// `fusedMultiplyAdd` and guaranteed not to change.
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// #![feature(f16)]
230    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
231    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
232    /// # #[cfg(not(miri))]
233    /// # #[cfg(not(bootstrap))]
234    /// # #[cfg(target_has_reliable_f16_math)] {
235    ///
236    /// let m = 10.0_f16;
237    /// let x = 4.0_f16;
238    /// let b = 60.0_f16;
239    ///
240    /// assert_eq!(m.mul_add(x, b), 100.0);
241    /// assert_eq!(m * x + b, 100.0);
242    ///
243    /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
244    /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
245    /// let minus_one = -1.0_f16;
246    ///
247    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
248    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
249    /// // Different rounding with the non-fused multiply and add.
250    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
251    /// # }
252    /// ```
253    #[inline]
254    #[rustc_allow_incoherent_impl]
255    #[unstable(feature = "f16", issue = "116909")]
256    #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")]
257    #[must_use = "method returns a new number and does not mutate the original value"]
258    pub fn mul_add(self, a: f16, b: f16) -> f16 {
259        unsafe { intrinsics::fmaf16(self, a, b) }
260    }
261
262    /// Calculates Euclidean division, the matching method for `rem_euclid`.
263    ///
264    /// This computes the integer `n` such that
265    /// `self = n * rhs + self.rem_euclid(rhs)`.
266    /// In other words, the result is `self / rhs` rounded to the integer `n`
267    /// such that `self >= n * rhs`.
268    ///
269    /// # Precision
270    ///
271    /// The result of this operation is guaranteed to be the rounded
272    /// infinite-precision result.
273    ///
274    /// # Examples
275    ///
276    /// ```
277    /// #![feature(f16)]
278    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
279    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
280    /// # #[cfg(not(miri))]
281    /// # #[cfg(not(bootstrap))]
282    /// # #[cfg(target_has_reliable_f16_math)] {
283    ///
284    /// let a: f16 = 7.0;
285    /// let b = 4.0;
286    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
287    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
288    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
289    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
290    /// # }
291    /// ```
292    #[inline]
293    #[rustc_allow_incoherent_impl]
294    #[unstable(feature = "f16", issue = "116909")]
295    #[must_use = "method returns a new number and does not mutate the original value"]
296    pub fn div_euclid(self, rhs: f16) -> f16 {
297        let q = (self / rhs).trunc();
298        if self % rhs < 0.0 {
299            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
300        }
301        q
302    }
303
304    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
305    ///
306    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
307    /// most cases. However, due to a floating point round-off error it can
308    /// result in `r == rhs.abs()`, violating the mathematical definition, if
309    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
310    /// This result is not an element of the function's codomain, but it is the
311    /// closest floating point number in the real numbers and thus fulfills the
312    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
313    /// approximately.
314    ///
315    /// # Precision
316    ///
317    /// The result of this operation is guaranteed to be the rounded
318    /// infinite-precision result.
319    ///
320    /// # Examples
321    ///
322    /// ```
323    /// #![feature(f16)]
324    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
325    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
326    /// # #[cfg(not(miri))]
327    /// # #[cfg(not(bootstrap))]
328    /// # #[cfg(target_has_reliable_f16_math)] {
329    ///
330    /// let a: f16 = 7.0;
331    /// let b = 4.0;
332    /// assert_eq!(a.rem_euclid(b), 3.0);
333    /// assert_eq!((-a).rem_euclid(b), 1.0);
334    /// assert_eq!(a.rem_euclid(-b), 3.0);
335    /// assert_eq!((-a).rem_euclid(-b), 1.0);
336    /// // limitation due to round-off error
337    /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
338    /// # }
339    /// ```
340    #[inline]
341    #[rustc_allow_incoherent_impl]
342    #[doc(alias = "modulo", alias = "mod")]
343    #[unstable(feature = "f16", issue = "116909")]
344    #[must_use = "method returns a new number and does not mutate the original value"]
345    pub fn rem_euclid(self, rhs: f16) -> f16 {
346        let r = self % rhs;
347        if r < 0.0 { r + rhs.abs() } else { r }
348    }
349
350    /// Raises a number to an integer power.
351    ///
352    /// Using this function is generally faster than using `powf`.
353    /// It might have a different sequence of rounding operations than `powf`,
354    /// so the results are not guaranteed to agree.
355    ///
356    /// # Unspecified precision
357    ///
358    /// The precision of this function is non-deterministic. This means it varies by platform,
359    /// Rust version, and can even differ within the same execution from one invocation to the next.
360    ///
361    /// # Examples
362    ///
363    /// ```
364    /// #![feature(f16)]
365    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
366    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
367    /// # #[cfg(not(miri))]
368    /// # #[cfg(not(bootstrap))]
369    /// # #[cfg(target_has_reliable_f16_math)] {
370    ///
371    /// let x = 2.0_f16;
372    /// let abs_difference = (x.powi(2) - (x * x)).abs();
373    /// assert!(abs_difference <= f16::EPSILON);
374    ///
375    /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
376    /// # }
377    /// ```
378    #[inline]
379    #[rustc_allow_incoherent_impl]
380    #[unstable(feature = "f16", issue = "116909")]
381    #[must_use = "method returns a new number and does not mutate the original value"]
382    pub fn powi(self, n: i32) -> f16 {
383        unsafe { intrinsics::powif16(self, n) }
384    }
385
386    /// Raises a number to a floating point power.
387    ///
388    /// # Unspecified precision
389    ///
390    /// The precision of this function is non-deterministic. This means it varies by platform,
391    /// Rust version, and can even differ within the same execution from one invocation to the next.
392    ///
393    /// # Examples
394    ///
395    /// ```
396    /// #![feature(f16)]
397    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
398    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
399    /// # #[cfg(not(miri))]
400    /// # #[cfg(not(bootstrap))]
401    /// # #[cfg(target_has_reliable_f16_math)] {
402    ///
403    /// let x = 2.0_f16;
404    /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
405    /// assert!(abs_difference <= f16::EPSILON);
406    ///
407    /// assert_eq!(f16::powf(1.0, f16::NAN), 1.0);
408    /// assert_eq!(f16::powf(f16::NAN, 0.0), 1.0);
409    /// # }
410    /// ```
411    #[inline]
412    #[rustc_allow_incoherent_impl]
413    #[unstable(feature = "f16", issue = "116909")]
414    #[must_use = "method returns a new number and does not mutate the original value"]
415    pub fn powf(self, n: f16) -> f16 {
416        unsafe { intrinsics::powf16(self, n) }
417    }
418
419    /// Returns the square root of a number.
420    ///
421    /// Returns NaN if `self` is a negative number other than `-0.0`.
422    ///
423    /// # Precision
424    ///
425    /// The result of this operation is guaranteed to be the rounded
426    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
427    /// and guaranteed not to change.
428    ///
429    /// # Examples
430    ///
431    /// ```
432    /// #![feature(f16)]
433    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
434    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
435    /// # #[cfg(not(miri))]
436    /// # #[cfg(not(bootstrap))]
437    /// # #[cfg(target_has_reliable_f16_math)] {
438    ///
439    /// let positive = 4.0_f16;
440    /// let negative = -4.0_f16;
441    /// let negative_zero = -0.0_f16;
442    ///
443    /// assert_eq!(positive.sqrt(), 2.0);
444    /// assert!(negative.sqrt().is_nan());
445    /// assert!(negative_zero.sqrt() == negative_zero);
446    /// # }
447    /// ```
448    #[inline]
449    #[doc(alias = "squareRoot")]
450    #[rustc_allow_incoherent_impl]
451    #[unstable(feature = "f16", issue = "116909")]
452    #[must_use = "method returns a new number and does not mutate the original value"]
453    pub fn sqrt(self) -> f16 {
454        unsafe { intrinsics::sqrtf16(self) }
455    }
456
457    /// Returns `e^(self)`, (the exponential function).
458    ///
459    /// # Unspecified precision
460    ///
461    /// The precision of this function is non-deterministic. This means it varies by platform,
462    /// Rust version, and can even differ within the same execution from one invocation to the next.
463    ///
464    /// # Examples
465    ///
466    /// ```
467    /// #![feature(f16)]
468    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
469    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
470    /// # #[cfg(not(miri))]
471    /// # #[cfg(not(bootstrap))]
472    /// # #[cfg(target_has_reliable_f16_math)] {
473    ///
474    /// let one = 1.0f16;
475    /// // e^1
476    /// let e = one.exp();
477    ///
478    /// // ln(e) - 1 == 0
479    /// let abs_difference = (e.ln() - 1.0).abs();
480    ///
481    /// assert!(abs_difference <= f16::EPSILON);
482    /// # }
483    /// ```
484    #[inline]
485    #[rustc_allow_incoherent_impl]
486    #[unstable(feature = "f16", issue = "116909")]
487    #[must_use = "method returns a new number and does not mutate the original value"]
488    pub fn exp(self) -> f16 {
489        unsafe { intrinsics::expf16(self) }
490    }
491
492    /// Returns `2^(self)`.
493    ///
494    /// # Unspecified precision
495    ///
496    /// The precision of this function is non-deterministic. This means it varies by platform,
497    /// Rust version, and can even differ within the same execution from one invocation to the next.
498    ///
499    /// # Examples
500    ///
501    /// ```
502    /// #![feature(f16)]
503    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
504    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
505    /// # #[cfg(not(miri))]
506    /// # #[cfg(not(bootstrap))]
507    /// # #[cfg(target_has_reliable_f16_math)] {
508    ///
509    /// let f = 2.0f16;
510    ///
511    /// // 2^2 - 4 == 0
512    /// let abs_difference = (f.exp2() - 4.0).abs();
513    ///
514    /// assert!(abs_difference <= f16::EPSILON);
515    /// # }
516    /// ```
517    #[inline]
518    #[rustc_allow_incoherent_impl]
519    #[unstable(feature = "f16", issue = "116909")]
520    #[must_use = "method returns a new number and does not mutate the original value"]
521    pub fn exp2(self) -> f16 {
522        unsafe { intrinsics::exp2f16(self) }
523    }
524
525    /// Returns the natural logarithm of the number.
526    ///
527    /// This returns NaN when the number is negative, and negative infinity when number is zero.
528    ///
529    /// # Unspecified precision
530    ///
531    /// The precision of this function is non-deterministic. This means it varies by platform,
532    /// Rust version, and can even differ within the same execution from one invocation to the next.
533    ///
534    /// # Examples
535    ///
536    /// ```
537    /// #![feature(f16)]
538    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
539    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
540    /// # #[cfg(not(miri))]
541    /// # #[cfg(not(bootstrap))]
542    /// # #[cfg(target_has_reliable_f16_math)] {
543    ///
544    /// let one = 1.0f16;
545    /// // e^1
546    /// let e = one.exp();
547    ///
548    /// // ln(e) - 1 == 0
549    /// let abs_difference = (e.ln() - 1.0).abs();
550    ///
551    /// assert!(abs_difference <= f16::EPSILON);
552    /// # }
553    /// ```
554    ///
555    /// Non-positive values:
556    /// ```
557    /// #![feature(f16)]
558    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
559    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
560    /// # #[cfg(not(miri))]
561    /// # #[cfg(not(bootstrap))]
562    /// # #[cfg(target_has_reliable_f16_math)] {
563    ///
564    /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY);
565    /// assert!((-42_f16).ln().is_nan());
566    /// # }
567    /// ```
568    #[inline]
569    #[rustc_allow_incoherent_impl]
570    #[unstable(feature = "f16", issue = "116909")]
571    #[must_use = "method returns a new number and does not mutate the original value"]
572    pub fn ln(self) -> f16 {
573        unsafe { intrinsics::logf16(self) }
574    }
575
576    /// Returns the logarithm of the number with respect to an arbitrary base.
577    ///
578    /// This returns NaN when the number is negative, and negative infinity when number is zero.
579    ///
580    /// The result might not be correctly rounded owing to implementation details;
581    /// `self.log2()` can produce more accurate results for base 2, and
582    /// `self.log10()` can produce more accurate results for base 10.
583    ///
584    /// # Unspecified precision
585    ///
586    /// The precision of this function is non-deterministic. This means it varies by platform,
587    /// Rust version, and can even differ within the same execution from one invocation to the next.
588    ///
589    /// # Examples
590    ///
591    /// ```
592    /// #![feature(f16)]
593    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
594    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
595    /// # #[cfg(not(miri))]
596    /// # #[cfg(not(bootstrap))]
597    /// # #[cfg(target_has_reliable_f16_math)] {
598    ///
599    /// let five = 5.0f16;
600    ///
601    /// // log5(5) - 1 == 0
602    /// let abs_difference = (five.log(5.0) - 1.0).abs();
603    ///
604    /// assert!(abs_difference <= f16::EPSILON);
605    /// # }
606    /// ```
607    ///
608    /// Non-positive values:
609    /// ```
610    /// #![feature(f16)]
611    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
612    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
613    /// # #[cfg(not(miri))]
614    /// # #[cfg(not(bootstrap))]
615    /// # #[cfg(target_has_reliable_f16_math)] {
616    ///
617    /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY);
618    /// assert!((-42_f16).log(10.0).is_nan());
619    /// # }
620    /// ```
621    #[inline]
622    #[rustc_allow_incoherent_impl]
623    #[unstable(feature = "f16", issue = "116909")]
624    #[must_use = "method returns a new number and does not mutate the original value"]
625    pub fn log(self, base: f16) -> f16 {
626        self.ln() / base.ln()
627    }
628
629    /// Returns the base 2 logarithm of the number.
630    ///
631    /// This returns NaN when the number is negative, and negative infinity when number is zero.
632    ///
633    /// # Unspecified precision
634    ///
635    /// The precision of this function is non-deterministic. This means it varies by platform,
636    /// Rust version, and can even differ within the same execution from one invocation to the next.
637    ///
638    /// # Examples
639    ///
640    /// ```
641    /// #![feature(f16)]
642    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
643    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
644    /// # #[cfg(not(miri))]
645    /// # #[cfg(not(bootstrap))]
646    /// # #[cfg(target_has_reliable_f16_math)] {
647    ///
648    /// let two = 2.0f16;
649    ///
650    /// // log2(2) - 1 == 0
651    /// let abs_difference = (two.log2() - 1.0).abs();
652    ///
653    /// assert!(abs_difference <= f16::EPSILON);
654    /// # }
655    /// ```
656    ///
657    /// Non-positive values:
658    /// ```
659    /// #![feature(f16)]
660    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
661    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
662    /// # #[cfg(not(miri))]
663    /// # #[cfg(not(bootstrap))]
664    /// # #[cfg(target_has_reliable_f16_math)] {
665    ///
666    /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY);
667    /// assert!((-42_f16).log2().is_nan());
668    /// # }
669    /// ```
670    #[inline]
671    #[rustc_allow_incoherent_impl]
672    #[unstable(feature = "f16", issue = "116909")]
673    #[must_use = "method returns a new number and does not mutate the original value"]
674    pub fn log2(self) -> f16 {
675        unsafe { intrinsics::log2f16(self) }
676    }
677
678    /// Returns the base 10 logarithm of the number.
679    ///
680    /// This returns NaN when the number is negative, and negative infinity when number is zero.
681    ///
682    /// # Unspecified precision
683    ///
684    /// The precision of this function is non-deterministic. This means it varies by platform,
685    /// Rust version, and can even differ within the same execution from one invocation to the next.
686    ///
687    /// # Examples
688    ///
689    /// ```
690    /// #![feature(f16)]
691    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
692    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
693    /// # #[cfg(not(miri))]
694    /// # #[cfg(not(bootstrap))]
695    /// # #[cfg(target_has_reliable_f16_math)] {
696    ///
697    /// let ten = 10.0f16;
698    ///
699    /// // log10(10) - 1 == 0
700    /// let abs_difference = (ten.log10() - 1.0).abs();
701    ///
702    /// assert!(abs_difference <= f16::EPSILON);
703    /// # }
704    /// ```
705    ///
706    /// Non-positive values:
707    /// ```
708    /// #![feature(f16)]
709    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
710    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
711    /// # #[cfg(not(miri))]
712    /// # #[cfg(not(bootstrap))]
713    /// # #[cfg(target_has_reliable_f16_math)] {
714    ///
715    /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY);
716    /// assert!((-42_f16).log10().is_nan());
717    /// # }
718    /// ```
719    #[inline]
720    #[rustc_allow_incoherent_impl]
721    #[unstable(feature = "f16", issue = "116909")]
722    #[must_use = "method returns a new number and does not mutate the original value"]
723    pub fn log10(self) -> f16 {
724        unsafe { intrinsics::log10f16(self) }
725    }
726
727    /// Returns the cube root of a number.
728    ///
729    /// # Unspecified precision
730    ///
731    /// The precision of this function is non-deterministic. This means it varies by platform,
732    /// Rust version, and can even differ within the same execution from one invocation to the next.
733    ///
734    /// This function currently corresponds to the `cbrtf` from libc on Unix
735    /// and Windows. Note that this might change in the future.
736    ///
737    /// # Examples
738    ///
739    /// ```
740    /// #![feature(f16)]
741    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
742    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
743    /// # #[cfg(not(miri))]
744    /// # #[cfg(not(bootstrap))]
745    /// # #[cfg(target_has_reliable_f16_math)] {
746    ///
747    /// let x = 8.0f16;
748    ///
749    /// // x^(1/3) - 2 == 0
750    /// let abs_difference = (x.cbrt() - 2.0).abs();
751    ///
752    /// assert!(abs_difference <= f16::EPSILON);
753    /// # }
754    /// ```
755    #[inline]
756    #[rustc_allow_incoherent_impl]
757    #[unstable(feature = "f16", issue = "116909")]
758    #[must_use = "method returns a new number and does not mutate the original value"]
759    pub fn cbrt(self) -> f16 {
760        cmath::cbrtf(self as f32) as f16
761    }
762
763    /// Compute the distance between the origin and a point (`x`, `y`) on the
764    /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
765    /// right-angle triangle with other sides having length `x.abs()` and
766    /// `y.abs()`.
767    ///
768    /// # Unspecified precision
769    ///
770    /// The precision of this function is non-deterministic. This means it varies by platform,
771    /// Rust version, and can even differ within the same execution from one invocation to the next.
772    ///
773    /// This function currently corresponds to the `hypotf` from libc on Unix
774    /// and Windows. Note that this might change in the future.
775    ///
776    /// # Examples
777    ///
778    /// ```
779    /// #![feature(f16)]
780    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
781    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
782    /// # #[cfg(not(miri))]
783    /// # #[cfg(not(bootstrap))]
784    /// # #[cfg(target_has_reliable_f16_math)] {
785    ///
786    /// let x = 2.0f16;
787    /// let y = 3.0f16;
788    ///
789    /// // sqrt(x^2 + y^2)
790    /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
791    ///
792    /// assert!(abs_difference <= f16::EPSILON);
793    /// # }
794    /// ```
795    #[inline]
796    #[rustc_allow_incoherent_impl]
797    #[unstable(feature = "f16", issue = "116909")]
798    #[must_use = "method returns a new number and does not mutate the original value"]
799    pub fn hypot(self, other: f16) -> f16 {
800        cmath::hypotf(self as f32, other as f32) as f16
801    }
802
803    /// Computes the sine of a number (in radians).
804    ///
805    /// # Unspecified precision
806    ///
807    /// The precision of this function is non-deterministic. This means it varies by platform,
808    /// Rust version, and can even differ within the same execution from one invocation to the next.
809    ///
810    /// # Examples
811    ///
812    /// ```
813    /// #![feature(f16)]
814    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
815    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
816    /// # #[cfg(not(miri))]
817    /// # #[cfg(not(bootstrap))]
818    /// # #[cfg(target_has_reliable_f16_math)] {
819    ///
820    /// let x = std::f16::consts::FRAC_PI_2;
821    ///
822    /// let abs_difference = (x.sin() - 1.0).abs();
823    ///
824    /// assert!(abs_difference <= f16::EPSILON);
825    /// # }
826    /// ```
827    #[inline]
828    #[rustc_allow_incoherent_impl]
829    #[unstable(feature = "f16", issue = "116909")]
830    #[must_use = "method returns a new number and does not mutate the original value"]
831    pub fn sin(self) -> f16 {
832        unsafe { intrinsics::sinf16(self) }
833    }
834
835    /// Computes the cosine of a number (in radians).
836    ///
837    /// # Unspecified precision
838    ///
839    /// The precision of this function is non-deterministic. This means it varies by platform,
840    /// Rust version, and can even differ within the same execution from one invocation to the next.
841    ///
842    /// # Examples
843    ///
844    /// ```
845    /// #![feature(f16)]
846    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
847    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
848    /// # #[cfg(not(miri))]
849    /// # #[cfg(not(bootstrap))]
850    /// # #[cfg(target_has_reliable_f16_math)] {
851    ///
852    /// let x = 2.0 * std::f16::consts::PI;
853    ///
854    /// let abs_difference = (x.cos() - 1.0).abs();
855    ///
856    /// assert!(abs_difference <= f16::EPSILON);
857    /// # }
858    /// ```
859    #[inline]
860    #[rustc_allow_incoherent_impl]
861    #[unstable(feature = "f16", issue = "116909")]
862    #[must_use = "method returns a new number and does not mutate the original value"]
863    pub fn cos(self) -> f16 {
864        unsafe { intrinsics::cosf16(self) }
865    }
866
867    /// Computes the tangent of a number (in radians).
868    ///
869    /// # Unspecified precision
870    ///
871    /// The precision of this function is non-deterministic. This means it varies by platform,
872    /// Rust version, and can even differ within the same execution from one invocation to the next.
873    ///
874    /// This function currently corresponds to the `tanf` from libc on Unix and
875    /// Windows. Note that this might change in the future.
876    ///
877    /// # Examples
878    ///
879    /// ```
880    /// #![feature(f16)]
881    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
882    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
883    /// # #[cfg(not(miri))]
884    /// # #[cfg(not(bootstrap))]
885    /// # #[cfg(target_has_reliable_f16_math)] {
886    ///
887    /// let x = std::f16::consts::FRAC_PI_4;
888    /// let abs_difference = (x.tan() - 1.0).abs();
889    ///
890    /// assert!(abs_difference <= f16::EPSILON);
891    /// # }
892    /// ```
893    #[inline]
894    #[rustc_allow_incoherent_impl]
895    #[unstable(feature = "f16", issue = "116909")]
896    #[must_use = "method returns a new number and does not mutate the original value"]
897    pub fn tan(self) -> f16 {
898        cmath::tanf(self as f32) as f16
899    }
900
901    /// Computes the arcsine of a number. Return value is in radians in
902    /// the range [-pi/2, pi/2] or NaN if the number is outside the range
903    /// [-1, 1].
904    ///
905    /// # Unspecified precision
906    ///
907    /// The precision of this function is non-deterministic. This means it varies by platform,
908    /// Rust version, and can even differ within the same execution from one invocation to the next.
909    ///
910    /// This function currently corresponds to the `asinf` from libc on Unix
911    /// and Windows. Note that this might change in the future.
912    ///
913    /// # Examples
914    ///
915    /// ```
916    /// #![feature(f16)]
917    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
918    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
919    /// # #[cfg(not(miri))]
920    /// # #[cfg(not(bootstrap))]
921    /// # #[cfg(target_has_reliable_f16_math)] {
922    ///
923    /// let f = std::f16::consts::FRAC_PI_2;
924    ///
925    /// // asin(sin(pi/2))
926    /// let abs_difference = (f.sin().asin() - std::f16::consts::FRAC_PI_2).abs();
927    ///
928    /// assert!(abs_difference <= f16::EPSILON);
929    /// # }
930    /// ```
931    #[inline]
932    #[doc(alias = "arcsin")]
933    #[rustc_allow_incoherent_impl]
934    #[unstable(feature = "f16", issue = "116909")]
935    #[must_use = "method returns a new number and does not mutate the original value"]
936    pub fn asin(self) -> f16 {
937        cmath::asinf(self as f32) as f16
938    }
939
940    /// Computes the arccosine of a number. Return value is in radians in
941    /// the range [0, pi] or NaN if the number is outside the range
942    /// [-1, 1].
943    ///
944    /// # Unspecified precision
945    ///
946    /// The precision of this function is non-deterministic. This means it varies by platform,
947    /// Rust version, and can even differ within the same execution from one invocation to the next.
948    ///
949    /// This function currently corresponds to the `acosf` from libc on Unix
950    /// and Windows. Note that this might change in the future.
951    ///
952    /// # Examples
953    ///
954    /// ```
955    /// #![feature(f16)]
956    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
957    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
958    /// # #[cfg(not(miri))]
959    /// # #[cfg(not(bootstrap))]
960    /// # #[cfg(target_has_reliable_f16_math)] {
961    ///
962    /// let f = std::f16::consts::FRAC_PI_4;
963    ///
964    /// // acos(cos(pi/4))
965    /// let abs_difference = (f.cos().acos() - std::f16::consts::FRAC_PI_4).abs();
966    ///
967    /// assert!(abs_difference <= f16::EPSILON);
968    /// # }
969    /// ```
970    #[inline]
971    #[doc(alias = "arccos")]
972    #[rustc_allow_incoherent_impl]
973    #[unstable(feature = "f16", issue = "116909")]
974    #[must_use = "method returns a new number and does not mutate the original value"]
975    pub fn acos(self) -> f16 {
976        cmath::acosf(self as f32) as f16
977    }
978
979    /// Computes the arctangent of a number. Return value is in radians in the
980    /// range [-pi/2, pi/2];
981    ///
982    /// # Unspecified precision
983    ///
984    /// The precision of this function is non-deterministic. This means it varies by platform,
985    /// Rust version, and can even differ within the same execution from one invocation to the next.
986    ///
987    /// This function currently corresponds to the `atanf` from libc on Unix
988    /// and Windows. Note that this might change in the future.
989    ///
990    /// # Examples
991    ///
992    /// ```
993    /// #![feature(f16)]
994    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
995    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
996    /// # #[cfg(not(miri))]
997    /// # #[cfg(not(bootstrap))]
998    /// # #[cfg(target_has_reliable_f16_math)] {
999    ///
1000    /// let f = 1.0f16;
1001    ///
1002    /// // atan(tan(1))
1003    /// let abs_difference = (f.tan().atan() - 1.0).abs();
1004    ///
1005    /// assert!(abs_difference <= f16::EPSILON);
1006    /// # }
1007    /// ```
1008    #[inline]
1009    #[doc(alias = "arctan")]
1010    #[rustc_allow_incoherent_impl]
1011    #[unstable(feature = "f16", issue = "116909")]
1012    #[must_use = "method returns a new number and does not mutate the original value"]
1013    pub fn atan(self) -> f16 {
1014        cmath::atanf(self as f32) as f16
1015    }
1016
1017    /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
1018    ///
1019    /// * `x = 0`, `y = 0`: `0`
1020    /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
1021    /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
1022    /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
1023    ///
1024    /// # Unspecified precision
1025    ///
1026    /// The precision of this function is non-deterministic. This means it varies by platform,
1027    /// Rust version, and can even differ within the same execution from one invocation to the next.
1028    ///
1029    /// This function currently corresponds to the `atan2f` from libc on Unix
1030    /// and Windows. Note that this might change in the future.
1031    ///
1032    /// # Examples
1033    ///
1034    /// ```
1035    /// #![feature(f16)]
1036    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1037    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1038    /// # #[cfg(not(miri))]
1039    /// # #[cfg(not(bootstrap))]
1040    /// # #[cfg(target_has_reliable_f16_math)] {
1041    ///
1042    /// // Positive angles measured counter-clockwise
1043    /// // from positive x axis
1044    /// // -pi/4 radians (45 deg clockwise)
1045    /// let x1 = 3.0f16;
1046    /// let y1 = -3.0f16;
1047    ///
1048    /// // 3pi/4 radians (135 deg counter-clockwise)
1049    /// let x2 = -3.0f16;
1050    /// let y2 = 3.0f16;
1051    ///
1052    /// let abs_difference_1 = (y1.atan2(x1) - (-std::f16::consts::FRAC_PI_4)).abs();
1053    /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f16::consts::FRAC_PI_4)).abs();
1054    ///
1055    /// assert!(abs_difference_1 <= f16::EPSILON);
1056    /// assert!(abs_difference_2 <= f16::EPSILON);
1057    /// # }
1058    /// ```
1059    #[inline]
1060    #[rustc_allow_incoherent_impl]
1061    #[unstable(feature = "f16", issue = "116909")]
1062    #[must_use = "method returns a new number and does not mutate the original value"]
1063    pub fn atan2(self, other: f16) -> f16 {
1064        cmath::atan2f(self as f32, other as f32) as f16
1065    }
1066
1067    /// Simultaneously computes the sine and cosine of the number, `x`. Returns
1068    /// `(sin(x), cos(x))`.
1069    ///
1070    /// # Unspecified precision
1071    ///
1072    /// The precision of this function is non-deterministic. This means it varies by platform,
1073    /// Rust version, and can even differ within the same execution from one invocation to the next.
1074    ///
1075    /// This function currently corresponds to the `(f16::sin(x),
1076    /// f16::cos(x))`. Note that this might change in the future.
1077    ///
1078    /// # Examples
1079    ///
1080    /// ```
1081    /// #![feature(f16)]
1082    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1083    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1084    /// # #[cfg(not(miri))]
1085    /// # #[cfg(not(bootstrap))]
1086    /// # #[cfg(target_has_reliable_f16_math)] {
1087    ///
1088    /// let x = std::f16::consts::FRAC_PI_4;
1089    /// let f = x.sin_cos();
1090    ///
1091    /// let abs_difference_0 = (f.0 - x.sin()).abs();
1092    /// let abs_difference_1 = (f.1 - x.cos()).abs();
1093    ///
1094    /// assert!(abs_difference_0 <= f16::EPSILON);
1095    /// assert!(abs_difference_1 <= f16::EPSILON);
1096    /// # }
1097    /// ```
1098    #[inline]
1099    #[doc(alias = "sincos")]
1100    #[rustc_allow_incoherent_impl]
1101    #[unstable(feature = "f16", issue = "116909")]
1102    pub fn sin_cos(self) -> (f16, f16) {
1103        (self.sin(), self.cos())
1104    }
1105
1106    /// Returns `e^(self) - 1` in a way that is accurate even if the
1107    /// number is close to zero.
1108    ///
1109    /// # Unspecified precision
1110    ///
1111    /// The precision of this function is non-deterministic. This means it varies by platform,
1112    /// Rust version, and can even differ within the same execution from one invocation to the next.
1113    ///
1114    /// This function currently corresponds to the `expm1f` from libc on Unix
1115    /// and Windows. Note that this might change in the future.
1116    ///
1117    /// # Examples
1118    ///
1119    /// ```
1120    /// #![feature(f16)]
1121    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1122    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1123    /// # #[cfg(not(miri))]
1124    /// # #[cfg(not(bootstrap))]
1125    /// # #[cfg(target_has_reliable_f16_math)] {
1126    ///
1127    /// let x = 1e-4_f16;
1128    ///
1129    /// // for very small x, e^x is approximately 1 + x + x^2 / 2
1130    /// let approx = x + x * x / 2.0;
1131    /// let abs_difference = (x.exp_m1() - approx).abs();
1132    ///
1133    /// assert!(abs_difference < 1e-4);
1134    /// # }
1135    /// ```
1136    #[inline]
1137    #[rustc_allow_incoherent_impl]
1138    #[unstable(feature = "f16", issue = "116909")]
1139    #[must_use = "method returns a new number and does not mutate the original value"]
1140    pub fn exp_m1(self) -> f16 {
1141        cmath::expm1f(self as f32) as f16
1142    }
1143
1144    /// Returns `ln(1+n)` (natural logarithm) more accurately than if
1145    /// the operations were performed separately.
1146    ///
1147    /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`.
1148    ///
1149    /// # Unspecified precision
1150    ///
1151    /// The precision of this function is non-deterministic. This means it varies by platform,
1152    /// Rust version, and can even differ within the same execution from one invocation to the next.
1153    ///
1154    /// This function currently corresponds to the `log1pf` from libc on Unix
1155    /// and Windows. Note that this might change in the future.
1156    ///
1157    /// # Examples
1158    ///
1159    /// ```
1160    /// #![feature(f16)]
1161    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1162    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1163    /// # #[cfg(not(miri))]
1164    /// # #[cfg(not(bootstrap))]
1165    /// # #[cfg(target_has_reliable_f16_math)] {
1166    ///
1167    /// let x = 1e-4_f16;
1168    ///
1169    /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
1170    /// let approx = x - x * x / 2.0;
1171    /// let abs_difference = (x.ln_1p() - approx).abs();
1172    ///
1173    /// assert!(abs_difference < 1e-4);
1174    /// # }
1175    /// ```
1176    ///
1177    /// Out-of-range values:
1178    /// ```
1179    /// #![feature(f16)]
1180    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1181    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1182    /// # #[cfg(not(miri))]
1183    /// # #[cfg(not(bootstrap))]
1184    /// # #[cfg(target_has_reliable_f16_math)] {
1185    ///
1186    /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
1187    /// assert!((-2.0_f16).ln_1p().is_nan());
1188    /// # }
1189    /// ```
1190    #[inline]
1191    #[doc(alias = "log1p")]
1192    #[rustc_allow_incoherent_impl]
1193    #[unstable(feature = "f16", issue = "116909")]
1194    #[must_use = "method returns a new number and does not mutate the original value"]
1195    pub fn ln_1p(self) -> f16 {
1196        cmath::log1pf(self as f32) as f16
1197    }
1198
1199    /// Hyperbolic sine function.
1200    ///
1201    /// # Unspecified precision
1202    ///
1203    /// The precision of this function is non-deterministic. This means it varies by platform,
1204    /// Rust version, and can even differ within the same execution from one invocation to the next.
1205    ///
1206    /// This function currently corresponds to the `sinhf` from libc on Unix
1207    /// and Windows. Note that this might change in the future.
1208    ///
1209    /// # Examples
1210    ///
1211    /// ```
1212    /// #![feature(f16)]
1213    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1214    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1215    /// # #[cfg(not(miri))]
1216    /// # #[cfg(not(bootstrap))]
1217    /// # #[cfg(target_has_reliable_f16_math)] {
1218    ///
1219    /// let e = std::f16::consts::E;
1220    /// let x = 1.0f16;
1221    ///
1222    /// let f = x.sinh();
1223    /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
1224    /// let g = ((e * e) - 1.0) / (2.0 * e);
1225    /// let abs_difference = (f - g).abs();
1226    ///
1227    /// assert!(abs_difference <= f16::EPSILON);
1228    /// # }
1229    /// ```
1230    #[inline]
1231    #[rustc_allow_incoherent_impl]
1232    #[unstable(feature = "f16", issue = "116909")]
1233    #[must_use = "method returns a new number and does not mutate the original value"]
1234    pub fn sinh(self) -> f16 {
1235        cmath::sinhf(self as f32) as f16
1236    }
1237
1238    /// Hyperbolic cosine function.
1239    ///
1240    /// # Unspecified precision
1241    ///
1242    /// The precision of this function is non-deterministic. This means it varies by platform,
1243    /// Rust version, and can even differ within the same execution from one invocation to the next.
1244    ///
1245    /// This function currently corresponds to the `coshf` from libc on Unix
1246    /// and Windows. Note that this might change in the future.
1247    ///
1248    /// # Examples
1249    ///
1250    /// ```
1251    /// #![feature(f16)]
1252    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1253    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1254    /// # #[cfg(not(miri))]
1255    /// # #[cfg(not(bootstrap))]
1256    /// # #[cfg(target_has_reliable_f16_math)] {
1257    ///
1258    /// let e = std::f16::consts::E;
1259    /// let x = 1.0f16;
1260    /// let f = x.cosh();
1261    /// // Solving cosh() at 1 gives this result
1262    /// let g = ((e * e) + 1.0) / (2.0 * e);
1263    /// let abs_difference = (f - g).abs();
1264    ///
1265    /// // Same result
1266    /// assert!(abs_difference <= f16::EPSILON);
1267    /// # }
1268    /// ```
1269    #[inline]
1270    #[rustc_allow_incoherent_impl]
1271    #[unstable(feature = "f16", issue = "116909")]
1272    #[must_use = "method returns a new number and does not mutate the original value"]
1273    pub fn cosh(self) -> f16 {
1274        cmath::coshf(self as f32) as f16
1275    }
1276
1277    /// Hyperbolic tangent function.
1278    ///
1279    /// # Unspecified precision
1280    ///
1281    /// The precision of this function is non-deterministic. This means it varies by platform,
1282    /// Rust version, and can even differ within the same execution from one invocation to the next.
1283    ///
1284    /// This function currently corresponds to the `tanhf` from libc on Unix
1285    /// and Windows. Note that this might change in the future.
1286    ///
1287    /// # Examples
1288    ///
1289    /// ```
1290    /// #![feature(f16)]
1291    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1292    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1293    /// # #[cfg(not(miri))]
1294    /// # #[cfg(not(bootstrap))]
1295    /// # #[cfg(target_has_reliable_f16_math)] {
1296    ///
1297    /// let e = std::f16::consts::E;
1298    /// let x = 1.0f16;
1299    ///
1300    /// let f = x.tanh();
1301    /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
1302    /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
1303    /// let abs_difference = (f - g).abs();
1304    ///
1305    /// assert!(abs_difference <= f16::EPSILON);
1306    /// # }
1307    /// ```
1308    #[inline]
1309    #[rustc_allow_incoherent_impl]
1310    #[unstable(feature = "f16", issue = "116909")]
1311    #[must_use = "method returns a new number and does not mutate the original value"]
1312    pub fn tanh(self) -> f16 {
1313        cmath::tanhf(self as f32) as f16
1314    }
1315
1316    /// Inverse hyperbolic sine function.
1317    ///
1318    /// # Unspecified precision
1319    ///
1320    /// The precision of this function is non-deterministic. This means it varies by platform,
1321    /// Rust version, and can even differ within the same execution from one invocation to the next.
1322    ///
1323    /// # Examples
1324    ///
1325    /// ```
1326    /// #![feature(f16)]
1327    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1328    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1329    /// # #[cfg(not(miri))]
1330    /// # #[cfg(not(bootstrap))]
1331    /// # #[cfg(target_has_reliable_f16_math)] {
1332    ///
1333    /// let x = 1.0f16;
1334    /// let f = x.sinh().asinh();
1335    ///
1336    /// let abs_difference = (f - x).abs();
1337    ///
1338    /// assert!(abs_difference <= f16::EPSILON);
1339    /// # }
1340    /// ```
1341    #[inline]
1342    #[doc(alias = "arcsinh")]
1343    #[rustc_allow_incoherent_impl]
1344    #[unstable(feature = "f16", issue = "116909")]
1345    #[must_use = "method returns a new number and does not mutate the original value"]
1346    pub fn asinh(self) -> f16 {
1347        let ax = self.abs();
1348        let ix = 1.0 / ax;
1349        (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
1350    }
1351
1352    /// Inverse hyperbolic cosine function.
1353    ///
1354    /// # Unspecified precision
1355    ///
1356    /// The precision of this function is non-deterministic. This means it varies by platform,
1357    /// Rust version, and can even differ within the same execution from one invocation to the next.
1358    ///
1359    /// # Examples
1360    ///
1361    /// ```
1362    /// #![feature(f16)]
1363    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1364    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1365    /// # #[cfg(not(miri))]
1366    /// # #[cfg(not(bootstrap))]
1367    /// # #[cfg(target_has_reliable_f16_math)] {
1368    ///
1369    /// let x = 1.0f16;
1370    /// let f = x.cosh().acosh();
1371    ///
1372    /// let abs_difference = (f - x).abs();
1373    ///
1374    /// assert!(abs_difference <= f16::EPSILON);
1375    /// # }
1376    /// ```
1377    #[inline]
1378    #[doc(alias = "arccosh")]
1379    #[rustc_allow_incoherent_impl]
1380    #[unstable(feature = "f16", issue = "116909")]
1381    #[must_use = "method returns a new number and does not mutate the original value"]
1382    pub fn acosh(self) -> f16 {
1383        if self < 1.0 {
1384            Self::NAN
1385        } else {
1386            (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
1387        }
1388    }
1389
1390    /// Inverse hyperbolic tangent function.
1391    ///
1392    /// # Unspecified precision
1393    ///
1394    /// The precision of this function is non-deterministic. This means it varies by platform,
1395    /// Rust version, and can even differ within the same execution from one invocation to the next.
1396    ///
1397    /// # Examples
1398    ///
1399    /// ```
1400    /// #![feature(f16)]
1401    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1402    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1403    /// # #[cfg(not(miri))]
1404    /// # #[cfg(not(bootstrap))]
1405    /// # #[cfg(target_has_reliable_f16_math)] {
1406    ///
1407    /// let e = std::f16::consts::E;
1408    /// let f = e.tanh().atanh();
1409    ///
1410    /// let abs_difference = (f - e).abs();
1411    ///
1412    /// assert!(abs_difference <= 0.01);
1413    /// # }
1414    /// ```
1415    #[inline]
1416    #[doc(alias = "arctanh")]
1417    #[rustc_allow_incoherent_impl]
1418    #[unstable(feature = "f16", issue = "116909")]
1419    #[must_use = "method returns a new number and does not mutate the original value"]
1420    pub fn atanh(self) -> f16 {
1421        0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
1422    }
1423
1424    /// Gamma function.
1425    ///
1426    /// # Unspecified precision
1427    ///
1428    /// The precision of this function is non-deterministic. This means it varies by platform,
1429    /// Rust version, and can even differ within the same execution from one invocation to the next.
1430    ///
1431    /// This function currently corresponds to the `tgammaf` from libc on Unix
1432    /// and Windows. Note that this might change in the future.
1433    ///
1434    /// # Examples
1435    ///
1436    /// ```
1437    /// #![feature(f16)]
1438    /// #![feature(float_gamma)]
1439    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1440    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1441    /// # #[cfg(not(miri))]
1442    /// # #[cfg(not(bootstrap))]
1443    /// # #[cfg(target_has_reliable_f16_math)] {
1444    ///
1445    /// let x = 5.0f16;
1446    ///
1447    /// let abs_difference = (x.gamma() - 24.0).abs();
1448    ///
1449    /// assert!(abs_difference <= f16::EPSILON);
1450    /// # }
1451    /// ```
1452    #[inline]
1453    #[rustc_allow_incoherent_impl]
1454    #[unstable(feature = "f16", issue = "116909")]
1455    // #[unstable(feature = "float_gamma", issue = "99842")]
1456    #[must_use = "method returns a new number and does not mutate the original value"]
1457    pub fn gamma(self) -> f16 {
1458        cmath::tgammaf(self as f32) as f16
1459    }
1460
1461    /// Natural logarithm of the absolute value of the gamma function
1462    ///
1463    /// The integer part of the tuple indicates the sign of the gamma function.
1464    ///
1465    /// # Unspecified precision
1466    ///
1467    /// The precision of this function is non-deterministic. This means it varies by platform,
1468    /// Rust version, and can even differ within the same execution from one invocation to the next.
1469    ///
1470    /// This function currently corresponds to the `lgamma_r` from libc on Unix
1471    /// and Windows. Note that this might change in the future.
1472    ///
1473    /// # Examples
1474    ///
1475    /// ```
1476    /// #![feature(f16)]
1477    /// #![feature(float_gamma)]
1478    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1479    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1480    /// # #[cfg(not(miri))]
1481    /// # #[cfg(not(bootstrap))]
1482    /// # #[cfg(target_has_reliable_f16_math)] {
1483    ///
1484    /// let x = 2.0f16;
1485    ///
1486    /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
1487    ///
1488    /// assert!(abs_difference <= f16::EPSILON);
1489    /// # }
1490    /// ```
1491    #[inline]
1492    #[rustc_allow_incoherent_impl]
1493    #[unstable(feature = "f16", issue = "116909")]
1494    // #[unstable(feature = "float_gamma", issue = "99842")]
1495    #[must_use = "method returns a new number and does not mutate the original value"]
1496    pub fn ln_gamma(self) -> (f16, i32) {
1497        let mut signgamp: i32 = 0;
1498        let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16;
1499        (x, signgamp)
1500    }
1501
1502    /// Error function.
1503    ///
1504    /// # Unspecified precision
1505    ///
1506    /// The precision of this function is non-deterministic. This means it varies by platform,
1507    /// Rust version, and can even differ within the same execution from one invocation to the next.
1508    ///
1509    /// This function currently corresponds to the `erff` from libc on Unix
1510    /// and Windows. Note that this might change in the future.
1511    ///
1512    /// # Examples
1513    ///
1514    /// ```
1515    /// #![feature(f16)]
1516    /// #![feature(float_erf)]
1517    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1518    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1519    /// # #[cfg(not(miri))]
1520    /// # #[cfg(not(bootstrap))]
1521    /// # #[cfg(target_has_reliable_f16_math)] {
1522    /// /// The error function relates what percent of a normal distribution lies
1523    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
1524    /// fn within_standard_deviations(x: f16) -> f16 {
1525    ///     (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
1526    /// }
1527    ///
1528    /// // 68% of a normal distribution is within one standard deviation
1529    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
1530    /// // 95% of a normal distribution is within two standard deviations
1531    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
1532    /// // 99.7% of a normal distribution is within three standard deviations
1533    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
1534    /// # }
1535    /// ```
1536    #[rustc_allow_incoherent_impl]
1537    #[must_use = "method returns a new number and does not mutate the original value"]
1538    #[unstable(feature = "f16", issue = "116909")]
1539    // #[unstable(feature = "float_erf", issue = "136321")]
1540    #[inline]
1541    pub fn erf(self) -> f16 {
1542        cmath::erff(self as f32) as f16
1543    }
1544
1545    /// Complementary error function.
1546    ///
1547    /// # Unspecified precision
1548    ///
1549    /// The precision of this function is non-deterministic. This means it varies by platform,
1550    /// Rust version, and can even differ within the same execution from one invocation to the next.
1551    ///
1552    /// This function currently corresponds to the `erfcf` from libc on Unix
1553    /// and Windows. Note that this might change in the future.
1554    ///
1555    /// # Examples
1556    ///
1557    /// ```
1558    /// #![feature(f16)]
1559    /// #![feature(float_erf)]
1560    /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1561    /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1562    /// # #[cfg(not(miri))]
1563    /// # #[cfg(not(bootstrap))]
1564    /// # #[cfg(target_has_reliable_f16_math)] {
1565    /// let x: f16 = 0.123;
1566    ///
1567    /// let one = x.erf() + x.erfc();
1568    /// let abs_difference = (one - 1.0).abs();
1569    ///
1570    /// assert!(abs_difference <= f16::EPSILON);
1571    /// # }
1572    /// ```
1573    #[rustc_allow_incoherent_impl]
1574    #[must_use = "method returns a new number and does not mutate the original value"]
1575    #[unstable(feature = "f16", issue = "116909")]
1576    // #[unstable(feature = "float_erf", issue = "136321")]
1577    #[inline]
1578    pub fn erfc(self) -> f16 {
1579        cmath::erfcf(self as f32) as f16
1580    }
1581}