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