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