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_nan, Float};
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 {
570 o
571 } else {
572 o.reverse()
573 }
574 }
575 }
576 }
577
578 /// Takes the reciprocal of a [`Float`] in place, rounding the result to the nearest value of
579 /// the specified precision. An [`Ordering`] is returned, indicating whether the rounded
580 /// reciprocal is less than, equal to, or greater than the exact reciprocal. Although `NaN`s are
581 /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also
582 /// returns `Equal`.
583 ///
584 /// If the reciprocal is equidistant from two [`Float`]s with the specified precision, the
585 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
586 /// description of the `Nearest` rounding mode.
587 ///
588 /// $$
589 /// x \gets 1/x+\varepsilon.
590 /// $$
591 /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
592 /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$.
593 ///
594 /// If the output has a precision, it is `prec`.
595 ///
596 /// See the [`Float::reciprocal_prec`] documentation for information on special cases.
597 ///
598 /// If you want to use a rounding mode other than `Nearest`, consider using
599 /// [`Float::reciprocal_prec_round_assign`] instead. If you know that your target precision is
600 /// the precision of the input, consider using [`Float::reciprocal`] instead.
601 ///
602 /// # Worst-case complexity
603 /// $T(n) = O(n \log n \log\log n)$
604 ///
605 /// $M(n) = O(n \log n)$
606 ///
607 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
608 /// prec)`.
609 ///
610 /// # Examples
611 /// ```
612 /// use core::f64::consts::PI;
613 /// use malachite_float::Float;
614 /// use std::cmp::Ordering::*;
615 ///
616 /// let mut x = Float::from(PI);
617 /// assert_eq!(x.reciprocal_prec_assign(5), Less);
618 /// assert_eq!(x.to_string(), "0.31");
619 ///
620 /// let mut x = Float::from(PI);
621 /// assert_eq!(x.reciprocal_prec_assign(20), Less);
622 /// assert_eq!(x.to_string(), "0.3183098");
623 /// ```
624 #[inline]
625 pub fn reciprocal_prec_assign(&mut self, prec: u64) -> Ordering {
626 self.reciprocal_prec_round_assign(prec, Nearest)
627 }
628
629 /// Takes the reciprocal of a [`Float`] in place, rounding the result with the specified
630 /// rounding mode. An [`Ordering`] is returned, indicating whether the rounded reciprocal is
631 /// less than, equal to, or greater than the exact reciprocal. Although `NaN`s are not
632 /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also
633 /// returns `Equal`.
634 ///
635 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
636 /// description of the possible rounding modes.
637 ///
638 /// $$
639 /// x \gets 1/x+\varepsilon.
640 /// $$
641 /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
642 /// - If $1/x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
643 /// 2^{\lfloor\log_2 |1/x|\rfloor-p+1}$, where $p$ is the maximum precision of the inputs.
644 /// - If $1/x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| <
645 /// 2^{\lfloor\log_2 |1/x|\rfloor-p}$, where $p$ is the maximum precision of the inputs.
646 ///
647 /// If the output has a precision, it is the precision of the input.
648 ///
649 /// See the [`Float::reciprocal_round`] documentation for information on special cases.
650 ///
651 /// If you want to specify an output precision, consider using
652 /// [`Float::reciprocal_prec_round_assign`] instead. If you know you'll be using the `Nearest`
653 /// rounding mode, consider using [`Float::reciprocal_assign`] instead.
654 ///
655 /// # Worst-case complexity
656 /// $T(n) = O(n \log n \log\log n)$
657 ///
658 /// $M(n) = O(n \log n)$
659 ///
660 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
661 ///
662 /// # Panics
663 /// Panics if `rm` is `Exact` but the precision of the input is not high enough to represent the
664 /// output.
665 ///
666 /// # Examples
667 /// ```
668 /// use core::f64::consts::PI;
669 /// use malachite_base::rounding_modes::RoundingMode::*;
670 /// use malachite_float::Float;
671 /// use std::cmp::Ordering::*;
672 ///
673 /// let mut x = Float::from(PI);
674 /// assert_eq!(x.reciprocal_round_assign(Floor), Less);
675 /// assert_eq!(x.to_string(), "0.3183098861837905");
676 ///
677 /// let mut x = Float::from(PI);
678 /// assert_eq!(x.reciprocal_round_assign(Ceiling), Greater);
679 /// assert_eq!(x.to_string(), "0.318309886183791");
680 ///
681 /// let mut x = Float::from(PI);
682 /// assert_eq!(x.reciprocal_round_assign(Nearest), Less);
683 /// assert_eq!(x.to_string(), "0.3183098861837905");
684 /// ```
685 #[inline]
686 pub fn reciprocal_round_assign(&mut self, rm: RoundingMode) -> Ordering {
687 let prec = self.significant_bits();
688 self.reciprocal_prec_round_assign(prec, rm)
689 }
690}
691
692impl Reciprocal for Float {
693 type Output = Float;
694
695 /// Takes the reciprocal of a [`Float`], taking it by value.
696 ///
697 /// If the output has a precision, it is the precision of the input. If the reciprocal is
698 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
699 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
700 /// rounding mode.
701 ///
702 /// $$
703 /// f(x,y) = 1/x+\varepsilon.
704 /// $$
705 /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
706 /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$,
707 /// where $p$ is the maximum precision of the inputs.
708 ///
709 /// Special cases:
710 /// - $f(\text{NaN})=\text{NaN}$
711 /// - $f(\infty)=0.0$
712 /// - $f(-\infty)=-0.0$
713 /// - $f(0.0)=\infty$
714 /// - $f(-0.0)=-\infty$
715 ///
716 /// If you want to use a rounding mode other than `Nearest`, consider using
717 /// [`Float::reciprocal_prec`] instead. If you want to specify the output precision, consider
718 /// using [`Float::reciprocal_round`]. If you want both of these things, consider using
719 /// [`Float::reciprocal_prec_round`].
720 ///
721 /// # Worst-case complexity
722 /// $T(n) = O(n \log n \log\log n)$
723 ///
724 /// $M(n) = O(n \log n)$
725 ///
726 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
727 ///
728 /// # Examples
729 /// ```
730 /// use malachite_base::num::arithmetic::traits::Reciprocal;
731 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
732 /// use malachite_float::Float;
733 ///
734 /// assert!(Float::NAN.reciprocal().is_nan());
735 /// assert_eq!(Float::INFINITY.reciprocal().to_string(), "0.0");
736 /// assert_eq!(Float::NEGATIVE_INFINITY.reciprocal().to_string(), "-0.0");
737 /// assert_eq!(Float::from(1.5).reciprocal().to_string(), "0.8");
738 /// assert_eq!(Float::from(-1.5).reciprocal().to_string(), "-0.8");
739 /// ```
740 #[inline]
741 fn reciprocal(self) -> Float {
742 let prec = self.significant_bits();
743 self.reciprocal_prec_round(prec, Nearest).0
744 }
745}
746
747impl Reciprocal for &Float {
748 type Output = Float;
749
750 /// Takes the reciprocal of a [`Float`], taking it by reference.
751 ///
752 /// If the output has a precision, it is the precision of the input. If the reciprocal is
753 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
754 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
755 /// rounding mode.
756 ///
757 /// $$
758 /// f(x,y) = 1/x+\varepsilon.
759 /// $$
760 /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
761 /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$,
762 /// where $p$ is the maximum precision of the inputs.
763 ///
764 /// Special cases:
765 /// - $f(\text{NaN})=\text{NaN}$
766 /// - $f(\infty)=0.0$
767 /// - $f(-\infty)=-0.0$
768 /// - $f(0.0)=\infty$
769 /// - $f(-0.0)=-\infty$
770 ///
771 /// If you want to use a rounding mode other than `Nearest`, consider using
772 /// [`Float::reciprocal_prec_ref`] instead. If you want to specify the output precision,
773 /// consider using [`Float::reciprocal_round_ref`]. If you want both of these things, consider
774 /// using [`Float::reciprocal_prec_round_ref`].
775 ///
776 /// # Worst-case complexity
777 /// $T(n) = O(n \log n \log\log n)$
778 ///
779 /// $M(n) = O(n \log n)$
780 ///
781 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
782 ///
783 /// # Examples
784 /// ```
785 /// use malachite_base::num::arithmetic::traits::Reciprocal;
786 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
787 /// use malachite_float::Float;
788 ///
789 /// assert!((&Float::NAN).reciprocal().is_nan());
790 /// assert_eq!((&Float::INFINITY).reciprocal().to_string(), "0.0");
791 /// assert_eq!((&Float::NEGATIVE_INFINITY).reciprocal().to_string(), "-0.0");
792 /// assert_eq!((&Float::from(1.5)).reciprocal().to_string(), "0.8");
793 /// assert_eq!((&Float::from(-1.5)).reciprocal().to_string(), "-0.8");
794 /// ```
795 #[inline]
796 fn reciprocal(self) -> Float {
797 let prec = self.significant_bits();
798 self.reciprocal_prec_round_ref(prec, Nearest).0
799 }
800}
801
802impl ReciprocalAssign for Float {
803 /// Takes the reciprocal of a [`Float`] in place.
804 ///
805 /// If the output has a precision, it is the precision of the input. If the reciprocal is
806 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
807 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
808 /// rounding mode.
809 ///
810 /// $$
811 /// x\gets = 1/x+\varepsilon.
812 /// $$
813 /// - If $1/x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
814 /// - If $1/x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |1/x|\rfloor-p}$,
815 /// where $p$ is the maximum precision of the inputs.
816 ///
817 /// See the [`Float::reciprocal`] documentation for information on special cases.
818 ///
819 /// If you want to use a rounding mode other than `Nearest`, consider using
820 /// [`Float::reciprocal_prec_assign`] instead. If you want to specify the output precision,
821 /// consider using [`Float::reciprocal_round_assign`]. If you want both of these things,
822 /// consider using [`Float::reciprocal_prec_round_assign`].
823 ///
824 /// # Worst-case complexity
825 /// $T(n) = O(n \log n \log\log n)$
826 ///
827 /// $M(n) = O(n \log n)$
828 ///
829 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
830 ///
831 /// # Examples
832 /// ```
833 /// use malachite_base::num::arithmetic::traits::ReciprocalAssign;
834 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
835 /// use malachite_float::Float;
836 ///
837 /// let mut x = Float::NAN;
838 /// x.reciprocal_assign();
839 /// assert!(x.is_nan());
840 ///
841 /// let mut x = Float::INFINITY;
842 /// x.reciprocal_assign();
843 /// assert_eq!(x.to_string(), "0.0");
844 ///
845 /// let mut x = Float::NEGATIVE_INFINITY;
846 /// x.reciprocal_assign();
847 /// assert_eq!(x.to_string(), "-0.0");
848 ///
849 /// let mut x = Float::from(1.5);
850 /// x.reciprocal_assign();
851 /// assert_eq!(x.to_string(), "0.8");
852 ///
853 /// let mut x = Float::from(-1.5);
854 /// x.reciprocal_assign();
855 /// assert_eq!(x.to_string(), "-0.8");
856 /// ```
857 #[inline]
858 fn reciprocal_assign(&mut self) {
859 let prec = self.significant_bits();
860 self.reciprocal_prec_round_assign(prec, Nearest);
861 }
862}