-- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro <dmauro@google.com>: Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental <rogeeff@google.com>: This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck <shreck@google.com>: Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro <dmauro@google.com>: Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon <gfalcon@google.com>: Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1
		
			
				
	
	
		
			264 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2017 The Abseil Authors.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      https://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
#ifndef ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
 | 
						|
#define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
 | 
						|
 | 
						|
#include <cstddef>
 | 
						|
#include <cstdint>
 | 
						|
#include <limits>
 | 
						|
#include <type_traits>
 | 
						|
 | 
						|
#include "absl/base/config.h"
 | 
						|
 | 
						|
namespace absl {
 | 
						|
ABSL_NAMESPACE_BEGIN
 | 
						|
namespace random_internal {
 | 
						|
// Returns true if the input value is zero or a power of two. Useful for
 | 
						|
// determining if the range of output values in a URBG
 | 
						|
template <typename UIntType>
 | 
						|
constexpr bool IsPowerOfTwoOrZero(UIntType n) {
 | 
						|
  return (n == 0) || ((n & (n - 1)) == 0);
 | 
						|
}
 | 
						|
 | 
						|
// Computes the length of the range of values producible by the URBG, or returns
 | 
						|
// zero if that would encompass the entire range of representable values in
 | 
						|
// URBG::result_type.
 | 
						|
template <typename URBG>
 | 
						|
constexpr typename URBG::result_type RangeSize() {
 | 
						|
  using result_type = typename URBG::result_type;
 | 
						|
  return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&
 | 
						|
          (URBG::min)() == std::numeric_limits<result_type>::lowest())
 | 
						|
             ? result_type{0}
 | 
						|
             : (URBG::max)() - (URBG::min)() + result_type{1};
 | 
						|
}
 | 
						|
 | 
						|
template <typename UIntType>
 | 
						|
constexpr UIntType LargestPowerOfTwoLessThanOrEqualTo(UIntType n) {
 | 
						|
  return n < 2 ? n : 2 * LargestPowerOfTwoLessThanOrEqualTo(n / 2);
 | 
						|
}
 | 
						|
 | 
						|
// Given a URBG generating values in the closed interval [Lo, Hi], returns the
 | 
						|
// largest power of two less than or equal to `Hi - Lo + 1`.
 | 
						|
template <typename URBG>
 | 
						|
constexpr typename URBG::result_type PowerOfTwoSubRangeSize() {
 | 
						|
  return LargestPowerOfTwoLessThanOrEqualTo(RangeSize<URBG>());
 | 
						|
}
 | 
						|
 | 
						|
// Computes the floor of the log. (i.e., std::floor(std::log2(N));
 | 
						|
template <typename UIntType>
 | 
						|
constexpr UIntType IntegerLog2(UIntType n) {
 | 
						|
  return (n <= 1) ? 0 : 1 + IntegerLog2(n / 2);
 | 
						|
}
 | 
						|
 | 
						|
// Returns the number of bits of randomness returned through
 | 
						|
// `PowerOfTwoVariate(urbg)`.
 | 
						|
template <typename URBG>
 | 
						|
constexpr size_t NumBits() {
 | 
						|
  return RangeSize<URBG>() == 0
 | 
						|
             ? std::numeric_limits<typename URBG::result_type>::digits
 | 
						|
             : IntegerLog2(PowerOfTwoSubRangeSize<URBG>());
 | 
						|
}
 | 
						|
 | 
						|
// Given a shift value `n`, constructs a mask with exactly the low `n` bits set.
 | 
						|
// If `n == 0`, all bits are set.
 | 
						|
template <typename UIntType>
 | 
						|
constexpr UIntType MaskFromShift(UIntType n) {
 | 
						|
  return ((n % std::numeric_limits<UIntType>::digits) == 0)
 | 
						|
             ? ~UIntType{0}
 | 
						|
             : (UIntType{1} << n) - UIntType{1};
 | 
						|
}
 | 
						|
 | 
						|
// FastUniformBits implements a fast path to acquire uniform independent bits
 | 
						|
// from a type which conforms to the [rand.req.urbg] concept.
 | 
						|
// Parameterized by:
 | 
						|
//  `UIntType`: the result (output) type
 | 
						|
//
 | 
						|
// The std::independent_bits_engine [rand.adapt.ibits] adaptor can be
 | 
						|
// instantiated from an existing generator through a copy or a move. It does
 | 
						|
// not, however, facilitate the production of pseudorandom bits from an un-owned
 | 
						|
// generator that will outlive the std::independent_bits_engine instance.
 | 
						|
template <typename UIntType = uint64_t>
 | 
						|
class FastUniformBits {
 | 
						|
 public:
 | 
						|
  using result_type = UIntType;
 | 
						|
 | 
						|
  static constexpr result_type(min)() { return 0; }
 | 
						|
  static constexpr result_type(max)() {
 | 
						|
    return (std::numeric_limits<result_type>::max)();
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename URBG>
 | 
						|
  result_type operator()(URBG& g);  // NOLINT(runtime/references)
 | 
						|
 | 
						|
 private:
 | 
						|
  static_assert(std::is_unsigned<UIntType>::value,
 | 
						|
                "Class-template FastUniformBits<> must be parameterized using "
 | 
						|
                "an unsigned type.");
 | 
						|
 | 
						|
  // PowerOfTwoVariate() generates a single random variate, always returning a
 | 
						|
  // value in the half-open interval `[0, PowerOfTwoSubRangeSize<URBG>())`. If
 | 
						|
  // the URBG already generates values in a power-of-two range, the generator
 | 
						|
  // itself is used. Otherwise, we use rejection sampling on the largest
 | 
						|
  // possible power-of-two-sized subrange.
 | 
						|
  struct PowerOfTwoTag {};
 | 
						|
  struct RejectionSamplingTag {};
 | 
						|
  template <typename URBG>
 | 
						|
  static typename URBG::result_type PowerOfTwoVariate(
 | 
						|
      URBG& g) {  // NOLINT(runtime/references)
 | 
						|
    using tag =
 | 
						|
        typename std::conditional<IsPowerOfTwoOrZero(RangeSize<URBG>()),
 | 
						|
                                  PowerOfTwoTag, RejectionSamplingTag>::type;
 | 
						|
    return PowerOfTwoVariate(g, tag{});
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename URBG>
 | 
						|
  static typename URBG::result_type PowerOfTwoVariate(
 | 
						|
      URBG& g,  // NOLINT(runtime/references)
 | 
						|
      PowerOfTwoTag) {
 | 
						|
    return g() - (URBG::min)();
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename URBG>
 | 
						|
  static typename URBG::result_type PowerOfTwoVariate(
 | 
						|
      URBG& g,  // NOLINT(runtime/references)
 | 
						|
      RejectionSamplingTag) {
 | 
						|
    // Use rejection sampling to ensure uniformity across the range.
 | 
						|
    typename URBG::result_type u;
 | 
						|
    do {
 | 
						|
      u = g() - (URBG::min)();
 | 
						|
    } while (u >= PowerOfTwoSubRangeSize<URBG>());
 | 
						|
    return u;
 | 
						|
  }
 | 
						|
 | 
						|
  // Generate() generates a random value, dispatched on whether
 | 
						|
  // the underlying URBG must loop over multiple calls or not.
 | 
						|
  template <typename URBG>
 | 
						|
  result_type Generate(URBG& g,  // NOLINT(runtime/references)
 | 
						|
                       std::true_type /* avoid_looping */);
 | 
						|
 | 
						|
  template <typename URBG>
 | 
						|
  result_type Generate(URBG& g,  // NOLINT(runtime/references)
 | 
						|
                       std::false_type /* avoid_looping */);
 | 
						|
};
 | 
						|
 | 
						|
template <typename UIntType>
 | 
						|
template <typename URBG>
 | 
						|
typename FastUniformBits<UIntType>::result_type
 | 
						|
FastUniformBits<UIntType>::operator()(URBG& g) {  // NOLINT(runtime/references)
 | 
						|
  // kRangeMask is the mask used when sampling variates from the URBG when the
 | 
						|
  // width of the URBG range is not a power of 2.
 | 
						|
  // Y = (2 ^ kRange) - 1
 | 
						|
  static_assert((URBG::max)() > (URBG::min)(),
 | 
						|
                "URBG::max and URBG::min may not be equal.");
 | 
						|
  using urbg_result_type = typename URBG::result_type;
 | 
						|
  constexpr urbg_result_type kRangeMask =
 | 
						|
      RangeSize<URBG>() == 0
 | 
						|
          ? (std::numeric_limits<urbg_result_type>::max)()
 | 
						|
          : static_cast<urbg_result_type>(PowerOfTwoSubRangeSize<URBG>() - 1);
 | 
						|
  return Generate(g, std::integral_constant<bool, (kRangeMask >= (max)())>{});
 | 
						|
}
 | 
						|
 | 
						|
template <typename UIntType>
 | 
						|
template <typename URBG>
 | 
						|
typename FastUniformBits<UIntType>::result_type
 | 
						|
FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
 | 
						|
                                    std::true_type /* avoid_looping */) {
 | 
						|
  // The width of the result_type is less than than the width of the random bits
 | 
						|
  // provided by URBG.  Thus, generate a single value and then simply mask off
 | 
						|
  // the required bits.
 | 
						|
 | 
						|
  return PowerOfTwoVariate(g) & (max)();
 | 
						|
}
 | 
						|
 | 
						|
template <typename UIntType>
 | 
						|
template <typename URBG>
 | 
						|
typename FastUniformBits<UIntType>::result_type
 | 
						|
FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
 | 
						|
                                    std::false_type /* avoid_looping */) {
 | 
						|
  // See [rand.adapt.ibits] for more details on the constants calculated below.
 | 
						|
  //
 | 
						|
  // It is preferable to use roughly the same number of bits from each generator
 | 
						|
  // call, however this is only possible when the number of bits provided by the
 | 
						|
  // URBG is a divisor of the number of bits in `result_type`. In all other
 | 
						|
  // cases, the number of bits used cannot always be the same, but it can be
 | 
						|
  // guaranteed to be off by at most 1. Thus we run two loops, one with a
 | 
						|
  // smaller bit-width size (`kSmallWidth`) and one with a larger width size
 | 
						|
  // (satisfying `kLargeWidth == kSmallWidth + 1`). The loops are run
 | 
						|
  // `kSmallIters` and `kLargeIters` times respectively such
 | 
						|
  // that
 | 
						|
  //
 | 
						|
  //    `kTotalWidth == kSmallIters * kSmallWidth
 | 
						|
  //                    + kLargeIters * kLargeWidth`
 | 
						|
  //
 | 
						|
  // where `kTotalWidth` is the total number of bits in `result_type`.
 | 
						|
  //
 | 
						|
  constexpr size_t kTotalWidth = std::numeric_limits<result_type>::digits;
 | 
						|
  constexpr size_t kUrbgWidth = NumBits<URBG>();
 | 
						|
  constexpr size_t kTotalIters =
 | 
						|
      kTotalWidth / kUrbgWidth + (kTotalWidth % kUrbgWidth != 0);
 | 
						|
  constexpr size_t kSmallWidth = kTotalWidth / kTotalIters;
 | 
						|
  constexpr size_t kLargeWidth = kSmallWidth + 1;
 | 
						|
  //
 | 
						|
  // Because `kLargeWidth == kSmallWidth + 1`, it follows that
 | 
						|
  //
 | 
						|
  //     `kTotalWidth == kTotalIters * kSmallWidth + kLargeIters`
 | 
						|
  //
 | 
						|
  // and therefore
 | 
						|
  //
 | 
						|
  //     `kLargeIters == kTotalWidth % kSmallWidth`
 | 
						|
  //
 | 
						|
  // Intuitively, each iteration with the large width accounts for one unit
 | 
						|
  // of the remainder when `kTotalWidth` is divided by `kSmallWidth`. As
 | 
						|
  // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then
 | 
						|
  // there would be no need for any large iterations (i.e., one loop would
 | 
						|
  // suffice), and indeed, in this case, `kLargeIters` would be zero.
 | 
						|
  constexpr size_t kLargeIters = kTotalWidth % kSmallWidth;
 | 
						|
  constexpr size_t kSmallIters =
 | 
						|
      (kTotalWidth - (kLargeWidth * kLargeIters)) / kSmallWidth;
 | 
						|
 | 
						|
  static_assert(
 | 
						|
      kTotalWidth == kSmallIters * kSmallWidth + kLargeIters * kLargeWidth,
 | 
						|
      "Error in looping constant calculations.");
 | 
						|
 | 
						|
  result_type s = 0;
 | 
						|
 | 
						|
  constexpr size_t kSmallShift = kSmallWidth % kTotalWidth;
 | 
						|
  constexpr result_type kSmallMask = MaskFromShift(result_type{kSmallShift});
 | 
						|
  for (size_t n = 0; n < kSmallIters; ++n) {
 | 
						|
    s = (s << kSmallShift) +
 | 
						|
        (static_cast<result_type>(PowerOfTwoVariate(g)) & kSmallMask);
 | 
						|
  }
 | 
						|
 | 
						|
  constexpr size_t kLargeShift = kLargeWidth % kTotalWidth;
 | 
						|
  constexpr result_type kLargeMask = MaskFromShift(result_type{kLargeShift});
 | 
						|
  for (size_t n = 0; n < kLargeIters; ++n) {
 | 
						|
    s = (s << kLargeShift) +
 | 
						|
        (static_cast<result_type>(PowerOfTwoVariate(g)) & kLargeMask);
 | 
						|
  }
 | 
						|
 | 
						|
  static_assert(
 | 
						|
      kLargeShift == kSmallShift + 1 ||
 | 
						|
          (kLargeShift == 0 &&
 | 
						|
           kSmallShift == std::numeric_limits<result_type>::digits - 1),
 | 
						|
      "Error in looping constant calculations");
 | 
						|
 | 
						|
  return s;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace random_internal
 | 
						|
ABSL_NAMESPACE_END
 | 
						|
}  // namespace absl
 | 
						|
 | 
						|
#endif  // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
 |