// File: Konano[P]UselessDatabase/./json.hpp
// Function: nlohmann::detail::dtoa_impl::diyfp::mul(nlohmann::detail::dtoa_impl::diyfp const&, nlohmann::detail::dtoa_impl::diyfp const&)
static diyfp mul(const diyfp& x, const diyfp& y) noexcept
    {
        static_assert(kPrecision == 64, "internal error");

        // Computes:
        //  f = round((x.f * y.f) / 2^q)
        //  e = x.e + y.e + q

        // Emulate the 64-bit * 64-bit multiplication:
        //
        // p = u * v
        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
        //
        // (Since Q might be larger than 2^32 - 1)
        //
        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
        //
        // (Q_hi + H does not overflow a 64-bit int)
        //
        //   = p_lo + 2^64 p_hi

        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
        const std::uint64_t u_hi = x.f >> 32u;
        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
        const std::uint64_t v_hi = y.f >> 32u;

        const std::uint64_t p0 = u_lo * v_lo;
        const std::uint64_t p1 = u_lo * v_hi;
        const std::uint64_t p2 = u_hi * v_lo;
        const std::uint64_t p3 = u_hi * v_hi;

        const std::uint64_t p0_hi = p0 >> 32u;
        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
        const std::uint64_t p1_hi = p1 >> 32u;
        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
        const std::uint64_t p2_hi = p2 >> 32u;

        std::uint64_t Q = p0_hi + p1_lo + p2_lo;

        // The full product might now be computed as
        //
        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
        // p_lo = p0_lo + (Q << 32)
        //
        // But in this particular case here, the full p_lo is not required.
        // Effectively we only need to add the highest bit in p_lo to p_hi (and
        // Q_hi + 1 does not overflow).

        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up

        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);

        return {h, x.e + y.e + 64};
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x18(%rbp)
movq %rsi, -0x20(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %eax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movq -0x40(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rax
movq -0x40(%rbp), %rcx
imulq %rcx, %rax
movq %rax, -0x60(%rbp)
movl -0x44(%rbp), %eax
movq %rax, -0x68(%rbp)
movl -0x50(%rbp), %eax
movq %rax, -0x70(%rbp)
movl -0x4c(%rbp), %eax
movq %rax, -0x78(%rbp)
movl -0x58(%rbp), %eax
movq %rax, -0x80(%rbp)
movl -0x54(%rbp), %eax
movq %rax, -0x88(%rbp)
movq -0x68(%rbp), %rax
movq -0x70(%rbp), %rcx
addq %rcx, %rax
movq -0x80(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
subq $-0x80000000, %rax      # imm = 0x80000000
movq %rax, -0x90(%rbp)
movq -0x60(%rbp), %rax
movq -0x88(%rbp), %rcx
addq %rcx, %rax
movq -0x78(%rbp), %rcx
addq %rcx, %rax
movl -0x8c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rsi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %edx
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x40(%rax,%rcx), %edx
leaq -0x10(%rbp), %rdi
callq 0x16c90
movq -0x10(%rbp), %rax
movl -0x8(%rbp), %edx
addq $0xa0, %rsp
popq %rbp
retq
nopl (%rax,%rax)