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