// Ranlux24 PRNG. (2.01)
// Chaotic with long period but slow due to discard.
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
// Utility.
#define BITS(x) \
(sizeof(x) * CHAR_BIT)
#define UNLIKELY(cond) \
__builtin_expect(!!(cond), 0)
#define NEW_T(T, n) \
((T *) allocate(n * sizeof(T)))
void *allocate(size_t n)
{
return r;
}
// Ranlux24.
typedef struct {
int *x, c, i, j;
} Ranlux24;
static inline int next(int *x, int i_s, int i_r, int *carry)
{
int y = x[i_s] - x[i_r] - *carry;
*carry = -(y >> (BITS(int) - 1));
return y & 0xFFFFFF;
}
static int subtract_with_carry_next(Ranlux24 *self)
{
self->i += 1;
int *x = self->x, i = self->i;
if (UNLIKELY(i >= 24))
{
int c = self->c;
for (i = 0; i < 10; i++)
x[i] = next(x, i + 14, i, &c);
for (i = 10; i < 24; i++)
x[i] = next(x, i - 10, i, &c);
self->c = c;
self->i = i = 0;
}
return x[i];
}
static void subtract_with_carry_discard(Ranlux24 *self, int n)
{
for (int i = 0; i < n; i++)
subtract_with_carry_next(self);
}
int ranlux24_next(Ranlux24 *self)
{
if (self->j == 0)
{
subtract_with_carry_discard(self, 223 - 23);
self->j = 23;
}
self->j -= 1;
return subtract_with_carry_next(self);
}
void ranlux24_discard(Ranlux24 *self, int n)
{
for (int i = 0; i < n; i++)
ranlux24_next(self);
}
void ranlux24_delete(Ranlux24 *self)
{
if (self != 0)
{
}
}
Ranlux24 *ranlux24_new(unsigned int seed)
{
Ranlux24 *self = NEW_T(Ranlux24, 1);
self->x = NEW_T(int, 24);
self->c = 0;
self->i = 24-1;
self->j = 23;
unsigned short rs[] = {0x330E, seed, seed>>16};
for (int i = 0; i < 24; i++)
self->x[i] = nrand48(rs) & 0xFFFFFF;
return self;
}
// Main.
double clock_now(void)
{
struct timespec now;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now);
return now.tv_sec + now.tv_nsec / 1.0E+09;
}
int main(void)
{
unsigned int seed
= time(0); Ranlux24 *engine = ranlux24_new(seed);
for (int i = 0; i < 24; i++)
{
int r = ranlux24_next(engine);
}
int n = 10000000;
double t = clock_now();
ranlux24_discard(engine, n);
printf("Elapsed: %.9fs\n", clock_now
() - t
);
ranlux24_delete(engine);
return 0;
}
Ly8gUmFubHV4MjQgUFJORy4gKDIuMDEpCi8vIENoYW90aWMgd2l0aCBsb25nIHBlcmlvZCBidXQgc2xvdyBkdWUgdG8gZGlzY2FyZC4KCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8dGltZS5oPgoKLy8gVXRpbGl0eS4KCiNkZWZpbmUgQklUUyh4KSBcCiAgICAoc2l6ZW9mKHgpICogQ0hBUl9CSVQpCgojZGVmaW5lIFVOTElLRUxZKGNvbmQpIFwKICAgIF9fYnVpbHRpbl9leHBlY3QoISEoY29uZCksIDApCgojZGVmaW5lIE5FV19UKFQsIG4pIFwKICAgICgoVCAqKSBhbGxvY2F0ZShuICogc2l6ZW9mKFQpKSkKCnZvaWQgKmFsbG9jYXRlKHNpemVfdCBuKQp7CiAgICB2b2lkICpyID0gbWFsbG9jKG4pOwogICAgYXNzZXJ0KHIgIT0gMCB8fCBuID09IDApOwogICAgcmV0dXJuIHI7Cn0KCi8vIFJhbmx1eDI0LgoKdHlwZWRlZiBzdHJ1Y3QgewogICAgaW50ICp4LCBjLCBpLCBqOwp9IFJhbmx1eDI0OwoKc3RhdGljIGlubGluZSBpbnQgbmV4dChpbnQgKngsIGludCBpX3MsIGludCBpX3IsIGludCAqY2FycnkpCnsKICAgIGludCB5ID0geFtpX3NdIC0geFtpX3JdIC0gKmNhcnJ5OwogICAgKmNhcnJ5ID0gLSh5ID4+IChCSVRTKGludCkgLSAxKSk7CiAgICByZXR1cm4geSAmIDB4RkZGRkZGOwp9CgpzdGF0aWMgaW50IHN1YnRyYWN0X3dpdGhfY2FycnlfbmV4dChSYW5sdXgyNCAqc2VsZikKewogICAgc2VsZi0+aSArPSAxOwogICAgaW50ICp4ID0gc2VsZi0+eCwgaSA9IHNlbGYtPmk7CgogICAgaWYgKFVOTElLRUxZKGkgPj0gMjQpKQogICAgewogICAgICAgIGludCBjID0gc2VsZi0+YzsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTA7IGkrKykKICAgICAgICAgICAgeFtpXSA9IG5leHQoeCwgaSArIDE0LCBpLCAmYyk7CiAgICAgICAgZm9yIChpID0gMTA7IGkgPCAyNDsgaSsrKQogICAgICAgICAgICB4W2ldID0gbmV4dCh4LCBpIC0gMTAsIGksICZjKTsKICAgICAgICBzZWxmLT5jID0gYzsKICAgICAgICBzZWxmLT5pID0gaSA9IDA7CiAgICB9CiAgICByZXR1cm4geFtpXTsKfQoKc3RhdGljIHZvaWQgc3VidHJhY3Rfd2l0aF9jYXJyeV9kaXNjYXJkKFJhbmx1eDI0ICpzZWxmLCBpbnQgbikKewogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgc3VidHJhY3Rfd2l0aF9jYXJyeV9uZXh0KHNlbGYpOwp9CgppbnQgcmFubHV4MjRfbmV4dChSYW5sdXgyNCAqc2VsZikKewogICAgaWYgKHNlbGYtPmogPT0gMCkKICAgIHsKICAgICAgICBzdWJ0cmFjdF93aXRoX2NhcnJ5X2Rpc2NhcmQoc2VsZiwgMjIzIC0gMjMpOwogICAgICAgIHNlbGYtPmogPSAyMzsKICAgIH0KICAgIHNlbGYtPmogLT0gMTsKICAgIHJldHVybiBzdWJ0cmFjdF93aXRoX2NhcnJ5X25leHQoc2VsZik7Cn0KCnZvaWQgcmFubHV4MjRfZGlzY2FyZChSYW5sdXgyNCAqc2VsZiwgaW50IG4pCnsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgICAgIHJhbmx1eDI0X25leHQoc2VsZik7Cn0KCnZvaWQgcmFubHV4MjRfZGVsZXRlKFJhbmx1eDI0ICpzZWxmKQp7CiAgICBpZiAoc2VsZiAhPSAwKQogICAgewogICAgICAgIGZyZWUoc2VsZi0+eCk7CiAgICAgICAgZnJlZShzZWxmKTsKICAgIH0KfQoKUmFubHV4MjQgKnJhbmx1eDI0X25ldyh1bnNpZ25lZCBpbnQgc2VlZCkKewogICAgUmFubHV4MjQgKnNlbGYgPSBORVdfVChSYW5sdXgyNCwgMSk7CiAgICBzZWxmLT54ID0gTkVXX1QoaW50LCAyNCk7CiAgICBzZWxmLT5jID0gMDsKICAgIHNlbGYtPmkgPSAyNC0xOwogICAgc2VsZi0+aiA9IDIzOwoKICAgIHVuc2lnbmVkIHNob3J0IHJzW10gPSB7MHgzMzBFLCBzZWVkLCBzZWVkPj4xNn07CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDI0OyBpKyspCiAgICAgICAgc2VsZi0+eFtpXSA9IG5yYW5kNDgocnMpICYgMHhGRkZGRkY7CiAgICByZXR1cm4gc2VsZjsKfQoKLy8gTWFpbi4KCmRvdWJsZSBjbG9ja19ub3codm9pZCkKewogICAgc3RydWN0IHRpbWVzcGVjIG5vdzsKICAgIGNsb2NrX2dldHRpbWUoQ0xPQ0tfUFJPQ0VTU19DUFVUSU1FX0lELCAmbm93KTsKICAgIHJldHVybiBub3cudHZfc2VjICsgbm93LnR2X25zZWMgLyAxLjBFKzA5Owp9CgppbnQgbWFpbih2b2lkKQp7CiAgICB1bnNpZ25lZCBpbnQgc2VlZCA9IHRpbWUoMCk7CiAgICBSYW5sdXgyNCAqZW5naW5lID0gcmFubHV4MjRfbmV3KHNlZWQpOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMjQ7IGkrKykKICAgIHsKICAgICAgICBpbnQgciA9IHJhbmx1eDI0X25leHQoZW5naW5lKTsKICAgICAgICBwcmludGYoIiVkXG4iLCByKTsKICAgIH0KCiAgICBpbnQgbiA9IDEwMDAwMDAwOwogICAgZG91YmxlIHQgPSBjbG9ja19ub3coKTsKICAgIHJhbmx1eDI0X2Rpc2NhcmQoZW5naW5lLCBuKTsKICAgIHByaW50ZigiRWxhcHNlZDogJS45ZnNcbiIsIGNsb2NrX25vdygpIC0gdCk7CgogICAgcmFubHV4MjRfZGVsZXRlKGVuZ2luZSk7CiAgICByZXR1cm4gMDsKfQ==