malachite_nz/integer/arithmetic/
root.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 core::ops::Neg;
12use malachite_base::num::arithmetic::traits::{
13    CeilingRoot, CeilingRootAssign, CheckedRoot, FloorRoot, FloorRootAssign, Parity, UnsignedAbs,
14};
15
16impl FloorRoot<u64> for Integer {
17    type Output = Integer;
18
19    /// Returns the floor of the $n$th root of an [`Integer`], taking the [`Integer`] by value.
20    ///
21    /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$.
22    ///
23    /// # Worst-case complexity
24    /// $T(n) = O(n (\log n)^2 \log\log n)$
25    ///
26    /// $M(n) = O(n \log n)$
27    ///
28    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
29    ///
30    /// # Panics
31    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
32    ///
33    /// # Examples
34    /// ```
35    /// use malachite_base::num::arithmetic::traits::FloorRoot;
36    /// use malachite_nz::integer::Integer;
37    ///
38    /// assert_eq!(Integer::from(999).floor_root(3), 9);
39    /// assert_eq!(Integer::from(1000).floor_root(3), 10);
40    /// assert_eq!(Integer::from(1001).floor_root(3), 10);
41    /// assert_eq!(Integer::from(100000000000i64).floor_root(5), 158);
42    /// assert_eq!(Integer::from(-100000000000i64).floor_root(5), -159);
43    /// ```
44    #[inline]
45    fn floor_root(mut self, exp: u64) -> Integer {
46        self.floor_root_assign(exp);
47        self
48    }
49}
50
51impl FloorRoot<u64> for &Integer {
52    type Output = Integer;
53
54    /// Returns the floor of the $n$th root of an [`Integer`], taking the [`Integer`] by reference.
55    ///
56    /// $f(x, n) = \lfloor\sqrt\[n\]{x}\rfloor$.
57    ///
58    /// # Worst-case complexity
59    /// $T(n) = O(n (\log n)^2 \log\log n)$
60    ///
61    /// $M(n) = O(n \log n)$
62    ///
63    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
64    ///
65    /// # Panics
66    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
67    ///
68    /// # Examples
69    /// ```
70    /// use malachite_base::num::arithmetic::traits::FloorRoot;
71    /// use malachite_nz::integer::Integer;
72    ///
73    /// assert_eq!((&Integer::from(999)).floor_root(3), 9);
74    /// assert_eq!((&Integer::from(1000)).floor_root(3), 10);
75    /// assert_eq!((&Integer::from(1001)).floor_root(3), 10);
76    /// assert_eq!((&Integer::from(100000000000i64)).floor_root(5), 158);
77    /// assert_eq!((&Integer::from(-100000000000i64)).floor_root(5), -159);
78    /// ```
79    #[inline]
80    fn floor_root(self, exp: u64) -> Integer {
81        if *self >= 0 {
82            Integer::from(self.unsigned_abs_ref().floor_root(exp))
83        } else if exp.odd() {
84            -self.unsigned_abs_ref().ceiling_root(exp)
85        } else {
86            panic!("Cannot take even root of {self}")
87        }
88    }
89}
90
91impl FloorRootAssign<u64> for Integer {
92    /// Replaces an [`Integer`] with the floor of its $n$th root.
93    ///
94    /// $x \gets \lfloor\sqrt\[n\]{x}\rfloor$.
95    ///
96    /// # Worst-case complexity
97    /// $T(n) = O(n (\log n)^2 \log\log n)$
98    ///
99    /// $M(n) = O(n \log n)$
100    ///
101    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
102    ///
103    /// # Panics
104    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
105    ///
106    /// # Examples
107    /// ```
108    /// use malachite_base::num::arithmetic::traits::FloorRootAssign;
109    /// use malachite_nz::integer::Integer;
110    ///
111    /// let mut x = Integer::from(999);
112    /// x.floor_root_assign(3);
113    /// assert_eq!(x, 9);
114    ///
115    /// let mut x = Integer::from(1000);
116    /// x.floor_root_assign(3);
117    /// assert_eq!(x, 10);
118    ///
119    /// let mut x = Integer::from(1001);
120    /// x.floor_root_assign(3);
121    /// assert_eq!(x, 10);
122    ///
123    /// let mut x = Integer::from(100000000000i64);
124    /// x.floor_root_assign(5);
125    /// assert_eq!(x, 158);
126    ///
127    /// let mut x = Integer::from(-100000000000i64);
128    /// x.floor_root_assign(5);
129    /// assert_eq!(x, -159);
130    /// ```
131    #[inline]
132    fn floor_root_assign(&mut self, exp: u64) {
133        if *self >= 0 {
134            self.mutate_unsigned_abs(|n| n.floor_root_assign(exp));
135        } else if exp.odd() {
136            self.mutate_unsigned_abs(|n| n.ceiling_root_assign(exp));
137        } else {
138            panic!("Cannot take even root of {self}")
139        }
140    }
141}
142
143impl CeilingRoot<u64> for Integer {
144    type Output = Integer;
145
146    /// Returns the ceiling of the $n$th root of an [`Integer`], taking the [`Integer`] by value.
147    ///
148    /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$.
149    ///
150    /// # Worst-case complexity
151    /// $T(n) = O(n (\log n)^2 \log\log n)$
152    ///
153    /// $M(n) = O(n \log n)$
154    ///
155    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
156    ///
157    /// # Panics
158    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
159    ///
160    /// # Examples
161    /// ```
162    /// use malachite_base::num::arithmetic::traits::CeilingRoot;
163    /// use malachite_nz::integer::Integer;
164    ///
165    /// assert_eq!(Integer::from(999).ceiling_root(3), 10);
166    /// assert_eq!(Integer::from(1000).ceiling_root(3), 10);
167    /// assert_eq!(Integer::from(1001).ceiling_root(3), 11);
168    /// assert_eq!(Integer::from(100000000000i64).ceiling_root(5), 159);
169    /// assert_eq!(Integer::from(-100000000000i64).ceiling_root(5), -158);
170    /// ```
171    #[inline]
172    fn ceiling_root(mut self, exp: u64) -> Integer {
173        self.ceiling_root_assign(exp);
174        self
175    }
176}
177
178impl CeilingRoot<u64> for &Integer {
179    type Output = Integer;
180
181    /// Returns the ceiling of the $n$th root of an [`Integer`], taking the [`Integer`] by
182    /// reference.
183    ///
184    /// $f(x, n) = \lceil\sqrt\[n\]{x}\rceil$.
185    ///
186    /// # Worst-case complexity
187    /// $T(n) = O(n (\log n)^2 \log\log n)$
188    ///
189    /// $M(n) = O(n \log n)$
190    ///
191    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
192    ///
193    /// # Panics
194    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
195    ///
196    /// # Examples
197    /// ```
198    /// use malachite_base::num::arithmetic::traits::CeilingRoot;
199    /// use malachite_nz::integer::Integer;
200    ///
201    /// assert_eq!(Integer::from(999).ceiling_root(3), 10);
202    /// assert_eq!(Integer::from(1000).ceiling_root(3), 10);
203    /// assert_eq!(Integer::from(1001).ceiling_root(3), 11);
204    /// assert_eq!(Integer::from(100000000000i64).ceiling_root(5), 159);
205    /// assert_eq!(Integer::from(-100000000000i64).ceiling_root(5), -158);
206    /// ```
207    #[inline]
208    fn ceiling_root(self, exp: u64) -> Integer {
209        if *self >= 0 {
210            Integer::from(self.unsigned_abs_ref().ceiling_root(exp))
211        } else if exp.odd() {
212            -self.unsigned_abs_ref().floor_root(exp)
213        } else {
214            panic!("Cannot take even root of {self}")
215        }
216    }
217}
218
219impl CeilingRootAssign<u64> for Integer {
220    /// Replaces an [`Integer`] with the ceiling of its $n$th root.
221    ///
222    /// $x \gets \lceil\sqrt\[n\]{x}\rceil$.
223    ///
224    /// # Worst-case complexity
225    /// $T(n) = O(n (\log n)^2 \log\log n)$
226    ///
227    /// $M(n) = O(n \log n)$
228    ///
229    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
230    ///
231    /// # Panics
232    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
233    ///
234    /// # Examples
235    /// ```
236    /// use malachite_base::num::arithmetic::traits::CeilingRootAssign;
237    /// use malachite_nz::integer::Integer;
238    ///
239    /// let mut x = Integer::from(999);
240    /// x.ceiling_root_assign(3);
241    /// assert_eq!(x, 10);
242    ///
243    /// let mut x = Integer::from(1000);
244    /// x.ceiling_root_assign(3);
245    /// assert_eq!(x, 10);
246    ///
247    /// let mut x = Integer::from(1001);
248    /// x.ceiling_root_assign(3);
249    /// assert_eq!(x, 11);
250    ///
251    /// let mut x = Integer::from(100000000000i64);
252    /// x.ceiling_root_assign(5);
253    /// assert_eq!(x, 159);
254    ///
255    /// let mut x = Integer::from(-100000000000i64);
256    /// x.ceiling_root_assign(5);
257    /// assert_eq!(x, -158);
258    /// ```
259    #[inline]
260    fn ceiling_root_assign(&mut self, exp: u64) {
261        if *self >= 0 {
262            self.mutate_unsigned_abs(|n| n.ceiling_root_assign(exp));
263        } else if exp.odd() {
264            self.mutate_unsigned_abs(|n| n.floor_root_assign(exp));
265        } else {
266            panic!("Cannot take even root of {self}")
267        }
268    }
269}
270
271impl CheckedRoot<u64> for Integer {
272    type Output = Integer;
273
274    /// Returns the the $n$th root of an [`Integer`], or `None` if the [`Integer`] is not a perfect
275    /// $n$th power. The [`Integer`] is taken by value.
276    ///
277    /// $$
278    /// f(x, n) = \\begin{cases}
279    ///     \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\
280    ///     \operatorname{None} & \textrm{otherwise}.
281    /// \\end{cases}
282    /// $$
283    ///
284    /// # Worst-case complexity
285    /// $T(n) = O(n (\log n)^2 \log\log n)$
286    ///
287    /// $M(n) = O(n \log n)$
288    ///
289    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
290    ///
291    /// # Panics
292    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
293    ///
294    /// # Examples
295    /// ```
296    /// use malachite_base::num::arithmetic::traits::CheckedRoot;
297    /// use malachite_base::strings::ToDebugString;
298    /// use malachite_nz::integer::Integer;
299    ///
300    /// assert_eq!(Integer::from(999).checked_root(3).to_debug_string(), "None");
301    /// assert_eq!(
302    ///     Integer::from(1000).checked_root(3).to_debug_string(),
303    ///     "Some(10)"
304    /// );
305    /// assert_eq!(
306    ///     Integer::from(1001).checked_root(3).to_debug_string(),
307    ///     "None"
308    /// );
309    /// assert_eq!(
310    ///     Integer::from(100000000000i64)
311    ///         .checked_root(5)
312    ///         .to_debug_string(),
313    ///     "None"
314    /// );
315    /// assert_eq!(
316    ///     Integer::from(-100000000000i64)
317    ///         .checked_root(5)
318    ///         .to_debug_string(),
319    ///     "None"
320    /// );
321    /// assert_eq!(
322    ///     Integer::from(10000000000i64)
323    ///         .checked_root(5)
324    ///         .to_debug_string(),
325    ///     "Some(100)"
326    /// );
327    /// assert_eq!(
328    ///     Integer::from(-10000000000i64)
329    ///         .checked_root(5)
330    ///         .to_debug_string(),
331    ///     "Some(-100)"
332    /// );
333    /// ```
334    #[inline]
335    fn checked_root(self, exp: u64) -> Option<Integer> {
336        if self >= 0 {
337            self.unsigned_abs().checked_root(exp).map(Integer::from)
338        } else if exp.odd() {
339            self.unsigned_abs().checked_root(exp).map(Natural::neg)
340        } else {
341            panic!("Cannot take even root of {self}")
342        }
343    }
344}
345
346impl CheckedRoot<u64> for &Integer {
347    type Output = Integer;
348
349    /// Returns the the $n$th root of an [`Integer`], or `None` if the [`Integer`] is not a perfect
350    /// $n$th power. The [`Integer`] is taken by reference.
351    ///
352    /// $$
353    /// f(x, n) = \\begin{cases}
354    ///     \operatorname{Some}(sqrt\[n\]{x}) & \text{if} \\quad \sqrt\[n\]{x} \in \Z, \\\\
355    ///     \operatorname{None} & \textrm{otherwise}.
356    /// \\end{cases}
357    /// $$
358    ///
359    /// # Worst-case complexity
360    /// $T(n) = O(n (\log n)^2 \log\log n)$
361    ///
362    /// $M(n) = O(n \log n)$
363    ///
364    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
365    ///
366    /// # Panics
367    /// Panics if `exp` is zero, or if `exp` is even and `self` is negative.
368    ///
369    /// # Examples
370    /// ```
371    /// use malachite_base::num::arithmetic::traits::CheckedRoot;
372    /// use malachite_base::strings::ToDebugString;
373    /// use malachite_nz::integer::Integer;
374    ///
375    /// assert_eq!(
376    ///     (&Integer::from(999)).checked_root(3).to_debug_string(),
377    ///     "None"
378    /// );
379    /// assert_eq!(
380    ///     (&Integer::from(1000)).checked_root(3).to_debug_string(),
381    ///     "Some(10)"
382    /// );
383    /// assert_eq!(
384    ///     (&Integer::from(1001)).checked_root(3).to_debug_string(),
385    ///     "None"
386    /// );
387    /// assert_eq!(
388    ///     (&Integer::from(100000000000i64))
389    ///         .checked_root(5)
390    ///         .to_debug_string(),
391    ///     "None"
392    /// );
393    /// assert_eq!(
394    ///     (&Integer::from(-100000000000i64))
395    ///         .checked_root(5)
396    ///         .to_debug_string(),
397    ///     "None"
398    /// );
399    /// assert_eq!(
400    ///     (&Integer::from(10000000000i64))
401    ///         .checked_root(5)
402    ///         .to_debug_string(),
403    ///     "Some(100)"
404    /// );
405    /// assert_eq!(
406    ///     (&Integer::from(-10000000000i64))
407    ///         .checked_root(5)
408    ///         .to_debug_string(),
409    ///     "Some(-100)"
410    /// );
411    /// ```
412    #[inline]
413    fn checked_root(self, exp: u64) -> Option<Integer> {
414        if *self >= 0 {
415            self.unsigned_abs_ref().checked_root(exp).map(Integer::from)
416        } else if exp.odd() {
417            self.unsigned_abs_ref().checked_root(exp).map(Natural::neg)
418        } else {
419            panic!("Cannot take even root of {self}")
420        }
421    }
422}