// Ranlux24 PRNG. (1.05)
// 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;
}
// Engine Base.
typedef struct EngineBase {
int (*next) (struct EngineBase*);
void (*discard) (struct EngineBase*, int);
void (*delete) (struct EngineBase*);
} EngineBase;
int engineBase_next(EngineBase *self)
{
return self->next(self);
}
void engineBase_discard(EngineBase *self, int n)
{
return self->discard(self, n);
}
void engineBase_delete(EngineBase *self)
{
return self->delete(self);
}
// Subtract With Carry.
typedef struct {
EngineBase base;
int *x, c, i, m, r, s;
} SubtractWithCarryEngine;
static inline int next(int *x, int mask, int i_s, int i_r, int *carry)
{
int y = x[i_s] - x[i_r] - *carry;
*carry = -(y >> (BITS(int) - 1));
return y & mask;
}
int subtractWithCarryEngine_next(EngineBase *base)
{
SubtractWithCarryEngine *self = (SubtractWithCarryEngine *) base;
self->i += 1;
int *x = self->x, i = self->i, r = self->r;
if (UNLIKELY(i >= r))
{
int c = self->c, m = self->m, s = self->s, t = r - s;
for (i = 0; i < s; i++)
x[i] = next(x, m, i + t, i, &c);
for (i = s; i < r; i++)
x[i] = next(x, m, i - s, i, &c);
self->c = c;
self->i = i = 0;
}
return x[i];
}
void subtractWithCarryEngine_discard(EngineBase *base, int n)
{
for (int i = 0; i < n; i++)
subtractWithCarryEngine_next(base);
}
void subtractWithCarryEngine_delete(EngineBase *base)
{
SubtractWithCarryEngine *self = (SubtractWithCarryEngine *) base;
if (self != 0)
{
}
}
EngineBase *subtractWithCarryEngine_new(int w, int s, int r, unsigned int seed)
{
assert(0 < w
&& w
< BITS
(int));
SubtractWithCarryEngine *self = NEW_T(SubtractWithCarryEngine, 1);
self->base.next = subtractWithCarryEngine_next;
self->base.discard = subtractWithCarryEngine_discard;
self->base.delete = subtractWithCarryEngine_delete;
self->x = NEW_T(int, r);
self->c = 0;
self->i = r-1;
self->m = -1U >> (BITS(int) - w);
self->r = r;
self->s = s;
unsigned short state[] = {0x330E, seed, seed>>16};
for (int i = 0; i < r; i++)
self->x[i] = nrand48(state) & self->m;
return (EngineBase *) self;
}
// Discard Block.
typedef struct {
EngineBase base, *owned;
int p, r, i;
} DiscardBlockEngine;
int discardBlockEngine_next(EngineBase *base)
{
DiscardBlockEngine *self = (DiscardBlockEngine *) base;
if (self->i == 0)
{
engineBase_discard(self->owned, self->p - self->r);
self->i = self->r;
}
self->i -= 1;
return engineBase_next(self->owned);
}
void discardBlockEngine_discard(EngineBase *base, int n)
{
for (int i = 0; i < n; i++)
discardBlockEngine_next(base);
}
void discardBlockEngine_delete(EngineBase *base)
{
DiscardBlockEngine *self = (DiscardBlockEngine *) base;
if (self != 0)
{
engineBase_delete(self->owned);
}
}
EngineBase *discardBlockEngine_new(EngineBase **unique, int p, int r)
{
DiscardBlockEngine *self = NEW_T(DiscardBlockEngine, 1);
self->base.next = discardBlockEngine_next;
self->base.discard = discardBlockEngine_discard;
self->base.delete = discardBlockEngine_delete;
self->owned = *unique; *unique = 0; // Transfer ownership.
self->p = p;
self->r = r;
self->i = r;
return (EngineBase *) self;
}
// Ranlux24.
EngineBase *ranlux24_new(unsigned int seed)
{
EngineBase *ranlux24_base = subtractWithCarryEngine_new(24, 10, 24, seed);
return discardBlockEngine_new(&ranlux24_base, 223, 23);
}
// 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); EngineBase *engine = ranlux24_new(seed);
for (int i = 0; i < 24; i++)
{
int r = engineBase_next(engine);
}
int n = 10000000;
double t = clock_now();
engineBase_discard(engine, n);
printf("Elapsed: %.9fs\n", clock_now
() - t
);
engineBase_delete(engine);
return 0;
}
Ly8gUmFubHV4MjQgUFJORy4gKDEuMDUpCi8vIENoYW90aWMgd2l0aCBsb25nIHBlcmlvZCBidXQgc2xvdyBkdWUgdG8gZGlzY2FyZC4KCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8dGltZS5oPgoKLy8gVXRpbGl0eS4KCiNkZWZpbmUgQklUUyh4KSBcCiAgICAoc2l6ZW9mKHgpICogQ0hBUl9CSVQpCgojZGVmaW5lIFVOTElLRUxZKGNvbmQpIFwKICAgIF9fYnVpbHRpbl9leHBlY3QoISEoY29uZCksIDApCgojZGVmaW5lIE5FV19UKFQsIG4pIFwKICAgICgoVCAqKSBhbGxvY2F0ZShuICogc2l6ZW9mKFQpKSkKCnZvaWQgKmFsbG9jYXRlKHNpemVfdCBuKQp7CiAgICB2b2lkICpyID0gbWFsbG9jKG4pOwogICAgYXNzZXJ0KHIgIT0gMCB8fCBuID09IDApOwogICAgcmV0dXJuIHI7Cn0KCi8vIEVuZ2luZSBCYXNlLgoKdHlwZWRlZiBzdHJ1Y3QgRW5naW5lQmFzZSB7CiAgICBpbnQgICgqbmV4dCkgICAgKHN0cnVjdCBFbmdpbmVCYXNlKik7CiAgICB2b2lkICgqZGlzY2FyZCkgKHN0cnVjdCBFbmdpbmVCYXNlKiwgaW50KTsKICAgIHZvaWQgKCpkZWxldGUpICAoc3RydWN0IEVuZ2luZUJhc2UqKTsKfSBFbmdpbmVCYXNlOwoKaW50IGVuZ2luZUJhc2VfbmV4dChFbmdpbmVCYXNlICpzZWxmKQp7CiAgICByZXR1cm4gc2VsZi0+bmV4dChzZWxmKTsKfQoKdm9pZCBlbmdpbmVCYXNlX2Rpc2NhcmQoRW5naW5lQmFzZSAqc2VsZiwgaW50IG4pCnsKICAgIHJldHVybiBzZWxmLT5kaXNjYXJkKHNlbGYsIG4pOwp9Cgp2b2lkIGVuZ2luZUJhc2VfZGVsZXRlKEVuZ2luZUJhc2UgKnNlbGYpCnsKICAgIHJldHVybiBzZWxmLT5kZWxldGUoc2VsZik7Cn0KCi8vIFN1YnRyYWN0IFdpdGggQ2FycnkuCgp0eXBlZGVmIHN0cnVjdCB7CiAgICBFbmdpbmVCYXNlIGJhc2U7CiAgICBpbnQgKngsIGMsIGksIG0sIHIsIHM7Cn0gU3VidHJhY3RXaXRoQ2FycnlFbmdpbmU7CgpzdGF0aWMgaW5saW5lIGludCBuZXh0KGludCAqeCwgaW50IG1hc2ssIGludCBpX3MsIGludCBpX3IsIGludCAqY2FycnkpCnsKICAgIGludCB5ID0geFtpX3NdIC0geFtpX3JdIC0gKmNhcnJ5OwogICAgKmNhcnJ5ID0gLSh5ID4+IChCSVRTKGludCkgLSAxKSk7CiAgICByZXR1cm4geSAmIG1hc2s7Cn0KCmludCBzdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZV9uZXh0KEVuZ2luZUJhc2UgKmJhc2UpCnsKICAgIFN1YnRyYWN0V2l0aENhcnJ5RW5naW5lICpzZWxmID0gKFN1YnRyYWN0V2l0aENhcnJ5RW5naW5lICopIGJhc2U7CgogICAgc2VsZi0+aSArPSAxOwogICAgaW50ICp4ID0gc2VsZi0+eCwgaSA9IHNlbGYtPmksIHIgPSBzZWxmLT5yOwoKICAgIGlmIChVTkxJS0VMWShpID49IHIpKQogICAgewogICAgICAgIGludCBjID0gc2VsZi0+YywgbSA9IHNlbGYtPm0sIHMgPSBzZWxmLT5zLCB0ID0gciAtIHM7CgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBzOyBpKyspCiAgICAgICAgICAgIHhbaV0gPSBuZXh0KHgsIG0sIGkgKyB0LCBpLCAmYyk7CiAgICAgICAgZm9yIChpID0gczsgaSA8IHI7IGkrKykKICAgICAgICAgICAgeFtpXSA9IG5leHQoeCwgbSwgaSAtIHMsIGksICZjKTsKICAgICAgICBzZWxmLT5jID0gYzsKICAgICAgICBzZWxmLT5pID0gaSA9IDA7CiAgICB9CiAgICByZXR1cm4geFtpXTsKfQoKdm9pZCBzdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZV9kaXNjYXJkKEVuZ2luZUJhc2UgKmJhc2UsIGludCBuKQp7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBzdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZV9uZXh0KGJhc2UpOwp9Cgp2b2lkIHN1YnRyYWN0V2l0aENhcnJ5RW5naW5lX2RlbGV0ZShFbmdpbmVCYXNlICpiYXNlKQp7CiAgICBTdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZSAqc2VsZiA9IChTdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZSAqKSBiYXNlOwoKICAgIGlmIChzZWxmICE9IDApCiAgICB7CiAgICAgICAgZnJlZShzZWxmLT54KTsKICAgICAgICBmcmVlKHNlbGYpOwogICAgfQp9CgpFbmdpbmVCYXNlICpzdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZV9uZXcoaW50IHcsIGludCBzLCBpbnQgciwgdW5zaWduZWQgaW50IHNlZWQpCnsKICAgIGFzc2VydCgwIDwgdyAmJiB3IDwgQklUUyhpbnQpKTsKICAgIGFzc2VydCgwIDwgcyAmJiBzIDwgcik7CgogICAgU3VidHJhY3RXaXRoQ2FycnlFbmdpbmUgKnNlbGYgPSBORVdfVChTdWJ0cmFjdFdpdGhDYXJyeUVuZ2luZSwgMSk7CgogICAgc2VsZi0+YmFzZS5uZXh0ID0gc3VidHJhY3RXaXRoQ2FycnlFbmdpbmVfbmV4dDsKICAgIHNlbGYtPmJhc2UuZGlzY2FyZCA9IHN1YnRyYWN0V2l0aENhcnJ5RW5naW5lX2Rpc2NhcmQ7CiAgICBzZWxmLT5iYXNlLmRlbGV0ZSA9IHN1YnRyYWN0V2l0aENhcnJ5RW5naW5lX2RlbGV0ZTsKICAgIHNlbGYtPnggPSBORVdfVChpbnQsIHIpOwogICAgc2VsZi0+YyA9IDA7CiAgICBzZWxmLT5pID0gci0xOwogICAgc2VsZi0+bSA9IC0xVSA+PiAoQklUUyhpbnQpIC0gdyk7CiAgICBzZWxmLT5yID0gcjsKICAgIHNlbGYtPnMgPSBzOwoKICAgIHVuc2lnbmVkIHNob3J0IHN0YXRlW10gPSB7MHgzMzBFLCBzZWVkLCBzZWVkPj4xNn07CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHI7IGkrKykKICAgICAgICBzZWxmLT54W2ldID0gbnJhbmQ0OChzdGF0ZSkgJiBzZWxmLT5tOwogICAgcmV0dXJuIChFbmdpbmVCYXNlICopIHNlbGY7Cn0KCi8vIERpc2NhcmQgQmxvY2suCgp0eXBlZGVmIHN0cnVjdCB7CiAgICBFbmdpbmVCYXNlIGJhc2UsICpvd25lZDsKICAgIGludCBwLCByLCBpOwp9IERpc2NhcmRCbG9ja0VuZ2luZTsKCmludCBkaXNjYXJkQmxvY2tFbmdpbmVfbmV4dChFbmdpbmVCYXNlICpiYXNlKQp7CiAgICBEaXNjYXJkQmxvY2tFbmdpbmUgKnNlbGYgPSAoRGlzY2FyZEJsb2NrRW5naW5lICopIGJhc2U7CgogICAgaWYgKHNlbGYtPmkgPT0gMCkKICAgIHsKICAgICAgICBlbmdpbmVCYXNlX2Rpc2NhcmQoc2VsZi0+b3duZWQsIHNlbGYtPnAgLSBzZWxmLT5yKTsKICAgICAgICBzZWxmLT5pID0gc2VsZi0+cjsKICAgIH0KICAgIHNlbGYtPmkgLT0gMTsKICAgIHJldHVybiBlbmdpbmVCYXNlX25leHQoc2VsZi0+b3duZWQpOwp9Cgp2b2lkIGRpc2NhcmRCbG9ja0VuZ2luZV9kaXNjYXJkKEVuZ2luZUJhc2UgKmJhc2UsIGludCBuKQp7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBkaXNjYXJkQmxvY2tFbmdpbmVfbmV4dChiYXNlKTsKfQoKdm9pZCBkaXNjYXJkQmxvY2tFbmdpbmVfZGVsZXRlKEVuZ2luZUJhc2UgKmJhc2UpCnsKICAgIERpc2NhcmRCbG9ja0VuZ2luZSAqc2VsZiA9IChEaXNjYXJkQmxvY2tFbmdpbmUgKikgYmFzZTsKCiAgICBpZiAoc2VsZiAhPSAwKQogICAgewogICAgICAgIGVuZ2luZUJhc2VfZGVsZXRlKHNlbGYtPm93bmVkKTsKICAgICAgICBmcmVlKHNlbGYpOwogICAgfQp9CgpFbmdpbmVCYXNlICpkaXNjYXJkQmxvY2tFbmdpbmVfbmV3KEVuZ2luZUJhc2UgKip1bmlxdWUsIGludCBwLCBpbnQgcikKewogICAgYXNzZXJ0KDAgPCByICYmIHIgPD0gcCk7CgogICAgRGlzY2FyZEJsb2NrRW5naW5lICpzZWxmID0gTkVXX1QoRGlzY2FyZEJsb2NrRW5naW5lLCAxKTsKCiAgICBzZWxmLT5iYXNlLm5leHQgPSBkaXNjYXJkQmxvY2tFbmdpbmVfbmV4dDsKICAgIHNlbGYtPmJhc2UuZGlzY2FyZCA9IGRpc2NhcmRCbG9ja0VuZ2luZV9kaXNjYXJkOwogICAgc2VsZi0+YmFzZS5kZWxldGUgPSBkaXNjYXJkQmxvY2tFbmdpbmVfZGVsZXRlOwogICAgc2VsZi0+b3duZWQgPSAqdW5pcXVlOyAqdW5pcXVlID0gMDsgLy8gVHJhbnNmZXIgb3duZXJzaGlwLgogICAgc2VsZi0+cCA9IHA7CiAgICBzZWxmLT5yID0gcjsKICAgIHNlbGYtPmkgPSByOwogICAgcmV0dXJuIChFbmdpbmVCYXNlICopIHNlbGY7Cn0KCi8vIFJhbmx1eDI0LgoKRW5naW5lQmFzZSAqcmFubHV4MjRfbmV3KHVuc2lnbmVkIGludCBzZWVkKQp7CiAgICBFbmdpbmVCYXNlICpyYW5sdXgyNF9iYXNlID0gc3VidHJhY3RXaXRoQ2FycnlFbmdpbmVfbmV3KDI0LCAxMCwgMjQsIHNlZWQpOwogICAgcmV0dXJuIGRpc2NhcmRCbG9ja0VuZ2luZV9uZXcoJnJhbmx1eDI0X2Jhc2UsIDIyMywgMjMpOwp9CgovLyBNYWluLgoKZG91YmxlIGNsb2NrX25vdyh2b2lkKQp7CiAgICBzdHJ1Y3QgdGltZXNwZWMgbm93OwogICAgY2xvY2tfZ2V0dGltZShDTE9DS19QUk9DRVNTX0NQVVRJTUVfSUQsICZub3cpOwogICAgcmV0dXJuIG5vdy50dl9zZWMgKyBub3cudHZfbnNlYyAvIDEuMEUrMDk7Cn0KCmludCBtYWluKHZvaWQpCnsKICAgIHVuc2lnbmVkIGludCBzZWVkID0gdGltZSgwKTsKICAgIEVuZ2luZUJhc2UgKmVuZ2luZSA9IHJhbmx1eDI0X25ldyhzZWVkKTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IDI0OyBpKyspCiAgICB7CiAgICAgICAgaW50IHIgPSBlbmdpbmVCYXNlX25leHQoZW5naW5lKTsKICAgICAgICBwcmludGYoIiVkXG4iLCByKTsKICAgIH0KCiAgICBpbnQgbiA9IDEwMDAwMDAwOwogICAgZG91YmxlIHQgPSBjbG9ja19ub3coKTsKICAgIGVuZ2luZUJhc2VfZGlzY2FyZChlbmdpbmUsIG4pOwogICAgcHJpbnRmKCJFbGFwc2VkOiAlLjlmc1xuIiwgY2xvY2tfbm93KCkgLSB0KTsKCiAgICBlbmdpbmVCYXNlX2RlbGV0ZShlbmdpbmUpOwogICAgcmV0dXJuIDA7Cn0=