mirror of https://github.com/CGAL/cgal
112 lines
2.8 KiB
C++
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
|