Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2025 Christian Mazakas
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
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 } // namespace detail
0096 } // namespace hash2
0097 } // namespace boost
0098 
0099 #endif // #ifndef BOOST_HASH2_DETAIL_MUL128_HPP_INCLUDED