malachite_float/arithmetic/
abs.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::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{
11    Float, float_either_infinity, float_either_zero, float_infinity, float_nan,
12    float_negative_zero, float_zero,
13};
14use malachite_base::num::arithmetic::traits::{Abs, AbsAssign};
15
16impl Float {
17    /// If `self` is negative zero, returns positive zero; otherwise, returns `self`, taking `self`
18    /// by value.
19    ///
20    /// This function does not overflow or underflow.
21    ///
22    /// # Worst-case complexity
23    /// Constant time and additional memory.
24    ///
25    /// # Examples
26    /// ```
27    /// use malachite_base::num::basic::traits::{
28    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
29    /// };
30    /// use malachite_float::{ComparableFloat, Float};
31    ///
32    /// assert_eq!(
33    ///     ComparableFloat(Float::NAN.abs_negative_zero()),
34    ///     ComparableFloat(Float::NAN)
35    /// );
36    /// assert_eq!(Float::INFINITY.abs_negative_zero(), Float::INFINITY);
37    /// assert_eq!(
38    ///     Float::NEGATIVE_INFINITY.abs_negative_zero(),
39    ///     Float::NEGATIVE_INFINITY
40    /// );
41    /// assert_eq!(
42    ///     ComparableFloat(Float::ZERO.abs_negative_zero()),
43    ///     ComparableFloat(Float::ZERO)
44    /// );
45    /// assert_eq!(
46    ///     ComparableFloat(Float::NEGATIVE_ZERO.abs_negative_zero()),
47    ///     ComparableFloat(Float::ZERO)
48    /// );
49    /// assert_eq!(Float::ONE.abs_negative_zero(), Float::ONE);
50    /// assert_eq!(Float::NEGATIVE_ONE.abs_negative_zero(), Float::NEGATIVE_ONE);
51    /// ```
52    #[inline]
53    pub const fn abs_negative_zero(mut self) -> Self {
54        self.abs_negative_zero_assign();
55        self
56    }
57
58    /// If `self` is negative zero, returns positive zero; otherwise, returns `self`, taking `self`
59    /// by reference.
60    ///
61    /// This function does not overflow or underflow.
62    ///
63    /// # Worst-case complexity
64    /// $T(n) = O(n)$
65    ///
66    /// $M(n) = O(n)$
67    ///
68    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
69    ///
70    /// # Examples
71    /// ```
72    /// use malachite_base::num::basic::traits::{
73    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
74    /// };
75    /// use malachite_float::{ComparableFloat, Float};
76    ///
77    /// assert_eq!(
78    ///     ComparableFloat(Float::NAN.abs_negative_zero_ref()),
79    ///     ComparableFloat(Float::NAN)
80    /// );
81    /// assert_eq!(Float::INFINITY.abs_negative_zero_ref(), Float::INFINITY);
82    /// assert_eq!(
83    ///     Float::NEGATIVE_INFINITY.abs_negative_zero_ref(),
84    ///     Float::NEGATIVE_INFINITY
85    /// );
86    /// assert_eq!(
87    ///     ComparableFloat(Float::ZERO.abs_negative_zero_ref()),
88    ///     ComparableFloat(Float::ZERO)
89    /// );
90    /// assert_eq!(
91    ///     ComparableFloat(Float::NEGATIVE_ZERO.abs_negative_zero_ref()),
92    ///     ComparableFloat(Float::ZERO)
93    /// );
94    /// assert_eq!(Float::ONE.abs_negative_zero_ref(), Float::ONE);
95    /// assert_eq!(
96    ///     Float::NEGATIVE_ONE.abs_negative_zero_ref(),
97    ///     Float::NEGATIVE_ONE
98    /// );
99    /// ```
100    pub fn abs_negative_zero_ref(&self) -> Self {
101        match self {
102            float_negative_zero!() => float_zero!(),
103            x => x.clone(),
104        }
105    }
106
107    /// If `self` is negative zero, replaces it with positive zero; otherwise, does nothing.
108    ///
109    /// This function does not overflow or underflow.
110    ///
111    /// # Worst-case complexity
112    /// Constant time and additional memory.
113    ///
114    /// # Examples
115    /// ```
116    /// use malachite_base::num::basic::traits::{
117    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
118    /// };
119    /// use malachite_float::{ComparableFloat, Float};
120    ///
121    /// let mut x = Float::NAN;
122    /// x.abs_negative_zero_assign();
123    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN));
124    ///
125    /// let mut x = Float::INFINITY;
126    /// x.abs_negative_zero_assign();
127    /// assert_eq!(x, Float::INFINITY);
128    ///
129    /// let mut x = Float::NEGATIVE_INFINITY;
130    /// x.abs_negative_zero_assign();
131    /// assert_eq!(x, Float::NEGATIVE_INFINITY);
132    ///
133    /// let mut x = Float::ZERO;
134    /// x.abs_negative_zero_assign();
135    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO));
136    ///
137    /// let mut x = Float::NEGATIVE_ZERO;
138    /// x.abs_negative_zero_assign();
139    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO));
140    ///
141    /// let mut x = Float::ONE;
142    /// x.abs_negative_zero_assign();
143    /// assert_eq!(x, Float::ONE);
144    ///
145    /// let mut x = Float::NEGATIVE_ONE;
146    /// x.abs_negative_zero_assign();
147    /// assert_eq!(x, Float::NEGATIVE_ONE);
148    /// ```
149    pub const fn abs_negative_zero_assign(&mut self) {
150        if let Self(Zero { sign }) = self {
151            *sign = true;
152        }
153    }
154}
155
156impl Abs for Float {
157    type Output = Self;
158
159    /// Takes the absolute value of a [`Float`], taking the [`Float`] by value.
160    ///
161    /// $$
162    /// f(x) = |x|.
163    /// $$
164    ///
165    /// Special cases:
166    /// - $f(\text{NaN}) = \text{NaN}$
167    /// - $f(\infty) = f(-\infty) = \infty$
168    /// - $f(0.0) = f(-0.0) = 0.0$
169    ///
170    /// This function does not overflow or underflow.
171    ///
172    /// # Worst-case complexity
173    /// Constant time and additional memory.
174    ///
175    /// # Examples
176    /// ```
177    /// use malachite_base::num::arithmetic::traits::Abs;
178    /// use malachite_base::num::basic::traits::{
179    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
180    /// };
181    /// use malachite_float::{ComparableFloat, Float};
182    ///
183    /// assert_eq!(
184    ///     ComparableFloat(Float::NAN.abs()),
185    ///     ComparableFloat(Float::NAN)
186    /// );
187    /// assert_eq!(Float::INFINITY.abs(), Float::INFINITY);
188    /// assert_eq!(Float::NEGATIVE_INFINITY.abs(), Float::INFINITY);
189    /// assert_eq!(
190    ///     ComparableFloat(Float::ZERO.abs()),
191    ///     ComparableFloat(Float::ZERO)
192    /// );
193    /// assert_eq!(
194    ///     ComparableFloat(Float::NEGATIVE_ZERO.abs()),
195    ///     ComparableFloat(Float::ZERO)
196    /// );
197    /// assert_eq!(Float::ONE.abs(), Float::ONE);
198    /// assert_eq!(Float::NEGATIVE_ONE.abs(), Float::ONE);
199    /// ```
200    #[inline]
201    fn abs(mut self) -> Self {
202        self.abs_assign();
203        self
204    }
205}
206
207impl Abs for &Float {
208    type Output = Float;
209
210    /// Takes the absolute value of a [`Float`], taking the [`Float`] by reference.
211    ///
212    /// $$
213    /// f(x) = |x|.
214    /// $$
215    ///
216    /// Special cases:
217    /// - $f(\text{NaN}) = \text{NaN}$
218    /// - $f(\infty) = f(-\infty) = \infty$
219    /// - $f(0.0) = f(-0.0) = 0.0$
220    ///
221    /// This function does not overflow or underflow.
222    ///
223    /// # Worst-case complexity
224    /// $T(n) = O(n)$
225    ///
226    /// $M(n) = O(n)$
227    ///
228    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
229    ///
230    /// # Examples
231    /// ```
232    /// use malachite_base::num::arithmetic::traits::Abs;
233    /// use malachite_base::num::basic::traits::{
234    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
235    /// };
236    /// use malachite_float::{ComparableFloat, Float};
237    ///
238    /// assert_eq!(
239    ///     ComparableFloat((&Float::NAN).abs()),
240    ///     ComparableFloat(Float::NAN)
241    /// );
242    /// assert_eq!((&Float::INFINITY).abs(), Float::INFINITY);
243    /// assert_eq!((&Float::NEGATIVE_INFINITY).abs(), Float::INFINITY);
244    /// assert_eq!(
245    ///     ComparableFloat((&Float::ZERO).abs()),
246    ///     ComparableFloat(Float::ZERO)
247    /// );
248    /// assert_eq!(
249    ///     ComparableFloat((&Float::NEGATIVE_ZERO).abs()),
250    ///     ComparableFloat(Float::ZERO)
251    /// );
252    /// assert_eq!((&Float::ONE).abs(), Float::ONE);
253    /// assert_eq!((&Float::NEGATIVE_ONE).abs(), Float::ONE);
254    /// ```
255    fn abs(self) -> Float {
256        match self {
257            float_nan!() => float_nan!(),
258            float_either_infinity!() => float_infinity!(),
259            float_either_zero!() => float_zero!(),
260            Float(Finite {
261                exponent,
262                precision,
263                significand,
264                ..
265            }) => Float(Finite {
266                sign: true,
267                exponent: *exponent,
268                precision: *precision,
269                significand: significand.clone(),
270            }),
271        }
272    }
273}
274
275impl AbsAssign for Float {
276    /// Replaces a [`Float`] with its absolute value.
277    ///
278    /// $$
279    /// x \gets |x|.
280    /// $$
281    ///
282    /// Special cases:
283    /// - $\text{NaN} \gets \text{NaN}$
284    /// - $\infty \gets \infty$
285    /// - $-\infty \gets \infty$
286    /// - $0.0 \gets 0.0$
287    /// - $-0.0 \gets 0.0$
288    ///
289    /// This function does not overflow or underflow.
290    ///
291    /// # Worst-case complexity
292    /// Constant time and additional memory.
293    ///
294    /// # Examples
295    /// ```
296    /// use malachite_base::num::arithmetic::traits::AbsAssign;
297    /// use malachite_base::num::basic::traits::{
298    ///     Infinity, NaN, NegativeInfinity, NegativeOne, NegativeZero, One, Zero,
299    /// };
300    /// use malachite_float::{ComparableFloat, Float};
301    ///
302    /// let mut x = Float::NAN;
303    /// x.abs_assign();
304    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::NAN));
305    ///
306    /// let mut x = Float::INFINITY;
307    /// x.abs_assign();
308    /// assert_eq!(x, Float::INFINITY);
309    ///
310    /// let mut x = Float::NEGATIVE_INFINITY;
311    /// x.abs_assign();
312    /// assert_eq!(x, Float::INFINITY);
313    ///
314    /// let mut x = Float::ZERO;
315    /// x.abs_assign();
316    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO));
317    ///
318    /// let mut x = Float::NEGATIVE_ZERO;
319    /// x.abs_assign();
320    /// assert_eq!(ComparableFloat(x), ComparableFloat(Float::ZERO));
321    ///
322    /// let mut x = Float::ONE;
323    /// x.abs_assign();
324    /// assert_eq!(x, Float::ONE);
325    ///
326    /// let mut x = Float::NEGATIVE_ONE;
327    /// x.abs_assign();
328    /// assert_eq!(x, Float::ONE);
329    /// ```
330    fn abs_assign(&mut self) {
331        if let Self(Infinity { sign } | Zero { sign } | Finite { sign, .. }) = self {
332            *sign = true;
333        }
334    }
335}