// Ranlux24. (1.01)
// These are probably too clunky to be generally useful.
// @todo Consolidate to a single class.
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
// Utility.
#define unlikely(c) \
__builtin_expect(!!(c), 0)
#define BITS(x) \
(sizeof(x) * CHAR_BIT)
#define NEW_T(T, count) \
((T *) allocate(count * sizeof(T)))
void *allocate(size_t n)
{
return r;
}
// EngineBase.
typedef struct EngineBase {
int (*next) (struct EngineBase*);
void (*discard) (struct EngineBase*, int);
void (*delete) (struct EngineBase*);
} EngineBase;
int nextEngineBase(EngineBase *self)
{
return self->next(self);
}
void discardEngineBase(EngineBase *self, int n)
{
return self->discard(self, n);
}
void deleteEngineBase(EngineBase *self)
{
return self->delete(self);
}
// SubtractWithCarry.
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 nextSubtractWithCarryEngine(EngineBase *base)
{
SubtractWithCarryEngine *self = (SubtractWithCarryEngine *) base;
self->i = 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 (int i = 0; i < s; i++)
x[i] = next_(x, m, i + t, i, c);
for (int i = s; i < r; i++)
x[i] = next_(x, m, i - s, i, c);
self->i = i = 0;
}
return x[i];
}
void discardSubtractWithCarryEngine(EngineBase *base, int n)
{
for (int i = 0; i < n; i++)
nextSubtractWithCarryEngine(base);
}
void deleteSubtractWithCarryEngine(EngineBase *base)
{
SubtractWithCarryEngine *self = (SubtractWithCarryEngine *) base;
if (self != 0)
{
}
}
EngineBase *newSubtractWithCarryEngine(int w, int s, int r)
{
assert(0 < w
&& w
< BITS
(int));
SubtractWithCarryEngine *self = NEW_T(SubtractWithCarryEngine, 1);
self->base.next = nextSubtractWithCarryEngine;
self->base.discard = discardSubtractWithCarryEngine;
self->base.delete = deleteSubtractWithCarryEngine;
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;
for (int i = 0; i < r; i++)
self
->x
[i
] = rand() & self
->m
; return (EngineBase *) self;
}
// DiscardBlock.
typedef struct {
EngineBase base, *owned;
int p, r, i;
} DiscardBlockEngine;
int nextDiscardBlockEngine(EngineBase *base)
{
DiscardBlockEngine *self = (DiscardBlockEngine *) base;
if (self->i == 0)
{
discardEngineBase(self->owned, self->p - self->r);
self->i = self->r;
}
self->i -= 1;
return nextEngineBase(self->owned);
}
void deleteDiscardBlockEngine(EngineBase *base)
{
DiscardBlockEngine *self = (DiscardBlockEngine *) base;
if (self != 0)
{
deleteEngineBase(self->owned);
}
}
EngineBase *newDiscardBlockEngine(EngineBase **unique, int p, int r)
{
DiscardBlockEngine *self = NEW_T(DiscardBlockEngine, 1);
self->base.next = nextDiscardBlockEngine;
self->base.discard = 0;
self->base.delete = deleteDiscardBlockEngine;
self->owned = *unique; *unique = 0; // Transfer ownership.
self->p = p;
self->r = r;
self->i = r;
return (EngineBase *) self;
}
// Ranlux24.
EngineBase *newRanlux24(void)
{
EngineBase *ranlux24_base = newSubtractWithCarryEngine(24, 10, 24);
return newDiscardBlockEngine(&ranlux24_base, 223, 23);
}
int main(void)
{
EngineBase *ranlux24 = newRanlux24();
for (int i = 0; i < 24; i++)
{
int r = nextEngineBase(ranlux24);
}
deleteEngineBase(ranlux24);
return 0;
}