Skip to main content

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}