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