1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// Copyright © 2026 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
use crate::Float;
use alloc::vec::Vec;
use core::cmp::Ordering::{self, *};
use core::cmp::max;
use malachite_base::num::arithmetic::traits::{CheckedLogBase2, FloorLogBase2, Pow, PowerOf2};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::One;
use malachite_base::num::conversion::traits::{Digits, ExactFrom};
use malachite_base::num::logic::traits::{BitAccess, SignificantBits};
use malachite_base::rounding_modes::RoundingMode::{self, *};
use malachite_nz::natural::Natural;
use malachite_q::Rational;
// Rounds the exact quotient of two `Natural`s, the second nonzero, to a `Float` of the given
// precision. The conversions are exact, so the division sees the exact quotient and the returned
// `Ordering` describes the quotient itself.
fn quotient_prec_round(n: Natural, d: Natural, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
// A `Natural` needs an exponent of `significant_bits` to be a `Float`, so past `MAX_EXPONENT`
// it has no `Float` of its own even when the quotient is perfectly ordinary -- which is the
// usual case here, since the quotient is a digit expansion less than 1 while the numerator and
// denominator both grow with the precision. Building the `Rational` first never forms either
// endpoint as a `Float`. It costs a gcd, so it is worth avoiding until it is needed.
//
// Both arguments are taken by value: at these sizes the conversions would otherwise copy them,
// and one caller-side clone is cheaper than two internal ones.
if max(n.significant_bits(), d.significant_bits()) > Float::MAX_EXPONENT_U64 {
Float::from_rational_prec_round(Rational::from_naturals(n, d), prec, rm)
} else {
Float::exact_from(n).div_prec_round(Float::exact_from(d), prec, rm)
}
}
impl Float {
/// Returns an approximation of a real number, given the number's digits in a base that is a
/// power of 2.
///
/// Each digit contributes exactly $\log_2 b$ bits, so this is
/// [`non_dyadic_from_bits_prec_round`](Float::non_dyadic_from_bits_prec_round) with the digits
/// expanded, and it reads the same number of digits that that function reads bits, rounded up
/// to a whole digit.
///
/// $$
/// f((x_k),b,p,m) = C+\varepsilon, \quad C=\sum_{k=0}^\infty x_k b^{-(k+1)}.
/// $$
/// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p+1}$.
/// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$.
///
/// The output has precision `prec`.
///
/// # Preconditions
/// $C$ must not be a dyadic rational: the digits must be infinite and not eventually all zero
/// or all $b-1$. Given that, the rounded value never equals $C$, so the returned [`Ordering`]
/// is never `Equal` and `Exact` is never a sensible rounding mode. $C$ must also be less than
/// 1, which holds whenever the digits are read as lying wholly after the point.
///
/// # Worst-case complexity
/// $T(n) = O(n)$
///
/// $M(n) = O(n)$
///
/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
///
/// # Panics
/// Panics if `log_base` is zero or greater than 64, if a digit is greater than or equal to
/// $2^{\ell}$, if `prec` is zero, or if `rm` is `Exact`.
///
/// # Examples
/// ```
/// use malachite_base::rounding_modes::RoundingMode::*;
/// use malachite_float::Float;
/// use std::cmp::Ordering::*;
///
/// // 0.4444... in base 16 is 4/15
/// let (x, o) = Float::non_dyadic_from_power_of_2_digits_prec_round(
/// core::iter::repeat(4),
/// 4,
/// 20,
/// Floor,
/// );
/// assert_eq!(x.to_string(), "0.26666641");
/// assert_eq!(o, Less);
/// ```
pub fn non_dyadic_from_power_of_2_digits_prec_round<I: Iterator<Item = u64>>(
digits: I,
log_base: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert_ne!(log_base, 0);
assert!(log_base <= u64::WIDTH);
Self::non_dyadic_from_bits_prec_round(
digits.flat_map(move |d| {
assert!(
log_base == u64::WIDTH || d < u64::power_of_2(log_base),
"digit out of range"
);
(0..log_base).rev().map(move |i| d.get_bit(i))
}),
prec,
rm,
)
}
/// Returns an approximation of a real number, given the number's digits in a base that is a
/// power of 2, rounding to nearest.
///
/// See [`non_dyadic_from_power_of_2_digits_prec_round`](
/// Float::non_dyadic_from_power_of_2_digits_prec_round) for details and preconditions.
///
/// # Worst-case complexity
/// $T(n) = O(n)$
///
/// $M(n) = O(n)$
///
/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
///
/// # Panics
/// Panics if `log_base` is zero or greater than 64, if a digit is greater than or equal to
/// $2^{\ell}$, or if `prec` is zero.
///
/// # Examples
/// ```
/// use malachite_float::Float;
/// use std::cmp::Ordering::*;
///
/// let (x, o) = Float::non_dyadic_from_power_of_2_digits_prec(core::iter::repeat(4), 4, 20);
/// assert_eq!(x.to_string(), "0.26666689");
/// assert_eq!(o, Greater);
/// ```
#[inline]
pub fn non_dyadic_from_power_of_2_digits_prec<I: Iterator<Item = u64>>(
digits: I,
log_base: u64,
prec: u64,
) -> (Self, Ordering) {
Self::non_dyadic_from_power_of_2_digits_prec_round(digits, log_base, prec, Nearest)
}
/// Returns an approximation of a real number, given the number's digits in an arbitrary base.
///
/// A digit in a base that is not a power of 2 does not correspond to a whole number of bits, so
/// this reads a batch of digits, brackets $C$ between the values those digits allow, and reads
/// more if the bracket is not yet narrow enough to determine both the rounded value and its
/// position relative to $C$. When the base is a power of 2 it defers to
/// [`non_dyadic_from_power_of_2_digits_prec_round`](
/// Float::non_dyadic_from_power_of_2_digits_prec_round), which needs no such loop.
///
/// $$
/// f((x_k),b,p,m) = C+\varepsilon, \quad C=\sum_{k=0}^\infty x_k b^{-(k+1)}.
/// $$
/// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p+1}$.
/// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 C\rfloor-p}$.
///
/// The output has precision `prec`.
///
/// # Preconditions
/// $C$ must not be a dyadic rational. If it is, the bracket can never separate it from the
/// [`Float`] that equals it and this function does not terminate. Note that this is a condition
/// on $C$, not on the digits: in a base that is not a power of 2 a dyadic rational has a
/// non-terminating expansion, as $1/2$ does in base 3. Given the precondition, the rounded
/// value never equals $C$, so the returned [`Ordering`] is never `Equal` and `Exact` is never a
/// sensible rounding mode. $C$ must also be less than 1, and the iterator must be infinite.
///
/// # Worst-case complexity
/// $T(n) = O(n (\log n)^2 \log\log n)$
///
/// $M(n) = O(n \log n)$
///
/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
///
/// # Panics
/// Panics if `base` is less than 2, if a digit is greater than or equal to `base`, if `prec` is
/// zero, or if `rm` is `Exact`.
///
/// # Examples
/// ```
/// use malachite_base::rounding_modes::RoundingMode::*;
/// use malachite_float::Float;
/// use std::cmp::Ordering::*;
///
/// // 0.3333... in base 10 is 1/3
/// let (x, o) = Float::non_dyadic_from_digits_prec_round(core::iter::repeat(3), 10, 20, Floor);
/// assert_eq!(x.to_string(), "0.33333302");
/// assert_eq!(o, Less);
/// ```
pub fn non_dyadic_from_digits_prec_round<I: Iterator<Item = u64>>(
mut digits: I,
base: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert!(base >= 2, "base out of range");
assert_ne!(prec, 0);
assert_ne!(rm, Exact);
if let Some(log_base) = base.checked_log_base_2() {
return Self::non_dyadic_from_power_of_2_digits_prec_round(digits, log_base, prec, rm);
}
// Each digit carries at least `floor(log2(base))` bits, so this many digits is enough to
// cover the precision, with a few to spare for the rounding decision.
let per_digit = base.floor_log_base_2();
let mut target = (prec + 8).div_ceil(per_digit);
let base_n = Natural::from(base);
let mut buf: Vec<u64> = Vec::new();
loop {
while (buf.len() as u64) < target {
let d = digits
.next()
.expect("the digit iterator must not run out; see the preconditions");
assert!(d < base, "digit out of range");
buf.push(d);
}
let n = Natural::from_digits_desc(&base, buf.iter().copied()).unwrap();
let power = (&base_n).pow(target);
// C lies strictly between n / power and (n + 1) / power. The second call consumes both
// values, so only the first has to clone.
let (lo, o_lo) = quotient_prec_round(n.clone(), power.clone(), prec, rm);
let (hi, o_hi) = quotient_prec_round(n + Natural::ONE, power, prec, rm);
if lo == hi {
// Rounding is monotonic, so `lo` is the rounding of everything in the bracket, and
// hence of C. It only remains to place it relative to C, which the orderings of the
// endpoints settle whenever `lo` falls outside the bracket.
if o_lo != Greater {
return (lo, Less);
}
if o_hi != Less {
return (hi, Greater);
}
}
target += max(4, target >> 1);
}
}
/// Returns an approximation of a real number, given the number's digits in an arbitrary base,
/// rounding to nearest.
///
/// See [`non_dyadic_from_digits_prec_round`](Float::non_dyadic_from_digits_prec_round) for
/// details and preconditions.
///
/// # Worst-case complexity
/// $T(n) = O(n (\log n)^2 \log\log n)$
///
/// $M(n) = O(n \log n)$
///
/// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
///
/// # Panics
/// Panics if `base` is less than 2, if a digit is greater than or equal to `base`, or if `prec`
/// is zero.
///
/// # Examples
/// ```
/// use malachite_float::Float;
/// use std::cmp::Ordering::*;
///
/// let (x, o) = Float::non_dyadic_from_digits_prec(core::iter::repeat(3), 10, 20);
/// assert_eq!(x.to_string(), "0.33333349");
/// assert_eq!(o, Greater);
/// ```
#[inline]
pub fn non_dyadic_from_digits_prec<I: Iterator<Item = u64>>(
digits: I,
base: u64,
prec: u64,
) -> (Self, Ordering) {
Self::non_dyadic_from_digits_prec_round(digits, base, prec, Nearest)
}
}