15 #ifndef ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
16 #define ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
23 #include <type_traits>
25 #include "absl/random/internal/iostream_state_saver.h"
26 #include "absl/random/uniform_real_distribution.h"
50 template <
typename IntType =
int>
51 class zipf_distribution {
65 double q = 2.0,
double v = 1.0);
68 double q()
const {
return q_; }
69 double v()
const {
return v_; }
72 return a.k_ ==
b.k_ &&
a.q_ ==
b.q_ &&
a.v_ ==
b.v_;
80 inline double h(
double x)
const;
81 inline double hinv(
double x)
const;
98 "Class-template absl::zipf_distribution<> must be "
99 "parameterized using an integral type.");
112 template <
typename URBG>
117 template <
typename URBG>
119 const param_type&
p);
133 return a.param_ ==
b.param_;
137 return a.param_ !=
b.param_;
148 template <
typename IntType>
151 :
k_(
k), q_(q), v_(
v), one_minus_q_(1 - q) {
155 one_minus_q_inv_ = 1 / one_minus_q_;
159 constexpr
double kMax = 18446744073709549568.0;
160 double kd =
static_cast<double>(
k);
171 const bool use_precomputed = (
v == 1.0 &&
q == 2.0);
172 const double h0x5 = use_precomputed ? (-1.0 / 1.5)
174 const double elogv_q = (v_ == 1.0) ? 1 : pow_negative_q(v_);
177 hx0_minus_hxm_ = (h0x5 - elogv_q) - hxm_;
180 s_ = use_precomputed ? 0.46153846153846123 : compute_s();
183 template <
typename IntType>
192 template <
typename IntType>
195 return -v_ + ((one_minus_q_ == -1.0)
197 : std::exp(one_minus_q_inv_ *
std::log(one_minus_q_ *
x)));
200 template <
typename IntType>
203 return 1.0 - hinv(
h(1.5) - pow_negative_q(v_ + 1.0));
206 template <
typename IntType>
209 return q_ == 2.0 ? (1.0 / (
x *
x)) : std::exp(
std::log(
x) * -q_);
212 template <
typename IntType>
213 template <
typename URBG>
216 URBG&
g,
const param_type&
p) {
220 const double v = uniform_double(
g);
221 const double u =
p.hxm_ +
v *
p.hx0_minus_hxm_;
222 const double x =
p.hinv(
u);
224 if (
k >
p.k())
continue;
225 if (
k -
x <=
p.s_)
break;
226 const double h =
p.h(
k + 0.5);
227 const double r =
p.pow_negative_q(
p.v_ +
k);
228 if (
u >= h -
r)
break;
230 IntType ki =
static_cast<IntType
>(
k);
235 template <
typename CharT,
typename Traits,
typename IntType>
236 std::basic_ostream<CharT, Traits>&
operator<<(
237 std::basic_ostream<CharT, Traits>& os,
238 const zipf_distribution<IntType>&
x) {
243 os << static_cast<stream_type>(
x.k()) << os.fill() <<
x.q() << os.fill()
248 template <
typename CharT,
typename Traits,
typename IntType>
249 std::basic_istream<CharT, Traits>&
operator>>(
250 std::basic_istream<CharT, Traits>& is,
251 zipf_distribution<IntType>&
x) {
253 using param_type =
typename zipf_distribution<IntType>::param_type;
271 #endif // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_