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