13 #if !defined(RANDOMLIB_RANDOMCANONICAL_HPP)
14 #define RANDOMLIB_RANDOMCANONICAL_HPP 1
23 # pragma warning (push)
24 # pragma warning (disable: 4127 4310)
54 template<
class Generator>
82 template<
typename IntType>
91 template<
typename InputIterator>
139 {
return Integer<result_type>(n); }
150 template<
typename IntType,
int bits> IntType
Integer() throw() {
153 std::numeric_limits<IntType>::radix == 2,
154 "Integer<T,b>(): bad integer type IntType");
156 STATIC_ASSERT(bits > 0 && bits <= std::numeric_limits<IntType>::digits &&
157 bits <= 64,
"Integer<T,b>(): invalid value for bits");
160 return bits <=
width ?
161 IntType(Generator::Ran() & Generator::mask
163 IntType(Generator::Ran64() &
u64::mask >> (64 - bits));
182 template<
typename IntType> IntType
Integer() throw();
190 {
return Integer<result_type>(); }
205 template<
typename IntType> IntType
Integer(IntType n)
throw();
214 template<
typename IntType> IntType
IntegerC(IntType n)
throw();
224 template<
typename IntType> IntType
IntegerC(IntType m, IntType n)
throw();
253 template<
typename RealType,
int prec> RealType
Fixed() throw() {
257 std::numeric_limits<RealType>::radix == 2,
258 "Fixed(): bad real type RealType");
259 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits,
260 "Fixed(): invalid precision");
269 x += RandomPower2::shiftf<RealType>
270 (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)),
271 -(s > prec ? prec : s));
281 template<
typename RealType> RealType
Fixed() throw()
282 {
return Fixed<RealType, std::numeric_limits<RealType>::digits>(); }
288 double Fixed() throw() {
return Fixed<double>(); }
297 template<
typename RealType> RealType
Real() throw()
298 {
return Fixed<RealType>(); }
316 template<
typename RealType,
int prec> RealType
FixedU() throw()
317 {
return RealType(1) - Fixed<RealType, prec>(); }
324 template<
typename RealType> RealType
FixedU() throw()
325 {
return FixedU<RealType, std::numeric_limits<RealType>::digits>(); }
331 double FixedU() throw() {
return FixedU<double>(); }
343 template<
typename RealType,
int prec> RealType
FixedN() throw() {
344 const RealType x = Fixed<RealType, prec>();
345 return x ||
Boolean() ? x : RealType(1);
353 template<
typename RealType> RealType
FixedN() throw()
354 {
return FixedN<RealType, std::numeric_limits<RealType>::digits>(); }
360 double FixedN() throw() {
return FixedN<double>(); }
373 template<
typename RealType,
int prec> RealType
FixedW() throw() {
378 std::numeric_limits<RealType>::radix == 2,
379 "FixedW(): bad real type RealType");
380 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits,
381 "FixedW(): invalid precision");
382 RealType x = -RealType(1);
386 x += RandomPower2::shiftf<RealType>
387 (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)),
388 -(s > prec ? prec : s));
390 return (x + RealType(1) != RealType(0)) ||
Boolean() ? x : RealType(1);
398 template<
typename RealType> RealType
FixedW() throw()
399 {
return FixedW<RealType, std::numeric_limits<RealType>::digits>(); }
405 double FixedW() throw() {
return FixedW<double>(); }
417 template<
typename RealType,
int prec> RealType
FixedS() throw()
418 {
return Fixed<RealType, prec>() -
419 ( RealType(1) - RandomPower2::pow2<RealType>(-prec) ) / 2; }
426 template<
typename RealType> RealType
FixedS() throw()
427 {
return FixedS<RealType, std::numeric_limits<RealType>::digits>(); }
433 double FixedS() throw() {
return FixedS<double>(); }
444 template<
typename RealType,
int prec> RealType
FixedO() throw() {
447 std::numeric_limits<RealType>::radix == 2,
448 "FixedO(): bad real type RealType");
449 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits,
450 "FixedO(): invalid precision");
454 x = Fixed<RealType, prec>();
464 template<
typename RealType> RealType
FixedO() throw()
465 {
return FixedO<RealType, std::numeric_limits<RealType>::digits>(); }
471 double FixedO() throw() {
return FixedO<double>(); }
482 template<
typename RealType,
int prec> RealType
FixedC() throw() {
485 std::numeric_limits<RealType>::radix == 2,
486 "FixedC(): bad real type RealType");
487 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits,
488 "FixedC(): invalid precision");
499 r = Generator::mask / n,
503 u = Generator::Ran();
506 return RandomPower2::shiftf<RealType>(RealType(u / r), -prec);
523 return Fixed<RealType, prec>();
526 int s = prec + 1 -
width;
532 if (Generator::Ran() >> (s > width ? 0 : width - s))
545 template<
typename RealType> RealType
FixedC() throw()
546 {
return FixedC<RealType, std::numeric_limits<RealType>::digits>(); }
552 double FixedC() throw() {
return FixedC<double>(); }
586 template<
typename RealType,
int prec,
int erange> RealType
Float() throw()
587 {
return FloatZ<RealType, prec, erange, false>(0, 0); }
594 template<
typename RealType> RealType
Float() throw() {
595 return Float<RealType, std::numeric_limits<RealType>::digits,
596 -std::numeric_limits<RealType>::min_exponent>();
603 double Float() throw() {
return Float<double>(); }
614 template<
typename RealType,
int prec,
int erange> RealType
FloatU() throw()
615 {
return FloatZ<RealType, prec, erange, true>(0, 0); }
622 template<
typename RealType> RealType
FloatU() throw() {
623 return FloatU<RealType, std::numeric_limits<RealType>::digits,
624 -std::numeric_limits<RealType>::min_exponent>();
631 double FloatU() throw() {
return FloatU<double>(); }
642 template<
typename RealType,
int prec,
int erange> RealType
FloatN()
649 return x >> (
width - 1) ?
651 FloatZ<RealType, prec, erange, false>(
width - 1, x) :
653 FloatZ<RealType, prec, erange, true>(
width - 1, x);
661 template<
typename RealType> RealType
FloatN() throw() {
662 return FloatN<RealType, std::numeric_limits<RealType>::digits,
663 -std::numeric_limits<RealType>::min_exponent>();
670 double FloatN() throw() {
return FloatN<double>(); }
681 template<
typename RealType,
int prec,
int erange>
684 const int y = int(x >> (
width - 2));
685 return (1 - (y & 2)) *
688 FloatZ<RealType, prec, erange, false>(
width - 2, x) :
690 FloatZ<RealType, prec, erange, true>(width - 2, x) );
698 template<
typename RealType> RealType
FloatW() throw() {
699 return FloatW<RealType, std::numeric_limits<RealType>::digits,
700 -std::numeric_limits<RealType>::min_exponent>();
707 double FloatW() throw() {
return FloatW<double>(); }
719 bool Boolean() throw() {
return Generator::Ran() & 1u; }
730 template<
typename NumericType>
bool Prob(NumericType p)
throw();
742 template<
typename NumericType>
743 bool Prob(NumericType m, NumericType n)
throw();
760 template<
int nbits> std::bitset<nbits>
Bits() throw();
778 template<typename UIntT>
779 typename UIntT::type Unsigned(typename UIntT::type n) throw();
785 template<typename RealType,
int prec,
int erange,
bool up>
791 template<typename RealType>
bool ProbF(RealType z) throw();
795 template<typename RealType>
bool ProbF(RealType x, RealType y) throw();
798 template<class Generator>
804 std::numeric_limits<double>::radix == 2 &&
805 std::numeric_limits<long double>::radix == 2,
806 "RandomCanonical: illegal floating type");
808 std::numeric_limits<float>::digits <=
809 std::numeric_limits<double>::digits &&
810 std::numeric_limits<double>::digits <=
811 std::numeric_limits<long double>::digits,
812 "RandomCanonical: inconsistent floating precision");
815 std::numeric_limits<double>::radix == 2,
816 "RandomCanonical: illegal floating type");
818 std::numeric_limits<float>::digits <=
819 std::numeric_limits<double>::digits,
820 "RandomCanonical: inconsistent floating precision");
824 #if RANDOMLIB_POWERTABLE
829 "RandomPower2: RANDOMLIB_LONGDOUBLEPREC incorrect");
833 "RandomPower2: RANDOMLIB_LONGDOUBLEPREC incorrect");
837 std::numeric_limits<float>::min_exponent -
839 std::numeric_limits<float>::digits : 1),
840 "RandomPower2 table underflow");
842 "RandomPower2 table empty");
846 -std::numeric_limits<long double>::digits,
847 "RandomPower2 minpow not small enough for long double");
850 -std::numeric_limits<double>::digits,
851 "RandomPower2 minpow not small enough for double");
855 "RandomPower2 maxpow not large enough for ProbF");
859 "Bits<n>(): unsigned long too small");
862 template<
class Generator>
template<
typename IntType>
866 std::numeric_limits<IntType>::radix == 2,
867 "Integer: bad integer type IntType");
868 const int d = std::numeric_limits<IntType>::digits +
869 std::numeric_limits<IntType>::is_signed;
873 return IntType(Generator::Ran());
875 return IntType(Generator::Ran64());
878 template<
class Generator>
template<
typename UIntT>
879 inline typename UIntT::type
894 const typename UIntT::type n1 = ~n ? n + 1U : 1U;
898 const typename UIntT::type
904 r1 = ((UIntT::width == 32 ?
typename UIntT::type(
u32::mask) :
905 typename UIntT::type(u64::mask)) - n) / n1,
908 typename UIntT::type u;
912 u = UIntT::width == 32 ?
typename UIntT::type(Generator::Ran32()) :
913 typename UIntT::type(Generator::Ran64());
917 return u / (r1 + 1U);
920 template<
class Generator>
template<
typename IntType>
928 std::numeric_limits<IntType>::radix == 2,
929 "Integer(n): bad integer type IntType");
930 const int d = std::numeric_limits<IntType>::digits;
933 return n > IntType(1) ?
934 (d <= 32 || n - 1 <= IntType(
u32::mask) ?
935 IntType(Unsigned<u32>(
u32::type(n - 1))) :
936 IntType(Unsigned<u64>(
u64::type(n - 1)))) :
938 Integer<IntType, d>());
941 template<
class Generator>
template<
typename IntType>
945 std::numeric_limits<IntType>::radix == 2,
946 "IntegerC(n): bad integer type IntType");
947 const int d = std::numeric_limits<IntType>::digits;
949 STATIC_ASSERT(d > 0 && d <= 64,
"IntegerC(n): bad bit-size");
950 return n > IntType(0) ?
957 template<
class Generator>
template<
typename IntType>
962 std::numeric_limits<IntType>::radix == 2,
963 "IntegerC(m,n): bad integer type IntType");
964 const int d = std::numeric_limits<IntType>::digits +
965 std::numeric_limits<IntType>::is_signed;
967 STATIC_ASSERT(d > 0 && d <= 64,
"IntegerC(m,n): bad bit-size");
970 return m + (n <= m ? 0 :
976 template<
class Generator>
977 template<
typename RealType,
int prec,
int erange,
bool up>
inline
982 std::numeric_limits<RealType>::radix == 2,
983 "FloatZ: bad real type RealType");
984 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits,
985 "FloatZ: invalid precision");
986 STATIC_ASSERT(erange >= 0,
"FloatZ: invalid exponent range");
990 prec + erange <= std::numeric_limits<RealType>::digits -
991 std::numeric_limits<RealType>::min_exponent,
992 "FloatZ: smallest number cannot be represented");
996 erange <= - std::numeric_limits<RealType>::min_exponent,
997 "FloatZ: underflow possible");
1023 RealType x = up ? FixedU<RealType, prec>() : Fixed<RealType, prec>();
1025 if (erange == 0 || (up ? x > RealType(0.5) : x >= RealType(0.5)))
1029 m = Generator::Ran();
1041 m = Generator::Ran();
1049 prec + erange <= -std::numeric_limits<RealType>::min_exponent + 1 ||
1053 RandomPower2::pow2<RealType>
1054 (erange + std::numeric_limits<RealType>::min_exponent)) *
1056 std::pow(RealType(2), - erange - 1) :
1057 RandomPower2::pow2<RealType>(- erange - 1)))
1064 std::pow(RealType(2), -(erange + 1)/2) *
1065 std::pow(RealType(2), -(erange + 1) + (erange + 1)/2) :
1066 RandomPower2::pow2<RealType>(- erange - 1));
1070 std::pow(RealType(2), std::numeric_limits<RealType>::min_exponent - 1)
1077 template<
class Generator>
template<
typename IntType>
1080 "Prob(n): invalid integer type IntType");
1086 template<
class Generator>
template<
typename RealType>
1087 inline bool RandomCanonical<Generator>::ProbF(RealType p)
throw() {
1096 std::numeric_limits<RealType>::radix == 2,
1097 "ProbF(p): invalid real type RealType");
1100 const int c = std::numeric_limits<RealType>::digits >
width ?
1101 width : std::numeric_limits<RealType>::digits;
1103 const RealType mult = RandomPower2::pow2<RealType>(c);
1111 if (!(p > RealType(0)))
1113 else if (p >= RealType(1))
1120 p -= RealType(Integer<result_type, c>());
1121 if (p <= RealType(0))
1125 }
while (p < RealType(1));
1131 template<
class Generator>
template<
typename IntType>
1134 "Prob(m,n): invalid integer type IntType");
1136 return m > 0 && (n > 0 || n == 0) && (m >= n || Integer<IntType>(n) < m);
1141 template<
class Generator>
template<
typename RealType>
1142 inline bool RandomCanonical<Generator>::ProbF(RealType x, RealType y)
1145 std::numeric_limits<RealType>::radix == 2,
1146 "ProbF(x,y): invalid real type RealType");
1147 if (!(x > RealType(0) && y >= RealType(0)))
1153 x = std::frexp(x, &ex);
1154 y = std::frexp(y, &ey);
1165 if (Generator::Ran() >> (s >
width ? 0 :
width - s))
1170 const int c = std::numeric_limits<RealType>::digits >
width ?
1171 width : std::numeric_limits<RealType>::digits;
1173 const RealType mult = RandomPower2::pow2<RealType>(c);
1179 RealType xa = x, ya = y;
1185 const RealType d = RealType(Integer<result_type, c>());
1186 if (ya < RealType(1)) {
1189 if (ya <= RealType(0))
1192 if (xa > RealType(0)) {
1195 if (xa >= RealType(1))
1198 if (xa <= RealType(0) && ya >= RealType(1))
1204 template<
class Generator>
template<
int nbits>
1208 const int ulbits = std::numeric_limits<bitset_uint_t>::digits;
1210 "Bits<n>(): integer constructor type too narrow");
1211 std::bitset<nbits> b;
1217 b <<= (width > ulbits ?
width - ulbits :
width);
1218 if (
width > ulbits &&
1221 (nbits > ((nbits-1)/
width) *
width + ulbits || m < nbits)) {
1237 #if HAVE_LONG_DOUBLE
1238 #define RANDOMCANONICAL_SPECIALIZE(RandomType) \
1239 template<> template<> \
1240 inline bool RandomType::Integer<bool>() \
1241 throw() { return Boolean(); } \
1242 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, float) \
1243 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, double) \
1244 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, long double)
1246 #define RANDOMCANONICAL_SPECIALIZE(RandomType) \
1247 template<> template<> \
1248 inline bool RandomType::Integer<bool>() \
1249 throw() { return Boolean(); } \
1250 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, float) \
1251 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, double)
1256 #define RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, RealType) \
1257 template<> template<> \
1258 inline bool RandomType::Prob<RealType>(RealType p) \
1259 throw() { return ProbF<RealType>(p); } \
1260 template<> template<> \
1261 inline bool RandomType::Prob<RealType>(RealType x, RealType y) \
1262 throw() { return ProbF<RealType>(x, y); }
1269 #undef RANDOMCANONICAL_SPECIALIZE
1270 #undef RANDOMCANONICAL_SPECIALIZE_PROB
1289 template<
class Generator>
1297 #if defined(_MSC_VER)
1298 # pragma warning (pop)
1301 #endif // RANDOMLIB_RANDOMCANONICAL_HPP
unsigned long bitset_uint_t
RandomCanonical< SRandomGenerator32 > SRandom32
Generate random integers, reals, and booleans.
Class to hold bit-width and unsigned type.
RandomSeed::seed_type seed_type
IntType IntegerC(IntType n)
A base class for random generators.
RandomCanonical(InputIterator a, InputIterator b)
result_type operator()(result_type n)
std::bitset< nbits > Bits()
#define STATIC_ASSERT(cond, reason)
Generator::result_type result_type
#define RANDOMLIB_LONGDOUBLEPREC
void swap(RandomLib::RandomCanonical< Generator > &r, RandomLib::RandomCanonical< Generator > &s)
#define RANDOMLIB_HASDENORM(RealType)
RandomCanonical(const std::string &s)
RandomCanonical< MRandomGenerator64 > MRandom64
RandomCanonical(const std::vector< IntType > &v)
Uniform random number generator.
RandomCanonical< SRandomGenerator64 > SRandom64
RandomCanonical< MRandomGenerator32 > MRandom32
RandomCanonical< MRandomGenerator32 > Global