Skip to content

Instantly share code, notes, and snippets.

@iamtakingiteasy
Created November 8, 2013 18:57
Show Gist options
  • Save iamtakingiteasy/7375762 to your computer and use it in GitHub Desktop.
Save iamtakingiteasy/7375762 to your computer and use it in GitHub Desktop.
void exploreLCG() {
uint64_t min = pow(10,1);
uint64_t max = pow(10,2);
auto f = computeLCG(min, max);
srand(time(0));
uint64_t terminator = min + (rand() % (max-min));
uint64_t x = f(terminator);
std::cout << x << "\n";
while (x != terminator) {
x = f(x);
std::cout << x << "\n";
}
}
std::function<uint64_t(uint64_t)> computeLCG(uint64_t min, uint64_t max) {
uint64_t gen_a = -1;
bool found_a = false;
uint64_t gen_c = -1;
bool found_c = false;
uint64_t range = max - min;
// prime factors generator
uint64_t z = 2;
uint64_t n = range;
std::vector<uint64_t> factors;
while (z*z <= n) {
if (n%z == 0) {
factors.push_back(z);
n /= z;
} else {
z++;
}
}
if (n > 1) {
factors.push_back(n);
}
// LCG a sieve
for (uint64_t i = range; i > 1; i--) {
if (std::all_of(factors.begin(), factors.end(), [i](uint64_t p) { return (i-1) % p == 0; })) {
if (range % 4 == 0) {
if ((i-1) % 4 ==0) {
gen_a = i;
found_a = true;
break;
}
} else {
gen_a = i;
found_a = true;
break;
}
}
}
// LCG c sieve
for (uint64_t i = 2; i <= range; i++) {
// GCD
uint64_t u = range, v = i;
while (v != 0) {
uint64_t r = u % v;
u = v;
v = r;
}
if (u == 1) {
gen_c = i;
found_c = true;
break;
}
}
if (!found_a || !found_c) {
throw std::runtime_error("could not compute LCG for given boundaries");
}
return [gen_a, gen_c, range, min](uint64_t x) {
return (gen_a * x + gen_c) % range + min;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment