File indexing completed on 2026-08-17 08:46:45
0001 #ifndef BOOST_HASH2_DETAIL_MUL128_HPP_INCLUDED
0002 #define BOOST_HASH2_DETAIL_MUL128_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/hash2/detail/is_constant_evaluated.hpp>
0009 #include <boost/config.hpp>
0010 #include <cstdint>
0011
0012 #if defined(_MSC_VER)
0013 #include <intrin.h>
0014 #endif
0015
0016 namespace boost
0017 {
0018 namespace hash2
0019 {
0020 namespace detail
0021 {
0022
0023 struct uint128
0024 {
0025 std::uint64_t low;
0026 std::uint64_t high;
0027 };
0028
0029 BOOST_CXX14_CONSTEXPR inline uint128 mul128_impl( std::uint64_t x, std::uint64_t y ) noexcept
0030 {
0031 std::uint64_t lo_lo = ( x & 0xffffffff ) * ( y & 0xffffffff );
0032 std::uint64_t hi_lo = ( x >> 32 ) * ( y & 0xffffffff );
0033 std::uint64_t lo_hi = ( x & 0xffffffff ) * ( y >> 32 );
0034 std::uint64_t hi_hi = ( x >> 32 ) * ( y >> 32 );
0035
0036 std::uint64_t cross = ( lo_lo >> 32 ) + ( hi_lo & 0xffffffff ) + lo_hi;
0037 std::uint64_t upper = ( hi_lo >> 32 ) + ( cross >> 32 ) + hi_hi;
0038 std::uint64_t lower = ( cross << 32 ) | ( lo_lo & 0xffffffff );
0039
0040 uint128 r = { 0, 0 };
0041 r.low = lower;
0042 r.high = upper;
0043 return r;
0044 }
0045
0046 BOOST_CXX14_CONSTEXPR inline uint128 mul128( std::uint64_t x, std::uint64_t y ) noexcept
0047 {
0048 #if defined(BOOST_HAS_INT128)
0049
0050 __uint128_t product = __uint128_t( x ) * __uint128_t( y );
0051
0052 uint128 r = { 0, 0 };
0053 r.low = static_cast<std::uint64_t>( product );
0054 r.high = static_cast<std::uint64_t>( product >> 64 );
0055 return r;
0056
0057 #elif ( defined(_M_X64) || defined(_M_IA64) ) && !defined(_M_ARM64EC)
0058
0059 if( !detail::is_constant_evaluated() )
0060 {
0061 uint128 r = { 0, 0 };
0062 std::uint64_t high_product = 0;
0063 r.low = _umul128( x, y, &high_product );
0064 r.high = high_product;
0065 return r;
0066 }
0067 else
0068 {
0069 return mul128_impl( x, y );
0070 }
0071
0072 #elif defined(_M_ARM64) || defined(_M_ARM64EC)
0073
0074 BOOST_CXX14_CONSTEXPR inline uint128 mul128_impl( std::uint64_t x, std::uint64_t y ) noexcept
0075 {
0076 if( !detail::is_constant_evaluated() )
0077 {
0078 uint128 r = { 0, 0 };
0079 r.low = x * y;
0080 r.high = __umulh( x, y );
0081 return r;
0082 }
0083 else
0084 {
0085 return mul128_impl( x, y );
0086 }
0087
0088 #else
0089
0090 return mul128_impl( x, y );
0091
0092 #endif
0093 }
0094
0095 }
0096 }
0097 }
0098
0099 #endif