compute 64-bit a*b
| 468 | |
| 469 | // compute 64-bit a*b |
| 470 | fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 |
| 471 | full_multiplication(uint64_t a, uint64_t b) { |
| 472 | if (cpp20_and_in_constexpr()) { |
| 473 | value128 answer; |
| 474 | answer.low = umul128_generic(a, b, &answer.high); |
| 475 | return answer; |
| 476 | } |
| 477 | value128 answer; |
| 478 | #if defined(_M_ARM64) && !defined(__MINGW32__) |
| 479 | // ARM64 has native support for 64-bit multiplications, no need to emulate |
| 480 | // But MinGW on ARM64 doesn't have native support for 64-bit multiplications |
| 481 | answer.high = __umulh(a, b); |
| 482 | answer.low = a * b; |
| 483 | #elif defined(FASTFLOAT_32BIT) || \ |
| 484 | (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64)) |
| 485 | answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 |
| 486 | #elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) |
| 487 | __uint128_t r = ((__uint128_t)a) * b; |
| 488 | answer.low = uint64_t(r); |
| 489 | answer.high = uint64_t(r >> 64); |
| 490 | #else |
| 491 | answer.low = umul128_generic(a, b, &answer.high); |
| 492 | #endif |
| 493 | return answer; |
| 494 | } |
| 495 | |
| 496 | struct adjusted_mantissa { |
| 497 | uint64_t mantissa{0}; |
no test coverage detected