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