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 /// Returns the largest integer less than or equal to `self`.
18 ///
19 /// This function always returns the precise result.
20 ///
21 /// # Examples
22 ///
23 /// ```
24 /// #![feature(f16)]
25 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
26 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
27 /// # #[cfg(not(miri))]
28 /// # #[cfg(not(bootstrap))]
29 /// # #[cfg(target_has_reliable_f16_math)] {
30 ///
31 /// let f = 3.7_f16;
32 /// let g = 3.0_f16;
33 /// let h = -3.7_f16;
34 ///
35 /// assert_eq!(f.floor(), 3.0);
36 /// assert_eq!(g.floor(), 3.0);
37 /// assert_eq!(h.floor(), -4.0);
38 /// # }
39 /// ```
40 #[inline]
41 #[rustc_allow_incoherent_impl]
42 #[unstable(feature = "f16", issue = "116909")]
43 #[must_use = "method returns a new number and does not mutate the original value"]
44 pub fn floor(self) -> f16 {
45 unsafe { intrinsics::floorf16(self) }
46 }
47
48 /// Returns the smallest integer greater than or equal to `self`.
49 ///
50 /// This function always returns the precise result.
51 ///
52 /// # Examples
53 ///
54 /// ```
55 /// #![feature(f16)]
56 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
57 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
58 /// # #[cfg(not(miri))]
59 /// # #[cfg(not(bootstrap))]
60 /// # #[cfg(target_has_reliable_f16_math)] {
61 ///
62 /// let f = 3.01_f16;
63 /// let g = 4.0_f16;
64 ///
65 /// assert_eq!(f.ceil(), 4.0);
66 /// assert_eq!(g.ceil(), 4.0);
67 /// # }
68 /// ```
69 #[inline]
70 #[doc(alias = "ceiling")]
71 #[rustc_allow_incoherent_impl]
72 #[unstable(feature = "f16", issue = "116909")]
73 #[must_use = "method returns a new number and does not mutate the original value"]
74 pub fn ceil(self) -> f16 {
75 unsafe { intrinsics::ceilf16(self) }
76 }
77
78 /// Returns the nearest integer to `self`. If a value is half-way between two
79 /// integers, round away from `0.0`.
80 ///
81 /// This function always returns the precise result.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// #![feature(f16)]
87 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
88 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
89 /// # #[cfg(not(miri))]
90 /// # #[cfg(not(bootstrap))]
91 /// # #[cfg(target_has_reliable_f16_math)] {
92 ///
93 /// let f = 3.3_f16;
94 /// let g = -3.3_f16;
95 /// let h = -3.7_f16;
96 /// let i = 3.5_f16;
97 /// let j = 4.5_f16;
98 ///
99 /// assert_eq!(f.round(), 3.0);
100 /// assert_eq!(g.round(), -3.0);
101 /// assert_eq!(h.round(), -4.0);
102 /// assert_eq!(i.round(), 4.0);
103 /// assert_eq!(j.round(), 5.0);
104 /// # }
105 /// ```
106 #[inline]
107 #[rustc_allow_incoherent_impl]
108 #[unstable(feature = "f16", issue = "116909")]
109 #[must_use = "method returns a new number and does not mutate the original value"]
110 pub fn round(self) -> f16 {
111 unsafe { intrinsics::roundf16(self) }
112 }
113
114 /// Returns the nearest integer to a number. Rounds half-way cases to the number
115 /// with an even least significant digit.
116 ///
117 /// This function always returns the precise result.
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// #![feature(f16)]
123 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
124 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
125 /// # #[cfg(not(miri))]
126 /// # #[cfg(not(bootstrap))]
127 /// # #[cfg(target_has_reliable_f16_math)] {
128 ///
129 /// let f = 3.3_f16;
130 /// let g = -3.3_f16;
131 /// let h = 3.5_f16;
132 /// let i = 4.5_f16;
133 ///
134 /// assert_eq!(f.round_ties_even(), 3.0);
135 /// assert_eq!(g.round_ties_even(), -3.0);
136 /// assert_eq!(h.round_ties_even(), 4.0);
137 /// assert_eq!(i.round_ties_even(), 4.0);
138 /// # }
139 /// ```
140 #[inline]
141 #[rustc_allow_incoherent_impl]
142 #[unstable(feature = "f16", issue = "116909")]
143 #[must_use = "method returns a new number and does not mutate the original value"]
144 pub fn round_ties_even(self) -> f16 {
145 intrinsics::round_ties_even_f16(self)
146 }
147
148 /// Returns the integer part of `self`.
149 /// This means that non-integer numbers are always truncated towards zero.
150 ///
151 /// This function always returns the precise result.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// #![feature(f16)]
157 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
158 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
159 /// # #[cfg(not(miri))]
160 /// # #[cfg(not(bootstrap))]
161 /// # #[cfg(target_has_reliable_f16_math)] {
162 ///
163 /// let f = 3.7_f16;
164 /// let g = 3.0_f16;
165 /// let h = -3.7_f16;
166 ///
167 /// assert_eq!(f.trunc(), 3.0);
168 /// assert_eq!(g.trunc(), 3.0);
169 /// assert_eq!(h.trunc(), -3.0);
170 /// # }
171 /// ```
172 #[inline]
173 #[doc(alias = "truncate")]
174 #[rustc_allow_incoherent_impl]
175 #[unstable(feature = "f16", issue = "116909")]
176 #[must_use = "method returns a new number and does not mutate the original value"]
177 pub fn trunc(self) -> f16 {
178 unsafe { intrinsics::truncf16(self) }
179 }
180
181 /// Returns the fractional part of `self`.
182 ///
183 /// This function always returns the precise result.
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// #![feature(f16)]
189 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
190 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
191 /// # #[cfg(not(miri))]
192 /// # #[cfg(not(bootstrap))]
193 /// # #[cfg(target_has_reliable_f16_math)] {
194 ///
195 /// let x = 3.6_f16;
196 /// let y = -3.6_f16;
197 /// let abs_difference_x = (x.fract() - 0.6).abs();
198 /// let abs_difference_y = (y.fract() - (-0.6)).abs();
199 ///
200 /// assert!(abs_difference_x <= f16::EPSILON);
201 /// assert!(abs_difference_y <= f16::EPSILON);
202 /// # }
203 /// ```
204 #[inline]
205 #[rustc_allow_incoherent_impl]
206 #[unstable(feature = "f16", issue = "116909")]
207 #[must_use = "method returns a new number and does not mutate the original value"]
208 pub fn fract(self) -> f16 {
209 self - self.trunc()
210 }
211
212 /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
213 /// error, yielding a more accurate result than an unfused multiply-add.
214 ///
215 /// Using `mul_add` *may* be more performant than an unfused multiply-add if
216 /// the target architecture has a dedicated `fma` CPU instruction. However,
217 /// this is not always true, and will be heavily dependant on designing
218 /// algorithms with specific target hardware in mind.
219 ///
220 /// # Precision
221 ///
222 /// The result of this operation is guaranteed to be the rounded
223 /// infinite-precision result. It is specified by IEEE 754 as
224 /// `fusedMultiplyAdd` and guaranteed not to change.
225 ///
226 /// # Examples
227 ///
228 /// ```
229 /// #![feature(f16)]
230 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
231 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
232 /// # #[cfg(not(miri))]
233 /// # #[cfg(not(bootstrap))]
234 /// # #[cfg(target_has_reliable_f16_math)] {
235 ///
236 /// let m = 10.0_f16;
237 /// let x = 4.0_f16;
238 /// let b = 60.0_f16;
239 ///
240 /// assert_eq!(m.mul_add(x, b), 100.0);
241 /// assert_eq!(m * x + b, 100.0);
242 ///
243 /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
244 /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
245 /// let minus_one = -1.0_f16;
246 ///
247 /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
248 /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
249 /// // Different rounding with the non-fused multiply and add.
250 /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
251 /// # }
252 /// ```
253 #[inline]
254 #[rustc_allow_incoherent_impl]
255 #[unstable(feature = "f16", issue = "116909")]
256 #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")]
257 #[must_use = "method returns a new number and does not mutate the original value"]
258 pub fn mul_add(self, a: f16, b: f16) -> f16 {
259 unsafe { intrinsics::fmaf16(self, a, b) }
260 }
261
262 /// Calculates Euclidean division, the matching method for `rem_euclid`.
263 ///
264 /// This computes the integer `n` such that
265 /// `self = n * rhs + self.rem_euclid(rhs)`.
266 /// In other words, the result is `self / rhs` rounded to the integer `n`
267 /// such that `self >= n * rhs`.
268 ///
269 /// # Precision
270 ///
271 /// The result of this operation is guaranteed to be the rounded
272 /// infinite-precision result.
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// #![feature(f16)]
278 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
279 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
280 /// # #[cfg(not(miri))]
281 /// # #[cfg(not(bootstrap))]
282 /// # #[cfg(target_has_reliable_f16_math)] {
283 ///
284 /// let a: f16 = 7.0;
285 /// let b = 4.0;
286 /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
287 /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
288 /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
289 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
290 /// # }
291 /// ```
292 #[inline]
293 #[rustc_allow_incoherent_impl]
294 #[unstable(feature = "f16", issue = "116909")]
295 #[must_use = "method returns a new number and does not mutate the original value"]
296 pub fn div_euclid(self, rhs: f16) -> f16 {
297 let q = (self / rhs).trunc();
298 if self % rhs < 0.0 {
299 return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
300 }
301 q
302 }
303
304 /// Calculates the least nonnegative remainder of `self (mod rhs)`.
305 ///
306 /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
307 /// most cases. However, due to a floating point round-off error it can
308 /// result in `r == rhs.abs()`, violating the mathematical definition, if
309 /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
310 /// This result is not an element of the function's codomain, but it is the
311 /// closest floating point number in the real numbers and thus fulfills the
312 /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
313 /// approximately.
314 ///
315 /// # Precision
316 ///
317 /// The result of this operation is guaranteed to be the rounded
318 /// infinite-precision result.
319 ///
320 /// # Examples
321 ///
322 /// ```
323 /// #![feature(f16)]
324 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
325 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
326 /// # #[cfg(not(miri))]
327 /// # #[cfg(not(bootstrap))]
328 /// # #[cfg(target_has_reliable_f16_math)] {
329 ///
330 /// let a: f16 = 7.0;
331 /// let b = 4.0;
332 /// assert_eq!(a.rem_euclid(b), 3.0);
333 /// assert_eq!((-a).rem_euclid(b), 1.0);
334 /// assert_eq!(a.rem_euclid(-b), 3.0);
335 /// assert_eq!((-a).rem_euclid(-b), 1.0);
336 /// // limitation due to round-off error
337 /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
338 /// # }
339 /// ```
340 #[inline]
341 #[rustc_allow_incoherent_impl]
342 #[doc(alias = "modulo", alias = "mod")]
343 #[unstable(feature = "f16", issue = "116909")]
344 #[must_use = "method returns a new number and does not mutate the original value"]
345 pub fn rem_euclid(self, rhs: f16) -> f16 {
346 let r = self % rhs;
347 if r < 0.0 { r + rhs.abs() } else { r }
348 }
349
350 /// Raises a number to an integer power.
351 ///
352 /// Using this function is generally faster than using `powf`.
353 /// It might have a different sequence of rounding operations than `powf`,
354 /// so the results are not guaranteed to agree.
355 ///
356 /// # Unspecified precision
357 ///
358 /// The precision of this function is non-deterministic. This means it varies by platform,
359 /// Rust version, and can even differ within the same execution from one invocation to the next.
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// #![feature(f16)]
365 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
366 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
367 /// # #[cfg(not(miri))]
368 /// # #[cfg(not(bootstrap))]
369 /// # #[cfg(target_has_reliable_f16_math)] {
370 ///
371 /// let x = 2.0_f16;
372 /// let abs_difference = (x.powi(2) - (x * x)).abs();
373 /// assert!(abs_difference <= f16::EPSILON);
374 ///
375 /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
376 /// # }
377 /// ```
378 #[inline]
379 #[rustc_allow_incoherent_impl]
380 #[unstable(feature = "f16", issue = "116909")]
381 #[must_use = "method returns a new number and does not mutate the original value"]
382 pub fn powi(self, n: i32) -> f16 {
383 unsafe { intrinsics::powif16(self, n) }
384 }
385
386 /// Raises a number to a floating point power.
387 ///
388 /// # Unspecified precision
389 ///
390 /// The precision of this function is non-deterministic. This means it varies by platform,
391 /// Rust version, and can even differ within the same execution from one invocation to the next.
392 ///
393 /// # Examples
394 ///
395 /// ```
396 /// #![feature(f16)]
397 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
398 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
399 /// # #[cfg(not(miri))]
400 /// # #[cfg(not(bootstrap))]
401 /// # #[cfg(target_has_reliable_f16_math)] {
402 ///
403 /// let x = 2.0_f16;
404 /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
405 /// assert!(abs_difference <= f16::EPSILON);
406 ///
407 /// assert_eq!(f16::powf(1.0, f16::NAN), 1.0);
408 /// assert_eq!(f16::powf(f16::NAN, 0.0), 1.0);
409 /// # }
410 /// ```
411 #[inline]
412 #[rustc_allow_incoherent_impl]
413 #[unstable(feature = "f16", issue = "116909")]
414 #[must_use = "method returns a new number and does not mutate the original value"]
415 pub fn powf(self, n: f16) -> f16 {
416 unsafe { intrinsics::powf16(self, n) }
417 }
418
419 /// Returns the square root of a number.
420 ///
421 /// Returns NaN if `self` is a negative number other than `-0.0`.
422 ///
423 /// # Precision
424 ///
425 /// The result of this operation is guaranteed to be the rounded
426 /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
427 /// and guaranteed not to change.
428 ///
429 /// # Examples
430 ///
431 /// ```
432 /// #![feature(f16)]
433 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
434 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
435 /// # #[cfg(not(miri))]
436 /// # #[cfg(not(bootstrap))]
437 /// # #[cfg(target_has_reliable_f16_math)] {
438 ///
439 /// let positive = 4.0_f16;
440 /// let negative = -4.0_f16;
441 /// let negative_zero = -0.0_f16;
442 ///
443 /// assert_eq!(positive.sqrt(), 2.0);
444 /// assert!(negative.sqrt().is_nan());
445 /// assert!(negative_zero.sqrt() == negative_zero);
446 /// # }
447 /// ```
448 #[inline]
449 #[doc(alias = "squareRoot")]
450 #[rustc_allow_incoherent_impl]
451 #[unstable(feature = "f16", issue = "116909")]
452 #[must_use = "method returns a new number and does not mutate the original value"]
453 pub fn sqrt(self) -> f16 {
454 unsafe { intrinsics::sqrtf16(self) }
455 }
456
457 /// Returns `e^(self)`, (the exponential function).
458 ///
459 /// # Unspecified precision
460 ///
461 /// The precision of this function is non-deterministic. This means it varies by platform,
462 /// Rust version, and can even differ within the same execution from one invocation to the next.
463 ///
464 /// # Examples
465 ///
466 /// ```
467 /// #![feature(f16)]
468 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
469 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
470 /// # #[cfg(not(miri))]
471 /// # #[cfg(not(bootstrap))]
472 /// # #[cfg(target_has_reliable_f16_math)] {
473 ///
474 /// let one = 1.0f16;
475 /// // e^1
476 /// let e = one.exp();
477 ///
478 /// // ln(e) - 1 == 0
479 /// let abs_difference = (e.ln() - 1.0).abs();
480 ///
481 /// assert!(abs_difference <= f16::EPSILON);
482 /// # }
483 /// ```
484 #[inline]
485 #[rustc_allow_incoherent_impl]
486 #[unstable(feature = "f16", issue = "116909")]
487 #[must_use = "method returns a new number and does not mutate the original value"]
488 pub fn exp(self) -> f16 {
489 unsafe { intrinsics::expf16(self) }
490 }
491
492 /// Returns `2^(self)`.
493 ///
494 /// # Unspecified precision
495 ///
496 /// The precision of this function is non-deterministic. This means it varies by platform,
497 /// Rust version, and can even differ within the same execution from one invocation to the next.
498 ///
499 /// # Examples
500 ///
501 /// ```
502 /// #![feature(f16)]
503 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
504 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
505 /// # #[cfg(not(miri))]
506 /// # #[cfg(not(bootstrap))]
507 /// # #[cfg(target_has_reliable_f16_math)] {
508 ///
509 /// let f = 2.0f16;
510 ///
511 /// // 2^2 - 4 == 0
512 /// let abs_difference = (f.exp2() - 4.0).abs();
513 ///
514 /// assert!(abs_difference <= f16::EPSILON);
515 /// # }
516 /// ```
517 #[inline]
518 #[rustc_allow_incoherent_impl]
519 #[unstable(feature = "f16", issue = "116909")]
520 #[must_use = "method returns a new number and does not mutate the original value"]
521 pub fn exp2(self) -> f16 {
522 unsafe { intrinsics::exp2f16(self) }
523 }
524
525 /// Returns the natural logarithm of the number.
526 ///
527 /// This returns NaN when the number is negative, and negative infinity when number is zero.
528 ///
529 /// # Unspecified precision
530 ///
531 /// The precision of this function is non-deterministic. This means it varies by platform,
532 /// Rust version, and can even differ within the same execution from one invocation to the next.
533 ///
534 /// # Examples
535 ///
536 /// ```
537 /// #![feature(f16)]
538 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
539 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
540 /// # #[cfg(not(miri))]
541 /// # #[cfg(not(bootstrap))]
542 /// # #[cfg(target_has_reliable_f16_math)] {
543 ///
544 /// let one = 1.0f16;
545 /// // e^1
546 /// let e = one.exp();
547 ///
548 /// // ln(e) - 1 == 0
549 /// let abs_difference = (e.ln() - 1.0).abs();
550 ///
551 /// assert!(abs_difference <= f16::EPSILON);
552 /// # }
553 /// ```
554 ///
555 /// Non-positive values:
556 /// ```
557 /// #![feature(f16)]
558 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
559 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
560 /// # #[cfg(not(miri))]
561 /// # #[cfg(not(bootstrap))]
562 /// # #[cfg(target_has_reliable_f16_math)] {
563 ///
564 /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY);
565 /// assert!((-42_f16).ln().is_nan());
566 /// # }
567 /// ```
568 #[inline]
569 #[rustc_allow_incoherent_impl]
570 #[unstable(feature = "f16", issue = "116909")]
571 #[must_use = "method returns a new number and does not mutate the original value"]
572 pub fn ln(self) -> f16 {
573 unsafe { intrinsics::logf16(self) }
574 }
575
576 /// Returns the logarithm of the number with respect to an arbitrary base.
577 ///
578 /// This returns NaN when the number is negative, and negative infinity when number is zero.
579 ///
580 /// The result might not be correctly rounded owing to implementation details;
581 /// `self.log2()` can produce more accurate results for base 2, and
582 /// `self.log10()` can produce more accurate results for base 10.
583 ///
584 /// # Unspecified precision
585 ///
586 /// The precision of this function is non-deterministic. This means it varies by platform,
587 /// Rust version, and can even differ within the same execution from one invocation to the next.
588 ///
589 /// # Examples
590 ///
591 /// ```
592 /// #![feature(f16)]
593 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
594 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
595 /// # #[cfg(not(miri))]
596 /// # #[cfg(not(bootstrap))]
597 /// # #[cfg(target_has_reliable_f16_math)] {
598 ///
599 /// let five = 5.0f16;
600 ///
601 /// // log5(5) - 1 == 0
602 /// let abs_difference = (five.log(5.0) - 1.0).abs();
603 ///
604 /// assert!(abs_difference <= f16::EPSILON);
605 /// # }
606 /// ```
607 ///
608 /// Non-positive values:
609 /// ```
610 /// #![feature(f16)]
611 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
612 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
613 /// # #[cfg(not(miri))]
614 /// # #[cfg(not(bootstrap))]
615 /// # #[cfg(target_has_reliable_f16_math)] {
616 ///
617 /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY);
618 /// assert!((-42_f16).log(10.0).is_nan());
619 /// # }
620 /// ```
621 #[inline]
622 #[rustc_allow_incoherent_impl]
623 #[unstable(feature = "f16", issue = "116909")]
624 #[must_use = "method returns a new number and does not mutate the original value"]
625 pub fn log(self, base: f16) -> f16 {
626 self.ln() / base.ln()
627 }
628
629 /// Returns the base 2 logarithm of the number.
630 ///
631 /// This returns NaN when the number is negative, and negative infinity when number is zero.
632 ///
633 /// # Unspecified precision
634 ///
635 /// The precision of this function is non-deterministic. This means it varies by platform,
636 /// Rust version, and can even differ within the same execution from one invocation to the next.
637 ///
638 /// # Examples
639 ///
640 /// ```
641 /// #![feature(f16)]
642 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
643 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
644 /// # #[cfg(not(miri))]
645 /// # #[cfg(not(bootstrap))]
646 /// # #[cfg(target_has_reliable_f16_math)] {
647 ///
648 /// let two = 2.0f16;
649 ///
650 /// // log2(2) - 1 == 0
651 /// let abs_difference = (two.log2() - 1.0).abs();
652 ///
653 /// assert!(abs_difference <= f16::EPSILON);
654 /// # }
655 /// ```
656 ///
657 /// Non-positive values:
658 /// ```
659 /// #![feature(f16)]
660 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
661 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
662 /// # #[cfg(not(miri))]
663 /// # #[cfg(not(bootstrap))]
664 /// # #[cfg(target_has_reliable_f16_math)] {
665 ///
666 /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY);
667 /// assert!((-42_f16).log2().is_nan());
668 /// # }
669 /// ```
670 #[inline]
671 #[rustc_allow_incoherent_impl]
672 #[unstable(feature = "f16", issue = "116909")]
673 #[must_use = "method returns a new number and does not mutate the original value"]
674 pub fn log2(self) -> f16 {
675 unsafe { intrinsics::log2f16(self) }
676 }
677
678 /// Returns the base 10 logarithm of the number.
679 ///
680 /// This returns NaN when the number is negative, and negative infinity when number is zero.
681 ///
682 /// # Unspecified precision
683 ///
684 /// The precision of this function is non-deterministic. This means it varies by platform,
685 /// Rust version, and can even differ within the same execution from one invocation to the next.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// #![feature(f16)]
691 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
692 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
693 /// # #[cfg(not(miri))]
694 /// # #[cfg(not(bootstrap))]
695 /// # #[cfg(target_has_reliable_f16_math)] {
696 ///
697 /// let ten = 10.0f16;
698 ///
699 /// // log10(10) - 1 == 0
700 /// let abs_difference = (ten.log10() - 1.0).abs();
701 ///
702 /// assert!(abs_difference <= f16::EPSILON);
703 /// # }
704 /// ```
705 ///
706 /// Non-positive values:
707 /// ```
708 /// #![feature(f16)]
709 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
710 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
711 /// # #[cfg(not(miri))]
712 /// # #[cfg(not(bootstrap))]
713 /// # #[cfg(target_has_reliable_f16_math)] {
714 ///
715 /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY);
716 /// assert!((-42_f16).log10().is_nan());
717 /// # }
718 /// ```
719 #[inline]
720 #[rustc_allow_incoherent_impl]
721 #[unstable(feature = "f16", issue = "116909")]
722 #[must_use = "method returns a new number and does not mutate the original value"]
723 pub fn log10(self) -> f16 {
724 unsafe { intrinsics::log10f16(self) }
725 }
726
727 /// Returns the cube root of a number.
728 ///
729 /// # Unspecified precision
730 ///
731 /// The precision of this function is non-deterministic. This means it varies by platform,
732 /// Rust version, and can even differ within the same execution from one invocation to the next.
733 ///
734 /// This function currently corresponds to the `cbrtf` from libc on Unix
735 /// and Windows. Note that this might change in the future.
736 ///
737 /// # Examples
738 ///
739 /// ```
740 /// #![feature(f16)]
741 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
742 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
743 /// # #[cfg(not(miri))]
744 /// # #[cfg(not(bootstrap))]
745 /// # #[cfg(target_has_reliable_f16_math)] {
746 ///
747 /// let x = 8.0f16;
748 ///
749 /// // x^(1/3) - 2 == 0
750 /// let abs_difference = (x.cbrt() - 2.0).abs();
751 ///
752 /// assert!(abs_difference <= f16::EPSILON);
753 /// # }
754 /// ```
755 #[inline]
756 #[rustc_allow_incoherent_impl]
757 #[unstable(feature = "f16", issue = "116909")]
758 #[must_use = "method returns a new number and does not mutate the original value"]
759 pub fn cbrt(self) -> f16 {
760 cmath::cbrtf(self as f32) as f16
761 }
762
763 /// Compute the distance between the origin and a point (`x`, `y`) on the
764 /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
765 /// right-angle triangle with other sides having length `x.abs()` and
766 /// `y.abs()`.
767 ///
768 /// # Unspecified precision
769 ///
770 /// The precision of this function is non-deterministic. This means it varies by platform,
771 /// Rust version, and can even differ within the same execution from one invocation to the next.
772 ///
773 /// This function currently corresponds to the `hypotf` from libc on Unix
774 /// and Windows. Note that this might change in the future.
775 ///
776 /// # Examples
777 ///
778 /// ```
779 /// #![feature(f16)]
780 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
781 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
782 /// # #[cfg(not(miri))]
783 /// # #[cfg(not(bootstrap))]
784 /// # #[cfg(target_has_reliable_f16_math)] {
785 ///
786 /// let x = 2.0f16;
787 /// let y = 3.0f16;
788 ///
789 /// // sqrt(x^2 + y^2)
790 /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
791 ///
792 /// assert!(abs_difference <= f16::EPSILON);
793 /// # }
794 /// ```
795 #[inline]
796 #[rustc_allow_incoherent_impl]
797 #[unstable(feature = "f16", issue = "116909")]
798 #[must_use = "method returns a new number and does not mutate the original value"]
799 pub fn hypot(self, other: f16) -> f16 {
800 cmath::hypotf(self as f32, other as f32) as f16
801 }
802
803 /// Computes the sine of a number (in radians).
804 ///
805 /// # Unspecified precision
806 ///
807 /// The precision of this function is non-deterministic. This means it varies by platform,
808 /// Rust version, and can even differ within the same execution from one invocation to the next.
809 ///
810 /// # Examples
811 ///
812 /// ```
813 /// #![feature(f16)]
814 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
815 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
816 /// # #[cfg(not(miri))]
817 /// # #[cfg(not(bootstrap))]
818 /// # #[cfg(target_has_reliable_f16_math)] {
819 ///
820 /// let x = std::f16::consts::FRAC_PI_2;
821 ///
822 /// let abs_difference = (x.sin() - 1.0).abs();
823 ///
824 /// assert!(abs_difference <= f16::EPSILON);
825 /// # }
826 /// ```
827 #[inline]
828 #[rustc_allow_incoherent_impl]
829 #[unstable(feature = "f16", issue = "116909")]
830 #[must_use = "method returns a new number and does not mutate the original value"]
831 pub fn sin(self) -> f16 {
832 unsafe { intrinsics::sinf16(self) }
833 }
834
835 /// Computes the cosine of a number (in radians).
836 ///
837 /// # Unspecified precision
838 ///
839 /// The precision of this function is non-deterministic. This means it varies by platform,
840 /// Rust version, and can even differ within the same execution from one invocation to the next.
841 ///
842 /// # Examples
843 ///
844 /// ```
845 /// #![feature(f16)]
846 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
847 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
848 /// # #[cfg(not(miri))]
849 /// # #[cfg(not(bootstrap))]
850 /// # #[cfg(target_has_reliable_f16_math)] {
851 ///
852 /// let x = 2.0 * std::f16::consts::PI;
853 ///
854 /// let abs_difference = (x.cos() - 1.0).abs();
855 ///
856 /// assert!(abs_difference <= f16::EPSILON);
857 /// # }
858 /// ```
859 #[inline]
860 #[rustc_allow_incoherent_impl]
861 #[unstable(feature = "f16", issue = "116909")]
862 #[must_use = "method returns a new number and does not mutate the original value"]
863 pub fn cos(self) -> f16 {
864 unsafe { intrinsics::cosf16(self) }
865 }
866
867 /// Computes the tangent of a number (in radians).
868 ///
869 /// # Unspecified precision
870 ///
871 /// The precision of this function is non-deterministic. This means it varies by platform,
872 /// Rust version, and can even differ within the same execution from one invocation to the next.
873 ///
874 /// This function currently corresponds to the `tanf` from libc on Unix and
875 /// Windows. Note that this might change in the future.
876 ///
877 /// # Examples
878 ///
879 /// ```
880 /// #![feature(f16)]
881 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
882 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
883 /// # #[cfg(not(miri))]
884 /// # #[cfg(not(bootstrap))]
885 /// # #[cfg(target_has_reliable_f16_math)] {
886 ///
887 /// let x = std::f16::consts::FRAC_PI_4;
888 /// let abs_difference = (x.tan() - 1.0).abs();
889 ///
890 /// assert!(abs_difference <= f16::EPSILON);
891 /// # }
892 /// ```
893 #[inline]
894 #[rustc_allow_incoherent_impl]
895 #[unstable(feature = "f16", issue = "116909")]
896 #[must_use = "method returns a new number and does not mutate the original value"]
897 pub fn tan(self) -> f16 {
898 cmath::tanf(self as f32) as f16
899 }
900
901 /// Computes the arcsine of a number. Return value is in radians in
902 /// the range [-pi/2, pi/2] or NaN if the number is outside the range
903 /// [-1, 1].
904 ///
905 /// # Unspecified precision
906 ///
907 /// The precision of this function is non-deterministic. This means it varies by platform,
908 /// Rust version, and can even differ within the same execution from one invocation to the next.
909 ///
910 /// This function currently corresponds to the `asinf` from libc on Unix
911 /// and Windows. Note that this might change in the future.
912 ///
913 /// # Examples
914 ///
915 /// ```
916 /// #![feature(f16)]
917 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
918 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
919 /// # #[cfg(not(miri))]
920 /// # #[cfg(not(bootstrap))]
921 /// # #[cfg(target_has_reliable_f16_math)] {
922 ///
923 /// let f = std::f16::consts::FRAC_PI_2;
924 ///
925 /// // asin(sin(pi/2))
926 /// let abs_difference = (f.sin().asin() - std::f16::consts::FRAC_PI_2).abs();
927 ///
928 /// assert!(abs_difference <= f16::EPSILON);
929 /// # }
930 /// ```
931 #[inline]
932 #[doc(alias = "arcsin")]
933 #[rustc_allow_incoherent_impl]
934 #[unstable(feature = "f16", issue = "116909")]
935 #[must_use = "method returns a new number and does not mutate the original value"]
936 pub fn asin(self) -> f16 {
937 cmath::asinf(self as f32) as f16
938 }
939
940 /// Computes the arccosine of a number. Return value is in radians in
941 /// the range [0, pi] or NaN if the number is outside the range
942 /// [-1, 1].
943 ///
944 /// # Unspecified precision
945 ///
946 /// The precision of this function is non-deterministic. This means it varies by platform,
947 /// Rust version, and can even differ within the same execution from one invocation to the next.
948 ///
949 /// This function currently corresponds to the `acosf` from libc on Unix
950 /// and Windows. Note that this might change in the future.
951 ///
952 /// # Examples
953 ///
954 /// ```
955 /// #![feature(f16)]
956 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
957 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
958 /// # #[cfg(not(miri))]
959 /// # #[cfg(not(bootstrap))]
960 /// # #[cfg(target_has_reliable_f16_math)] {
961 ///
962 /// let f = std::f16::consts::FRAC_PI_4;
963 ///
964 /// // acos(cos(pi/4))
965 /// let abs_difference = (f.cos().acos() - std::f16::consts::FRAC_PI_4).abs();
966 ///
967 /// assert!(abs_difference <= f16::EPSILON);
968 /// # }
969 /// ```
970 #[inline]
971 #[doc(alias = "arccos")]
972 #[rustc_allow_incoherent_impl]
973 #[unstable(feature = "f16", issue = "116909")]
974 #[must_use = "method returns a new number and does not mutate the original value"]
975 pub fn acos(self) -> f16 {
976 cmath::acosf(self as f32) as f16
977 }
978
979 /// Computes the arctangent of a number. Return value is in radians in the
980 /// range [-pi/2, pi/2];
981 ///
982 /// # Unspecified precision
983 ///
984 /// The precision of this function is non-deterministic. This means it varies by platform,
985 /// Rust version, and can even differ within the same execution from one invocation to the next.
986 ///
987 /// This function currently corresponds to the `atanf` from libc on Unix
988 /// and Windows. Note that this might change in the future.
989 ///
990 /// # Examples
991 ///
992 /// ```
993 /// #![feature(f16)]
994 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
995 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
996 /// # #[cfg(not(miri))]
997 /// # #[cfg(not(bootstrap))]
998 /// # #[cfg(target_has_reliable_f16_math)] {
999 ///
1000 /// let f = 1.0f16;
1001 ///
1002 /// // atan(tan(1))
1003 /// let abs_difference = (f.tan().atan() - 1.0).abs();
1004 ///
1005 /// assert!(abs_difference <= f16::EPSILON);
1006 /// # }
1007 /// ```
1008 #[inline]
1009 #[doc(alias = "arctan")]
1010 #[rustc_allow_incoherent_impl]
1011 #[unstable(feature = "f16", issue = "116909")]
1012 #[must_use = "method returns a new number and does not mutate the original value"]
1013 pub fn atan(self) -> f16 {
1014 cmath::atanf(self as f32) as f16
1015 }
1016
1017 /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
1018 ///
1019 /// * `x = 0`, `y = 0`: `0`
1020 /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
1021 /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
1022 /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
1023 ///
1024 /// # Unspecified precision
1025 ///
1026 /// The precision of this function is non-deterministic. This means it varies by platform,
1027 /// Rust version, and can even differ within the same execution from one invocation to the next.
1028 ///
1029 /// This function currently corresponds to the `atan2f` from libc on Unix
1030 /// and Windows. Note that this might change in the future.
1031 ///
1032 /// # Examples
1033 ///
1034 /// ```
1035 /// #![feature(f16)]
1036 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1037 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1038 /// # #[cfg(not(miri))]
1039 /// # #[cfg(not(bootstrap))]
1040 /// # #[cfg(target_has_reliable_f16_math)] {
1041 ///
1042 /// // Positive angles measured counter-clockwise
1043 /// // from positive x axis
1044 /// // -pi/4 radians (45 deg clockwise)
1045 /// let x1 = 3.0f16;
1046 /// let y1 = -3.0f16;
1047 ///
1048 /// // 3pi/4 radians (135 deg counter-clockwise)
1049 /// let x2 = -3.0f16;
1050 /// let y2 = 3.0f16;
1051 ///
1052 /// let abs_difference_1 = (y1.atan2(x1) - (-std::f16::consts::FRAC_PI_4)).abs();
1053 /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f16::consts::FRAC_PI_4)).abs();
1054 ///
1055 /// assert!(abs_difference_1 <= f16::EPSILON);
1056 /// assert!(abs_difference_2 <= f16::EPSILON);
1057 /// # }
1058 /// ```
1059 #[inline]
1060 #[rustc_allow_incoherent_impl]
1061 #[unstable(feature = "f16", issue = "116909")]
1062 #[must_use = "method returns a new number and does not mutate the original value"]
1063 pub fn atan2(self, other: f16) -> f16 {
1064 cmath::atan2f(self as f32, other as f32) as f16
1065 }
1066
1067 /// Simultaneously computes the sine and cosine of the number, `x`. Returns
1068 /// `(sin(x), cos(x))`.
1069 ///
1070 /// # Unspecified precision
1071 ///
1072 /// The precision of this function is non-deterministic. This means it varies by platform,
1073 /// Rust version, and can even differ within the same execution from one invocation to the next.
1074 ///
1075 /// This function currently corresponds to the `(f16::sin(x),
1076 /// f16::cos(x))`. Note that this might change in the future.
1077 ///
1078 /// # Examples
1079 ///
1080 /// ```
1081 /// #![feature(f16)]
1082 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1083 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1084 /// # #[cfg(not(miri))]
1085 /// # #[cfg(not(bootstrap))]
1086 /// # #[cfg(target_has_reliable_f16_math)] {
1087 ///
1088 /// let x = std::f16::consts::FRAC_PI_4;
1089 /// let f = x.sin_cos();
1090 ///
1091 /// let abs_difference_0 = (f.0 - x.sin()).abs();
1092 /// let abs_difference_1 = (f.1 - x.cos()).abs();
1093 ///
1094 /// assert!(abs_difference_0 <= f16::EPSILON);
1095 /// assert!(abs_difference_1 <= f16::EPSILON);
1096 /// # }
1097 /// ```
1098 #[inline]
1099 #[doc(alias = "sincos")]
1100 #[rustc_allow_incoherent_impl]
1101 #[unstable(feature = "f16", issue = "116909")]
1102 pub fn sin_cos(self) -> (f16, f16) {
1103 (self.sin(), self.cos())
1104 }
1105
1106 /// Returns `e^(self) - 1` in a way that is accurate even if the
1107 /// number is close to zero.
1108 ///
1109 /// # Unspecified precision
1110 ///
1111 /// The precision of this function is non-deterministic. This means it varies by platform,
1112 /// Rust version, and can even differ within the same execution from one invocation to the next.
1113 ///
1114 /// This function currently corresponds to the `expm1f` from libc on Unix
1115 /// and Windows. Note that this might change in the future.
1116 ///
1117 /// # Examples
1118 ///
1119 /// ```
1120 /// #![feature(f16)]
1121 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1122 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1123 /// # #[cfg(not(miri))]
1124 /// # #[cfg(not(bootstrap))]
1125 /// # #[cfg(target_has_reliable_f16_math)] {
1126 ///
1127 /// let x = 1e-4_f16;
1128 ///
1129 /// // for very small x, e^x is approximately 1 + x + x^2 / 2
1130 /// let approx = x + x * x / 2.0;
1131 /// let abs_difference = (x.exp_m1() - approx).abs();
1132 ///
1133 /// assert!(abs_difference < 1e-4);
1134 /// # }
1135 /// ```
1136 #[inline]
1137 #[rustc_allow_incoherent_impl]
1138 #[unstable(feature = "f16", issue = "116909")]
1139 #[must_use = "method returns a new number and does not mutate the original value"]
1140 pub fn exp_m1(self) -> f16 {
1141 cmath::expm1f(self as f32) as f16
1142 }
1143
1144 /// Returns `ln(1+n)` (natural logarithm) more accurately than if
1145 /// the operations were performed separately.
1146 ///
1147 /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`.
1148 ///
1149 /// # Unspecified precision
1150 ///
1151 /// The precision of this function is non-deterministic. This means it varies by platform,
1152 /// Rust version, and can even differ within the same execution from one invocation to the next.
1153 ///
1154 /// This function currently corresponds to the `log1pf` from libc on Unix
1155 /// and Windows. Note that this might change in the future.
1156 ///
1157 /// # Examples
1158 ///
1159 /// ```
1160 /// #![feature(f16)]
1161 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1162 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1163 /// # #[cfg(not(miri))]
1164 /// # #[cfg(not(bootstrap))]
1165 /// # #[cfg(target_has_reliable_f16_math)] {
1166 ///
1167 /// let x = 1e-4_f16;
1168 ///
1169 /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
1170 /// let approx = x - x * x / 2.0;
1171 /// let abs_difference = (x.ln_1p() - approx).abs();
1172 ///
1173 /// assert!(abs_difference < 1e-4);
1174 /// # }
1175 /// ```
1176 ///
1177 /// Out-of-range values:
1178 /// ```
1179 /// #![feature(f16)]
1180 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1181 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1182 /// # #[cfg(not(miri))]
1183 /// # #[cfg(not(bootstrap))]
1184 /// # #[cfg(target_has_reliable_f16_math)] {
1185 ///
1186 /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
1187 /// assert!((-2.0_f16).ln_1p().is_nan());
1188 /// # }
1189 /// ```
1190 #[inline]
1191 #[doc(alias = "log1p")]
1192 #[rustc_allow_incoherent_impl]
1193 #[unstable(feature = "f16", issue = "116909")]
1194 #[must_use = "method returns a new number and does not mutate the original value"]
1195 pub fn ln_1p(self) -> f16 {
1196 cmath::log1pf(self as f32) as f16
1197 }
1198
1199 /// Hyperbolic sine function.
1200 ///
1201 /// # Unspecified precision
1202 ///
1203 /// The precision of this function is non-deterministic. This means it varies by platform,
1204 /// Rust version, and can even differ within the same execution from one invocation to the next.
1205 ///
1206 /// This function currently corresponds to the `sinhf` from libc on Unix
1207 /// and Windows. Note that this might change in the future.
1208 ///
1209 /// # Examples
1210 ///
1211 /// ```
1212 /// #![feature(f16)]
1213 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1214 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1215 /// # #[cfg(not(miri))]
1216 /// # #[cfg(not(bootstrap))]
1217 /// # #[cfg(target_has_reliable_f16_math)] {
1218 ///
1219 /// let e = std::f16::consts::E;
1220 /// let x = 1.0f16;
1221 ///
1222 /// let f = x.sinh();
1223 /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
1224 /// let g = ((e * e) - 1.0) / (2.0 * e);
1225 /// let abs_difference = (f - g).abs();
1226 ///
1227 /// assert!(abs_difference <= f16::EPSILON);
1228 /// # }
1229 /// ```
1230 #[inline]
1231 #[rustc_allow_incoherent_impl]
1232 #[unstable(feature = "f16", issue = "116909")]
1233 #[must_use = "method returns a new number and does not mutate the original value"]
1234 pub fn sinh(self) -> f16 {
1235 cmath::sinhf(self as f32) as f16
1236 }
1237
1238 /// Hyperbolic cosine function.
1239 ///
1240 /// # Unspecified precision
1241 ///
1242 /// The precision of this function is non-deterministic. This means it varies by platform,
1243 /// Rust version, and can even differ within the same execution from one invocation to the next.
1244 ///
1245 /// This function currently corresponds to the `coshf` from libc on Unix
1246 /// and Windows. Note that this might change in the future.
1247 ///
1248 /// # Examples
1249 ///
1250 /// ```
1251 /// #![feature(f16)]
1252 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1253 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1254 /// # #[cfg(not(miri))]
1255 /// # #[cfg(not(bootstrap))]
1256 /// # #[cfg(target_has_reliable_f16_math)] {
1257 ///
1258 /// let e = std::f16::consts::E;
1259 /// let x = 1.0f16;
1260 /// let f = x.cosh();
1261 /// // Solving cosh() at 1 gives this result
1262 /// let g = ((e * e) + 1.0) / (2.0 * e);
1263 /// let abs_difference = (f - g).abs();
1264 ///
1265 /// // Same result
1266 /// assert!(abs_difference <= f16::EPSILON);
1267 /// # }
1268 /// ```
1269 #[inline]
1270 #[rustc_allow_incoherent_impl]
1271 #[unstable(feature = "f16", issue = "116909")]
1272 #[must_use = "method returns a new number and does not mutate the original value"]
1273 pub fn cosh(self) -> f16 {
1274 cmath::coshf(self as f32) as f16
1275 }
1276
1277 /// Hyperbolic tangent function.
1278 ///
1279 /// # Unspecified precision
1280 ///
1281 /// The precision of this function is non-deterministic. This means it varies by platform,
1282 /// Rust version, and can even differ within the same execution from one invocation to the next.
1283 ///
1284 /// This function currently corresponds to the `tanhf` from libc on Unix
1285 /// and Windows. Note that this might change in the future.
1286 ///
1287 /// # Examples
1288 ///
1289 /// ```
1290 /// #![feature(f16)]
1291 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1292 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1293 /// # #[cfg(not(miri))]
1294 /// # #[cfg(not(bootstrap))]
1295 /// # #[cfg(target_has_reliable_f16_math)] {
1296 ///
1297 /// let e = std::f16::consts::E;
1298 /// let x = 1.0f16;
1299 ///
1300 /// let f = x.tanh();
1301 /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
1302 /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
1303 /// let abs_difference = (f - g).abs();
1304 ///
1305 /// assert!(abs_difference <= f16::EPSILON);
1306 /// # }
1307 /// ```
1308 #[inline]
1309 #[rustc_allow_incoherent_impl]
1310 #[unstable(feature = "f16", issue = "116909")]
1311 #[must_use = "method returns a new number and does not mutate the original value"]
1312 pub fn tanh(self) -> f16 {
1313 cmath::tanhf(self as f32) as f16
1314 }
1315
1316 /// Inverse hyperbolic sine function.
1317 ///
1318 /// # Unspecified precision
1319 ///
1320 /// The precision of this function is non-deterministic. This means it varies by platform,
1321 /// Rust version, and can even differ within the same execution from one invocation to the next.
1322 ///
1323 /// # Examples
1324 ///
1325 /// ```
1326 /// #![feature(f16)]
1327 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1328 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1329 /// # #[cfg(not(miri))]
1330 /// # #[cfg(not(bootstrap))]
1331 /// # #[cfg(target_has_reliable_f16_math)] {
1332 ///
1333 /// let x = 1.0f16;
1334 /// let f = x.sinh().asinh();
1335 ///
1336 /// let abs_difference = (f - x).abs();
1337 ///
1338 /// assert!(abs_difference <= f16::EPSILON);
1339 /// # }
1340 /// ```
1341 #[inline]
1342 #[doc(alias = "arcsinh")]
1343 #[rustc_allow_incoherent_impl]
1344 #[unstable(feature = "f16", issue = "116909")]
1345 #[must_use = "method returns a new number and does not mutate the original value"]
1346 pub fn asinh(self) -> f16 {
1347 let ax = self.abs();
1348 let ix = 1.0 / ax;
1349 (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
1350 }
1351
1352 /// Inverse hyperbolic cosine function.
1353 ///
1354 /// # Unspecified precision
1355 ///
1356 /// The precision of this function is non-deterministic. This means it varies by platform,
1357 /// Rust version, and can even differ within the same execution from one invocation to the next.
1358 ///
1359 /// # Examples
1360 ///
1361 /// ```
1362 /// #![feature(f16)]
1363 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1364 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1365 /// # #[cfg(not(miri))]
1366 /// # #[cfg(not(bootstrap))]
1367 /// # #[cfg(target_has_reliable_f16_math)] {
1368 ///
1369 /// let x = 1.0f16;
1370 /// let f = x.cosh().acosh();
1371 ///
1372 /// let abs_difference = (f - x).abs();
1373 ///
1374 /// assert!(abs_difference <= f16::EPSILON);
1375 /// # }
1376 /// ```
1377 #[inline]
1378 #[doc(alias = "arccosh")]
1379 #[rustc_allow_incoherent_impl]
1380 #[unstable(feature = "f16", issue = "116909")]
1381 #[must_use = "method returns a new number and does not mutate the original value"]
1382 pub fn acosh(self) -> f16 {
1383 if self < 1.0 {
1384 Self::NAN
1385 } else {
1386 (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
1387 }
1388 }
1389
1390 /// Inverse hyperbolic tangent function.
1391 ///
1392 /// # Unspecified precision
1393 ///
1394 /// The precision of this function is non-deterministic. This means it varies by platform,
1395 /// Rust version, and can even differ within the same execution from one invocation to the next.
1396 ///
1397 /// # Examples
1398 ///
1399 /// ```
1400 /// #![feature(f16)]
1401 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1402 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1403 /// # #[cfg(not(miri))]
1404 /// # #[cfg(not(bootstrap))]
1405 /// # #[cfg(target_has_reliable_f16_math)] {
1406 ///
1407 /// let e = std::f16::consts::E;
1408 /// let f = e.tanh().atanh();
1409 ///
1410 /// let abs_difference = (f - e).abs();
1411 ///
1412 /// assert!(abs_difference <= 0.01);
1413 /// # }
1414 /// ```
1415 #[inline]
1416 #[doc(alias = "arctanh")]
1417 #[rustc_allow_incoherent_impl]
1418 #[unstable(feature = "f16", issue = "116909")]
1419 #[must_use = "method returns a new number and does not mutate the original value"]
1420 pub fn atanh(self) -> f16 {
1421 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
1422 }
1423
1424 /// Gamma function.
1425 ///
1426 /// # Unspecified precision
1427 ///
1428 /// The precision of this function is non-deterministic. This means it varies by platform,
1429 /// Rust version, and can even differ within the same execution from one invocation to the next.
1430 ///
1431 /// This function currently corresponds to the `tgammaf` from libc on Unix
1432 /// and Windows. Note that this might change in the future.
1433 ///
1434 /// # Examples
1435 ///
1436 /// ```
1437 /// #![feature(f16)]
1438 /// #![feature(float_gamma)]
1439 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1440 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1441 /// # #[cfg(not(miri))]
1442 /// # #[cfg(not(bootstrap))]
1443 /// # #[cfg(target_has_reliable_f16_math)] {
1444 ///
1445 /// let x = 5.0f16;
1446 ///
1447 /// let abs_difference = (x.gamma() - 24.0).abs();
1448 ///
1449 /// assert!(abs_difference <= f16::EPSILON);
1450 /// # }
1451 /// ```
1452 #[inline]
1453 #[rustc_allow_incoherent_impl]
1454 #[unstable(feature = "f16", issue = "116909")]
1455 // #[unstable(feature = "float_gamma", issue = "99842")]
1456 #[must_use = "method returns a new number and does not mutate the original value"]
1457 pub fn gamma(self) -> f16 {
1458 cmath::tgammaf(self as f32) as f16
1459 }
1460
1461 /// Natural logarithm of the absolute value of the gamma function
1462 ///
1463 /// The integer part of the tuple indicates the sign of the gamma function.
1464 ///
1465 /// # Unspecified precision
1466 ///
1467 /// The precision of this function is non-deterministic. This means it varies by platform,
1468 /// Rust version, and can even differ within the same execution from one invocation to the next.
1469 ///
1470 /// This function currently corresponds to the `lgamma_r` from libc on Unix
1471 /// and Windows. Note that this might change in the future.
1472 ///
1473 /// # Examples
1474 ///
1475 /// ```
1476 /// #![feature(f16)]
1477 /// #![feature(float_gamma)]
1478 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1479 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1480 /// # #[cfg(not(miri))]
1481 /// # #[cfg(not(bootstrap))]
1482 /// # #[cfg(target_has_reliable_f16_math)] {
1483 ///
1484 /// let x = 2.0f16;
1485 ///
1486 /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
1487 ///
1488 /// assert!(abs_difference <= f16::EPSILON);
1489 /// # }
1490 /// ```
1491 #[inline]
1492 #[rustc_allow_incoherent_impl]
1493 #[unstable(feature = "f16", issue = "116909")]
1494 // #[unstable(feature = "float_gamma", issue = "99842")]
1495 #[must_use = "method returns a new number and does not mutate the original value"]
1496 pub fn ln_gamma(self) -> (f16, i32) {
1497 let mut signgamp: i32 = 0;
1498 let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16;
1499 (x, signgamp)
1500 }
1501
1502 /// Error function.
1503 ///
1504 /// # Unspecified precision
1505 ///
1506 /// The precision of this function is non-deterministic. This means it varies by platform,
1507 /// Rust version, and can even differ within the same execution from one invocation to the next.
1508 ///
1509 /// This function currently corresponds to the `erff` from libc on Unix
1510 /// and Windows. Note that this might change in the future.
1511 ///
1512 /// # Examples
1513 ///
1514 /// ```
1515 /// #![feature(f16)]
1516 /// #![feature(float_erf)]
1517 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1518 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1519 /// # #[cfg(not(miri))]
1520 /// # #[cfg(not(bootstrap))]
1521 /// # #[cfg(target_has_reliable_f16_math)] {
1522 /// /// The error function relates what percent of a normal distribution lies
1523 /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
1524 /// fn within_standard_deviations(x: f16) -> f16 {
1525 /// (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
1526 /// }
1527 ///
1528 /// // 68% of a normal distribution is within one standard deviation
1529 /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
1530 /// // 95% of a normal distribution is within two standard deviations
1531 /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
1532 /// // 99.7% of a normal distribution is within three standard deviations
1533 /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
1534 /// # }
1535 /// ```
1536 #[rustc_allow_incoherent_impl]
1537 #[must_use = "method returns a new number and does not mutate the original value"]
1538 #[unstable(feature = "f16", issue = "116909")]
1539 // #[unstable(feature = "float_erf", issue = "136321")]
1540 #[inline]
1541 pub fn erf(self) -> f16 {
1542 cmath::erff(self as f32) as f16
1543 }
1544
1545 /// Complementary error function.
1546 ///
1547 /// # Unspecified precision
1548 ///
1549 /// The precision of this function is non-deterministic. This means it varies by platform,
1550 /// Rust version, and can even differ within the same execution from one invocation to the next.
1551 ///
1552 /// This function currently corresponds to the `erfcf` from libc on Unix
1553 /// and Windows. Note that this might change in the future.
1554 ///
1555 /// # Examples
1556 ///
1557 /// ```
1558 /// #![feature(f16)]
1559 /// #![feature(float_erf)]
1560 /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
1561 /// # #![cfg_attr(not(bootstrap), expect(internal_features))]
1562 /// # #[cfg(not(miri))]
1563 /// # #[cfg(not(bootstrap))]
1564 /// # #[cfg(target_has_reliable_f16_math)] {
1565 /// let x: f16 = 0.123;
1566 ///
1567 /// let one = x.erf() + x.erfc();
1568 /// let abs_difference = (one - 1.0).abs();
1569 ///
1570 /// assert!(abs_difference <= f16::EPSILON);
1571 /// # }
1572 /// ```
1573 #[rustc_allow_incoherent_impl]
1574 #[must_use = "method returns a new number and does not mutate the original value"]
1575 #[unstable(feature = "f16", issue = "116909")]
1576 // #[unstable(feature = "float_erf", issue = "136321")]
1577 #[inline]
1578 pub fn erfc(self) -> f16 {
1579 cmath::erfcf(self as f32) as f16
1580 }
1581}