File indexing completed on 2024-11-15 09:01:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
0016 #define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
0017
0018
0019
0020
0021 #include <cstdint>
0022 #include <cstring>
0023 #include <limits>
0024 #include <type_traits>
0025
0026 #include "absl/meta/type_traits.h"
0027 #include "absl/numeric/bits.h"
0028 #include "absl/random/internal/fastmath.h"
0029 #include "absl/random/internal/traits.h"
0030
0031 namespace absl {
0032 ABSL_NAMESPACE_BEGIN
0033 namespace random_internal {
0034
0035
0036 struct GeneratePositiveTag {};
0037 struct GenerateNegativeTag {};
0038 struct GenerateSignedTag {};
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 template <typename RealType,
0066 typename SignedTag = GeneratePositiveTag,
0067
0068
0069 bool IncludeZero = true>
0070 inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {
0071 using real_type = RealType;
0072 using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,
0073 uint32_t, uint64_t>;
0074
0075 static_assert(
0076 (std::is_same<double, real_type>::value ||
0077 std::is_same<float, real_type>::value),
0078 "GenerateRealFromBits must be parameterized by either float or double.");
0079
0080 static_assert(sizeof(uint_type) == sizeof(real_type),
0081 "Mismatched unsigned and real types.");
0082
0083 static_assert((std::numeric_limits<real_type>::is_iec559 &&
0084 std::numeric_limits<real_type>::radix == 2),
0085 "RealType representation is not IEEE 754 binary.");
0086
0087 static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value ||
0088 std::is_same<SignedTag, GenerateNegativeTag>::value ||
0089 std::is_same<SignedTag, GenerateSignedTag>::value),
0090 "");
0091
0092 static constexpr int kExp = std::numeric_limits<real_type>::digits - 1;
0093 static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u;
0094 static constexpr int kUintBits = sizeof(uint_type) * 8;
0095
0096 int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2};
0097
0098
0099
0100
0101 uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value
0102 ? (static_cast<uint_type>(1) << (kUintBits - 1))
0103 : 0;
0104 if (std::is_same<SignedTag, GenerateSignedTag>::value) {
0105 if (std::is_same<uint_type, uint64_t>::value) {
0106 sign = bits & uint64_t{0x8000000000000000};
0107 }
0108 if (std::is_same<uint_type, uint32_t>::value) {
0109 const uint64_t tmp = bits & uint64_t{0x8000000000000000};
0110 sign = static_cast<uint32_t>(tmp >> 32);
0111 }
0112
0113
0114 bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF};
0115 exp++;
0116 }
0117 if (IncludeZero) {
0118 if (bits == 0u) return 0;
0119 }
0120
0121
0122
0123 int clz = countl_zero(bits);
0124 bits <<= (IncludeZero ? clz : (clz & 63));
0125 exp -= clz;
0126 bits >>= (63 - kExp);
0127
0128
0129
0130 uint_type val = sign | (static_cast<uint_type>(exp) << kExp) |
0131 (static_cast<uint_type>(bits) & kMask);
0132
0133
0134 real_type result;
0135 memcpy(static_cast<void*>(&result), static_cast<const void*>(&val),
0136 sizeof(result));
0137 return result;
0138 }
0139
0140 }
0141 ABSL_NAMESPACE_END
0142 }
0143
0144 #endif