17template <
typename IntType>
24 double invHarmonicNumber = 1;
26 static constexpr int tableSize = 16;
28 double table[tableSize];
31 ZipfRand(
double exponent = 2.0, IntType number = 1);
33 [[nodiscard]] std::string
Name()
const override;
35 [[nodiscard]] IntType
MinValue()
const override {
return 1; }
36 [[nodiscard]] IntType
MaxValue()
const override {
return n; }
39 [[nodiscard]]
inline double GetExponent() const noexcept {
return s; }
40 [[nodiscard]]
inline IntType
GetNumber() const noexcept {
return n; }
42 [[nodiscard]]
double P(
const IntType &k)
const override;
43 [[nodiscard]]
double logP(
const IntType &k)
const override;
44 [[nodiscard]]
double F(
const IntType &k)
const override;
45 template <std::uniform_random_bit_generator G>
48 [[nodiscard]]
long double Mean()
const override;
49 [[nodiscard]]
long double Variance()
const override;
50 [[nodiscard]] IntType
Mode()
const override;
51 [[nodiscard]]
long double Skewness()
const override;
55 std::complex<double> CFImpl(
double t)
const override;
65template <
typename IntType>
68 SetParameters(exponent, number);
71template <
typename IntType>
74 return "Zipf(" + this->toStringWithPrecision(GetExponent()) +
", " + this->toStringWithPrecision(GetNumber()) +
")";
77template <
typename IntType>
80 if (!(exponent > 1.0))
81 throw std::invalid_argument(
"Zipf distribution: exponent should be greater than 1, but it's equal to " +
82 std::to_string(exponent));
84 throw std::invalid_argument(
"Zipf distribution: number should be positive, but it's equal to " +
85 std::to_string(number));
92 hashedVarNum = n > tableSize ? tableSize : n;
94 for (
int i = 1; i < hashedVarNum - 1; ++i)
95 table[i] = table[i - 1] + std::pow(i + 1, -s);
96 if (hashedVarNum == n)
97 table[hashedVarNum - 1] = 1.0 / invHarmonicNumber;
99 table[hashedVarNum - 1] = table[hashedVarNum - 2] + std::pow(hashedVarNum, -s);
100 for (
int i = 0; i < hashedVarNum; ++i)
101 table[i] *= invHarmonicNumber;
104template <
typename IntType>
107 return (k < 1 || k > n) ? 0.0 : std::pow(k, -s) * invHarmonicNumber;
110template <
typename IntType>
113 return (k < 1 || k > n) ? -INFINITY : -s * std::log(k) + std::log(invHarmonicNumber);
116template <
typename IntType>
126template <
typename IntType>
127template <std::uniform_random_bit_generator G>
133 if (U > table[hashedVarNum - 1]) {
135 double sum = table[hashedVarNum - 1];
138 sum += std::pow(k, -s) * invHarmonicNumber;
141 while (k <= hashedVarNum && table[k - 1] < U)
147template <
typename IntType>
153template <
typename IntType>
157 numerator *= numerator;
159 return numerator * invHarmonicNumber * invHarmonicNumber;
162template <
typename IntType>
168template <
typename IntType>
171 std::complex<double> sum(0.0, 0.0);
172 for (
int i = 1; i <= n; ++i) {
173 std::complex<double> addon(-s * std::log(i), i * t);
174 sum += std::exp(addon);
176 return invHarmonicNumber * sum;
179template <
typename IntType>
182 long double harmonic0 = 1.0 / invHarmonicNumber;
186 long double first = harmonic3 * harmonic0 * harmonic0;
187 long double harmonic2prod0 = harmonic2 * harmonic0;
188 long double second = -3 * harmonic1 * harmonic2prod0;
189 long double harmonic1Sq = harmonic1 * harmonic1;
190 long double third = 2 * harmonic1 * harmonic1Sq;
191 long double numerator = first + second + third;
192 long double denominator = harmonic2prod0 - harmonic1Sq;
193 denominator *= std::sqrt(denominator);
194 return numerator / denominator;
197template <
typename IntType>
200 long double harmonic0 = 1.0 / invHarmonicNumber;
205 long double harmonic2prod0 = harmonic2 * harmonic0;
206 long double harmonic0Sq = harmonic0 * harmonic0;
207 long double harmonic1Sq = harmonic1 * harmonic1;
208 long double denominator = harmonic2prod0 - harmonic1Sq;
209 denominator *= denominator;
210 long double numerator = harmonic0Sq * harmonic0 * harmonic4;
211 numerator -= 4 * harmonic0Sq * harmonic1 * harmonic3;
212 numerator += 6 * harmonic2prod0 * harmonic1Sq;
213 numerator -= 3 * harmonic1Sq * harmonic1Sq;
214 return numerator / denominator - 3;
The DiscreteDistribution class Abstract class for all discrete distributions.
Definition discrete.hpp:21
The ZipfRand class Zipf distribution.
Definition zipf.hpp:19
IntType MaxValue() const override
Definition zipf.hpp:36
long double Variance() const override
Definition zipf.hpp:154
std::string Name() const override
Definition zipf.hpp:72
void SetParameters(double exponent, IntType number)
Definition zipf.hpp:78
long double Skewness() const override
Definition zipf.hpp:180
double P(const IntType &k) const override
Definition zipf.hpp:105
ZipfRand(double exponent=2.0, IntType number=1)
Definition zipf.hpp:66
long double Mean() const override
Definition zipf.hpp:148
Support SupportType() const override
Definition zipf.hpp:34
double F(const IntType &k) const override
Definition zipf.hpp:117
IntType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition zipf.hpp:163
double GetExponent() const noexcept
Definition zipf.hpp:39
IntType GetNumber() const noexcept
Definition zipf.hpp:40
double logP(const IntType &k) const override
Definition zipf.hpp:111
IntType operator()(G &g) const
Definition zipf.hpp:128
long double ExcessKurtosis() const override
Definition zipf.hpp:198
IntType MinValue() const override
Definition zipf.hpp:35
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Real harmonicNumber(Real exponent, int number)
Definition functions.hpp:533
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15