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 unsafe { 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 unsafe { 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 unsafe { 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 unsafe { 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 unsafe { 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 unsafe { 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 unsafe { 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 unsafe { 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_2;
436 ///
437 /// // asin(sin(pi/2))
438 /// let abs_difference = (f.sin().asin() - std::f16::consts::FRAC_PI_2).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 = 0`, `y = 0`: `0`
526 /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
527 /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
528 /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
529 ///
530 /// # Unspecified precision
531 ///
532 /// The precision of this function is non-deterministic. This means it varies by platform,
533 /// Rust version, and can even differ within the same execution from one invocation to the next.
534 ///
535 /// This function currently corresponds to the `atan2f` from libc on Unix
536 /// and Windows. Note that this might change in the future.
537 ///
538 /// # Examples
539 ///
540 /// ```
541 /// #![feature(f16)]
542 /// # #[cfg(not(miri))]
543 /// # #[cfg(target_has_reliable_f16_math)] {
544 ///
545 /// // Positive angles measured counter-clockwise
546 /// // from positive x axis
547 /// // -pi/4 radians (45 deg clockwise)
548 /// let x1 = 3.0f16;
549 /// let y1 = -3.0f16;
550 ///
551 /// // 3pi/4 radians (135 deg counter-clockwise)
552 /// let x2 = -3.0f16;
553 /// let y2 = 3.0f16;
554 ///
555 /// let abs_difference_1 = (y1.atan2(x1) - (-std::f16::consts::FRAC_PI_4)).abs();
556 /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f16::consts::FRAC_PI_4)).abs();
557 ///
558 /// assert!(abs_difference_1 <= f16::EPSILON);
559 /// assert!(abs_difference_2 <= f16::EPSILON);
560 /// # }
561 /// ```
562 #[inline]
563 #[rustc_allow_incoherent_impl]
564 #[unstable(feature = "f16", issue = "116909")]
565 #[must_use = "method returns a new number and does not mutate the original value"]
566 pub fn atan2(self, other: f16) -> f16 {
567 cmath::atan2f(self as f32, other as f32) as f16
568 }
569
570 /// Simultaneously computes the sine and cosine of the number, `x`. Returns
571 /// `(sin(x), cos(x))`.
572 ///
573 /// # Unspecified precision
574 ///
575 /// The precision of this function is non-deterministic. This means it varies by platform,
576 /// Rust version, and can even differ within the same execution from one invocation to the next.
577 ///
578 /// This function currently corresponds to the `(f16::sin(x),
579 /// f16::cos(x))`. Note that this might change in the future.
580 ///
581 /// # Examples
582 ///
583 /// ```
584 /// #![feature(f16)]
585 /// # #[cfg(not(miri))]
586 /// # #[cfg(target_has_reliable_f16_math)] {
587 ///
588 /// let x = std::f16::consts::FRAC_PI_4;
589 /// let f = x.sin_cos();
590 ///
591 /// let abs_difference_0 = (f.0 - x.sin()).abs();
592 /// let abs_difference_1 = (f.1 - x.cos()).abs();
593 ///
594 /// assert!(abs_difference_0 <= f16::EPSILON);
595 /// assert!(abs_difference_1 <= f16::EPSILON);
596 /// # }
597 /// ```
598 #[inline]
599 #[doc(alias = "sincos")]
600 #[rustc_allow_incoherent_impl]
601 #[unstable(feature = "f16", issue = "116909")]
602 pub fn sin_cos(self) -> (f16, f16) {
603 (self.sin(), self.cos())
604 }
605
606 /// Returns `e^(self) - 1` in a way that is accurate even if the
607 /// number is close to zero.
608 ///
609 /// # Unspecified precision
610 ///
611 /// The precision of this function is non-deterministic. This means it varies by platform,
612 /// Rust version, and can even differ within the same execution from one invocation to the next.
613 ///
614 /// This function currently corresponds to the `expm1f` from libc on Unix
615 /// and Windows. Note that this might change in the future.
616 ///
617 /// # Examples
618 ///
619 /// ```
620 /// #![feature(f16)]
621 /// # #[cfg(not(miri))]
622 /// # #[cfg(target_has_reliable_f16_math)] {
623 ///
624 /// let x = 1e-4_f16;
625 ///
626 /// // for very small x, e^x is approximately 1 + x + x^2 / 2
627 /// let approx = x + x * x / 2.0;
628 /// let abs_difference = (x.exp_m1() - approx).abs();
629 ///
630 /// assert!(abs_difference < 1e-4);
631 /// # }
632 /// ```
633 #[inline]
634 #[rustc_allow_incoherent_impl]
635 #[unstable(feature = "f16", issue = "116909")]
636 #[must_use = "method returns a new number and does not mutate the original value"]
637 pub fn exp_m1(self) -> f16 {
638 cmath::expm1f(self as f32) as f16
639 }
640
641 /// Returns `ln(1+n)` (natural logarithm) more accurately than if
642 /// the operations were performed separately.
643 ///
644 /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`.
645 ///
646 /// # Unspecified precision
647 ///
648 /// The precision of this function is non-deterministic. This means it varies by platform,
649 /// Rust version, and can even differ within the same execution from one invocation to the next.
650 ///
651 /// This function currently corresponds to the `log1pf` from libc on Unix
652 /// and Windows. Note that this might change in the future.
653 ///
654 /// # Examples
655 ///
656 /// ```
657 /// #![feature(f16)]
658 /// # #[cfg(not(miri))]
659 /// # #[cfg(target_has_reliable_f16_math)] {
660 ///
661 /// let x = 1e-4_f16;
662 ///
663 /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
664 /// let approx = x - x * x / 2.0;
665 /// let abs_difference = (x.ln_1p() - approx).abs();
666 ///
667 /// assert!(abs_difference < 1e-4);
668 /// # }
669 /// ```
670 ///
671 /// Out-of-range values:
672 /// ```
673 /// #![feature(f16)]
674 /// # #[cfg(not(miri))]
675 /// # #[cfg(target_has_reliable_f16_math)] {
676 ///
677 /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
678 /// assert!((-2.0_f16).ln_1p().is_nan());
679 /// # }
680 /// ```
681 #[inline]
682 #[doc(alias = "log1p")]
683 #[rustc_allow_incoherent_impl]
684 #[unstable(feature = "f16", issue = "116909")]
685 #[must_use = "method returns a new number and does not mutate the original value"]
686 pub fn ln_1p(self) -> f16 {
687 cmath::log1pf(self as f32) as f16
688 }
689
690 /// Hyperbolic sine function.
691 ///
692 /// # Unspecified precision
693 ///
694 /// The precision of this function is non-deterministic. This means it varies by platform,
695 /// Rust version, and can even differ within the same execution from one invocation to the next.
696 ///
697 /// This function currently corresponds to the `sinhf` from libc on Unix
698 /// and Windows. Note that this might change in the future.
699 ///
700 /// # Examples
701 ///
702 /// ```
703 /// #![feature(f16)]
704 /// # #[cfg(not(miri))]
705 /// # #[cfg(target_has_reliable_f16_math)] {
706 ///
707 /// let e = std::f16::consts::E;
708 /// let x = 1.0f16;
709 ///
710 /// let f = x.sinh();
711 /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
712 /// let g = ((e * e) - 1.0) / (2.0 * e);
713 /// let abs_difference = (f - g).abs();
714 ///
715 /// assert!(abs_difference <= f16::EPSILON);
716 /// # }
717 /// ```
718 #[inline]
719 #[rustc_allow_incoherent_impl]
720 #[unstable(feature = "f16", issue = "116909")]
721 #[must_use = "method returns a new number and does not mutate the original value"]
722 pub fn sinh(self) -> f16 {
723 cmath::sinhf(self as f32) as f16
724 }
725
726 /// Hyperbolic cosine function.
727 ///
728 /// # Unspecified precision
729 ///
730 /// The precision of this function is non-deterministic. This means it varies by platform,
731 /// Rust version, and can even differ within the same execution from one invocation to the next.
732 ///
733 /// This function currently corresponds to the `coshf` from libc on Unix
734 /// and Windows. Note that this might change in the future.
735 ///
736 /// # Examples
737 ///
738 /// ```
739 /// #![feature(f16)]
740 /// # #[cfg(not(miri))]
741 /// # #[cfg(target_has_reliable_f16_math)] {
742 ///
743 /// let e = std::f16::consts::E;
744 /// let x = 1.0f16;
745 /// let f = x.cosh();
746 /// // Solving cosh() at 1 gives this result
747 /// let g = ((e * e) + 1.0) / (2.0 * e);
748 /// let abs_difference = (f - g).abs();
749 ///
750 /// // Same result
751 /// assert!(abs_difference <= f16::EPSILON);
752 /// # }
753 /// ```
754 #[inline]
755 #[rustc_allow_incoherent_impl]
756 #[unstable(feature = "f16", issue = "116909")]
757 #[must_use = "method returns a new number and does not mutate the original value"]
758 pub fn cosh(self) -> f16 {
759 cmath::coshf(self as f32) as f16
760 }
761
762 /// Hyperbolic tangent function.
763 ///
764 /// # Unspecified precision
765 ///
766 /// The precision of this function is non-deterministic. This means it varies by platform,
767 /// Rust version, and can even differ within the same execution from one invocation to the next.
768 ///
769 /// This function currently corresponds to the `tanhf` from libc on Unix
770 /// and Windows. Note that this might change in the future.
771 ///
772 /// # Examples
773 ///
774 /// ```
775 /// #![feature(f16)]
776 /// # #[cfg(not(miri))]
777 /// # #[cfg(target_has_reliable_f16_math)] {
778 ///
779 /// let e = std::f16::consts::E;
780 /// let x = 1.0f16;
781 ///
782 /// let f = x.tanh();
783 /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
784 /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
785 /// let abs_difference = (f - g).abs();
786 ///
787 /// assert!(abs_difference <= f16::EPSILON);
788 /// # }
789 /// ```
790 #[inline]
791 #[rustc_allow_incoherent_impl]
792 #[unstable(feature = "f16", issue = "116909")]
793 #[must_use = "method returns a new number and does not mutate the original value"]
794 pub fn tanh(self) -> f16 {
795 cmath::tanhf(self as f32) as f16
796 }
797
798 /// Inverse hyperbolic sine function.
799 ///
800 /// # Unspecified precision
801 ///
802 /// The precision of this function is non-deterministic. This means it varies by platform,
803 /// Rust version, and can even differ within the same execution from one invocation to the next.
804 ///
805 /// # Examples
806 ///
807 /// ```
808 /// #![feature(f16)]
809 /// # #[cfg(not(miri))]
810 /// # #[cfg(target_has_reliable_f16_math)] {
811 ///
812 /// let x = 1.0f16;
813 /// let f = x.sinh().asinh();
814 ///
815 /// let abs_difference = (f - x).abs();
816 ///
817 /// assert!(abs_difference <= f16::EPSILON);
818 /// # }
819 /// ```
820 #[inline]
821 #[doc(alias = "arcsinh")]
822 #[rustc_allow_incoherent_impl]
823 #[unstable(feature = "f16", issue = "116909")]
824 #[must_use = "method returns a new number and does not mutate the original value"]
825 pub fn asinh(self) -> f16 {
826 let ax = self.abs();
827 let ix = 1.0 / ax;
828 (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
829 }
830
831 /// Inverse hyperbolic cosine function.
832 ///
833 /// # Unspecified precision
834 ///
835 /// The precision of this function is non-deterministic. This means it varies by platform,
836 /// Rust version, and can even differ within the same execution from one invocation to the next.
837 ///
838 /// # Examples
839 ///
840 /// ```
841 /// #![feature(f16)]
842 /// # #[cfg(not(miri))]
843 /// # #[cfg(target_has_reliable_f16_math)] {
844 ///
845 /// let x = 1.0f16;
846 /// let f = x.cosh().acosh();
847 ///
848 /// let abs_difference = (f - x).abs();
849 ///
850 /// assert!(abs_difference <= f16::EPSILON);
851 /// # }
852 /// ```
853 #[inline]
854 #[doc(alias = "arccosh")]
855 #[rustc_allow_incoherent_impl]
856 #[unstable(feature = "f16", issue = "116909")]
857 #[must_use = "method returns a new number and does not mutate the original value"]
858 pub fn acosh(self) -> f16 {
859 if self < 1.0 {
860 Self::NAN
861 } else {
862 (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
863 }
864 }
865
866 /// Inverse hyperbolic tangent function.
867 ///
868 /// # Unspecified precision
869 ///
870 /// The precision of this function is non-deterministic. This means it varies by platform,
871 /// Rust version, and can even differ within the same execution from one invocation to the next.
872 ///
873 /// # Examples
874 ///
875 /// ```
876 /// #![feature(f16)]
877 /// # #[cfg(not(miri))]
878 /// # #[cfg(target_has_reliable_f16_math)] {
879 ///
880 /// let e = std::f16::consts::E;
881 /// let f = e.tanh().atanh();
882 ///
883 /// let abs_difference = (f - e).abs();
884 ///
885 /// assert!(abs_difference <= 0.01);
886 /// # }
887 /// ```
888 #[inline]
889 #[doc(alias = "arctanh")]
890 #[rustc_allow_incoherent_impl]
891 #[unstable(feature = "f16", issue = "116909")]
892 #[must_use = "method returns a new number and does not mutate the original value"]
893 pub fn atanh(self) -> f16 {
894 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
895 }
896
897 /// Gamma function.
898 ///
899 /// # Unspecified precision
900 ///
901 /// The precision of this function is non-deterministic. This means it varies by platform,
902 /// Rust version, and can even differ within the same execution from one invocation to the next.
903 ///
904 /// This function currently corresponds to the `tgammaf` from libc on Unix
905 /// and Windows. Note that this might change in the future.
906 ///
907 /// # Examples
908 ///
909 /// ```
910 /// #![feature(f16)]
911 /// #![feature(float_gamma)]
912 /// # #[cfg(not(miri))]
913 /// # #[cfg(target_has_reliable_f16_math)] {
914 ///
915 /// let x = 5.0f16;
916 ///
917 /// let abs_difference = (x.gamma() - 24.0).abs();
918 ///
919 /// assert!(abs_difference <= f16::EPSILON);
920 /// # }
921 /// ```
922 #[inline]
923 #[rustc_allow_incoherent_impl]
924 #[unstable(feature = "f16", issue = "116909")]
925 // #[unstable(feature = "float_gamma", issue = "99842")]
926 #[must_use = "method returns a new number and does not mutate the original value"]
927 pub fn gamma(self) -> f16 {
928 cmath::tgammaf(self as f32) as f16
929 }
930
931 /// Natural logarithm of the absolute value of the gamma function
932 ///
933 /// The integer part of the tuple indicates the sign of the gamma function.
934 ///
935 /// # Unspecified precision
936 ///
937 /// The precision of this function is non-deterministic. This means it varies by platform,
938 /// Rust version, and can even differ within the same execution from one invocation to the next.
939 ///
940 /// This function currently corresponds to the `lgamma_r` from libc on Unix
941 /// and Windows. Note that this might change in the future.
942 ///
943 /// # Examples
944 ///
945 /// ```
946 /// #![feature(f16)]
947 /// #![feature(float_gamma)]
948 /// # #[cfg(not(miri))]
949 /// # #[cfg(target_has_reliable_f16_math)] {
950 ///
951 /// let x = 2.0f16;
952 ///
953 /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
954 ///
955 /// assert!(abs_difference <= f16::EPSILON);
956 /// # }
957 /// ```
958 #[inline]
959 #[rustc_allow_incoherent_impl]
960 #[unstable(feature = "f16", issue = "116909")]
961 // #[unstable(feature = "float_gamma", issue = "99842")]
962 #[must_use = "method returns a new number and does not mutate the original value"]
963 pub fn ln_gamma(self) -> (f16, i32) {
964 let mut signgamp: i32 = 0;
965 let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16;
966 (x, signgamp)
967 }
968
969 /// Error function.
970 ///
971 /// # Unspecified precision
972 ///
973 /// The precision of this function is non-deterministic. This means it varies by platform,
974 /// Rust version, and can even differ within the same execution from one invocation to the next.
975 ///
976 /// This function currently corresponds to the `erff` from libc on Unix
977 /// and Windows. Note that this might change in the future.
978 ///
979 /// # Examples
980 ///
981 /// ```
982 /// #![feature(f16)]
983 /// #![feature(float_erf)]
984 /// # #[cfg(not(miri))]
985 /// # #[cfg(target_has_reliable_f16_math)] {
986 /// /// The error function relates what percent of a normal distribution lies
987 /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
988 /// fn within_standard_deviations(x: f16) -> f16 {
989 /// (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
990 /// }
991 ///
992 /// // 68% of a normal distribution is within one standard deviation
993 /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
994 /// // 95% of a normal distribution is within two standard deviations
995 /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
996 /// // 99.7% of a normal distribution is within three standard deviations
997 /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
998 /// # }
999 /// ```
1000 #[rustc_allow_incoherent_impl]
1001 #[must_use = "method returns a new number and does not mutate the original value"]
1002 #[unstable(feature = "f16", issue = "116909")]
1003 // #[unstable(feature = "float_erf", issue = "136321")]
1004 #[inline]
1005 pub fn erf(self) -> f16 {
1006 cmath::erff(self as f32) as f16
1007 }
1008
1009 /// Complementary error function.
1010 ///
1011 /// # Unspecified precision
1012 ///
1013 /// The precision of this function is non-deterministic. This means it varies by platform,
1014 /// Rust version, and can even differ within the same execution from one invocation to the next.
1015 ///
1016 /// This function currently corresponds to the `erfcf` from libc on Unix
1017 /// and Windows. Note that this might change in the future.
1018 ///
1019 /// # Examples
1020 ///
1021 /// ```
1022 /// #![feature(f16)]
1023 /// #![feature(float_erf)]
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}