malachite_nz/integer/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::integer::Integer;
10use crate::natural::Natural;
11use malachite_base::num::arithmetic::traits::{Abs, AbsAssign, UnsignedAbs};
12
13impl Abs for Integer {
14    type Output = Self;
15
16    /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by value.
17    ///
18    /// $$
19    /// f(x) = |x|.
20    /// $$
21    ///
22    /// # Worst-case complexity
23    /// Constant time and additional memory.
24    ///
25    /// # Examples
26    /// ```
27    /// use malachite_base::num::arithmetic::traits::Abs;
28    /// use malachite_base::num::basic::traits::Zero;
29    /// use malachite_nz::integer::Integer;
30    ///
31    /// assert_eq!(Integer::ZERO.abs(), 0);
32    /// assert_eq!(Integer::from(123).abs(), 123);
33    /// assert_eq!(Integer::from(-123).abs(), 123);
34    /// ```
35    #[inline]
36    fn abs(mut self) -> Self {
37        self.sign = true;
38        self
39    }
40}
41
42impl Abs for &Integer {
43    type Output = Integer;
44
45    /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by reference.
46    ///
47    /// $$
48    /// f(x) = |x|.
49    /// $$
50    ///
51    /// # Worst-case complexity
52    /// $T(n) = O(n)$
53    ///
54    /// $M(n) = O(n)$
55    ///
56    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
57    ///
58    /// # Examples
59    /// ```
60    /// use malachite_base::num::arithmetic::traits::Abs;
61    /// use malachite_base::num::basic::traits::Zero;
62    /// use malachite_nz::integer::Integer;
63    ///
64    /// assert_eq!((&Integer::ZERO).abs(), 0);
65    /// assert_eq!((&Integer::from(123)).abs(), 123);
66    /// assert_eq!((&Integer::from(-123)).abs(), 123);
67    /// ```
68    fn abs(self) -> Integer {
69        Integer {
70            sign: true,
71            abs: self.abs.clone(),
72        }
73    }
74}
75
76impl AbsAssign for Integer {
77    /// Replaces an [`Integer`] with its absolute value.
78    ///
79    /// $$
80    /// x \gets |x|.
81    /// $$
82    ///
83    /// # Worst-case complexity
84    /// Constant time and additional memory.
85    ///
86    /// # Examples
87    /// ```
88    /// use malachite_base::num::arithmetic::traits::AbsAssign;
89    /// use malachite_base::num::basic::traits::Zero;
90    /// use malachite_nz::integer::Integer;
91    ///
92    /// let mut x = Integer::ZERO;
93    /// x.abs_assign();
94    /// assert_eq!(x, 0);
95    ///
96    /// let mut x = Integer::from(123);
97    /// x.abs_assign();
98    /// assert_eq!(x, 123);
99    ///
100    /// let mut x = Integer::from(-123);
101    /// x.abs_assign();
102    /// assert_eq!(x, 123);
103    /// ```
104    #[inline]
105    fn abs_assign(&mut self) {
106        self.sign = true;
107    }
108}
109
110impl UnsignedAbs for Integer {
111    type Output = Natural;
112
113    /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by value and converting
114    /// the result to a [`Natural`].
115    ///
116    /// $$
117    /// f(x) = |x|.
118    /// $$
119    ///
120    /// # Worst-case complexity
121    /// Constant time and additional memory.
122    ///
123    /// # Examples
124    /// ```
125    /// use malachite_base::num::arithmetic::traits::UnsignedAbs;
126    /// use malachite_base::num::basic::traits::Zero;
127    /// use malachite_nz::integer::Integer;
128    ///
129    /// assert_eq!(Integer::ZERO.unsigned_abs(), 0);
130    /// assert_eq!(Integer::from(123).unsigned_abs(), 123);
131    /// assert_eq!(Integer::from(-123).unsigned_abs(), 123);
132    /// ```
133    #[inline]
134    fn unsigned_abs(self) -> Natural {
135        self.abs
136    }
137}
138
139impl UnsignedAbs for &Integer {
140    type Output = Natural;
141
142    /// Takes the absolute value of an [`Integer`], taking the [`Integer`] by reference and
143    /// converting the result to a [`Natural`].
144    ///
145    /// $$
146    /// f(x) = |x|.
147    /// $$
148    ///
149    /// # Worst-case complexity
150    /// $T(n) = O(n)$
151    ///
152    /// $M(n) = O(n)$
153    ///
154    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
155    ///
156    /// # Examples
157    /// ```
158    /// use malachite_base::num::arithmetic::traits::UnsignedAbs;
159    /// use malachite_base::num::basic::traits::Zero;
160    /// use malachite_nz::integer::Integer;
161    ///
162    /// assert_eq!((&Integer::ZERO).unsigned_abs(), 0);
163    /// assert_eq!((&Integer::from(123)).unsigned_abs(), 123);
164    /// assert_eq!((&Integer::from(-123)).unsigned_abs(), 123);
165    /// ```
166    #[inline]
167    fn unsigned_abs(self) -> Natural {
168        self.abs.clone()
169    }
170}
171
172impl Integer {
173    /// Finds the absolute value of an [`Integer`], taking the [`Integer`] by reference and
174    /// returning a reference to the internal [`Natural`] absolute value.
175    ///
176    /// $$
177    /// f(x) = |x|.
178    /// $$
179    ///
180    /// # Worst-case complexity
181    /// Constant time and additional memory.
182    ///
183    /// # Examples
184    /// ```
185    /// use malachite_base::num::basic::traits::Zero;
186    /// use malachite_nz::integer::Integer;
187    ///
188    /// assert_eq!(*Integer::ZERO.unsigned_abs_ref(), 0);
189    /// assert_eq!(*Integer::from(123).unsigned_abs_ref(), 123);
190    /// assert_eq!(*Integer::from(-123).unsigned_abs_ref(), 123);
191    /// ```
192    #[inline]
193    pub const fn unsigned_abs_ref(&self) -> &Natural {
194        &self.abs
195    }
196
197    /// Mutates the absolute value of an [`Integer`] using a provided closure, and then returns
198    /// whatever the closure returns.
199    ///
200    /// This function is similar to the [`unsigned_abs_ref`](Integer::unsigned_abs_ref) function,
201    /// which returns a reference to the absolute value. A function that returns a _mutable_
202    /// reference would be too dangerous, as it could leave the [`Integer`] in an invalid state
203    /// (specifically, with a negative sign but a zero absolute value). So rather than returning a
204    /// mutable reference, this function allows mutation of the absolute value using a closure.
205    /// After the closure executes, this function ensures that the [`Integer`] remains valid.
206    ///
207    /// There is only constant time and memory overhead on top of the time and memory used by the
208    /// closure.
209    ///
210    /// # Examples
211    /// ```
212    /// use malachite_base::num::arithmetic::traits::DivAssignMod;
213    /// use malachite_base::num::basic::traits::Two;
214    /// use malachite_nz::integer::Integer;
215    /// use malachite_nz::natural::Natural;
216    ///
217    /// let mut n = Integer::from(-123);
218    /// let remainder = n.mutate_unsigned_abs(|x| x.div_assign_mod(Natural::TWO));
219    /// assert_eq!(n, -61);
220    /// assert_eq!(remainder, 1);
221    ///
222    /// let mut n = Integer::from(-123);
223    /// n.mutate_unsigned_abs(|x| *x >>= 10);
224    /// assert_eq!(n, 0);
225    /// ```
226    pub fn mutate_unsigned_abs<F: FnOnce(&mut Natural) -> T, T>(&mut self, f: F) -> T {
227        let out = f(&mut self.abs);
228        if !self.sign && self.abs == 0 {
229            self.sign = true;
230        }
231        out
232    }
233}