Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:40:56

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
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 // wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
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 // MultiplyU128ToU256 multiplies two 128-bit values to a 256-bit value.
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 }  // namespace random_internal
0093 ABSL_NAMESPACE_END
0094 }  // namespace absl
0095 
0096 #endif  // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_