12 #if !defined(RANDOMLIB_DISCRETENORMALALT_HPP)
13 #define RANDOMLIB_DISCRETENORMALALT_HPP 1
118 IntType mu_num = 0, IntType mu_den = 1);
126 template<
class Random>
132 IntType _sig, _mu, _d, _isig, _imu;
138 static IntType iceil(IntType n, IntType d);
140 static IntType iabs(IntType n);
141 static IntType gcd(IntType u, IntType v);
150 template<
class Random>
static int Choose(
Random& r,
int m);
155 template<
class Random>
bool ExpProbH(
Random& r)
const;
160 template<
class Random>
bool ExpProb(
Random& r,
int n)
const;
166 template<
class Random>
int ExpProbN(
Random& r)
const;
172 template<
class Random>
177 template<
typename IntType,
int bits>
179 (IntType sigma_num, IntType sigma_den, IntType mu_num, IntType mu_den) {
181 "DiscreteNormalAlt: invalid integer type IntType");
183 "DiscreteNormalAlt: IntType must be a signed type");
184 if (!( sigma_num > 0 && sigma_den > 0 && mu_den > 0 ))
185 throw RandomErr(
"DiscreteNormalAlt: need sigma > 0");
186 _imu = mu_num / mu_den;
187 if (_imu == (std::numeric_limits<IntType>::min)())
188 throw RandomErr(
"DiscreteNormalAlt: abs(mu) too large");
189 mu_num -= _imu * mu_den;
191 l = gcd(sigma_num, sigma_den); sigma_num /= l; sigma_den /= l;
192 l = gcd(mu_num, mu_den); mu_num /= l; mu_den /= l;
193 _isig = iceil(sigma_num, sigma_den);
194 l = gcd(sigma_den, mu_den);
195 _sig = sigma_num * (mu_den / l);
196 _mu = mu_num * (sigma_den / l);
197 _d = sigma_den * (mu_den / l);
200 IntType maxint = (std::numeric_limits<IntType>::max)();
201 if (!( mu_den / l <= maxint / sigma_num &&
202 iabs(mu_num) <= maxint / (sigma_den / l) &&
203 mu_den / l <= maxint / sigma_den ))
204 throw RandomErr(
"DiscreteNormalAlt: sigma or mu overflow");
206 throw RandomErr(
"DiscreteNormalAlt: overflow in UniformInteger");
211 if (!( kmax + 1 <= maxint / _isig &&
212 _isig * (kmax + 1) <= maxint - iabs(_imu) ))
213 throw RandomErr(
"DiscreteNormalAlt: possible overflow a");
215 if (!( kmax <= maxint / _sig &&
216 _sig * kmax <= maxint - iabs(_mu) ))
217 throw RandomErr(
"DiscreteNormalAlt: possible overflow b");
222 if (!( _d <= maxint >> bits ))
223 throw std::runtime_error(
"DiscreteNormalAlt: overflow in RandomNumber a");
224 if (!( (IntType(1) << bits) - 1 <= maxint / _sig ))
225 throw std::runtime_error(
"DiscreteNormalAlt: overflow in RandomNumber b");
228 template<
typename IntType,
int bits>
template<
class Random>
233 if (!ExpProb(r, k * (k - 1)))
continue;
237 xn0 = _sig * IntType(k) + s * _mu,
240 if (!j.
LessThan(r, _sig - xn0, _d) ||
241 (k == 0 && s < 0 && !j.
GreaterThan(r, -xn0, _d)))
continue;
242 int h = k + 1;
while (h-- && B(r, k, xn0, j));
243 if (!(h < 0))
continue;
244 j.
Add(i0 + s * _imu);
250 template<
typename IntType,
int bits>
252 { IntType k = n / d;
return k + (k * d < n ? 1 : 0); }
254 template<
typename IntType,
int bits>
255 IntType DiscreteNormalAlt<IntType, bits>::iabs(IntType n)
256 {
return n < 0 ? -n : n; }
258 template<
typename IntType,
int bits>
259 IntType DiscreteNormalAlt<IntType, bits>::gcd(IntType u, IntType v) {
261 u = iabs(u); v = iabs(v);
262 while (v > 0) { IntType r = u % v; u = v; v = r; }
266 template<
typename IntType,
int bits>
template<
class Random>
267 int DiscreteNormalAlt<IntType, bits>::Choose(
Random& r,
int m) {
269 const int b = bits > 15 ? 15 : bits;
270 const unsigned mask = (1u << b) - 1;
271 int n1 = m - 2, n2 = m - 1;
278 n1 = (std::max)((n1 << b) - d, 0);
279 if (n1 >= m)
return 1;
280 n2 = (std::min)((n2 << b) - d, m);
281 if (n2 <= 0)
return -1;
282 if (n1 == 0 && n2 == m)
return 0;
286 template<
typename IntType,
int bits>
template<
class Random>
287 bool DiscreteNormalAlt<IntType, bits>::ExpProbH(
Random& r)
const {
289 if (_p.Digit(r, 0) >> (bits - 1))
return true;
291 _q.Init();
if (!_q.LessThan(r, _p))
return false;
292 _p.Init();
if (!_p.LessThan(r, _q))
return true;
296 template<
typename IntType,
int bits>
template<
class Random>
297 bool DiscreteNormalAlt<IntType, bits>::ExpProb(
Random& r,
int n)
const {
298 while (n-- > 0) {
if (!ExpProbH(r))
return false; }
302 template<
typename IntType,
int bits>
template<
class Random>
303 int DiscreteNormalAlt<IntType, bits>::ExpProbN(
Random& r)
const {
305 while (ExpProbH(r)) ++n;
309 template<
typename IntType,
int bits>
template<
class Random>
bool
310 DiscreteNormalAlt<IntType, bits>::B(
Random& r,
int k, IntType xn0,
311 UniformInteger<IntType, bits>& j)
313 int n = 0, m = 2 * k + 2, f;
315 if ( ((f = k ? 0 : Choose(r, m)) < 0) ||
317 !(n ? _q.LessThan(r, _p) : _q.LessThan(r, xn0, _d, _sig, j))) ||
318 ((f = k ? Choose(r, m) : f) < 0) ||
319 (f == 0 && (_p.Init(), !_p.LessThan(r, xn0, _d, _sig, j))) )
328 #endif // RANDOMLIB_DISCRETENORMALALT_HPP
Generate random integers, reals, and booleans.
Infinite precision random numbers.
DiscreteNormalAlt(IntType sigma_num, IntType sigma_den=1, IntType mu_num=0, IntType mu_den=1)
The discrete normal distribution (alternate version).
Exception handling for RandomLib.
static unsigned RandomDigit(Random &r)
#define STATIC_ASSERT(cond, reason)
RandomCanonical< RandomGenerator > Random
UniformInteger< IntType, bits > operator()(Random &r) const