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