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