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