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}