/src/boost/boost/container_hash/detail/mulx.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2022, 2023 Peter Dimov |
2 | | // Distributed under the Boost Software License, Version 1.0. |
3 | | // https://www.boost.org/LICENSE_1_0.txt |
4 | | |
5 | | #ifndef BOOST_HASH_DETAIL_MULX_HPP |
6 | | #define BOOST_HASH_DETAIL_MULX_HPP |
7 | | |
8 | | #include <cstdint> |
9 | | #if defined(_MSC_VER) |
10 | | # include <intrin.h> |
11 | | #endif |
12 | | |
13 | | namespace boost |
14 | | { |
15 | | namespace hash_detail |
16 | | { |
17 | | |
18 | | #if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__) |
19 | | |
20 | | __forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) |
21 | | { |
22 | | std::uint64_t r2; |
23 | | std::uint64_t r = _umul128( x, y, &r2 ); |
24 | | return r ^ r2; |
25 | | } |
26 | | |
27 | | #elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) |
28 | | |
29 | | __forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) |
30 | | { |
31 | | std::uint64_t r = x * y; |
32 | | std::uint64_t r2 = __umulh( x, y ); |
33 | | return r ^ r2; |
34 | | } |
35 | | |
36 | | #elif defined(__SIZEOF_INT128__) |
37 | | |
38 | | inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) |
39 | 0 | { |
40 | 0 | __uint128_t r = static_cast<__uint128_t>( x ) * y; |
41 | 0 | return static_cast<std::uint64_t>( r ) ^ static_cast<std::uint64_t>( r >> 64 ); |
42 | 0 | } |
43 | | |
44 | | #else |
45 | | |
46 | | inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) |
47 | | { |
48 | | std::uint64_t x1 = static_cast<std::uint32_t>( x ); |
49 | | std::uint64_t x2 = x >> 32; |
50 | | |
51 | | std::uint64_t y1 = static_cast<std::uint32_t>( y ); |
52 | | std::uint64_t y2 = y >> 32; |
53 | | |
54 | | std::uint64_t r3 = x2 * y2; |
55 | | |
56 | | std::uint64_t r2a = x1 * y2; |
57 | | |
58 | | r3 += r2a >> 32; |
59 | | |
60 | | std::uint64_t r2b = x2 * y1; |
61 | | |
62 | | r3 += r2b >> 32; |
63 | | |
64 | | std::uint64_t r1 = x1 * y1; |
65 | | |
66 | | std::uint64_t r2 = (r1 >> 32) + static_cast<std::uint32_t>( r2a ) + static_cast<std::uint32_t>( r2b ); |
67 | | |
68 | | r1 = (r2 << 32) + static_cast<std::uint32_t>( r1 ); |
69 | | r3 += r2 >> 32; |
70 | | |
71 | | return r1 ^ r3; |
72 | | } |
73 | | |
74 | | #endif |
75 | | |
76 | | } // namespace hash_detail |
77 | | } // namespace boost |
78 | | |
79 | | #endif // #ifndef BOOST_HASH_DETAIL_MULX_HPP |