Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexical-parse-float-1.0.6/src/lemire.rs
Line
Count
Source
1
//! Implementation of the Eisel-Lemire algorithm.
2
//!
3
//! This is adapted from [fast-float-rust](https://github.com/aldanor/fast-float-rust),
4
//! a port of [fast_float](https://github.com/fastfloat/fast_float) to Rust.
5
6
#![cfg(not(feature = "compact"))]
7
#![doc(hidden)]
8
9
use crate::float::{ExtendedFloat80, LemireFloat};
10
use crate::number::Number;
11
use crate::shared;
12
use crate::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE};
13
14
/// Ensure truncation of digits doesn't affect our computation, by doing 2
15
/// passes.
16
#[must_use]
17
#[inline(always)]
18
3.74k
pub fn lemire<F: LemireFloat>(num: &Number, lossy: bool) -> ExtendedFloat80 {
19
    // If significant digits were truncated, then we can have rounding error
20
    // only if `mantissa + 1` produces a different result. We also avoid
21
    // redundantly using the Eisel-Lemire algorithm if it was unable to
22
    // correctly round on the first pass.
23
3.74k
    let mut fp = compute_float::<F>(num.exponent, num.mantissa, lossy);
24
3.74k
    if !lossy
25
3.74k
        && num.many_digits
26
2.63k
        && fp.exp >= 0
27
2.63k
        && fp != compute_float::<F>(num.exponent, num.mantissa + 1, false)
28
1.37k
    {
29
1.37k
        // Need to re-calculate, since the previous values are rounded
30
1.37k
        // when the slow path algorithm expects a normalized extended float.
31
1.37k
        fp = compute_error::<F>(num.exponent, num.mantissa);
32
2.36k
    }
33
3.74k
    fp
34
3.74k
}
lexical_parse_float::lemire::lemire::<f64>
Line
Count
Source
18
3.74k
pub fn lemire<F: LemireFloat>(num: &Number, lossy: bool) -> ExtendedFloat80 {
19
    // If significant digits were truncated, then we can have rounding error
20
    // only if `mantissa + 1` produces a different result. We also avoid
21
    // redundantly using the Eisel-Lemire algorithm if it was unable to
22
    // correctly round on the first pass.
23
3.74k
    let mut fp = compute_float::<F>(num.exponent, num.mantissa, lossy);
24
3.74k
    if !lossy
25
3.74k
        && num.many_digits
26
2.63k
        && fp.exp >= 0
27
2.63k
        && fp != compute_float::<F>(num.exponent, num.mantissa + 1, false)
28
1.37k
    {
29
1.37k
        // Need to re-calculate, since the previous values are rounded
30
1.37k
        // when the slow path algorithm expects a normalized extended float.
31
1.37k
        fp = compute_error::<F>(num.exponent, num.mantissa);
32
2.36k
    }
33
3.74k
    fp
34
3.74k
}
Unexecuted instantiation: lexical_parse_float::lemire::lemire::<_>
35
36
/// Compute a float using an extended-precision representation.
37
///
38
/// Fast conversion of a the significant digits and decimal exponent
39
/// a float to a extended representation with a binary float. This
40
/// algorithm will accurately parse the vast majority of cases,
41
/// and uses a 128-bit representation (with a fallback 192-bit
42
/// representation).
43
///
44
/// This algorithm scales the exponent by the decimal exponent
45
/// using pre-computed powers-of-5, and calculates if the
46
/// representation can be unambiguously rounded to the nearest
47
/// machine float. Near-halfway cases are not handled here,
48
/// and are represented by a negative, biased binary exponent.
49
///
50
/// The algorithm is described in detail in "Daniel Lemire, Number Parsing
51
/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and
52
/// section 6, "Exact Numbers And Ties", available online:
53
/// <https://arxiv.org/abs/2101.11408.pdf>.
54
#[inline]
55
#[must_use]
56
#[allow(clippy::missing_inline_in_public_items)] // reason="public for testing only"
57
6.37k
pub fn compute_float<F: LemireFloat>(q: i64, mut w: u64, lossy: bool) -> ExtendedFloat80 {
58
6.37k
    let fp_zero = ExtendedFloat80 {
59
6.37k
        mant: 0,
60
6.37k
        exp: 0,
61
6.37k
    };
62
6.37k
    let fp_inf = ExtendedFloat80 {
63
6.37k
        mant: 0,
64
6.37k
        exp: F::INFINITE_POWER,
65
6.37k
    };
66
67
    // Short-circuit if the value can only be a literal 0 or infinity.
68
6.37k
    if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 {
69
390
        return fp_zero;
70
5.98k
    } else if q > F::LARGEST_POWER_OF_TEN as i64 {
71
190
        return fp_inf;
72
5.79k
    }
73
    // Normalize our significant digits, so the most-significant bit is set.
74
5.79k
    let lz = w.leading_zeros() as i32;
75
5.79k
    w <<= lz;
76
5.79k
    let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3);
77
5.79k
    if !lossy && lo == 0xFFFF_FFFF_FFFF_FFFF {
78
        // If we have failed to approximate `w x 5^-q` with our 128-bit value.
79
        // Since the addition of 1 could lead to an overflow which could then
80
        // round up over the half-way point, this can lead to improper rounding
81
        // of a float.
82
        //
83
        // However, this can only occur if `q ∈ [-27, 55]`. The upper bound of q
84
        // is 55 because `5^55 < 2^128`, however, this can only happen if `5^q > 2^64`,
85
        // since otherwise the product can be represented in 64-bits, producing
86
        // an exact result. For negative exponents, rounding-to-even can
87
        // only occur if `5^-q < 2^64`.
88
        //
89
        // For detailed explanations of rounding for negative exponents, see
90
        // <https://arxiv.org/pdf/2101.11408.pdf#section.9.1>. For detailed
91
        // explanations of rounding for positive exponents, see
92
        // <https://arxiv.org/pdf/2101.11408.pdf#section.8>.
93
0
        let inside_safe_exponent = (-27..=55).contains(&q);
94
0
        if !inside_safe_exponent {
95
0
            return compute_error_scaled::<F>(q, hi, lz);
96
0
        }
97
5.79k
    }
98
5.79k
    let upperbit = (hi >> 63) as i32;
99
5.79k
    let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_SIZE - 3);
100
5.79k
    let mut power2 = power(q as i32) + upperbit - lz - F::MINIMUM_EXPONENT;
101
5.79k
    if power2 <= 0 {
102
35
        if -power2 + 1 >= 64 {
103
            // Have more than 64 bits below the minimum exponent, must be 0.
104
13
            return fp_zero;
105
22
        }
106
        // Have a subnormal value.
107
22
        mantissa >>= -power2 + 1;
108
22
        mantissa += mantissa & 1;
109
22
        mantissa >>= 1;
110
22
        power2 = (mantissa >= (1_u64 << F::MANTISSA_SIZE)) as i32;
111
22
        return ExtendedFloat80 {
112
22
            mant: mantissa,
113
22
            exp: power2,
114
22
        };
115
5.76k
    }
116
    // Need to handle rounding ties. Normally, we need to round up,
117
    // but if we fall right in between and and we have an even basis, we
118
    // need to round down.
119
    //
120
    // This will only occur if:
121
    //  1. The lower 64 bits of the 128-bit representation is 0. IE, `5^q` fits in
122
    //     single 64-bit word.
123
    //  2. The least-significant bit prior to truncated mantissa is odd.
124
    //  3. All the bits truncated when shifting to mantissa bits + 1 are 0.
125
    //
126
    // Or, we may fall between two floats: we are exactly halfway.
127
5.76k
    if lo <= 1
128
1.73k
        && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64
129
1.60k
        && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64
130
1.54k
        && mantissa & 3 == 1
131
664
        && (mantissa << (upperbit + 64 - F::MANTISSA_SIZE - 3)) == hi
132
371
    {
133
371
        // Zero the lowest bit, so we don't round up.
134
371
        mantissa &= !1_u64;
135
5.39k
    }
136
    // Round-to-even, then shift the significant digits into place.
137
5.76k
    mantissa += mantissa & 1;
138
5.76k
    mantissa >>= 1;
139
5.76k
    if mantissa >= (2_u64 << F::MANTISSA_SIZE) {
140
43
        // Rounding up overflowed, so the carry bit is set. Set the
141
43
        // mantissa to 1 (only the implicit, hidden bit is set) and
142
43
        // increase the exponent.
143
43
        mantissa = 1_u64 << F::MANTISSA_SIZE;
144
43
        power2 += 1;
145
5.72k
    }
146
    // Zero out the hidden bit.
147
5.76k
    mantissa &= !(1_u64 << F::MANTISSA_SIZE);
148
5.76k
    if power2 >= F::INFINITE_POWER {
149
        // Exponent is above largest normal value, must be infinite.
150
15
        return fp_inf;
151
5.74k
    }
152
5.74k
    ExtendedFloat80 {
153
5.74k
        mant: mantissa,
154
5.74k
        exp: power2,
155
5.74k
    }
156
6.37k
}
lexical_parse_float::lemire::compute_float::<f64>
Line
Count
Source
57
6.37k
pub fn compute_float<F: LemireFloat>(q: i64, mut w: u64, lossy: bool) -> ExtendedFloat80 {
58
6.37k
    let fp_zero = ExtendedFloat80 {
59
6.37k
        mant: 0,
60
6.37k
        exp: 0,
61
6.37k
    };
62
6.37k
    let fp_inf = ExtendedFloat80 {
63
6.37k
        mant: 0,
64
6.37k
        exp: F::INFINITE_POWER,
65
6.37k
    };
66
67
    // Short-circuit if the value can only be a literal 0 or infinity.
68
6.37k
    if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 {
69
390
        return fp_zero;
70
5.98k
    } else if q > F::LARGEST_POWER_OF_TEN as i64 {
71
190
        return fp_inf;
72
5.79k
    }
73
    // Normalize our significant digits, so the most-significant bit is set.
74
5.79k
    let lz = w.leading_zeros() as i32;
75
5.79k
    w <<= lz;
76
5.79k
    let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3);
77
5.79k
    if !lossy && lo == 0xFFFF_FFFF_FFFF_FFFF {
78
        // If we have failed to approximate `w x 5^-q` with our 128-bit value.
79
        // Since the addition of 1 could lead to an overflow which could then
80
        // round up over the half-way point, this can lead to improper rounding
81
        // of a float.
82
        //
83
        // However, this can only occur if `q ∈ [-27, 55]`. The upper bound of q
84
        // is 55 because `5^55 < 2^128`, however, this can only happen if `5^q > 2^64`,
85
        // since otherwise the product can be represented in 64-bits, producing
86
        // an exact result. For negative exponents, rounding-to-even can
87
        // only occur if `5^-q < 2^64`.
88
        //
89
        // For detailed explanations of rounding for negative exponents, see
90
        // <https://arxiv.org/pdf/2101.11408.pdf#section.9.1>. For detailed
91
        // explanations of rounding for positive exponents, see
92
        // <https://arxiv.org/pdf/2101.11408.pdf#section.8>.
93
0
        let inside_safe_exponent = (-27..=55).contains(&q);
94
0
        if !inside_safe_exponent {
95
0
            return compute_error_scaled::<F>(q, hi, lz);
96
0
        }
97
5.79k
    }
98
5.79k
    let upperbit = (hi >> 63) as i32;
99
5.79k
    let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_SIZE - 3);
100
5.79k
    let mut power2 = power(q as i32) + upperbit - lz - F::MINIMUM_EXPONENT;
101
5.79k
    if power2 <= 0 {
102
35
        if -power2 + 1 >= 64 {
103
            // Have more than 64 bits below the minimum exponent, must be 0.
104
13
            return fp_zero;
105
22
        }
106
        // Have a subnormal value.
107
22
        mantissa >>= -power2 + 1;
108
22
        mantissa += mantissa & 1;
109
22
        mantissa >>= 1;
110
22
        power2 = (mantissa >= (1_u64 << F::MANTISSA_SIZE)) as i32;
111
22
        return ExtendedFloat80 {
112
22
            mant: mantissa,
113
22
            exp: power2,
114
22
        };
115
5.76k
    }
116
    // Need to handle rounding ties. Normally, we need to round up,
117
    // but if we fall right in between and and we have an even basis, we
118
    // need to round down.
119
    //
120
    // This will only occur if:
121
    //  1. The lower 64 bits of the 128-bit representation is 0. IE, `5^q` fits in
122
    //     single 64-bit word.
123
    //  2. The least-significant bit prior to truncated mantissa is odd.
124
    //  3. All the bits truncated when shifting to mantissa bits + 1 are 0.
125
    //
126
    // Or, we may fall between two floats: we are exactly halfway.
127
5.76k
    if lo <= 1
128
1.73k
        && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64
129
1.60k
        && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64
130
1.54k
        && mantissa & 3 == 1
131
664
        && (mantissa << (upperbit + 64 - F::MANTISSA_SIZE - 3)) == hi
132
371
    {
133
371
        // Zero the lowest bit, so we don't round up.
134
371
        mantissa &= !1_u64;
135
5.39k
    }
136
    // Round-to-even, then shift the significant digits into place.
137
5.76k
    mantissa += mantissa & 1;
138
5.76k
    mantissa >>= 1;
139
5.76k
    if mantissa >= (2_u64 << F::MANTISSA_SIZE) {
140
43
        // Rounding up overflowed, so the carry bit is set. Set the
141
43
        // mantissa to 1 (only the implicit, hidden bit is set) and
142
43
        // increase the exponent.
143
43
        mantissa = 1_u64 << F::MANTISSA_SIZE;
144
43
        power2 += 1;
145
5.72k
    }
146
    // Zero out the hidden bit.
147
5.76k
    mantissa &= !(1_u64 << F::MANTISSA_SIZE);
148
5.76k
    if power2 >= F::INFINITE_POWER {
149
        // Exponent is above largest normal value, must be infinite.
150
15
        return fp_inf;
151
5.74k
    }
152
5.74k
    ExtendedFloat80 {
153
5.74k
        mant: mantissa,
154
5.74k
        exp: power2,
155
5.74k
    }
156
6.37k
}
Unexecuted instantiation: lexical_parse_float::lemire::compute_float::<_>
157
158
/// Fallback algorithm to calculate the non-rounded representation.
159
/// This calculates the extended representation, and then normalizes
160
/// the resulting representation, so the high bit is set.
161
#[must_use]
162
#[inline(always)]
163
1.37k
pub fn compute_error<F: LemireFloat>(q: i64, mut w: u64) -> ExtendedFloat80 {
164
1.37k
    let lz = w.leading_zeros() as i32;
165
1.37k
    w <<= lz;
166
1.37k
    let hi = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3).1;
167
1.37k
    compute_error_scaled::<F>(q, hi, lz)
168
1.37k
}
lexical_parse_float::lemire::compute_error::<f64>
Line
Count
Source
163
1.37k
pub fn compute_error<F: LemireFloat>(q: i64, mut w: u64) -> ExtendedFloat80 {
164
1.37k
    let lz = w.leading_zeros() as i32;
165
1.37k
    w <<= lz;
166
1.37k
    let hi = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3).1;
167
1.37k
    compute_error_scaled::<F>(q, hi, lz)
168
1.37k
}
Unexecuted instantiation: lexical_parse_float::lemire::compute_error::<_>
169
170
/// Compute the error from a mantissa scaled to the exponent.
171
#[must_use]
172
#[inline(always)]
173
1.37k
pub const fn compute_error_scaled<F: LemireFloat>(q: i64, mut w: u64, lz: i32) -> ExtendedFloat80 {
174
    // Want to normalize the float, but this is faster than ctlz on most
175
    // architectures.
176
1.37k
    let hilz = (w >> 63) as i32 ^ 1;
177
1.37k
    w <<= hilz;
178
1.37k
    let power2 = power(q as i32) + F::EXPONENT_BIAS - hilz - lz - 62;
179
180
1.37k
    ExtendedFloat80 {
181
1.37k
        mant: w,
182
1.37k
        exp: power2 + shared::INVALID_FP,
183
1.37k
    }
184
1.37k
}
lexical_parse_float::lemire::compute_error_scaled::<f64>
Line
Count
Source
173
1.37k
pub const fn compute_error_scaled<F: LemireFloat>(q: i64, mut w: u64, lz: i32) -> ExtendedFloat80 {
174
    // Want to normalize the float, but this is faster than ctlz on most
175
    // architectures.
176
1.37k
    let hilz = (w >> 63) as i32 ^ 1;
177
1.37k
    w <<= hilz;
178
1.37k
    let power2 = power(q as i32) + F::EXPONENT_BIAS - hilz - lz - 62;
179
180
1.37k
    ExtendedFloat80 {
181
1.37k
        mant: w,
182
1.37k
        exp: power2 + shared::INVALID_FP,
183
1.37k
    }
184
1.37k
}
Unexecuted instantiation: lexical_parse_float::lemire::compute_error_scaled::<_>
185
186
/// Calculate a base 2 exponent from a decimal exponent.
187
/// This uses a pre-computed integer approximation for
188
/// log2(10), where 217706 / 2^16 is accurate for the
189
/// entire range of non-finite decimal exponents.
190
#[inline(always)]
191
7.17k
const fn power(q: i32) -> i32 {
192
7.17k
    (q.wrapping_mul(152_170 + 65536) >> 16) + 63
193
7.17k
}
194
195
#[inline(always)]
196
8.57k
const fn full_multiplication(a: u64, b: u64) -> (u64, u64) {
197
8.57k
    let r = (a as u128) * (b as u128);
198
8.57k
    (r as u64, (r >> 64) as u64)
199
8.57k
}
200
201
// This will compute or rather approximate `w * 5**q` and return a pair of
202
// 64-bit words approximating the result, with the "high" part corresponding to
203
// the most significant bits and the low part corresponding to the least
204
// significant bits.
205
#[inline]
206
7.17k
fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) {
207
7.17k
    debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64, "must be within our required pow5 range");
208
7.17k
    debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64, "must be within our required pow5 range");
209
7.17k
    debug_assert!(precision <= 64, "requires a 64-bit or smaller float");
210
211
7.17k
    let mask = if precision < 64 {
212
7.17k
        0xFFFF_FFFF_FFFF_FFFF_u64 >> precision
213
    } else {
214
0
        0xFFFF_FFFF_FFFF_FFFF_u64
215
    };
216
217
    // `5^q < 2^64`, then the multiplication always provides an exact value.
218
    // That means whenever we need to round ties to even, we always have
219
    // an exact value.
220
7.17k
    let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize;
221
7.17k
    let (lo5, hi5) = POWER_OF_FIVE_128[index];
222
    // Only need one multiplication as long as there is 1 zero but
223
    // in the explicit mantissa bits, +1 for the hidden bit, +1 to
224
    // determine the rounding direction, +1 for if the computed
225
    // product has a leading zero.
226
7.17k
    let (mut first_lo, mut first_hi) = full_multiplication(w, lo5);
227
7.17k
    if first_hi & mask == mask {
228
        // Need to do a second multiplication to get better precision
229
        // for the lower product. This will always be exact
230
        // where q is < 55, since 5^55 < 2^128. If this wraps,
231
        // then we need to need to round up the hi product.
232
1.40k
        let (_, second_hi) = full_multiplication(w, hi5);
233
1.40k
        first_lo = first_lo.wrapping_add(second_hi);
234
1.40k
        if second_hi > first_lo {
235
769
            first_hi += 1;
236
769
        }
237
5.77k
    }
238
7.17k
    (first_lo, first_hi)
239
7.17k
}
lexical_parse_float::lemire::compute_product_approx
Line
Count
Source
206
7.17k
fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) {
207
7.17k
    debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64, "must be within our required pow5 range");
208
7.17k
    debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64, "must be within our required pow5 range");
209
7.17k
    debug_assert!(precision <= 64, "requires a 64-bit or smaller float");
210
211
7.17k
    let mask = if precision < 64 {
212
7.17k
        0xFFFF_FFFF_FFFF_FFFF_u64 >> precision
213
    } else {
214
0
        0xFFFF_FFFF_FFFF_FFFF_u64
215
    };
216
217
    // `5^q < 2^64`, then the multiplication always provides an exact value.
218
    // That means whenever we need to round ties to even, we always have
219
    // an exact value.
220
7.17k
    let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize;
221
7.17k
    let (lo5, hi5) = POWER_OF_FIVE_128[index];
222
    // Only need one multiplication as long as there is 1 zero but
223
    // in the explicit mantissa bits, +1 for the hidden bit, +1 to
224
    // determine the rounding direction, +1 for if the computed
225
    // product has a leading zero.
226
7.17k
    let (mut first_lo, mut first_hi) = full_multiplication(w, lo5);
227
7.17k
    if first_hi & mask == mask {
228
        // Need to do a second multiplication to get better precision
229
        // for the lower product. This will always be exact
230
        // where q is < 55, since 5^55 < 2^128. If this wraps,
231
        // then we need to need to round up the hi product.
232
1.40k
        let (_, second_hi) = full_multiplication(w, hi5);
233
1.40k
        first_lo = first_lo.wrapping_add(second_hi);
234
1.40k
        if second_hi > first_lo {
235
769
            first_hi += 1;
236
769
        }
237
5.77k
    }
238
7.17k
    (first_lo, first_hi)
239
7.17k
}
Unexecuted instantiation: lexical_parse_float::lemire::compute_product_approx