Skip to main content

std/num/
f16.rs

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