malachite_base/num/arithmetic/
reciprocal.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{Reciprocal, ReciprocalAssign};
10
11macro_rules! impl_reciprocal {
12    ($t:ident) => {
13        impl Reciprocal for $t {
14            type Output = $t;
15
16            /// Takes the reciprocal of a floating-point number.
17            ///
18            /// $$
19            /// f(x) = 1/x+\varepsilon.
20            /// $$
21            /// Let $p$ be the precision of the input float (typically 24 for `f32`s and 53 for
22            /// `f64`s, unless the float is subnormal).
23            /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
24            ///   be 0.
25            /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
26            ///   2^{\lfloor\log_2 |1/x|\rfloor-p+1}$.
27            /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
28            ///   2^{\lfloor\log_2 |1/x|\rfloor-p}$.
29            ///
30            /// If the output has a precision, it is `prec`.
31            ///
32            /// Special cases:
33            /// - $f(\text{NaN})=\text{NaN}$
34            /// - $f(\infty)=0.0$
35            /// - $f(-\infty)=-0.0$
36            /// - $f(0.0)=\infty$
37            /// - $f(-0.0)=-\infty$
38            ///
39            /// # Worst-case complexity
40            /// Constant time and additional memory.
41            ///
42            /// # Examples
43            /// See [here](super::reciprocal#reciprocal).
44            #[inline]
45            fn reciprocal(self) -> $t {
46                1.0 / self
47            }
48        }
49
50        impl ReciprocalAssign for $t {
51            /// Takes the reciprocal of a floating-point number, in place.
52            ///
53            /// $x \gets 1/x+\varepsilon$. Let $p$ be the precision of the input float (typically 24
54            /// for `f32`s and 53 for `f64`s, unless the float is subnormal).
55            /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
56            ///   be 0.
57            /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
58            ///   2^{\lfloor\log_2 |1/x|\rfloor-p+1}$.
59            /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
60            ///   2^{\lfloor\log_2 |1/x|\rfloor-p}$.
61            ///
62            /// See the `reciprocal` documentation for information on special cases.
63            ///
64            /// # Worst-case complexity
65            /// Constant time and additional memory.
66            ///
67            /// # Examples
68            /// See [here](super::reciprocal#reciprocal_assign).
69            #[inline]
70            fn reciprocal_assign(&mut self) {
71                *self = 1.0 / *self;
72            }
73        }
74    };
75}
76apply_to_primitive_floats!(impl_reciprocal);