File indexing completed on 2025-12-16 09:40:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
0016 #define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
0017
0018 #include <cstdint>
0019 #include <limits>
0020 #include <type_traits>
0021
0022 #if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
0023 #include <intrin.h> // NOLINT(build/include_order)
0024 #pragma intrinsic(_umul128)
0025 #define ABSL_INTERNAL_USE_UMUL128 1
0026 #endif
0027
0028 #include "absl/base/config.h"
0029 #include "absl/numeric/bits.h"
0030 #include "absl/numeric/int128.h"
0031 #include "absl/random/internal/traits.h"
0032
0033 namespace absl {
0034 ABSL_NAMESPACE_BEGIN
0035 namespace random_internal {
0036
0037
0038 template <typename UIntType>
0039 struct wide_multiply {
0040 static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
0041 using input_type = UIntType;
0042 using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
0043
0044 static result_type multiply(input_type a, input_type b) {
0045 return static_cast<result_type>(a) * b;
0046 }
0047
0048 static input_type hi(result_type r) {
0049 return static_cast<input_type>(r >> kN);
0050 }
0051 static input_type lo(result_type r) { return static_cast<input_type>(r); }
0052
0053 static_assert(std::is_unsigned<UIntType>::value,
0054 "Class-template wide_multiply<> argument must be unsigned.");
0055 };
0056
0057
0058 inline U256 MultiplyU128ToU256(uint128 a, uint128 b) {
0059 const uint128 a00 = static_cast<uint64_t>(a);
0060 const uint128 a64 = a >> 64;
0061 const uint128 b00 = static_cast<uint64_t>(b);
0062 const uint128 b64 = b >> 64;
0063
0064 const uint128 c00 = a00 * b00;
0065 const uint128 c64a = a00 * b64;
0066 const uint128 c64b = a64 * b00;
0067 const uint128 c128 = a64 * b64;
0068
0069 const uint64_t carry =
0070 static_cast<uint64_t>(((c00 >> 64) + static_cast<uint64_t>(c64a) +
0071 static_cast<uint64_t>(c64b)) >>
0072 64);
0073
0074 return {c128 + (c64a >> 64) + (c64b >> 64) + carry,
0075 c00 + (c64a << 64) + (c64b << 64)};
0076 }
0077
0078
0079 template <>
0080 struct wide_multiply<uint128> {
0081 using input_type = uint128;
0082 using result_type = U256;
0083
0084 static result_type multiply(input_type a, input_type b) {
0085 return MultiplyU128ToU256(a, b);
0086 }
0087
0088 static input_type hi(result_type r) { return r.hi; }
0089 static input_type lo(result_type r) { return r.lo; }
0090 };
0091
0092 }
0093 ABSL_NAMESPACE_END
0094 }
0095
0096 #endif