| 14461 | } |
| 14462 | |
| 14463 | struct diyfp // f * 2^e |
| 14464 | { |
| 14465 | static constexpr int kPrecision = 64; // = q |
| 14466 | |
| 14467 | std::uint64_t f = 0; |
| 14468 | int e = 0; |
| 14469 | |
| 14470 | constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} |
| 14471 | |
| 14472 | /*! |
| 14473 | @brief returns x - y |
| 14474 | @pre x.e == y.e and x.f >= y.f |
| 14475 | */ |
| 14476 | static diyfp sub(const diyfp& x, const diyfp& y) noexcept |
| 14477 | { |
| 14478 | JSON_ASSERT(x.e == y.e); |
| 14479 | JSON_ASSERT(x.f >= y.f); |
| 14480 | |
| 14481 | return {x.f - y.f, x.e}; |
| 14482 | } |
| 14483 | |
| 14484 | /*! |
| 14485 | @brief returns x * y |
| 14486 | @note The result is rounded. (Only the upper q bits are returned.) |
| 14487 | */ |
| 14488 | static diyfp mul(const diyfp& x, const diyfp& y) noexcept |
| 14489 | { |
| 14490 | static_assert(kPrecision == 64, "internal error"); |
| 14491 | |
| 14492 | // Computes: |
| 14493 | // f = round((x.f * y.f) / 2^q) |
| 14494 | // e = x.e + y.e + q |
| 14495 | |
| 14496 | // Emulate the 64-bit * 64-bit multiplication: |
| 14497 | // |
| 14498 | // p = u * v |
| 14499 | // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) |
| 14500 | // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) |
| 14501 | // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) |
| 14502 | // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) |
| 14503 | // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) |
| 14504 | // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) |
| 14505 | // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) |
| 14506 | // |
| 14507 | // (Since Q might be larger than 2^32 - 1) |
| 14508 | // |
| 14509 | // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) |
| 14510 | // |
| 14511 | // (Q_hi + H does not overflow a 64-bit int) |
| 14512 | // |
| 14513 | // = p_lo + 2^64 p_hi |
| 14514 | |
| 14515 | const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; |
| 14516 | const std::uint64_t u_hi = x.f >> 32u; |
| 14517 | const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; |
| 14518 | const std::uint64_t v_hi = y.f >> 32u; |
| 14519 | |
| 14520 | const std::uint64_t p0 = u_lo * v_lo; |
no outgoing calls
no test coverage detected