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