1cbd624adSopenharmony_ci//! Slow, fallback cases where we cannot unambiguously round a float.
2cbd624adSopenharmony_ci//!
3cbd624adSopenharmony_ci//! This occurs when we cannot determine the exact representation using
4cbd624adSopenharmony_ci//! both the fast path (native) cases nor the Lemire/Bellerophon algorithms,
5cbd624adSopenharmony_ci//! and therefore must fallback to a slow, arbitrary-precision representation.
6cbd624adSopenharmony_ci
7cbd624adSopenharmony_ci#![doc(hidden)]
8cbd624adSopenharmony_ci
9cbd624adSopenharmony_ciuse crate::bigint::{Bigint, Limb, LIMB_BITS};
10cbd624adSopenharmony_ciuse crate::extended_float::{extended_to_float, ExtendedFloat};
11cbd624adSopenharmony_ciuse crate::num::Float;
12cbd624adSopenharmony_ciuse crate::number::Number;
13cbd624adSopenharmony_ciuse crate::rounding::{round, round_down, round_nearest_tie_even};
14cbd624adSopenharmony_ciuse core::cmp;
15cbd624adSopenharmony_ci
16cbd624adSopenharmony_ci// ALGORITHM
17cbd624adSopenharmony_ci// ---------
18cbd624adSopenharmony_ci
19cbd624adSopenharmony_ci/// Parse the significant digits and biased, binary exponent of a float.
20cbd624adSopenharmony_ci///
21cbd624adSopenharmony_ci/// This is a fallback algorithm that uses a big-integer representation
22cbd624adSopenharmony_ci/// of the float, and therefore is considerably slower than faster
23cbd624adSopenharmony_ci/// approximations. However, it will always determine how to round
24cbd624adSopenharmony_ci/// the significant digits to the nearest machine float, allowing
25cbd624adSopenharmony_ci/// use to handle near half-way cases.
26cbd624adSopenharmony_ci///
27cbd624adSopenharmony_ci/// Near half-way cases are halfway between two consecutive machine floats.
28cbd624adSopenharmony_ci/// For example, the float `16777217.0` has a bitwise representation of
29cbd624adSopenharmony_ci/// `100000000000000000000000 1`. Rounding to a single-precision float,
30cbd624adSopenharmony_ci/// the trailing `1` is truncated. Using round-nearest, tie-even, any
31cbd624adSopenharmony_ci/// value above `16777217.0` must be rounded up to `16777218.0`, while
32cbd624adSopenharmony_ci/// any value before or equal to `16777217.0` must be rounded down
33cbd624adSopenharmony_ci/// to `16777216.0`. These near-halfway conversions therefore may require
34cbd624adSopenharmony_ci/// a large number of digits to unambiguously determine how to round.
35cbd624adSopenharmony_ci#[inline]
36cbd624adSopenharmony_cipub fn slow<'a, F, Iter1, Iter2>(
37cbd624adSopenharmony_ci    num: Number,
38cbd624adSopenharmony_ci    fp: ExtendedFloat,
39cbd624adSopenharmony_ci    integer: Iter1,
40cbd624adSopenharmony_ci    fraction: Iter2,
41cbd624adSopenharmony_ci) -> ExtendedFloat
42cbd624adSopenharmony_ciwhere
43cbd624adSopenharmony_ci    F: Float,
44cbd624adSopenharmony_ci    Iter1: Iterator<Item = &'a u8> + Clone,
45cbd624adSopenharmony_ci    Iter2: Iterator<Item = &'a u8> + Clone,
46cbd624adSopenharmony_ci{
47cbd624adSopenharmony_ci    // Ensure our preconditions are valid:
48cbd624adSopenharmony_ci    //  1. The significant digits are not shifted into place.
49cbd624adSopenharmony_ci    debug_assert!(fp.mant & (1 << 63) != 0);
50cbd624adSopenharmony_ci
51cbd624adSopenharmony_ci    // This assumes the sign bit has already been parsed, and we're
52cbd624adSopenharmony_ci    // starting with the integer digits, and the float format has been
53cbd624adSopenharmony_ci    // correctly validated.
54cbd624adSopenharmony_ci    let sci_exp = scientific_exponent(&num);
55cbd624adSopenharmony_ci
56cbd624adSopenharmony_ci    // We have 2 major algorithms we use for this:
57cbd624adSopenharmony_ci    //  1. An algorithm with a finite number of digits and a positive exponent.
58cbd624adSopenharmony_ci    //  2. An algorithm with a finite number of digits and a negative exponent.
59cbd624adSopenharmony_ci    let (bigmant, digits) = parse_mantissa(integer, fraction, F::MAX_DIGITS);
60cbd624adSopenharmony_ci    let exponent = sci_exp + 1 - digits as i32;
61cbd624adSopenharmony_ci    if exponent >= 0 {
62cbd624adSopenharmony_ci        positive_digit_comp::<F>(bigmant, exponent)
63cbd624adSopenharmony_ci    } else {
64cbd624adSopenharmony_ci        negative_digit_comp::<F>(bigmant, fp, exponent)
65cbd624adSopenharmony_ci    }
66cbd624adSopenharmony_ci}
67cbd624adSopenharmony_ci
68cbd624adSopenharmony_ci/// Generate the significant digits with a positive exponent relative to mantissa.
69cbd624adSopenharmony_cipub fn positive_digit_comp<F: Float>(mut bigmant: Bigint, exponent: i32) -> ExtendedFloat {
70cbd624adSopenharmony_ci    // Simple, we just need to multiply by the power of the radix.
71cbd624adSopenharmony_ci    // Now, we can calculate the mantissa and the exponent from this.
72cbd624adSopenharmony_ci    // The binary exponent is the binary exponent for the mantissa
73cbd624adSopenharmony_ci    // shifted to the hidden bit.
74cbd624adSopenharmony_ci    bigmant.pow(10, exponent as u32).unwrap();
75cbd624adSopenharmony_ci
76cbd624adSopenharmony_ci    // Get the exact representation of the float from the big integer.
77cbd624adSopenharmony_ci    // hi64 checks **all** the remaining bits after the mantissa,
78cbd624adSopenharmony_ci    // so it will check if **any** truncated digits exist.
79cbd624adSopenharmony_ci    let (mant, is_truncated) = bigmant.hi64();
80cbd624adSopenharmony_ci    let exp = bigmant.bit_length() as i32 - 64 + F::EXPONENT_BIAS;
81cbd624adSopenharmony_ci    let mut fp = ExtendedFloat {
82cbd624adSopenharmony_ci        mant,
83cbd624adSopenharmony_ci        exp,
84cbd624adSopenharmony_ci    };
85cbd624adSopenharmony_ci
86cbd624adSopenharmony_ci    // Shift the digits into position and determine if we need to round-up.
87cbd624adSopenharmony_ci    round::<F, _>(&mut fp, |f, s| {
88cbd624adSopenharmony_ci        round_nearest_tie_even(f, s, |is_odd, is_halfway, is_above| {
89cbd624adSopenharmony_ci            is_above || (is_halfway && is_truncated) || (is_odd && is_halfway)
90cbd624adSopenharmony_ci        });
91cbd624adSopenharmony_ci    });
92cbd624adSopenharmony_ci    fp
93cbd624adSopenharmony_ci}
94cbd624adSopenharmony_ci
95cbd624adSopenharmony_ci/// Generate the significant digits with a negative exponent relative to mantissa.
96cbd624adSopenharmony_ci///
97cbd624adSopenharmony_ci/// This algorithm is quite simple: we have the significant digits `m1 * b^N1`,
98cbd624adSopenharmony_ci/// where `m1` is the bigint mantissa, `b` is the radix, and `N1` is the radix
99cbd624adSopenharmony_ci/// exponent. We then calculate the theoretical representation of `b+h`, which
100cbd624adSopenharmony_ci/// is `m2 * 2^N2`, where `m2` is the bigint mantissa and `N2` is the binary
101cbd624adSopenharmony_ci/// exponent. If we had infinite, efficient floating precision, this would be
102cbd624adSopenharmony_ci/// equal to `m1 / b^-N1` and then compare it to `m2 * 2^N2`.
103cbd624adSopenharmony_ci///
104cbd624adSopenharmony_ci/// Since we cannot divide and keep precision, we must multiply the other:
105cbd624adSopenharmony_ci/// if we want to do `m1 / b^-N1 >= m2 * 2^N2`, we can do
106cbd624adSopenharmony_ci/// `m1 >= m2 * b^-N1 * 2^N2` Going to the decimal case, we can show and example
107cbd624adSopenharmony_ci/// and simplify this further: `m1 >= m2 * 2^N2 * 10^-N1`. Since we can remove
108cbd624adSopenharmony_ci/// a power-of-two, this is `m1 >= m2 * 2^(N2 - N1) * 5^-N1`. Therefore, if
109cbd624adSopenharmony_ci/// `N2 - N1 > 0`, we need have `m1 >= m2 * 2^(N2 - N1) * 5^-N1`, otherwise,
110cbd624adSopenharmony_ci/// we have `m1 * 2^(N1 - N2) >= m2 * 5^-N1`, where the resulting exponents
111cbd624adSopenharmony_ci/// are all positive.
112cbd624adSopenharmony_ci///
113cbd624adSopenharmony_ci/// This allows us to compare both floats using integers efficiently
114cbd624adSopenharmony_ci/// without any loss of precision.
115cbd624adSopenharmony_ci#[allow(clippy::comparison_chain)]
116cbd624adSopenharmony_cipub fn negative_digit_comp<F: Float>(
117cbd624adSopenharmony_ci    bigmant: Bigint,
118cbd624adSopenharmony_ci    mut fp: ExtendedFloat,
119cbd624adSopenharmony_ci    exponent: i32,
120cbd624adSopenharmony_ci) -> ExtendedFloat {
121cbd624adSopenharmony_ci    // Ensure our preconditions are valid:
122cbd624adSopenharmony_ci    //  1. The significant digits are not shifted into place.
123cbd624adSopenharmony_ci    debug_assert!(fp.mant & (1 << 63) != 0);
124cbd624adSopenharmony_ci
125cbd624adSopenharmony_ci    // Get the significant digits and radix exponent for the real digits.
126cbd624adSopenharmony_ci    let mut real_digits = bigmant;
127cbd624adSopenharmony_ci    let real_exp = exponent;
128cbd624adSopenharmony_ci    debug_assert!(real_exp < 0);
129cbd624adSopenharmony_ci
130cbd624adSopenharmony_ci    // Round down our extended-precision float and calculate `b`.
131cbd624adSopenharmony_ci    let mut b = fp;
132cbd624adSopenharmony_ci    round::<F, _>(&mut b, round_down);
133cbd624adSopenharmony_ci    let b = extended_to_float::<F>(b);
134cbd624adSopenharmony_ci
135cbd624adSopenharmony_ci    // Get the significant digits and the binary exponent for `b+h`.
136cbd624adSopenharmony_ci    let theor = bh(b);
137cbd624adSopenharmony_ci    let mut theor_digits = Bigint::from_u64(theor.mant);
138cbd624adSopenharmony_ci    let theor_exp = theor.exp;
139cbd624adSopenharmony_ci
140cbd624adSopenharmony_ci    // We need to scale the real digits and `b+h` digits to be the same
141cbd624adSopenharmony_ci    // order. We currently have `real_exp`, in `radix`, that needs to be
142cbd624adSopenharmony_ci    // shifted to `theor_digits` (since it is negative), and `theor_exp`
143cbd624adSopenharmony_ci    // to either `theor_digits` or `real_digits` as a power of 2 (since it
144cbd624adSopenharmony_ci    // may be positive or negative). Try to remove as many powers of 2
145cbd624adSopenharmony_ci    // as possible. All values are relative to `theor_digits`, that is,
146cbd624adSopenharmony_ci    // reflect the power you need to multiply `theor_digits` by.
147cbd624adSopenharmony_ci    //
148cbd624adSopenharmony_ci    // Both are on opposite-sides of equation, can factor out a
149cbd624adSopenharmony_ci    // power of two.
150cbd624adSopenharmony_ci    //
151cbd624adSopenharmony_ci    // Example: 10^-10, 2^-10   -> ( 0, 10, 0)
152cbd624adSopenharmony_ci    // Example: 10^-10, 2^-15   -> (-5, 10, 0)
153cbd624adSopenharmony_ci    // Example: 10^-10, 2^-5    -> ( 5, 10, 0)
154cbd624adSopenharmony_ci    // Example: 10^-10, 2^5     -> (15, 10, 0)
155cbd624adSopenharmony_ci    let binary_exp = theor_exp - real_exp;
156cbd624adSopenharmony_ci    let halfradix_exp = -real_exp;
157cbd624adSopenharmony_ci    if halfradix_exp != 0 {
158cbd624adSopenharmony_ci        theor_digits.pow(5, halfradix_exp as u32).unwrap();
159cbd624adSopenharmony_ci    }
160cbd624adSopenharmony_ci    if binary_exp > 0 {
161cbd624adSopenharmony_ci        theor_digits.pow(2, binary_exp as u32).unwrap();
162cbd624adSopenharmony_ci    } else if binary_exp < 0 {
163cbd624adSopenharmony_ci        real_digits.pow(2, (-binary_exp) as u32).unwrap();
164cbd624adSopenharmony_ci    }
165cbd624adSopenharmony_ci
166cbd624adSopenharmony_ci    // Compare our theoretical and real digits and round nearest, tie even.
167cbd624adSopenharmony_ci    let ord = real_digits.data.cmp(&theor_digits.data);
168cbd624adSopenharmony_ci    round::<F, _>(&mut fp, |f, s| {
169cbd624adSopenharmony_ci        round_nearest_tie_even(f, s, |is_odd, _, _| {
170cbd624adSopenharmony_ci            // Can ignore `is_halfway` and `is_above`, since those were
171cbd624adSopenharmony_ci            // calculates using less significant digits.
172cbd624adSopenharmony_ci            match ord {
173cbd624adSopenharmony_ci                cmp::Ordering::Greater => true,
174cbd624adSopenharmony_ci                cmp::Ordering::Less => false,
175cbd624adSopenharmony_ci                cmp::Ordering::Equal if is_odd => true,
176cbd624adSopenharmony_ci                cmp::Ordering::Equal => false,
177cbd624adSopenharmony_ci            }
178cbd624adSopenharmony_ci        });
179cbd624adSopenharmony_ci    });
180cbd624adSopenharmony_ci    fp
181cbd624adSopenharmony_ci}
182cbd624adSopenharmony_ci
183cbd624adSopenharmony_ci/// Add a digit to the temporary value.
184cbd624adSopenharmony_cimacro_rules! add_digit {
185cbd624adSopenharmony_ci    ($c:ident, $value:ident, $counter:ident, $count:ident) => {{
186cbd624adSopenharmony_ci        let digit = $c - b'0';
187cbd624adSopenharmony_ci        $value *= 10 as Limb;
188cbd624adSopenharmony_ci        $value += digit as Limb;
189cbd624adSopenharmony_ci
190cbd624adSopenharmony_ci        // Increment our counters.
191cbd624adSopenharmony_ci        $counter += 1;
192cbd624adSopenharmony_ci        $count += 1;
193cbd624adSopenharmony_ci    }};
194cbd624adSopenharmony_ci}
195cbd624adSopenharmony_ci
196cbd624adSopenharmony_ci/// Add a temporary value to our mantissa.
197cbd624adSopenharmony_cimacro_rules! add_temporary {
198cbd624adSopenharmony_ci    // Multiply by the small power and add the native value.
199cbd624adSopenharmony_ci    (@mul $result:ident, $power:expr, $value:expr) => {
200cbd624adSopenharmony_ci        $result.data.mul_small($power).unwrap();
201cbd624adSopenharmony_ci        $result.data.add_small($value).unwrap();
202cbd624adSopenharmony_ci    };
203cbd624adSopenharmony_ci
204cbd624adSopenharmony_ci    // # Safety
205cbd624adSopenharmony_ci    //
206cbd624adSopenharmony_ci    // Safe is `counter <= step`, or smaller than the table size.
207cbd624adSopenharmony_ci    ($format:ident, $result:ident, $counter:ident, $value:ident) => {
208cbd624adSopenharmony_ci        if $counter != 0 {
209cbd624adSopenharmony_ci            // SAFETY: safe, since `counter <= step`, or smaller than the table size.
210cbd624adSopenharmony_ci            let small_power = unsafe { f64::int_pow_fast_path($counter, 10) };
211cbd624adSopenharmony_ci            add_temporary!(@mul $result, small_power as Limb, $value);
212cbd624adSopenharmony_ci            $counter = 0;
213cbd624adSopenharmony_ci            $value = 0;
214cbd624adSopenharmony_ci        }
215cbd624adSopenharmony_ci    };
216cbd624adSopenharmony_ci
217cbd624adSopenharmony_ci    // Add a temporary where we won't read the counter results internally.
218cbd624adSopenharmony_ci    //
219cbd624adSopenharmony_ci    // # Safety
220cbd624adSopenharmony_ci    //
221cbd624adSopenharmony_ci    // Safe is `counter <= step`, or smaller than the table size.
222cbd624adSopenharmony_ci    (@end $format:ident, $result:ident, $counter:ident, $value:ident) => {
223cbd624adSopenharmony_ci        if $counter != 0 {
224cbd624adSopenharmony_ci            // SAFETY: safe, since `counter <= step`, or smaller than the table size.
225cbd624adSopenharmony_ci            let small_power = unsafe { f64::int_pow_fast_path($counter, 10) };
226cbd624adSopenharmony_ci            add_temporary!(@mul $result, small_power as Limb, $value);
227cbd624adSopenharmony_ci        }
228cbd624adSopenharmony_ci    };
229cbd624adSopenharmony_ci
230cbd624adSopenharmony_ci    // Add the maximum native value.
231cbd624adSopenharmony_ci    (@max $format:ident, $result:ident, $counter:ident, $value:ident, $max:ident) => {
232cbd624adSopenharmony_ci        add_temporary!(@mul $result, $max, $value);
233cbd624adSopenharmony_ci        $counter = 0;
234cbd624adSopenharmony_ci        $value = 0;
235cbd624adSopenharmony_ci    };
236cbd624adSopenharmony_ci}
237cbd624adSopenharmony_ci
238cbd624adSopenharmony_ci/// Round-up a truncated value.
239cbd624adSopenharmony_cimacro_rules! round_up_truncated {
240cbd624adSopenharmony_ci    ($format:ident, $result:ident, $count:ident) => {{
241cbd624adSopenharmony_ci        // Need to round-up.
242cbd624adSopenharmony_ci        // Can't just add 1, since this can accidentally round-up
243cbd624adSopenharmony_ci        // values to a halfway point, which can cause invalid results.
244cbd624adSopenharmony_ci        add_temporary!(@mul $result, 10, 1);
245cbd624adSopenharmony_ci        $count += 1;
246cbd624adSopenharmony_ci    }};
247cbd624adSopenharmony_ci}
248cbd624adSopenharmony_ci
249cbd624adSopenharmony_ci/// Check and round-up the fraction if any non-zero digits exist.
250cbd624adSopenharmony_cimacro_rules! round_up_nonzero {
251cbd624adSopenharmony_ci    ($format:ident, $iter:expr, $result:ident, $count:ident) => {{
252cbd624adSopenharmony_ci        for &digit in $iter {
253cbd624adSopenharmony_ci            if digit != b'0' {
254cbd624adSopenharmony_ci                round_up_truncated!($format, $result, $count);
255cbd624adSopenharmony_ci                return ($result, $count);
256cbd624adSopenharmony_ci            }
257cbd624adSopenharmony_ci        }
258cbd624adSopenharmony_ci    }};
259cbd624adSopenharmony_ci}
260cbd624adSopenharmony_ci
261cbd624adSopenharmony_ci/// Parse the full mantissa into a big integer.
262cbd624adSopenharmony_ci///
263cbd624adSopenharmony_ci/// Returns the parsed mantissa and the number of digits in the mantissa.
264cbd624adSopenharmony_ci/// The max digits is the maximum number of digits plus one.
265cbd624adSopenharmony_cipub fn parse_mantissa<'a, Iter1, Iter2>(
266cbd624adSopenharmony_ci    mut integer: Iter1,
267cbd624adSopenharmony_ci    mut fraction: Iter2,
268cbd624adSopenharmony_ci    max_digits: usize,
269cbd624adSopenharmony_ci) -> (Bigint, usize)
270cbd624adSopenharmony_ciwhere
271cbd624adSopenharmony_ci    Iter1: Iterator<Item = &'a u8> + Clone,
272cbd624adSopenharmony_ci    Iter2: Iterator<Item = &'a u8> + Clone,
273cbd624adSopenharmony_ci{
274cbd624adSopenharmony_ci    // Iteratively process all the data in the mantissa.
275cbd624adSopenharmony_ci    // We do this via small, intermediate values which once we reach
276cbd624adSopenharmony_ci    // the maximum number of digits we can process without overflow,
277cbd624adSopenharmony_ci    // we add the temporary to the big integer.
278cbd624adSopenharmony_ci    let mut counter: usize = 0;
279cbd624adSopenharmony_ci    let mut count: usize = 0;
280cbd624adSopenharmony_ci    let mut value: Limb = 0;
281cbd624adSopenharmony_ci    let mut result = Bigint::new();
282cbd624adSopenharmony_ci
283cbd624adSopenharmony_ci    // Now use our pre-computed small powers iteratively.
284cbd624adSopenharmony_ci    // This is calculated as `⌊log(2^BITS - 1, 10)⌋`.
285cbd624adSopenharmony_ci    let step: usize = if LIMB_BITS == 32 {
286cbd624adSopenharmony_ci        9
287cbd624adSopenharmony_ci    } else {
288cbd624adSopenharmony_ci        19
289cbd624adSopenharmony_ci    };
290cbd624adSopenharmony_ci    let max_native = (10 as Limb).pow(step as u32);
291cbd624adSopenharmony_ci
292cbd624adSopenharmony_ci    // Process the integer digits.
293cbd624adSopenharmony_ci    'integer: loop {
294cbd624adSopenharmony_ci        // Parse a digit at a time, until we reach step.
295cbd624adSopenharmony_ci        while counter < step && count < max_digits {
296cbd624adSopenharmony_ci            if let Some(&c) = integer.next() {
297cbd624adSopenharmony_ci                add_digit!(c, value, counter, count);
298cbd624adSopenharmony_ci            } else {
299cbd624adSopenharmony_ci                break 'integer;
300cbd624adSopenharmony_ci            }
301cbd624adSopenharmony_ci        }
302cbd624adSopenharmony_ci
303cbd624adSopenharmony_ci        // Check if we've exhausted our max digits.
304cbd624adSopenharmony_ci        if count == max_digits {
305cbd624adSopenharmony_ci            // Need to check if we're truncated, and round-up accordingly.
306cbd624adSopenharmony_ci            // SAFETY: safe since `counter <= step`.
307cbd624adSopenharmony_ci            add_temporary!(@end format, result, counter, value);
308cbd624adSopenharmony_ci            round_up_nonzero!(format, integer, result, count);
309cbd624adSopenharmony_ci            round_up_nonzero!(format, fraction, result, count);
310cbd624adSopenharmony_ci            return (result, count);
311cbd624adSopenharmony_ci        } else {
312cbd624adSopenharmony_ci            // Add our temporary from the loop.
313cbd624adSopenharmony_ci            // SAFETY: safe since `counter <= step`.
314cbd624adSopenharmony_ci            add_temporary!(@max format, result, counter, value, max_native);
315cbd624adSopenharmony_ci        }
316cbd624adSopenharmony_ci    }
317cbd624adSopenharmony_ci
318cbd624adSopenharmony_ci    // Skip leading fraction zeros.
319cbd624adSopenharmony_ci    // Required to get an accurate count.
320cbd624adSopenharmony_ci    if count == 0 {
321cbd624adSopenharmony_ci        for &c in &mut fraction {
322cbd624adSopenharmony_ci            if c != b'0' {
323cbd624adSopenharmony_ci                add_digit!(c, value, counter, count);
324cbd624adSopenharmony_ci                break;
325cbd624adSopenharmony_ci            }
326cbd624adSopenharmony_ci        }
327cbd624adSopenharmony_ci    }
328cbd624adSopenharmony_ci
329cbd624adSopenharmony_ci    // Process the fraction digits.
330cbd624adSopenharmony_ci    'fraction: loop {
331cbd624adSopenharmony_ci        // Parse a digit at a time, until we reach step.
332cbd624adSopenharmony_ci        while counter < step && count < max_digits {
333cbd624adSopenharmony_ci            if let Some(&c) = fraction.next() {
334cbd624adSopenharmony_ci                add_digit!(c, value, counter, count);
335cbd624adSopenharmony_ci            } else {
336cbd624adSopenharmony_ci                break 'fraction;
337cbd624adSopenharmony_ci            }
338cbd624adSopenharmony_ci        }
339cbd624adSopenharmony_ci
340cbd624adSopenharmony_ci        // Check if we've exhausted our max digits.
341cbd624adSopenharmony_ci        if count == max_digits {
342cbd624adSopenharmony_ci            // SAFETY: safe since `counter <= step`.
343cbd624adSopenharmony_ci            add_temporary!(@end format, result, counter, value);
344cbd624adSopenharmony_ci            round_up_nonzero!(format, fraction, result, count);
345cbd624adSopenharmony_ci            return (result, count);
346cbd624adSopenharmony_ci        } else {
347cbd624adSopenharmony_ci            // Add our temporary from the loop.
348cbd624adSopenharmony_ci            // SAFETY: safe since `counter <= step`.
349cbd624adSopenharmony_ci            add_temporary!(@max format, result, counter, value, max_native);
350cbd624adSopenharmony_ci        }
351cbd624adSopenharmony_ci    }
352cbd624adSopenharmony_ci
353cbd624adSopenharmony_ci    // We will always have a remainder, as long as we entered the loop
354cbd624adSopenharmony_ci    // once, or counter % step is 0.
355cbd624adSopenharmony_ci    // SAFETY: safe since `counter <= step`.
356cbd624adSopenharmony_ci    add_temporary!(@end format, result, counter, value);
357cbd624adSopenharmony_ci
358cbd624adSopenharmony_ci    (result, count)
359cbd624adSopenharmony_ci}
360cbd624adSopenharmony_ci
361cbd624adSopenharmony_ci// SCALING
362cbd624adSopenharmony_ci// -------
363cbd624adSopenharmony_ci
364cbd624adSopenharmony_ci/// Calculate the scientific exponent from a `Number` value.
365cbd624adSopenharmony_ci/// Any other attempts would require slowdowns for faster algorithms.
366cbd624adSopenharmony_ci#[inline]
367cbd624adSopenharmony_cipub fn scientific_exponent(num: &Number) -> i32 {
368cbd624adSopenharmony_ci    // Use power reduction to make this faster.
369cbd624adSopenharmony_ci    let mut mantissa = num.mantissa;
370cbd624adSopenharmony_ci    let mut exponent = num.exponent;
371cbd624adSopenharmony_ci    while mantissa >= 10000 {
372cbd624adSopenharmony_ci        mantissa /= 10000;
373cbd624adSopenharmony_ci        exponent += 4;
374cbd624adSopenharmony_ci    }
375cbd624adSopenharmony_ci    while mantissa >= 100 {
376cbd624adSopenharmony_ci        mantissa /= 100;
377cbd624adSopenharmony_ci        exponent += 2;
378cbd624adSopenharmony_ci    }
379cbd624adSopenharmony_ci    while mantissa >= 10 {
380cbd624adSopenharmony_ci        mantissa /= 10;
381cbd624adSopenharmony_ci        exponent += 1;
382cbd624adSopenharmony_ci    }
383cbd624adSopenharmony_ci    exponent as i32
384cbd624adSopenharmony_ci}
385cbd624adSopenharmony_ci
386cbd624adSopenharmony_ci/// Calculate `b` from a a representation of `b` as a float.
387cbd624adSopenharmony_ci#[inline]
388cbd624adSopenharmony_cipub fn b<F: Float>(float: F) -> ExtendedFloat {
389cbd624adSopenharmony_ci    ExtendedFloat {
390cbd624adSopenharmony_ci        mant: float.mantissa(),
391cbd624adSopenharmony_ci        exp: float.exponent(),
392cbd624adSopenharmony_ci    }
393cbd624adSopenharmony_ci}
394cbd624adSopenharmony_ci
395cbd624adSopenharmony_ci/// Calculate `b+h` from a a representation of `b` as a float.
396cbd624adSopenharmony_ci#[inline]
397cbd624adSopenharmony_cipub fn bh<F: Float>(float: F) -> ExtendedFloat {
398cbd624adSopenharmony_ci    let fp = b(float);
399cbd624adSopenharmony_ci    ExtendedFloat {
400cbd624adSopenharmony_ci        mant: (fp.mant << 1) + 1,
401cbd624adSopenharmony_ci        exp: fp.exp - 1,
402cbd624adSopenharmony_ci    }
403cbd624adSopenharmony_ci}
404