/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 |