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}