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