malachite_float/float/arithmetic/square.rs
1// Copyright © 2026 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::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::{
11 Float, float_either_infinity, float_either_zero, float_infinity, float_nan, float_zero,
12};
13use core::cmp::Ordering::{self, *};
14use malachite_base::num::arithmetic::traits::{
15 ArithmeticCheckedShl, IsPowerOf2, Square, SquareAssign,
16};
17use malachite_base::num::logic::traits::SignificantBits;
18use malachite_base::rounding_modes::RoundingMode::{self, *};
19use malachite_nz::natural::arithmetic::float::square::{
20 square_float_significand_in_place, square_float_significand_ref,
21};
22
23impl Float {
24 /// Squares a [`Float`], rounding the result to the specified precision and with the specified
25 /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating
26 /// whether the rounded square is less than, equal to, or greater than the exact square.
27 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
28 /// it also returns `Equal`.
29 ///
30 /// See [`RoundingMode`] for a description of the possible rounding modes.
31 ///
32 /// $$
33 /// f(x,p,m) = x^2+\varepsilon.
34 /// $$
35 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
36 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
37 /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$.
38 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
39 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
40 ///
41 /// If the output has a precision, it is `prec`.
42 ///
43 /// Special cases:
44 /// - $f(\text{NaN},p,m)=\text{NaN}$
45 /// - $f(\pm\infty,p,m)=\infty$
46 /// - $f(\pm0.0,p,m)=0.0$
47 ///
48 /// Overflow and underflow:
49 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
50 /// returned instead.
51 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
52 /// returned instead, where `p` is the precision of the input.
53 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
54 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
55 /// instead.
56 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
57 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
58 /// instead.
59 ///
60 /// Since the result is never negative, negative overflow and underflow cannot occur.
61 ///
62 /// If you know you'll be using `Nearest`, consider using [`Float::square_prec`] instead. If you
63 /// know that your target precision is the precision of the input, consider using
64 /// [`Float::square_round`] instead. If both of these things are true, consider using
65 /// [`Float::square`] instead.
66 ///
67 /// # Worst-case complexity
68 /// $T(n, m) = O(n \log n \log\log n + m)$
69 ///
70 /// $M(n, m) = O(n \log n + m)$
71 ///
72 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
73 /// `prec`.
74 ///
75 /// # Panics
76 /// Panics if `rm` is `Exact` but `prec` is too small for an exact squaring.
77 ///
78 /// # Examples
79 /// ```
80 /// use core::f64::consts::PI;
81 /// use malachite_base::rounding_modes::RoundingMode::*;
82 /// use malachite_float::Float;
83 /// use std::cmp::Ordering::*;
84 ///
85 /// let (square, o) = Float::from(PI).square_prec_round(5, Floor);
86 /// assert_eq!(square.to_string(), "9.50");
87 /// assert_eq!(o, Less);
88 ///
89 /// let (square, o) = Float::from(PI).square_prec_round(5, Ceiling);
90 /// assert_eq!(square.to_string(), "10.0");
91 /// assert_eq!(o, Greater);
92 ///
93 /// let (square, o) = Float::from(PI).square_prec_round(5, Nearest);
94 /// assert_eq!(square.to_string(), "10.0");
95 /// assert_eq!(o, Greater);
96 ///
97 /// let (square, o) = Float::from(PI).square_prec_round(20, Floor);
98 /// assert_eq!(square.to_string(), "9.8695984");
99 /// assert_eq!(o, Less);
100 ///
101 /// let (square, o) = Float::from(PI).square_prec_round(20, Ceiling);
102 /// assert_eq!(square.to_string(), "9.8696136");
103 /// assert_eq!(o, Greater);
104 ///
105 /// let (square, o) = Float::from(PI).square_prec_round(20, Nearest);
106 /// assert_eq!(square.to_string(), "9.8695984");
107 /// assert_eq!(o, Less);
108 /// ```
109 #[inline]
110 pub fn square_prec_round(mut self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
111 let o = self.square_prec_round_assign(prec, rm);
112 (self, o)
113 }
114
115 /// Squares a [`Float`], rounding the result to the specified precision and with the specified
116 /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned,
117 /// indicating whether the rounded square is less than, equal to, or greater than the exact
118 /// square. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
119 /// a `NaN` it also returns `Equal`.
120 ///
121 /// See [`RoundingMode`] for a description of the possible rounding modes.
122 ///
123 /// $$
124 /// f(x,p,m) = x^2+\varepsilon.
125 /// $$
126 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
127 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
128 /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$.
129 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
130 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
131 ///
132 /// If the output has a precision, it is `prec`.
133 ///
134 /// Special cases:
135 /// - $f(\text{NaN},p,m)=\text{NaN}$
136 /// - $f(\pm\infty,p,m)=\infty$
137 /// - $f(\pm0.0,p,m)=0.0$
138 ///
139 /// Overflow and underflow:
140 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
141 /// returned instead.
142 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
143 /// returned instead, where `p` is the precision of the input.
144 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
145 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
146 /// instead.
147 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
148 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
149 /// instead.
150 ///
151 /// Since the result is never negative, negative overflow and underflow cannot occur.
152 ///
153 /// If you know you'll be using `Nearest`, consider using [`Float::square_prec_ref`] instead. If
154 /// you know that your target precision is the precision of the input, consider using
155 /// [`Float::square_round_ref`] instead. If both of these things are true, consider using
156 /// `(&Float).square()`instead.
157 ///
158 /// # Worst-case complexity
159 /// $T(n, m) = O(n \log n \log\log n + m)$
160 ///
161 /// $M(n, m) = O(n \log n + m)$
162 ///
163 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
164 /// `prec`.
165 ///
166 /// # Panics
167 /// Panics if `rm` is `Exact` but `prec` is too small for an exact squaring.
168 ///
169 /// # Examples
170 /// ```
171 /// use core::f64::consts::PI;
172 /// use malachite_base::rounding_modes::RoundingMode::*;
173 /// use malachite_float::Float;
174 /// use std::cmp::Ordering::*;
175 ///
176 /// let (square, o) = Float::from(PI).square_prec_round_ref(5, Floor);
177 /// assert_eq!(square.to_string(), "9.50");
178 /// assert_eq!(o, Less);
179 ///
180 /// let (square, o) = Float::from(PI).square_prec_round_ref(5, Ceiling);
181 /// assert_eq!(square.to_string(), "10.0");
182 /// assert_eq!(o, Greater);
183 ///
184 /// let (square, o) = Float::from(PI).square_prec_round_ref(5, Nearest);
185 /// assert_eq!(square.to_string(), "10.0");
186 /// assert_eq!(o, Greater);
187 ///
188 /// let (square, o) = Float::from(PI).square_prec_round_ref(20, Floor);
189 /// assert_eq!(square.to_string(), "9.8695984");
190 /// assert_eq!(o, Less);
191 ///
192 /// let (square, o) = Float::from(PI).square_prec_round_ref(20, Ceiling);
193 /// assert_eq!(square.to_string(), "9.8696136");
194 /// assert_eq!(o, Greater);
195 ///
196 /// let (square, o) = Float::from(PI).square_prec_round_ref(20, Nearest);
197 /// assert_eq!(square.to_string(), "9.8695984");
198 /// assert_eq!(o, Less);
199 /// ```
200 #[inline]
201 pub fn square_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
202 assert_ne!(prec, 0);
203 match self {
204 float_nan!() => (float_nan!(), Equal),
205 float_either_infinity!() => (float_infinity!(), Equal),
206 float_either_zero!() => (float_zero!(), Equal),
207 Self(Finite {
208 exponent: x_exp,
209 precision: x_prec,
210 significand: x,
211 ..
212 }) => {
213 let twice_exp = x_exp << 1;
214 if twice_exp - 1 > Self::MAX_EXPONENT {
215 assert!(rm != Exact, "Inexact Float squaring");
216 return match rm {
217 Ceiling | Up | Nearest => (float_infinity!(), Greater),
218 _ => (Self::max_finite_value_with_prec(prec), Less),
219 };
220 } else if twice_exp < Self::MIN_EXPONENT_MINUS_1 {
221 assert!(rm != Exact, "Inexact Float squaring");
222 return match rm {
223 Floor | Down | Nearest => (float_zero!(), Less),
224 _ => (Self::min_positive_value_prec(prec), Greater),
225 };
226 }
227 let (square, exp_offset, o) = square_float_significand_ref(x, *x_prec, prec, rm);
228 let exp = x_exp
229 .arithmetic_checked_shl(1u32)
230 .unwrap()
231 .checked_add(exp_offset)
232 .unwrap();
233 if exp > Self::MAX_EXPONENT {
234 assert!(rm != Exact, "Inexact Float squaring");
235 return match rm {
236 Ceiling | Up | Nearest => (float_infinity!(), Greater),
237 _ => (Self::max_finite_value_with_prec(prec), Less),
238 };
239 } else if exp < Self::MIN_EXPONENT {
240 return if rm == Nearest
241 && exp == Self::MIN_EXPONENT_MINUS_1
242 && (o == Less || !square.is_power_of_2())
243 {
244 (Self::min_positive_value_prec(prec), Greater)
245 } else {
246 match rm {
247 Exact => panic!("Inexact float squaring"),
248 Ceiling | Up => (Self::min_positive_value_prec(prec), Greater),
249 _ => (float_zero!(), Less),
250 }
251 };
252 }
253 (
254 Self(Finite {
255 sign: true,
256 exponent: exp,
257 precision: prec,
258 significand: square,
259 }),
260 o,
261 )
262 }
263 }
264 }
265
266 /// Squares a [`Float`], rounding the result to the nearest value of the specified precision.
267 /// The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether the
268 /// rounded square is less than, equal to, or greater than the exact square. Although `NaN`s are
269 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
270 /// `Equal`.
271 ///
272 /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`]
273 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
274 /// the `Nearest` rounding mode.
275 ///
276 /// $$
277 /// f(x,p) = x^2+\varepsilon.
278 /// $$
279 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
280 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
281 ///
282 /// If the output has a precision, it is `prec`.
283 ///
284 /// Special cases:
285 /// - $f(\text{NaN},p)=\text{NaN}$
286 /// - $f(\pm\infty,p)=\infty$
287 /// - $f(\pm0.0,p)=0.0$
288 ///
289 /// Overflow and underflow:
290 /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
291 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
292 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
293 ///
294 /// Since the result is never negative, negative overflow and underflow cannot occur.
295 ///
296 /// If you want to use a rounding mode other than `Nearest`, consider using
297 /// [`Float::square_prec_round`] instead. If you know that your target precision is the
298 /// precision of the input, consider using [`Float::square`] instead.
299 ///
300 /// # Worst-case complexity
301 /// $T(n, m) = O(n \log n \log\log n + m)$
302 ///
303 /// $M(n, m) = O(n \log n + m)$
304 ///
305 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
306 /// `prec`.
307 ///
308 /// # Examples
309 /// ```
310 /// use core::f64::consts::PI;
311 /// use malachite_float::Float;
312 /// use std::cmp::Ordering::*;
313 ///
314 /// let (square, o) = Float::from(PI).square_prec(5);
315 /// assert_eq!(square.to_string(), "10.0");
316 /// assert_eq!(o, Greater);
317 ///
318 /// let (square, o) = Float::from(PI).square_prec(20);
319 /// assert_eq!(square.to_string(), "9.8695984");
320 /// assert_eq!(o, Less);
321 /// ```
322 #[inline]
323 pub fn square_prec(self, prec: u64) -> (Self, Ordering) {
324 self.square_prec_round(prec, Nearest)
325 }
326
327 /// Squares a [`Float`], rounding the result to the nearest value of the specified precision.
328 /// The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating whether
329 /// the rounded square is less than, equal to, or greater than the exact square. Although `NaN`s
330 /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
331 /// `Equal`.
332 ///
333 /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`]
334 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
335 /// the `Nearest` rounding mode.
336 ///
337 /// $$
338 /// f(x,p) = x^2+\varepsilon.
339 /// $$
340 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
341 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
342 ///
343 /// If the output has a precision, it is `prec`.
344 ///
345 /// Special cases:
346 /// - $f(\text{NaN},p)=\text{NaN}$
347 /// - $f(\pm\infty,p)=\infty$
348 /// - $f(\pm0.0,p)=0.0$
349 ///
350 /// Overflow and underflow:
351 /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
352 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
353 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
354 ///
355 /// Since the result is never negative, negative overflow and underflow cannot occur.
356 ///
357 /// If you want to use a rounding mode other than `Nearest`, consider using
358 /// [`Float::square_prec_round_ref`] instead. If you know that your target precision is the
359 /// precision of the input, consider using `(&Float).square()` instead.
360 ///
361 /// # Worst-case complexity
362 /// $T(n, m) = O(n \log n \log\log n + m)$
363 ///
364 /// $M(n, m) = O(n \log n + m)$
365 ///
366 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
367 /// `prec`.
368 ///
369 /// # Examples
370 /// ```
371 /// use core::f64::consts::PI;
372 /// use malachite_float::Float;
373 /// use std::cmp::Ordering::*;
374 ///
375 /// let (square, o) = Float::from(PI).square_prec_ref(5);
376 /// assert_eq!(square.to_string(), "10.0");
377 /// assert_eq!(o, Greater);
378 ///
379 /// let (square, o) = Float::from(PI).square_prec_ref(20);
380 /// assert_eq!(square.to_string(), "9.8695984");
381 /// assert_eq!(o, Less);
382 /// ```
383 #[inline]
384 pub fn square_prec_ref(&self, prec: u64) -> (Self, Ordering) {
385 self.square_prec_round_ref(prec, Nearest)
386 }
387
388 /// Squares a [`Float`], rounding the result with the specified rounding mode. The [`Float`] is
389 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded square is
390 /// less than, equal to, or greater than the exact square. Although `NaN`s are not comparable to
391 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
392 ///
393 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
394 /// description of the possible rounding modes.
395 ///
396 /// $$
397 /// f(x,m) = x^2+\varepsilon.
398 /// $$
399 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
400 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
401 /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input.
402 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
403 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input.
404 ///
405 /// If the output has a precision, it is the precision of the input.
406 ///
407 /// Special cases:
408 /// - $f(\text{NaN},m)=\text{NaN}$
409 /// - $f(\pm\infty,m)=\infty$
410 /// - $f(\pm0.0,m)=0.0$
411 ///
412 /// Overflow and underflow:
413 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
414 /// returned instead.
415 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
416 /// returned instead, where `p` is the precision of the input.
417 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
418 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
419 /// instead.
420 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
421 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
422 /// instead.
423 ///
424 /// Since the result is never negative, negative overflow and underflow cannot occur.
425 ///
426 /// If you want to specify an output precision, consider using [`Float::square_prec_round`]
427 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
428 /// [`Float::square`] instead.
429 ///
430 /// # Worst-case complexity
431 /// $T(n) = O(n \log n \log\log n)$
432 ///
433 /// $M(n) = O(n \log n)$
434 ///
435 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
436 ///
437 /// # Panics
438 /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the
439 /// output.
440 ///
441 /// # Examples
442 /// ```
443 /// use core::f64::consts::PI;
444 /// use malachite_base::rounding_modes::RoundingMode::*;
445 /// use malachite_float::Float;
446 /// use std::cmp::Ordering::*;
447 ///
448 /// let (square, o) = Float::from(PI).square_round(Floor);
449 /// assert_eq!(square.to_string(), "9.8696044010893473");
450 /// assert_eq!(o, Less);
451 ///
452 /// let (square, o) = Float::from(PI).square_round(Ceiling);
453 /// assert_eq!(square.to_string(), "9.8696044010893615");
454 /// assert_eq!(o, Greater);
455 ///
456 /// let (square, o) = Float::from(PI).square_round(Nearest);
457 /// assert_eq!(square.to_string(), "9.8696044010893615");
458 /// assert_eq!(o, Greater);
459 /// ```
460 #[inline]
461 pub fn square_round(self, rm: RoundingMode) -> (Self, Ordering) {
462 let prec = self.significant_bits();
463 self.square_prec_round(prec, rm)
464 }
465
466 /// Squares a [`Float`], rounding the result with the specified rounding mode. The [`Float`] is
467 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded square
468 /// is less than, equal to, or greater than the exact square. Although `NaN`s are not comparable
469 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
470 ///
471 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
472 /// description of the possible rounding modes.
473 ///
474 /// $$
475 /// f(x,m) = x^2+\varepsilon.
476 /// $$
477 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
478 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
479 /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the precision of the input.
480 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
481 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the precision of the input.
482 ///
483 /// If the output has a precision, it is the precision of the input.
484 ///
485 /// Special cases:
486 /// - $f(\text{NaN},m)=\text{NaN}$
487 /// - $f(\pm\infty,m)=\infty$
488 /// - $f(\pm0.0,m)=0.0$
489 ///
490 /// Overflow and underflow:
491 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
492 /// returned instead.
493 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
494 /// returned instead, where `p` is the precision of the input.
495 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
496 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
497 /// instead.
498 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
499 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
500 /// instead.
501 ///
502 /// Since the result is never negative, negative overflow and underflow cannot occur.
503 ///
504 /// If you want to specify an output precision, consider using [`Float::square_prec_round_ref`]
505 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
506 /// `(&Float).square()` instead.
507 ///
508 /// # Worst-case complexity
509 /// $T(n) = O(n \log n \log\log n)$
510 ///
511 /// $M(n) = O(n \log n)$
512 ///
513 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
514 ///
515 /// # Panics
516 /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the
517 /// output.
518 ///
519 /// # Examples
520 /// ```
521 /// use core::f64::consts::PI;
522 /// use malachite_base::rounding_modes::RoundingMode::*;
523 /// use malachite_float::Float;
524 /// use std::cmp::Ordering::*;
525 ///
526 /// let (square, o) = Float::from(PI).square_round_ref(Floor);
527 /// assert_eq!(square.to_string(), "9.8696044010893473");
528 /// assert_eq!(o, Less);
529 ///
530 /// let (square, o) = Float::from(PI).square_round_ref(Ceiling);
531 /// assert_eq!(square.to_string(), "9.8696044010893615");
532 /// assert_eq!(o, Greater);
533 ///
534 /// let (square, o) = Float::from(PI).square_round_ref(Nearest);
535 /// assert_eq!(square.to_string(), "9.8696044010893615");
536 /// assert_eq!(o, Greater);
537 /// ```
538 #[inline]
539 pub fn square_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
540 let prec = self.significant_bits();
541 self.square_prec_round_ref(prec, rm)
542 }
543
544 /// Squares a [`Float`] in place, rounding the result to the specified precision and with the
545 /// specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded square
546 /// is less than, equal to, or greater than the exact square. Although `NaN`s are not comparable
547 /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns
548 /// `Equal`.
549 ///
550 /// See [`RoundingMode`] for a description of the possible rounding modes.
551 ///
552 /// $$
553 /// x \gets x^2+\varepsilon.
554 /// $$
555 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
556 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
557 /// 2^{\lfloor\log_2 |xy|\rfloor-p+1}$.
558 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
559 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
560 ///
561 /// If the output has a precision, it is `prec`.
562 ///
563 /// See the [`Float::square_prec_round`] documentation for information on special cases,
564 /// overflow, and underflow.
565 ///
566 /// If you know you'll be using `Nearest`, consider using [`Float::square_prec_assign`] instead.
567 /// If you know that your target precision is the precision of the input, consider using
568 /// [`Float::square_round_assign`] instead. If both of these things are true, consider using
569 /// [`Float::square_assign`] instead.
570 ///
571 /// # Worst-case complexity
572 /// $T(n, m) = O(n \log n \log\log n + m)$
573 ///
574 /// $M(n, m) = O(n \log n + m)$
575 ///
576 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
577 /// `prec`.
578 ///
579 /// # Panics
580 /// Panics if `rm` is `Exact` but `prec` is too small for an exact squaring;
581 ///
582 /// # Examples
583 /// ```
584 /// use core::f64::consts::PI;
585 /// use malachite_base::rounding_modes::RoundingMode::*;
586 /// use malachite_float::Float;
587 /// use std::cmp::Ordering::*;
588 ///
589 /// let mut x = Float::from(PI);
590 /// assert_eq!(x.square_prec_round_assign(5, Floor), Less);
591 /// assert_eq!(x.to_string(), "9.50");
592 ///
593 /// let mut x = Float::from(PI);
594 /// assert_eq!(x.square_prec_round_assign(5, Ceiling), Greater);
595 /// assert_eq!(x.to_string(), "10.0");
596 ///
597 /// let mut x = Float::from(PI);
598 /// assert_eq!(x.square_prec_round_assign(5, Nearest), Greater);
599 /// assert_eq!(x.to_string(), "10.0");
600 ///
601 /// let mut x = Float::from(PI);
602 /// assert_eq!(x.square_prec_round_assign(20, Floor), Less);
603 /// assert_eq!(x.to_string(), "9.8695984");
604 ///
605 /// let mut x = Float::from(PI);
606 /// assert_eq!(x.square_prec_round_assign(20, Ceiling), Greater);
607 /// assert_eq!(x.to_string(), "9.8696136");
608 ///
609 /// let mut x = Float::from(PI);
610 /// assert_eq!(x.square_prec_round_assign(20, Nearest), Less);
611 /// assert_eq!(x.to_string(), "9.8695984");
612 /// ```
613 #[inline]
614 pub fn square_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
615 assert_ne!(prec, 0);
616 match self {
617 float_nan!() => Equal,
618 Self(Infinity { sign } | Zero { sign }) => {
619 *sign = true;
620 Equal
621 }
622 Self(Finite {
623 sign: x_sign,
624 exponent: x_exp,
625 precision: x_prec,
626 significand: x,
627 }) => {
628 let twice_exp = *x_exp << 1;
629 if twice_exp - 1 > Self::MAX_EXPONENT {
630 assert!(rm != Exact, "Inexact Float squaring");
631 return match rm {
632 Ceiling | Up | Nearest => {
633 *self = float_infinity!();
634 Greater
635 }
636 _ => {
637 *self = Self::max_finite_value_with_prec(prec);
638 Less
639 }
640 };
641 } else if twice_exp < Self::MIN_EXPONENT_MINUS_1 {
642 assert!(rm != Exact, "Inexact Float squaring");
643 return match rm {
644 Floor | Down | Nearest => {
645 *self = float_zero!();
646 Less
647 }
648 _ => {
649 *self = Self::min_positive_value_prec(prec);
650 Greater
651 }
652 };
653 }
654 let (exp_offset, o) = square_float_significand_in_place(x, *x_prec, prec, rm);
655 *x_exp = x_exp
656 .arithmetic_checked_shl(1u32)
657 .unwrap()
658 .checked_add(exp_offset)
659 .unwrap();
660 if *x_exp > Self::MAX_EXPONENT {
661 assert!(rm != Exact, "Inexact Float squaring");
662 return match rm {
663 Ceiling | Up | Nearest => {
664 *self = float_infinity!();
665 Greater
666 }
667 _ => {
668 *self = Self::max_finite_value_with_prec(prec);
669 Less
670 }
671 };
672 } else if *x_exp < Self::MIN_EXPONENT {
673 return if rm == Nearest
674 && *x_exp == Self::MIN_EXPONENT_MINUS_1
675 && (o == Less || !x.is_power_of_2())
676 {
677 {
678 *self = Self::min_positive_value_prec(prec);
679 Greater
680 }
681 } else {
682 match rm {
683 Exact => panic!("Inexact float squaring"),
684 Ceiling | Up => {
685 *self = Self::min_positive_value_prec(prec);
686 Greater
687 }
688 _ => {
689 *self = float_zero!();
690 Less
691 }
692 }
693 };
694 }
695 *x_sign = true;
696 *x_prec = prec;
697 o
698 }
699 }
700 }
701
702 /// Squares a [`Float`] in place, rounding the result to the nearest value of the specified
703 /// precision. An [`Ordering`] is returned, indicating whether the rounded square is less than,
704 /// equal to, or greater than the exact square. Although `NaN`s are not comparable to any
705 /// [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns `Equal`.
706 ///
707 /// If the square is equidistant from two [`Float`]s with the specified precision, the [`Float`]
708 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
709 /// the `Nearest` rounding mode.
710 ///
711 /// $$
712 /// x \gets x^2+\varepsilon.
713 /// $$
714 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
715 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$.
716 ///
717 /// If the output has a precision, it is `prec`.
718 ///
719 /// See the [`Float::square_prec`] documentation for information on special cases, overflow, and
720 /// underflow.
721 ///
722 /// If you want to use a rounding mode other than `Nearest`, consider using
723 /// [`Float::square_prec_round_assign`] instead. If you know that your target precision is the
724 /// precision of the input, consider using [`Float::square`] instead.
725 ///
726 /// # Worst-case complexity
727 /// $T(n, m) = O(n \log n \log\log n + m)$
728 ///
729 /// $M(n, m) = O(n \log n + m)$
730 ///
731 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $m$ is
732 /// `prec`.
733 ///
734 /// # Examples
735 /// ```
736 /// use core::f64::consts::PI;
737 /// use malachite_float::Float;
738 /// use std::cmp::Ordering::*;
739 ///
740 /// let mut x = Float::from(PI);
741 /// assert_eq!(x.square_prec_assign(5), Greater);
742 /// assert_eq!(x.to_string(), "10.0");
743 ///
744 /// let mut x = Float::from(PI);
745 /// assert_eq!(x.square_prec_assign(20), Less);
746 /// assert_eq!(x.to_string(), "9.8695984");
747 /// ```
748 #[inline]
749 pub fn square_prec_assign(&mut self, prec: u64) -> Ordering {
750 self.square_prec_round_assign(prec, Nearest)
751 }
752
753 /// Squares a [`Float`] in place, rounding the result with the specified rounding mode. An
754 /// [`Ordering`] is returned, indicating whether the rounded square is less than, equal to, or
755 /// greater than the exact square. Although `NaN`s are not comparable to any [`Float`], whenever
756 /// this function sets the [`Float`] to `NaN` it also returns `Equal`.
757 ///
758 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
759 /// description of the possible rounding modes.
760 ///
761 /// $$
762 /// x \gets x^2+\varepsilon.
763 /// $$
764 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
765 /// - If $x^2$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
766 /// 2^{\lfloor\log_2 |x^2|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
767 /// - If $x^2$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
768 /// 2^{\lfloor\log_2 |x^2|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
769 ///
770 /// If the output has a precision, it is the precision of the input.
771 ///
772 /// See the [`Float::square_round`] documentation for information on special cases, overflow,
773 /// and underflow.
774 ///
775 /// If you want to specify an output precision, consider using
776 /// [`Float::square_prec_round_assign`] instead. If you know you'll be using the `Nearest`
777 /// rounding mode, consider using [`Float::square_assign`] instead.
778 ///
779 /// # Worst-case complexity
780 /// $T(n) = O(n \log n \log\log n)$
781 ///
782 /// $M(n) = O(n \log n)$
783 ///
784 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
785 ///
786 /// # Panics
787 /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the
788 /// output.
789 ///
790 /// # Examples
791 /// ```
792 /// use core::f64::consts::PI;
793 /// use malachite_base::rounding_modes::RoundingMode::*;
794 /// use malachite_float::Float;
795 /// use std::cmp::Ordering::*;
796 ///
797 /// let mut x = Float::from(PI);
798 /// assert_eq!(x.square_round_assign(Floor), Less);
799 /// assert_eq!(x.to_string(), "9.8696044010893473");
800 ///
801 /// let mut x = Float::from(PI);
802 /// assert_eq!(x.square_round_assign(Ceiling), Greater);
803 /// assert_eq!(x.to_string(), "9.8696044010893615");
804 ///
805 /// let mut x = Float::from(PI);
806 /// assert_eq!(x.square_round_assign(Nearest), Greater);
807 /// assert_eq!(x.to_string(), "9.8696044010893615");
808 /// ```
809 #[inline]
810 pub fn square_round_assign(&mut self, rm: RoundingMode) -> Ordering {
811 let prec = self.significant_bits();
812 self.square_prec_round_assign(prec, rm)
813 }
814}
815
816impl Square for Float {
817 type Output = Self;
818
819 /// Squares a [`Float`], taking it by value.
820 ///
821 /// If the output has a precision, it is the precision of the input. If the square is
822 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
823 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
824 /// rounding mode.
825 ///
826 /// $$
827 /// f(x) = x^2+\varepsilon.
828 /// $$
829 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
830 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$,
831 /// where $p$ is the maximum precision of the inputs.
832 ///
833 /// Special cases:
834 /// - $f(\text{NaN})=\text{NaN}$
835 /// - $f(\pm\infty)=\infty$
836 /// - $f(\pm0.0)=0.0$
837 ///
838 /// Overflow and underflow:
839 /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
840 /// - If $0<f(x)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
841 /// - If $2^{-2^{30}-1}<f(x)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
842 ///
843 /// Since the result is never negative, negative overflow and underflow cannot occur.
844 ///
845 /// If you want to use a rounding mode other than `Nearest`, consider using
846 /// [`Float::square_prec`] instead. If you want to specify the output precision, consider using
847 /// [`Float::square_round`]. If you want both of these things, consider using
848 /// [`Float::square_prec_round`].
849 ///
850 /// # Worst-case complexity
851 /// $T(n) = O(n \log n \log\log n)$
852 ///
853 /// $M(n) = O(n \log n)$
854 ///
855 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
856 ///
857 /// # Examples
858 /// ```
859 /// use malachite_base::num::arithmetic::traits::Square;
860 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
861 /// use malachite_float::Float;
862 ///
863 /// assert!(Float::NAN.square().is_nan());
864 /// assert_eq!(Float::INFINITY.square(), Float::INFINITY);
865 /// assert_eq!(Float::NEGATIVE_INFINITY.square(), Float::INFINITY);
866 /// assert_eq!(Float::from(1.5).square(), 2.0);
867 /// assert_eq!(Float::from(-1.5).square(), 2.0);
868 /// ```
869 #[inline]
870 fn square(self) -> Self {
871 let prec = self.significant_bits();
872 self.square_prec_round(prec, Nearest).0
873 }
874}
875
876impl Square for &Float {
877 type Output = Float;
878
879 /// Squares a [`Float`], taking it by reference.
880 ///
881 /// If the output has a precision, it is the precision of the input. If the square is
882 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
883 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
884 /// rounding mode.
885 ///
886 /// $$
887 /// f(x) = x^2+\varepsilon.
888 /// $$
889 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
890 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$,
891 /// where $p$ is the maximum precision of the inputs.
892 ///
893 /// Special cases:
894 /// - $f(\text{NaN})=\text{NaN}$
895 /// - $f(\pm\infty)=\infty$
896 /// - $f(\pm0.0)=0.0$
897 ///
898 /// Overflow and underflow:
899 /// - If $f(x)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
900 /// - If $0<f(x)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
901 /// - If $2^{-2^{30}-1}<f(x)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
902 ///
903 /// Since the result is never negative, negative overflow and underflow cannot occur.
904 ///
905 /// If you want to use a rounding mode other than `Nearest`, consider using
906 /// [`Float::square_prec_ref`] instead. If you want to specify the output precision, consider
907 /// using [`Float::square_round_ref`]. If you want both of these things, consider using
908 /// [`Float::square_prec_round_ref`].
909 ///
910 /// # Worst-case complexity
911 /// $T(n) = O(n \log n \log\log n)$
912 ///
913 /// $M(n) = O(n \log n)$
914 ///
915 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
916 ///
917 /// # Examples
918 /// ```
919 /// use malachite_base::num::arithmetic::traits::Square;
920 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
921 /// use malachite_float::Float;
922 ///
923 /// assert!((&Float::NAN).square().is_nan());
924 /// assert_eq!((&Float::INFINITY).square(), Float::INFINITY);
925 /// assert_eq!((&Float::NEGATIVE_INFINITY).square(), Float::INFINITY);
926 /// assert_eq!((&Float::from(1.5)).square(), 2.0);
927 /// assert_eq!((&Float::from(-1.5)).square(), 2.0);
928 /// ```
929 #[inline]
930 fn square(self) -> Float {
931 let prec = self.significant_bits();
932 self.square_prec_round_ref(prec, Nearest).0
933 }
934}
935
936impl SquareAssign for Float {
937 /// Squares a [`Float`] in place.
938 ///
939 /// If the output has a precision, it is the precision of the input. If the square is
940 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
941 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
942 /// rounding mode.
943 ///
944 /// $$
945 /// x\gets = x^2+\varepsilon.
946 /// $$
947 /// - If $x^2$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
948 /// - If $x^2$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |x^2|\rfloor-p}$,
949 /// where $p$ is the maximum precision of the inputs.
950 ///
951 /// See the [`Float::square`] documentation for information on special cases, overflow, and
952 /// underflow.
953 ///
954 /// If you want to use a rounding mode other than `Nearest`, consider using
955 /// [`Float::square_prec_assign`] instead. If you want to specify the output precision, consider
956 /// using [`Float::square_round_assign`]. If you want both of these things, consider using
957 /// [`Float::square_prec_round_assign`].
958 ///
959 /// # Worst-case complexity
960 /// $T(n) = O(n \log n \log\log n)$
961 ///
962 /// $M(n) = O(n \log n)$
963 ///
964 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
965 ///
966 /// # Examples
967 /// ```
968 /// use malachite_base::num::arithmetic::traits::SquareAssign;
969 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
970 /// use malachite_float::Float;
971 ///
972 /// let mut x = Float::NAN;
973 /// x.square_assign();
974 /// assert!(x.is_nan());
975 ///
976 /// let mut x = Float::INFINITY;
977 /// x.square_assign();
978 /// assert_eq!(x, Float::INFINITY);
979 ///
980 /// let mut x = Float::NEGATIVE_INFINITY;
981 /// x.square_assign();
982 /// assert_eq!(x, Float::INFINITY);
983 ///
984 /// let mut x = Float::from(1.5);
985 /// x.square_assign();
986 /// assert_eq!(x, 2.0);
987 ///
988 /// let mut x = Float::from(-1.5);
989 /// x.square_assign();
990 /// assert_eq!(x, 2.0);
991 /// ```
992 #[inline]
993 fn square_assign(&mut self) {
994 let prec = self.significant_bits();
995 self.square_prec_round_assign(prec, Nearest);
996 }
997}