1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ 16*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker // This file contains some implementation details which are used by one or more 19*9356374aSAndroid Build Coastguard Worker // of the absl random number distributions. 20*9356374aSAndroid Build Coastguard Worker 21*9356374aSAndroid Build Coastguard Worker #include <cstdint> 22*9356374aSAndroid Build Coastguard Worker #include <cstring> 23*9356374aSAndroid Build Coastguard Worker #include <limits> 24*9356374aSAndroid Build Coastguard Worker #include <type_traits> 25*9356374aSAndroid Build Coastguard Worker 26*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 27*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/bits.h" 28*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/fastmath.h" 29*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/traits.h" 30*9356374aSAndroid Build Coastguard Worker 31*9356374aSAndroid Build Coastguard Worker namespace absl { 32*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 33*9356374aSAndroid Build Coastguard Worker namespace random_internal { 34*9356374aSAndroid Build Coastguard Worker 35*9356374aSAndroid Build Coastguard Worker // Tristate tag types controlling the output of GenerateRealFromBits. 36*9356374aSAndroid Build Coastguard Worker struct GeneratePositiveTag {}; 37*9356374aSAndroid Build Coastguard Worker struct GenerateNegativeTag {}; 38*9356374aSAndroid Build Coastguard Worker struct GenerateSignedTag {}; 39*9356374aSAndroid Build Coastguard Worker 40*9356374aSAndroid Build Coastguard Worker // GenerateRealFromBits generates a single real value from a single 64-bit 41*9356374aSAndroid Build Coastguard Worker // `bits` with template fields controlling the output. 42*9356374aSAndroid Build Coastguard Worker // 43*9356374aSAndroid Build Coastguard Worker // The `SignedTag` parameter controls whether positive, negative, 44*9356374aSAndroid Build Coastguard Worker // or either signed/unsigned may be returned. 45*9356374aSAndroid Build Coastguard Worker // When SignedTag == GeneratePositiveTag, range is U(0, 1) 46*9356374aSAndroid Build Coastguard Worker // When SignedTag == GenerateNegativeTag, range is U(-1, 0) 47*9356374aSAndroid Build Coastguard Worker // When SignedTag == GenerateSignedTag, range is U(-1, 1) 48*9356374aSAndroid Build Coastguard Worker // 49*9356374aSAndroid Build Coastguard Worker // When the `IncludeZero` parameter is true, the function may return 0 for some 50*9356374aSAndroid Build Coastguard Worker // inputs, otherwise it never returns 0. 51*9356374aSAndroid Build Coastguard Worker // 52*9356374aSAndroid Build Coastguard Worker // When a value in U(0,1) is required, use: 53*9356374aSAndroid Build Coastguard Worker // GenerateRealFromBits<double, PositiveValueT, true>; 54*9356374aSAndroid Build Coastguard Worker // 55*9356374aSAndroid Build Coastguard Worker // When a value in U(-1,1) is required, use: 56*9356374aSAndroid Build Coastguard Worker // GenerateRealFromBits<double, SignedValueT, false>; 57*9356374aSAndroid Build Coastguard Worker // 58*9356374aSAndroid Build Coastguard Worker // This generates more distinct values than the mathematical equivalent 59*9356374aSAndroid Build Coastguard Worker // `U(0, 1) * 2.0 - 1.0`. 60*9356374aSAndroid Build Coastguard Worker // 61*9356374aSAndroid Build Coastguard Worker // Scaling the result by powers of 2 (and avoiding a multiply) is also possible: 62*9356374aSAndroid Build Coastguard Worker // GenerateRealFromBits<double>(..., -1); => U(0, 0.5) 63*9356374aSAndroid Build Coastguard Worker // GenerateRealFromBits<double>(..., 1); => U(0, 2) 64*9356374aSAndroid Build Coastguard Worker // 65*9356374aSAndroid Build Coastguard Worker template <typename RealType, // Real type, either float or double. 66*9356374aSAndroid Build Coastguard Worker typename SignedTag = GeneratePositiveTag, // Whether a positive, 67*9356374aSAndroid Build Coastguard Worker // negative, or signed 68*9356374aSAndroid Build Coastguard Worker // value is generated. 69*9356374aSAndroid Build Coastguard Worker bool IncludeZero = true> 70*9356374aSAndroid Build Coastguard Worker inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) { 71*9356374aSAndroid Build Coastguard Worker using real_type = RealType; 72*9356374aSAndroid Build Coastguard Worker using uint_type = absl::conditional_t<std::is_same<real_type, float>::value, 73*9356374aSAndroid Build Coastguard Worker uint32_t, uint64_t>; 74*9356374aSAndroid Build Coastguard Worker 75*9356374aSAndroid Build Coastguard Worker static_assert( 76*9356374aSAndroid Build Coastguard Worker (std::is_same<double, real_type>::value || 77*9356374aSAndroid Build Coastguard Worker std::is_same<float, real_type>::value), 78*9356374aSAndroid Build Coastguard Worker "GenerateRealFromBits must be parameterized by either float or double."); 79*9356374aSAndroid Build Coastguard Worker 80*9356374aSAndroid Build Coastguard Worker static_assert(sizeof(uint_type) == sizeof(real_type), 81*9356374aSAndroid Build Coastguard Worker "Mismatched unsigned and real types."); 82*9356374aSAndroid Build Coastguard Worker 83*9356374aSAndroid Build Coastguard Worker static_assert((std::numeric_limits<real_type>::is_iec559 && 84*9356374aSAndroid Build Coastguard Worker std::numeric_limits<real_type>::radix == 2), 85*9356374aSAndroid Build Coastguard Worker "RealType representation is not IEEE 754 binary."); 86*9356374aSAndroid Build Coastguard Worker 87*9356374aSAndroid Build Coastguard Worker static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value || 88*9356374aSAndroid Build Coastguard Worker std::is_same<SignedTag, GenerateNegativeTag>::value || 89*9356374aSAndroid Build Coastguard Worker std::is_same<SignedTag, GenerateSignedTag>::value), 90*9356374aSAndroid Build Coastguard Worker ""); 91*9356374aSAndroid Build Coastguard Worker 92*9356374aSAndroid Build Coastguard Worker static constexpr int kExp = std::numeric_limits<real_type>::digits - 1; 93*9356374aSAndroid Build Coastguard Worker static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u; 94*9356374aSAndroid Build Coastguard Worker static constexpr int kUintBits = sizeof(uint_type) * 8; 95*9356374aSAndroid Build Coastguard Worker 96*9356374aSAndroid Build Coastguard Worker int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2}; 97*9356374aSAndroid Build Coastguard Worker 98*9356374aSAndroid Build Coastguard Worker // Determine the sign bit. 99*9356374aSAndroid Build Coastguard Worker // Depending on the SignedTag, this may use the left-most bit 100*9356374aSAndroid Build Coastguard Worker // or it may be a constant value. 101*9356374aSAndroid Build Coastguard Worker uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value 102*9356374aSAndroid Build Coastguard Worker ? (static_cast<uint_type>(1) << (kUintBits - 1)) 103*9356374aSAndroid Build Coastguard Worker : 0; 104*9356374aSAndroid Build Coastguard Worker if (std::is_same<SignedTag, GenerateSignedTag>::value) { 105*9356374aSAndroid Build Coastguard Worker if (std::is_same<uint_type, uint64_t>::value) { 106*9356374aSAndroid Build Coastguard Worker sign = bits & uint64_t{0x8000000000000000}; 107*9356374aSAndroid Build Coastguard Worker } 108*9356374aSAndroid Build Coastguard Worker if (std::is_same<uint_type, uint32_t>::value) { 109*9356374aSAndroid Build Coastguard Worker const uint64_t tmp = bits & uint64_t{0x8000000000000000}; 110*9356374aSAndroid Build Coastguard Worker sign = static_cast<uint32_t>(tmp >> 32); 111*9356374aSAndroid Build Coastguard Worker } 112*9356374aSAndroid Build Coastguard Worker // adjust the bits and the exponent to account for removing 113*9356374aSAndroid Build Coastguard Worker // the leading bit. 114*9356374aSAndroid Build Coastguard Worker bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF}; 115*9356374aSAndroid Build Coastguard Worker exp++; 116*9356374aSAndroid Build Coastguard Worker } 117*9356374aSAndroid Build Coastguard Worker if (IncludeZero) { 118*9356374aSAndroid Build Coastguard Worker if (bits == 0u) return 0; 119*9356374aSAndroid Build Coastguard Worker } 120*9356374aSAndroid Build Coastguard Worker 121*9356374aSAndroid Build Coastguard Worker // Number of leading zeros is mapped to the exponent: 2^-clz 122*9356374aSAndroid Build Coastguard Worker // bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0 123*9356374aSAndroid Build Coastguard Worker int clz = countl_zero(bits); 124*9356374aSAndroid Build Coastguard Worker bits <<= (IncludeZero ? clz : (clz & 63)); // remove 0-bits. 125*9356374aSAndroid Build Coastguard Worker exp -= clz; // set the exponent. 126*9356374aSAndroid Build Coastguard Worker bits >>= (63 - kExp); 127*9356374aSAndroid Build Coastguard Worker 128*9356374aSAndroid Build Coastguard Worker // Construct the 32-bit or 64-bit IEEE 754 floating-point value from 129*9356374aSAndroid Build Coastguard Worker // the individual fields: sign, exp, mantissa(bits). 130*9356374aSAndroid Build Coastguard Worker uint_type val = sign | (static_cast<uint_type>(exp) << kExp) | 131*9356374aSAndroid Build Coastguard Worker (static_cast<uint_type>(bits) & kMask); 132*9356374aSAndroid Build Coastguard Worker 133*9356374aSAndroid Build Coastguard Worker // bit_cast to the output-type 134*9356374aSAndroid Build Coastguard Worker real_type result; 135*9356374aSAndroid Build Coastguard Worker memcpy(static_cast<void*>(&result), static_cast<const void*>(&val), 136*9356374aSAndroid Build Coastguard Worker sizeof(result)); 137*9356374aSAndroid Build Coastguard Worker return result; 138*9356374aSAndroid Build Coastguard Worker } 139*9356374aSAndroid Build Coastguard Worker 140*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 141*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 142*9356374aSAndroid Build Coastguard Worker } // namespace absl 143*9356374aSAndroid Build Coastguard Worker 144*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ 145