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}