cgal/Apollonius_graph_2/generators/include/CGAL/random_integer.h

112 lines
2.8 KiB
C++

#ifndef CGAL_RANDOM_INTEGER_H
#define CGAL_RANDOM_INTEGER_H
#include <CGAL/basic.h>
#include <cstdlib>
#include <cassert>
#include <CGAL/Gmpz.h>
// type "man {rand, random, drand48}" for C functions that produce
// random numbers
//extern "C" int getpid();
//extern "C" int srandom(unsigned);
//extern "C" long random();
CGAL_BEGIN_NAMESPACE
// powers of 2 from 2^0 to 2^53
double
P2[54]={1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0,
512.0, 1024.0, 2048.0, 4096.0, 8192.0, 16384.0, 32768.0,
65536.0, 131072.0, 262144.0, 524288.0, 1048576.0,
2097152.0, 4194304.0, 8388608.0, 16777216.0, 33554432.0,
67108864.0, 134217728.0, 268435456.0, 536870912.0,
1073741824.0, 2147483648.0, 4294967296.0, 8589934592.0,
17179869184.0, 34359738368.0, 68719476736.0,
137438953472.0, 274877906944.0, 549755813888.0,
1099511627776.0, 2199023255552.0, 4398046511104.0,
8796093022208.0, 17592186044416.0, 35184372088832.0,
70368744177664.0, 140737488355328.0, 281474976710656.0,
562949953421312.0, 1125899906842624.0, 2251799813685248.0,
4503599627370496.0, 9007199254740992.0};
// set the random number generator seed
void set_seed(unsigned int seed)
{
srandom(seed);
}
// return random integer of b bits
double random_integer(int b, bool allow_negative = true)
{
double value;
if (b > 27) {
value = ((int)random()) % ((int)P2[27]);
value += ( ((int)random()) % ((int)P2[b - 27]) ) * P2[27];
} else {
value = ((int)random()) % (int)P2[b];
}
if ( allow_negative ) {
value *= ( ((int) random()) % 2 == 0 ) ? 1 : -1;
}
return value;
}
template<class Random>
double random_integer(Random& r, unsigned int b, bool allow_negative = true)
{
// returns random integers in the range [0, 2^b - 1).
// b is required to be at least 1 and at most 52
// and if allow_negative is true then the range includes negative
// numbers as well and becomes: [-2^b + 1, 2^b - 1).
CGAL_precondition( b >= 0 && b <= 52 );
if ( b == 0 ) { return 0; }
double M = pow(2.0,b);
CGAL::Gmpz z;
if ( allow_negative ) {
z = r.get_double(-M, M);
} else {
z = r.get_double(0, M);
}
return CGAL::to_double(z);
}
template<class Random>
double random_even_integer(Random& r, unsigned int b,
bool allow_negative = true)
{
// returns random even integers in the range [0, 2^b - 1).
// b is required to be at least 1 and at most 52
// and if allow_negative is true then the range includes negative
// numbers as well and becomes: [-2^b + 1, 2^b - 1).
assert( b >= 0 && b <= 52 );
if ( b == 0 ) { return 0; }
double M = pow(2.0,b);
CGAL::Gmpz z;
CGAL::Gmpz two(2);
do {
if ( allow_negative ) {
z = r.get_double(-M, M);
} else {
z = r.get_double(0, M);
}
} while ( z % two != 0 );
return CGAL::to_double(z);
}
CGAL_END_NAMESPACE
#endif // CGAL_RANDOM_INTEGER_H