Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:23

0001 // Copyright 2022, 2023 Peter Dimov
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // https://www.boost.org/LICENSE_1_0.txt
0004 
0005 #ifndef BOOST_HASH_DETAIL_MULX_HPP
0006 #define BOOST_HASH_DETAIL_MULX_HPP
0007 
0008 #include <cstdint>
0009 #if defined(_MSC_VER)
0010 # include <intrin.h>
0011 #endif
0012 
0013 namespace boost
0014 {
0015 namespace hash_detail
0016 {
0017 
0018 #if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__)
0019 
0020 __forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
0021 {
0022     std::uint64_t r2;
0023     std::uint64_t r = _umul128( x, y, &r2 );
0024     return r ^ r2;
0025 }
0026 
0027 #elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__)
0028 
0029 __forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
0030 {
0031     std::uint64_t r = x * y;
0032     std::uint64_t r2 = __umulh( x, y );
0033     return r ^ r2;
0034 }
0035 
0036 #elif defined(__SIZEOF_INT128__)
0037 
0038 inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
0039 {
0040     __uint128_t r = static_cast<__uint128_t>( x ) * y;
0041     return static_cast<std::uint64_t>( r ) ^ static_cast<std::uint64_t>( r >> 64 );
0042 }
0043 
0044 #else
0045 
0046 inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y )
0047 {
0048     std::uint64_t x1 = static_cast<std::uint32_t>( x );
0049     std::uint64_t x2 = x >> 32;
0050 
0051     std::uint64_t y1 = static_cast<std::uint32_t>( y );
0052     std::uint64_t y2 = y >> 32;
0053 
0054     std::uint64_t r3 = x2 * y2;
0055 
0056     std::uint64_t r2a = x1 * y2;
0057 
0058     r3 += r2a >> 32;
0059 
0060     std::uint64_t r2b = x2 * y1;
0061 
0062     r3 += r2b >> 32;
0063 
0064     std::uint64_t r1 = x1 * y1;
0065 
0066     std::uint64_t r2 = (r1 >> 32) + static_cast<std::uint32_t>( r2a ) + static_cast<std::uint32_t>( r2b );
0067 
0068     r1 = (r2 << 32) + static_cast<std::uint32_t>( r1 );
0069     r3 += r2 >> 32;
0070 
0071     return r1 ^ r3;
0072 }
0073 
0074 #endif
0075 
0076 } // namespace hash_detail
0077 } // namespace boost
0078 
0079 #endif // #ifndef BOOST_HASH_DETAIL_MULX_HPP