| 2300 | // |
| 2301 | template <int bit_precision> |
| 2302 | fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 |
| 2303 | compute_product_approximation(int64_t q, uint64_t w) { |
| 2304 | const int index = 2 * int(q - powers::smallest_power_of_five); |
| 2305 | // For small values of q, e.g., q in [0,27], the answer is always exact |
| 2306 | // because The line value128 firstproduct = full_multiplication(w, |
| 2307 | // power_of_five_128[index]); gives the exact answer. |
| 2308 | value128 firstproduct = |
| 2309 | full_multiplication(w, powers::power_of_five_128[index]); |
| 2310 | static_assert((bit_precision >= 0) && (bit_precision <= 64), |
| 2311 | " precision should be in (0,64]"); |
| 2312 | constexpr uint64_t precision_mask = |
| 2313 | (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) |
| 2314 | : uint64_t(0xFFFFFFFFFFFFFFFF); |
| 2315 | if ((firstproduct.high & precision_mask) == |
| 2316 | precision_mask) { // could further guard with (lower + w < lower) |
| 2317 | // regarding the second product, we only need secondproduct.high, but our |
| 2318 | // expectation is that the compiler will optimize this extra work away if |
| 2319 | // needed. |
| 2320 | value128 secondproduct = |
| 2321 | full_multiplication(w, powers::power_of_five_128[index + 1]); |
| 2322 | firstproduct.low += secondproduct.high; |
| 2323 | if (secondproduct.high > firstproduct.low) { |
| 2324 | firstproduct.high++; |
| 2325 | } |
| 2326 | } |
| 2327 | return firstproduct; |
| 2328 | } |
| 2329 | |
| 2330 | namespace detail { |
| 2331 | /** |
nothing calls this directly
no test coverage detected