|
|
@ -6,8 +6,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include "crand.h"
|
|
|
|
#include "crand.h"
|
|
|
|
|
|
|
|
|
|
|
|
typedef unsigned short uint48_t[3];
|
|
|
|
#define internal _export(internal)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef unsigned short uint48_t[3];
|
|
|
|
|
|
|
|
|
|
|
|
struct jr_state
|
|
|
|
struct jr_state
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -17,7 +18,8 @@ struct jr_state
|
|
|
|
};
|
|
|
|
};
|
|
|
|
struct drand48_data data;
|
|
|
|
struct drand48_data data;
|
|
|
|
union {
|
|
|
|
union {
|
|
|
|
unsigned short xsubi[3];
|
|
|
|
//unsigned short xsubi[3];
|
|
|
|
|
|
|
|
uint48_t xsubi;
|
|
|
|
struct {
|
|
|
|
struct {
|
|
|
|
uint64_t xsubh : 48;
|
|
|
|
uint64_t xsubh : 48;
|
|
|
|
uint16_t _xsub : 16;
|
|
|
|
uint16_t _xsub : 16;
|
|
|
@ -25,52 +27,51 @@ struct jr_state
|
|
|
|
uint64_t xsubl;
|
|
|
|
uint64_t xsubl;
|
|
|
|
} st;
|
|
|
|
} st;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef __typeof(((struct jr_state*)NULL)->st) jr_xsub_t;
|
|
|
|
|
|
|
|
|
|
|
|
_Static_assert( sizeof(uint48_t) == (sizeof(uint16_t) * 3), "bad uint48 (ushort[3])");
|
|
|
|
_Static_assert( sizeof(uint48_t) == (sizeof(uint16_t) * 3), "bad uint48 (ushort[3])");
|
|
|
|
_Static_assert( sizeof(((struct jr_state*)NULL)->st) == sizeof(uint64_t), "bad uint64 (union st)");
|
|
|
|
_Static_assert( sizeof(((struct jr_state*)NULL)->st) == sizeof(uint64_t), "bad uint64 (union st)");
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned short* _impl__jr_st_resolv__low(struct jr_state* restrict state)
|
|
|
|
__attribute__((nonnull, returns_nonnull))
|
|
|
|
|
|
|
|
static unsigned short* IFUNC_IMPL(_jr_st_resolv, low) (struct jr_state* restrict state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return state->st.xsubi;
|
|
|
|
return state->st.xsubi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__attribute__((nonnull, returns_nonnull))
|
|
|
|
static unsigned short* _impl__jr_st_resolv__high(struct jr_state* restrict state)
|
|
|
|
static unsigned short* IFUNC_IMPL(_jr_st_resolv, high) (struct jr_state* restrict state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return state->st.xsubi+1;
|
|
|
|
return state->st.xsubi+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__attribute__((returns_nonnull))
|
|
|
|
static unsigned short* (*_ifun__jr_st_resolv (void)) (struct jr_state* restrict state)
|
|
|
|
static unsigned short* IFUNC_RESOLVER(_jr_st_resolv) (struct jr_state* restrict state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct jr_state chk = {0};
|
|
|
|
struct jr_state chk = {0};
|
|
|
|
chk.st.xsubh = JR_MAX;
|
|
|
|
chk.st.xsubh = JR_MAX;
|
|
|
|
return chk.st._xsub
|
|
|
|
return chk.st._xsub
|
|
|
|
? &_impl__jr_st_resolv__high
|
|
|
|
? & IFUNC_IMPL(_jr_st_resolv, high)
|
|
|
|
: &_impl__jr_st_resolv__low;
|
|
|
|
: & IFUNC_IMPL(_jr_st_resolv, low);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned short* IFUNC_DEF(_jr_st_resolv, (struct jr_state* restrict state) __attribute__((nonnull, returns_nonnull)));
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned short* _jr_st_resolv(struct jr_state* restrict state)
|
|
|
|
internal void _jr_seed(struct jr_state* restrict state, unsigned long with)
|
|
|
|
__attribute__((ifunc("_ifun__jr_st_resolv")));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void _jr_seed(struct jr_state* restrict state, unsigned long with)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
state->st.xsubh = with;
|
|
|
|
state->st.xsubh = with;
|
|
|
|
seed48_r(_jr_st_resolv(state), &state->data);
|
|
|
|
seed48_r(_jr_st_resolv(state), &state->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long _jr_proc(struct jr_state* restrict state)
|
|
|
|
internal long _jr_proc(struct jr_state* restrict state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
jrand48_r(_jr_st_resolv(state), &state->data, &state->result);
|
|
|
|
jrand48_r(_jr_st_resolv(state), &state->data, &state->result);
|
|
|
|
return state->result;
|
|
|
|
return state->result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: a version of _jr_proc that uses use `erand48_r()` to return between 0..1.0 for _sample()
|
|
|
|
internal double _jr_procf(struct jr_state* restrict state)
|
|
|
|
|
|
|
|
|
|
|
|
double _jr_procf(struct jr_state* restrict state)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
erand48_r(_jr_st_resolv(state), &state->data, &state->fresult);
|
|
|
|
erand48_r(_jr_st_resolv(state), &state->data, &state->fresult);
|
|
|
|
return state->fresult;
|
|
|
|
return state->fresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct jr_state* _jr_alloc()
|
|
|
|
internal struct jr_state* _jr_alloc()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct jr_state* bx = aligned_alloc(_Alignof(struct jr_state), sizeof(struct jr_state));
|
|
|
|
struct jr_state* bx = aligned_alloc(_Alignof(struct jr_state), sizeof(struct jr_state));
|
|
|
|
memset(bx, 0, sizeof(struct jr_state));
|
|
|
|
memset(bx, 0, sizeof(struct jr_state));
|
|
|
@ -78,19 +79,18 @@ struct jr_state* _jr_alloc()
|
|
|
|
return bx;
|
|
|
|
return bx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct jr_state* _jr_new(unsigned long with)
|
|
|
|
internal struct jr_state* _jr_new(unsigned long with)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct jr_state* state = _jr_alloc();
|
|
|
|
struct jr_state* state = _jr_alloc();
|
|
|
|
_jr_seed(state, with);
|
|
|
|
_jr_seed(state, with);
|
|
|
|
return state;
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _jr_free(struct jr_state* restrict state)
|
|
|
|
internal void _jr_free(struct jr_state* restrict state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
free(state);
|
|
|
|
free(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: Use test macros from tracemac, run with attr(ctor) if `-DTEST` is provided.
|
|
|
|
|
|
|
|
void __TEST__jr_test()
|
|
|
|
void __TEST__jr_test()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct jr_state* st = _jr_alloc();
|
|
|
|
struct jr_state* st = _jr_alloc();
|
|
|
|