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}