abseil-cpp/absl/random/log_uniform_int_distribution.h
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
16 #define ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
17 
18 #include <algorithm>
19 #include <cassert>
20 #include <cmath>
21 #include <istream>
22 #include <limits>
23 #include <ostream>
24 #include <type_traits>
25 
26 #include "absl/numeric/bits.h"
27 #include "absl/random/internal/fastmath.h"
28 #include "absl/random/internal/generate_real.h"
29 #include "absl/random/internal/iostream_state_saver.h"
30 #include "absl/random/internal/traits.h"
31 #include "absl/random/uniform_int_distribution.h"
32 
33 namespace absl {
35 
36 // log_uniform_int_distribution:
37 //
38 // Returns a random variate R in range [min, max] such that
39 // floor(log(R-min, base)) is uniformly distributed.
40 // We ensure uniformity by discretization using the
41 // boundary sets [0, 1, base, base * base, ... min(base*n, max)]
42 //
43 template <typename IntType = int>
45  private:
46  using unsigned_type =
48 
49  public:
50  using result_type = IntType;
51 
52  class param_type {
53  public:
55 
56  explicit param_type(
57  result_type min = 0,
59  result_type base = 2)
60  : min_(min),
61  max_(max),
62  base_(base),
63  range_(static_cast<unsigned_type>(max_) -
64  static_cast<unsigned_type>(min_)),
65  log_range_(0) {
66  assert(max_ >= min_);
67  assert(base_ > 1);
68 
69  if (base_ == 2) {
70  // Determine where the first set bit is on range(), giving a log2(range)
71  // value which can be used to construct bounds.
73  std::numeric_limits<unsigned_type>::digits);
74  } else {
75  // NOTE: Computing the logN(x) introduces error from 2 sources:
76  // 1. Conversion of int to double loses precision for values >=
77  // 2^53, which may cause some log() computations to operate on
78  // different values.
79  // 2. The error introduced by the division will cause the result
80  // to differ from the expected value.
81  //
82  // Thus a result which should equal K may equal K +/- epsilon,
83  // which can eliminate some values depending on where the bounds fall.
84  const double inv_log_base = 1.0 / std::log(static_cast<double>(base_));
85  const double log_range = std::log(static_cast<double>(range()) + 0.5);
86  log_range_ = static_cast<int>(std::ceil(inv_log_base * log_range));
87  }
88  }
89 
90  result_type(min)() const { return min_; }
91  result_type(max)() const { return max_; }
92  result_type base() const { return base_; }
93 
94  friend bool operator==(const param_type& a, const param_type& b) {
95  return a.min_ == b.min_ && a.max_ == b.max_ && a.base_ == b.base_;
96  }
97 
98  friend bool operator!=(const param_type& a, const param_type& b) {
99  return !(a == b);
100  }
101 
102  private:
104 
105  int log_range() const { return log_range_; }
106  unsigned_type range() const { return range_; }
107 
111  unsigned_type range_; // max - min
112  int log_range_; // ceil(logN(range_))
113 
115  "Class-template absl::log_uniform_int_distribution<> must be "
116  "parameterized using an integral type.");
117  };
118 
120 
124  result_type base = 2)
125  : param_(min, max, base) {}
126 
128 
129  void reset() {}
130 
131  // generating functions
132  template <typename URBG>
133  result_type operator()(URBG& g) { // NOLINT(runtime/references)
134  return (*this)(g, param_);
135  }
136 
137  template <typename URBG>
138  result_type operator()(URBG& g, // NOLINT(runtime/references)
139  const param_type& p) {
140  return static_cast<result_type>((p.min)() + Generate(g, p));
141  }
142 
143  result_type(min)() const { return (param_.min)(); }
144  result_type(max)() const { return (param_.max)(); }
145  result_type base() const { return param_.base(); }
146 
147  param_type param() const { return param_; }
148  void param(const param_type& p) { param_ = p; }
149 
152  return a.param_ == b.param_;
153  }
156  return a.param_ != b.param_;
157  }
158 
159  private:
160  // Returns a log-uniform variate in the range [0, p.range()]. The caller
161  // should add min() to shift the result to the correct range.
162  template <typename URNG>
163  unsigned_type Generate(URNG& g, // NOLINT(runtime/references)
164  const param_type& p);
165 
167 };
168 
169 template <typename IntType>
170 template <typename URBG>
173  URBG& g, // NOLINT(runtime/references)
174  const param_type& p) {
175  // sample e over [0, log_range]. Map the results of e to this:
176  // 0 => 0
177  // 1 => [1, b-1]
178  // 2 => [b, (b^2)-1]
179  // n => [b^(n-1)..(b^n)-1]
180  const int e = absl::uniform_int_distribution<int>(0, p.log_range())(g);
181  if (e == 0) {
182  return 0;
183  }
184  const int d = e - 1;
185 
186  unsigned_type base_e, top_e;
187  if (p.base() == 2) {
188  base_e = static_cast<unsigned_type>(1) << d;
189 
190  top_e = (e >= std::numeric_limits<unsigned_type>::digits)
192  : (static_cast<unsigned_type>(1) << e) - 1;
193  } else {
194  const double r = std::pow(static_cast<double>(p.base()), d);
195  const double s = (r * static_cast<double>(p.base())) - 1.0;
196 
197  base_e =
198  (r > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
200  : static_cast<unsigned_type>(r);
201 
202  top_e =
203  (s > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
205  : static_cast<unsigned_type>(s);
206  }
207 
208  const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e;
209  const unsigned_type hi = (top_e >= p.range()) ? p.range() : top_e;
210 
211  // choose uniformly over [lo, hi]
213  static_cast<result_type>(lo), static_cast<result_type>(hi))(g);
214 }
215 
216 template <typename CharT, typename Traits, typename IntType>
217 std::basic_ostream<CharT, Traits>& operator<<(
218  std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
220  using stream_type =
223  os << static_cast<stream_type>((x.min)()) << os.fill()
224  << static_cast<stream_type>((x.max)()) << os.fill()
225  << static_cast<stream_type>(x.base());
226  return os;
227 }
228 
229 template <typename CharT, typename Traits, typename IntType>
230 std::basic_istream<CharT, Traits>& operator>>(
231  std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
232  log_uniform_int_distribution<IntType>& x) { // NOLINT(runtime/references)
233  using param_type = typename log_uniform_int_distribution<IntType>::param_type;
234  using result_type =
236  using stream_type =
238 
242 
244  is >> min >> max >> base;
245  if (!is.fail()) {
246  x.param(param_type(static_cast<result_type>(min),
247  static_cast<result_type>(max),
248  static_cast<result_type>(base)));
249  }
250  return is;
251 }
252 
254 } // namespace absl
255 
256 #endif // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
absl::log_uniform_int_distribution::param
param_type param() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:147
absl::log_uniform_int_distribution::param_type::log_uniform_int_distribution
friend class log_uniform_int_distribution
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:103
absl::log_uniform_int_distribution::reset
void reset()
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:129
absl::log_uniform_int_distribution::operator()
result_type operator()(URBG &g)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:133
absl::log_uniform_int_distribution::param_type::operator!=
friend bool operator!=(const param_type &a, const param_type &b)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:98
absl::log_uniform_int_distribution::log_uniform_int_distribution
log_uniform_int_distribution()
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:119
absl::log_uniform_int_distribution::operator!=
friend bool operator!=(const log_uniform_int_distribution &a, const log_uniform_int_distribution &b)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:154
absl::random_internal::make_istream_state_saver
istream_state_saver< std::basic_istream< CharT, Traits > > make_istream_state_saver(std::basic_istream< CharT, Traits > &is, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::scientific|std::ios_base::skipws)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:149
absl::operator<<
ABSL_NAMESPACE_BEGIN std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: abseil-cpp/absl/base/log_severity.cc:24
absl::log_uniform_int_distribution::operator==
friend bool operator==(const log_uniform_int_distribution &a, const log_uniform_int_distribution &b)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:150
absl::log_uniform_int_distribution::param_
param_type param_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:166
absl::uniform_int_distribution
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:30
absl::FormatConversionChar::s
@ s
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
absl::random_internal::make_unsigned_bits::type
typename unsigned_bits< std::numeric_limits< typename MakeUnsigned< IntType >::type >::digits >::type type
Definition: abseil-cpp/absl/random/internal/traits.h:129
xds_manager.p
p
Definition: xds_manager.py:60
absl::random_internal::IsIntegral
Definition: abseil-cpp/absl/random/internal/traits.h:65
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::log_uniform_int_distribution::param_type
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:52
absl::random_internal::stream_format_type
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:174
absl::log_uniform_int_distribution::log_uniform_int_distribution
log_uniform_int_distribution(result_type min, result_type max=(std::numeric_limits< result_type >::max)(), result_type base=2)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:121
absl::log_uniform_int_distribution::param
void param(const param_type &p)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:148
absl::FormatConversionChar::e
@ e
absl::log_uniform_int_distribution::param_type::range_
unsigned_type range_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:111
absl::log_uniform_int_distribution::operator()
result_type operator()(URBG &g, const param_type &p)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:138
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::log_uniform_int_distribution::param_type::base
result_type base() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:92
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::log_uniform_int_distribution::result_type
IntType result_type
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:50
absl::log_uniform_int_distribution::param_type::min_
result_type min_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:108
absl::log_uniform_int_distribution::param_type::max
result_type() max() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:91
result_type
const typedef int * result_type
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:4325
absl::log_uniform_int_distribution::Generate
unsigned_type Generate(URNG &g, const param_type &p)
absl::log_uniform_int_distribution::param_type::range
unsigned_type range() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:106
absl::log_uniform_int_distribution::param_type::operator==
friend bool operator==(const param_type &a, const param_type &b)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:94
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
absl::log_uniform_int_distribution
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:44
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
g
struct @717 g
d
static const fe d
Definition: curve25519_tables.h:19
absl::operator>>
constexpr uint128 operator>>(uint128 lhs, int amount)
Definition: abseil-cpp/absl/numeric/int128.h:917
absl::log_uniform_int_distribution::param_type::min
result_type() min() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:90
absl::log_uniform_int_distribution::base
result_type base() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:145
absl::log_uniform_int_distribution::param_type::param_type
param_type(result_type min=0, result_type max=(std::numeric_limits< result_type >::max)(), result_type base=2)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:56
fix_build_deps.r
r
Definition: fix_build_deps.py:491
log
bool log
Definition: abseil-cpp/absl/synchronization/mutex.cc:310
absl::log_uniform_int_distribution::param_type::base_
result_type base_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:110
absl::random_internal::BitWidth
int BitWidth(T v)
Definition: abseil-cpp/absl/random/internal/traits.h:133
absl::log_uniform_int_distribution::min
result_type() min() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:143
stream_type
stream_type
Definition: task.h:81
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::log_uniform_int_distribution::unsigned_type
typename random_internal::make_unsigned_bits< IntType >::type unsigned_type
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:47
absl::random_internal::make_ostream_state_saver
ostream_state_saver< std::basic_ostream< CharT, Traits > > make_ostream_state_saver(std::basic_ostream< CharT, Traits > &os, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::left|std::ios_base::scientific)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:82
absl::log_uniform_int_distribution::param_type::max_
result_type max_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:109
absl::log_uniform_int_distribution::max
result_type() max() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:144
absl::log_uniform_int_distribution::log_uniform_int_distribution
log_uniform_int_distribution(const param_type &p)
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:127
absl::log_uniform_int_distribution::param_type::log_range_
int log_range_
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:112
absl::log_uniform_int_distribution::param_type::log_range
int log_range() const
Definition: abseil-cpp/absl/random/log_uniform_int_distribution.h:105


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:16