malachite_float/float/basic/can_round.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright © 1999-2025 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::Float;
14use crate::InnerFloat::Finite;
15use malachite_base::rounding_modes::RoundingMode::{self, Exact};
16use malachite_nz::natural::arithmetic::float::round::float_can_round_raw;
17
18impl Float {
19 // This is mpfr_can_round from round_prec.c, MPFR 4.2.2, without the faithful-rounding cases,
20 // which have no counterpart among Malachite's rounding modes.
21 /// Determines whether an approximation is accurate enough to commit to a correctly rounded
22 /// result.
23 ///
24 /// `self` should be an approximation of some unknown real number $x$, obtained by rounding in
25 /// the direction `rnd1` with error at most $2^{e-\\text{{err}}}$, where $e$ is the raw exponent
26 /// of `self` (so the error is at most one ulp of `self` when `err` equals the precision of
27 /// `self`). This function returns whether that information suffices to round $x$ correctly to
28 /// precision `prec` in the direction `rnd2` — that is, whether every real number consistent
29 /// with the approximation rounds to the same value. If it returns true, rounding `self` to
30 /// precision `prec` with `rnd2` gives that value.
31 ///
32 /// This is the test at the heart of Ziv's strategy for computing correctly rounded functions:
33 /// compute an approximation with a known error bound, and retry with more precision until this
34 /// function accepts it.
35 ///
36 /// If `self` is `NaN`, infinite, or zero, the result is `false`: no error bound of this form
37 /// conveys enough information to round those.
38 ///
39 /// # Worst-case complexity
40 /// $T(n) = O(n)$
41 ///
42 /// $M(n) = O(n)$
43 ///
44 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
45 ///
46 /// # Panics
47 /// Panics if `prec` is zero, or if `rnd1` or `rnd2` is `Exact`.
48 ///
49 /// # Examples
50 /// ```
51 /// use malachite_base::num::basic::traits::Two;
52 /// use malachite_base::rounding_modes::RoundingMode::*;
53 /// use malachite_float::Float;
54 ///
55 /// // A 100-bit approximation of sqrt(2), accurate to about 90 bits, is more than enough
56 /// // to round to double precision...
57 /// let x = Float::TWO.sqrt_prec(100).0;
58 /// assert!(x.can_round(90, Nearest, Nearest, 53));
59 ///
60 /// // ...but knowing only 53 of its bits is not.
61 /// assert!(!x.can_round(53, Nearest, Nearest, 53));
62 /// ```
63 pub fn can_round(&self, err: i64, rnd1: RoundingMode, rnd2: RoundingMode, prec: u64) -> bool {
64 assert_ne!(prec, 0);
65 assert_ne!(rnd1, Exact);
66 assert_ne!(rnd2, Exact);
67 match self {
68 Self(Finite {
69 sign, significand, ..
70 }) => float_can_round_raw(significand, !sign, err, rnd1, rnd2, prec),
71 _ => false,
72 }
73 }
74}