#ifndef _random_hpp_INCLUDED
#define _random_hpp_INCLUDED
#include <cstdint>
namespace CaDiCaL {
class Random {
uint64_t state;
void add (uint64_t a) {
if (!(state += a))
state = 1;
next ();
}
public:
Random ();
Random (uint64_t seed) : state (seed) {}
void operator= (uint64_t seed) { state = seed; }
Random (const Random &other) : state (other.seed ()) {}
void operator+= (uint64_t a) { add (a); }
uint64_t seed () const { return state; }
uint64_t next () {
state *= 6364136223846793005ul;
state += 1442695040888963407ul;
assert (state);
return state;
}
uint32_t generate () {
next ();
return state >> 32;
}
int generate_int () { return (int) generate (); }
bool generate_bool () { return generate () < 2147483648u; }
double generate_double () { return generate () / 4294967295.0; }
int pick_int (int l, int r) {
assert (l <= r);
const unsigned delta = 1 + r - (unsigned) l;
unsigned tmp = generate (), scaled;
if (delta) {
const double fraction = tmp / 4294967296.0;
scaled = delta * fraction;
} else
scaled = tmp;
const int res = scaled + l;
assert (l <= res);
assert (res <= r);
return res;
}
int pick_log (int l, int r) {
assert (l <= r);
const unsigned delta = 1 + r - (unsigned) l;
int log_delta = delta ? 0 : 32;
while (log_delta < 32 && (1u << log_delta) < delta)
log_delta++;
const int log_res = pick_int (0, log_delta);
unsigned tmp = generate ();
if (log_res < 32)
tmp &= (1u << log_res) - 1;
if (delta)
tmp %= delta;
const int res = l + tmp;
assert (l <= res), assert (res <= r);
return res;
}
double pick_double (double l, double r) {
assert (l <= r);
double res = (r - l) * generate_double ();
res += l;
assert (l <= res);
assert (res <= r);
return res;
}
};
}
#endif