commit
01f12fba2e
@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
all: clean shuffle3
|
||||
|
||||
clean:
|
||||
rm -f build/*
|
||||
|
||||
shuffle3:
|
||||
gcc src/*.c -Iinclude/ -g -Wall -pedantic --std=gnu11 -o build/$@ -lm
|
||||
./build/$@
|
@ -0,0 +1,59 @@
|
||||
#ifndef _PTR_STORE_H
|
||||
#define _PTR_STORE_H
|
||||
|
||||
#include <stddef.h>
|
||||
typedef struct store_link {
|
||||
void* ptr;
|
||||
|
||||
int is_obj;
|
||||
|
||||
struct store_link* next;
|
||||
} store_t;
|
||||
|
||||
typedef struct store_obj {
|
||||
void* state;
|
||||
|
||||
void (*constructor)(struct store_obj* this);
|
||||
void (*destructor)(struct store_obj* this);
|
||||
|
||||
void (*copy_to)(struct store_obj* this, struct store_obj* other);
|
||||
} object;
|
||||
|
||||
store_t *new_store();
|
||||
void* store_malloc(store_t *store, size_t sz);
|
||||
void store_free(store_t* store, void* ptr);
|
||||
void destroy_store(store_t *store);
|
||||
void* store_ptr(store_t *store, void *heap);
|
||||
void store_collect(store_t *store);
|
||||
store_t* _store_first_empty(store_t *store, int setobj);
|
||||
object* copy_object(object* from, object* to);
|
||||
object* clone_object(store_t* store, object *from);
|
||||
|
||||
object *new_object_unmanaged(object prototype);
|
||||
void free_object_unmanaged(object* obj);
|
||||
object* store_object(store_t* store, object prototype);
|
||||
void free_object(store_t *store,object *obj);
|
||||
object object_prototype();
|
||||
|
||||
extern const object OBJ_PROTO;
|
||||
|
||||
#define strack _store_first_empty(__internal_store, 0)->ptr =
|
||||
#define strack_obj _store_first_empty(__internal_store, 1)->ptr =
|
||||
|
||||
#define S_LEXENV store_t* __internal_store
|
||||
#define S_LEXCALL(f, ...) f(__internal_store, __VA_ARGS__)
|
||||
#define LEXENV __internal_store
|
||||
#define scollect() store_collect(__internal_store)
|
||||
#define smalloc(sz) store_malloc(__internal_store, sz)
|
||||
#define sdelete(ptr) _Generic((ptr), object*: free_object, default: store_free)(__internal_store, ptr)
|
||||
#define snew(type) ((type*)smalloc(sizeof(type)))
|
||||
#define snew_obj(proto) store_object(__internal_store, proto)
|
||||
#define MANAGED(var) { \
|
||||
store_t * __internal_store = new_store(); \
|
||||
var; \
|
||||
destroy_store(__internal_store); \
|
||||
}
|
||||
|
||||
#define STORE_LEXBIND(type, name) type name = *((type*)store_malloc(__internal_store, sizeof(type)));
|
||||
|
||||
#endif /* _PTR_STORE_H */
|
@ -0,0 +1,25 @@
|
||||
#ifndef _RNG_H
|
||||
#define _RNG_H
|
||||
|
||||
typedef struct rng_algo *RNG; //RNG algorithm reference
|
||||
|
||||
#define rng_reinterpret(rng, value, type) (*((type*)rng_next(rng, &value, sizeof(type))))
|
||||
#define rng_reinterpret_new(rng, value, type) (*((type*)rng_next(rng, malloc(sizeof(type)), sizeof(type))))
|
||||
#define rng_reinterpret_stackalloc(rng, value, type) rng_reinterpret(rng, alloca(sizeof(type)), type)
|
||||
|
||||
#define RNG_LEXBIND(rng, type, name) type name = rng_reinterpret(rng, name, type)
|
||||
|
||||
double rng_next_double(RNG algo);
|
||||
int rng_next_int_bounded(RNG algo, int min, int max);
|
||||
int rng_next_int(RNG algo, int max);
|
||||
void* rng_next(RNG algo, void* data, int len);
|
||||
int rng_chance(RNG algo, double d);
|
||||
void rng_free(RNG algo);
|
||||
void rng_seed(RNG algo, void* seed);
|
||||
RNG rng_new(RNG (*instantiate)(void));
|
||||
|
||||
#define RNG_IMPL_DEFINITION(name) RNG __rng_impl_ ## name(void)
|
||||
#define RNG_ALGO(name) &__rng_impl_ ## name
|
||||
#define RNG_NEW(name) rng_new(RNG_ALGO(name))
|
||||
|
||||
#endif /* _RNG_H */
|
@ -0,0 +1,14 @@
|
||||
#ifndef _RNG_ALGOS_H
|
||||
#define _RNG_ALGOS_H
|
||||
|
||||
#include "rng.h"
|
||||
|
||||
RNG_IMPL_DEFINITION(xoroshiro128plus);
|
||||
void xoro_jump();
|
||||
void xoro_long_jump();
|
||||
|
||||
RNG_IMPL_DEFINITION(frng);
|
||||
|
||||
RNG_IMPL_DEFINITION(drng);
|
||||
|
||||
#endif /* _RNG_ALGOS_H */
|
@ -0,0 +1,17 @@
|
||||
#ifndef _RNG_IMPL_H
|
||||
#define _RNG_IMPL_H
|
||||
|
||||
#include "rng.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct rng_algo {
|
||||
void (*seed)(const void* state);
|
||||
double (*sample)(void);
|
||||
|
||||
void (*construct)(void);
|
||||
void (*destruct)(void);
|
||||
}; //*RNG
|
||||
|
||||
RNG rng_new_impl(const struct rng_algo *from);
|
||||
|
||||
#endif /* _RNG_IMPL_H */
|
@ -0,0 +1,24 @@
|
||||
#include <rng_impl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void _seed(const void* seed)
|
||||
{
|
||||
srand(*((const unsigned int*)seed));
|
||||
}
|
||||
|
||||
static double _next()
|
||||
{
|
||||
return (double)rand() / (double)RAND_MAX;
|
||||
}
|
||||
|
||||
RNG_IMPL_DEFINITION(drng)
|
||||
{
|
||||
struct rng_algo algo;
|
||||
memset(&algo,0,sizeof(algo));
|
||||
|
||||
algo.seed= &_seed;
|
||||
algo.sample = &_next;
|
||||
|
||||
return rng_new_impl(&algo);
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
#include <rng_impl.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
double vec[2];
|
||||
|
||||
static void _seed(const void* from)
|
||||
{
|
||||
memcpy(vec, from, sizeof(double)*2);
|
||||
}
|
||||
|
||||
double fract(double x)
|
||||
{
|
||||
return x - floor(x);
|
||||
}
|
||||
|
||||
double dot(double *v, double *u, int n)
|
||||
{
|
||||
register double res = 0;
|
||||
for(register int i=0;i<n;i++)
|
||||
{
|
||||
res += v[i]*u[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static double sample_double(double vec[2])
|
||||
{
|
||||
static double vec2[2] = { 12.9898, 78.223 };
|
||||
double res = fract(sin(dot(vec, vec2, 2)) * 43758.5453);
|
||||
return res;
|
||||
}
|
||||
static void next(double r)
|
||||
{
|
||||
float v1 = vec[0];
|
||||
float v2 = vec[1];
|
||||
|
||||
double nvec[2];
|
||||
|
||||
nvec[0] = r;
|
||||
nvec[1] = v2;
|
||||
|
||||
vec[0] = sample_double(nvec);
|
||||
|
||||
nvec[1] = v1;
|
||||
vec[1] = sample_double(nvec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static double _sample()
|
||||
{
|
||||
double res = sample_double(vec);
|
||||
next(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
RNG_IMPL_DEFINITION(frng)
|
||||
{
|
||||
struct rng_algo rng;
|
||||
|
||||
memset(&rng,0,sizeof(rng));
|
||||
|
||||
rng.seed = &_seed;
|
||||
rng.sample = &_sample;
|
||||
|
||||
return rng_new_impl(&rng);
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <rng.h>
|
||||
#include <rng_algos.h>
|
||||
#include <ptr_store.h>
|
||||
|
||||
/*void test_destructor(object* ptr)
|
||||
{
|
||||
printf("die\n");
|
||||
}*/
|
||||
void _rng_object_destructor(object* obj)
|
||||
{
|
||||
rng_free(obj->state);
|
||||
}
|
||||
RNG rng_object(S_LEXENV, RNG rng)
|
||||
{
|
||||
object proto = OBJ_PROTO;
|
||||
proto.state = rng;
|
||||
proto.destructor = &_rng_object_destructor;
|
||||
|
||||
return snew_obj(proto)->state;
|
||||
}
|
||||
|
||||
void shuffle_longs(RNG with, long *data, int n)
|
||||
{
|
||||
register long temp;
|
||||
for(register int i= n-1;i>0;i--)
|
||||
{
|
||||
int j = rng_next_int(with, i);
|
||||
temp = data[i];
|
||||
data[i] = data[j];
|
||||
data[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void shuffle_floats(RNG with, float* data, int n)
|
||||
{
|
||||
register float temp;
|
||||
for(register int i=n-1;i>0;i--)
|
||||
{
|
||||
int j = rng_next_int(with,i);
|
||||
temp = data[i];
|
||||
data[i] = data[j];
|
||||
data[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void shuffle_bytes(RNG with, unsigned char* data, int n)
|
||||
{
|
||||
register unsigned char temp;
|
||||
for(int i=n-1;i>0;i--)
|
||||
{
|
||||
int j = rng_next_int(with, i);
|
||||
temp = data[i];
|
||||
data[i] = data[j];
|
||||
data[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void minmax_longs(long* min, long* max, const long* data, int n)
|
||||
{
|
||||
for(register int i=0;i<n;i++)
|
||||
{
|
||||
if(data[i] > *max) *max = data[i];
|
||||
if(data[i] < *min) *min = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void minmax_floats(float* min, float* max, const float* data, int n)
|
||||
{
|
||||
for(register int i=0;i<n;i++)
|
||||
{
|
||||
if(data[i] > *max) *max = data[i];
|
||||
if(data[i] < *min) *min = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void minmax_sbytes(signed char* min, signed char* max, const signed char* data,int n)
|
||||
{
|
||||
for(register int i=0;i<n;i++)
|
||||
{
|
||||
if(data[i] > *max) *max = data[i];
|
||||
if(data[i] < *min) *min = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void print_array(unsigned char* data, int len)
|
||||
{
|
||||
for(register int i=0;i<len;i++)
|
||||
printf("%d ", (int)data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void shuffle3(S_LEXENV, void* data, int raw_len)
|
||||
{
|
||||
RNG xoro = S_LEXCALL(rng_object, rng_new(RNG_ALGO(xoroshiro128plus)));
|
||||
RNG frng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(frng)));
|
||||
RNG drng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(drng)));
|
||||
|
||||
long min = INT64_MAX;
|
||||
long max = INT64_MIN;
|
||||
|
||||
float fmin = (float)DBL_MAX;
|
||||
float fmax = (float)-DBL_MAX;
|
||||
|
||||
signed char bmax = INT8_MIN;
|
||||
signed char bmin = INT8_MAX;
|
||||
|
||||
minmax_longs(&min, &max, data, raw_len/sizeof(long));
|
||||
uint64_t xseed[2];
|
||||
xseed[0] = min;
|
||||
xseed[1] = max;
|
||||
|
||||
rng_seed(xoro, xseed);
|
||||
shuffle_longs(xoro, data, raw_len/sizeof(long));
|
||||
|
||||
minmax_floats(&fmin, &fmax, data, raw_len/sizeof(float));
|
||||
double fseed[2];
|
||||
fseed[0] = fmin;
|
||||
fseed[1] = fmax;
|
||||
rng_seed(frng, fseed);
|
||||
shuffle_floats(frng, data, raw_len/sizeof(float));
|
||||
|
||||
minmax_sbytes(&bmin, &bmax, data, raw_len);
|
||||
unsigned int seed = (0xfffa << 16) | (bmin<<8) | bmax;
|
||||
rng_seed(drng, &seed);
|
||||
shuffle_bytes(drng, data, raw_len);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
MANAGED({
|
||||
void * data = smalloc(255);
|
||||
int raw_len = 255;
|
||||
for(int i=0;i<raw_len;i++)
|
||||
((unsigned char*)data)[i] = i;
|
||||
|
||||
print_array(data,raw_len);
|
||||
|
||||
shuffle3(LEXENV, data, raw_len);
|
||||
|
||||
print_array(data,raw_len);
|
||||
|
||||
/*char* buffer = smalloc(32);
|
||||
int* nw = snew(int);
|
||||
object proto = OBJ_PROTO;
|
||||
proto.destructor = &test_destructor;
|
||||
proto.constructor = &test_destructor;
|
||||
object* obj = snew_obj(proto);
|
||||
*nw=22;
|
||||
sprintf(buffer, "hello %d\n", *nw);
|
||||
sdelete(nw);
|
||||
sdelete(obj);
|
||||
printf("%s", buffer);*/
|
||||
});
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
|
||||
|
||||
#include <ptr_store.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
store_t *new_store()
|
||||
{
|
||||
store_t *s = malloc(sizeof(store_t));
|
||||
memset(s,0,sizeof(store_t));
|
||||
return s;
|
||||
}
|
||||
|
||||
void* store_malloc(store_t *store, size_t sz)
|
||||
{
|
||||
void ** sptr;
|
||||
if(store->ptr == NULL)
|
||||
sptr = &store->ptr;
|
||||
else if (store->next == NULL) {
|
||||
store->next = new_store();
|
||||
return store_malloc(store->next, sz);
|
||||
} else {
|
||||
return store_malloc(store->next, sz);
|
||||
}
|
||||
|
||||
*sptr = malloc(sz);
|
||||
memset(*sptr, 0, sz);
|
||||
|
||||
return *sptr;
|
||||
}
|
||||
|
||||
void store_free(store_t* store, void* ptr)
|
||||
{
|
||||
if(store->ptr == ptr)
|
||||
{
|
||||
if(store->is_obj)
|
||||
{
|
||||
object* obj = store->ptr;
|
||||
if(obj->destructor!=NULL)
|
||||
obj->destructor(obj);
|
||||
}
|
||||
free(ptr);
|
||||
store->ptr = NULL;
|
||||
store->is_obj=0;
|
||||
} else if (store->next) {
|
||||
store_free(store->next,ptr);
|
||||
}
|
||||
}
|
||||
|
||||
store_t* _store_first_empty(store_t *store, int obj)
|
||||
{
|
||||
if(!store->ptr) { store->is_obj=obj; return store; }
|
||||
else if(store->next) return _store_first_empty(store->next, obj);
|
||||
else {
|
||||
store->next = new_store();
|
||||
store->next->is_obj = obj;
|
||||
return store->next;
|
||||
}
|
||||
}
|
||||
|
||||
static store_t* _store_ptr(store_t *store, void* heap)
|
||||
{
|
||||
if(!store->ptr)
|
||||
store->ptr = heap;
|
||||
else if(store->next)
|
||||
return _store_ptr(store->next, heap);
|
||||
else {
|
||||
store->next = new_store();
|
||||
return _store_ptr(store->next, heap);
|
||||
}
|
||||
return store;
|
||||
|
||||
}
|
||||
|
||||
void* store_ptr(store_t *store, void *heap)
|
||||
{
|
||||
if(!store->ptr)
|
||||
store->ptr = heap;
|
||||
else if(store->next)
|
||||
return store_ptr(store->next, heap);
|
||||
else {
|
||||
store->next = new_store();
|
||||
return store_ptr(store->next, heap);
|
||||
}
|
||||
return store->ptr;
|
||||
}
|
||||
|
||||
void destroy_store(store_t *store)
|
||||
{
|
||||
while(store)
|
||||
{
|
||||
if(store->ptr)
|
||||
{
|
||||
if(store->is_obj)
|
||||
{
|
||||
object *obj = store->ptr;
|
||||
if(obj->destructor!=NULL)
|
||||
obj->destructor(obj);
|
||||
}
|
||||
free(store->ptr);
|
||||
|
||||
}
|
||||
store_t *next = store->next;
|
||||
|
||||
free(store);
|
||||
store = next;
|
||||
}
|
||||
}
|
||||
|
||||
void store_collect(store_t *store)
|
||||
{
|
||||
int first=1;
|
||||
while(store)
|
||||
{
|
||||
if(store->ptr)
|
||||
{
|
||||
if(store->is_obj)
|
||||
{
|
||||
object *obj = store->ptr;
|
||||
if(obj->destructor!=NULL)
|
||||
obj->destructor(obj);
|
||||
}
|
||||
|
||||
free(store->ptr);
|
||||
}
|
||||
store_t *next = store->next;
|
||||
store->is_obj=0;
|
||||
if(!first) free(store);
|
||||
first=0;
|
||||
store=next;
|
||||
}
|
||||
}
|
||||
|
||||
object *new_object_unmanaged(object prototype)
|
||||
{
|
||||
object* ret = malloc(sizeof(object));
|
||||
memcpy(ret, &prototype, sizeof(object));
|
||||
|
||||
if(ret->constructor!=NULL)
|
||||
ret->constructor(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_object_unmanaged(object* obj)
|
||||
{
|
||||
if(obj->destructor!=NULL)
|
||||
obj->destructor(obj);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
object* store_object(store_t* store, object prototype)
|
||||
{
|
||||
object* obj = new_object_unmanaged(prototype);
|
||||
|
||||
store_t* s = _store_ptr(store, obj);
|
||||
s->is_obj = 1;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
object* copy_object(object* from, object* to)
|
||||
{
|
||||
to->constructor = from->constructor;
|
||||
to->destructor = from->destructor;
|
||||
|
||||
to->copy_to(from, to);
|
||||
return to;
|
||||
}
|
||||
|
||||
object* clone_object(store_t* store, object *from)
|
||||
{
|
||||
object* new = malloc(sizeof(object));
|
||||
|
||||
from->constructor(new);
|
||||
copy_object(from, new);
|
||||
|
||||
if(store)
|
||||
{
|
||||
store_t* s = _store_ptr(store, new);
|
||||
s->is_obj = 1;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void free_object(store_t *store,object *obj)
|
||||
{
|
||||
if(store->ptr == obj)
|
||||
{
|
||||
if(obj->destructor!=NULL)
|
||||
obj->destructor(obj);
|
||||
|
||||
free(obj);
|
||||
store->ptr = NULL;
|
||||
store->is_obj=0;
|
||||
} else if (store->next) {
|
||||
free_object(store->next,obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object object_prototype()
|
||||
{
|
||||
object o;
|
||||
memset(&o, 0, sizeof(object));
|
||||
return o;
|
||||
}
|
||||
|
||||
static void _copy_object_default(object* f, object* t)
|
||||
{
|
||||
t->state = f->state;
|
||||
}
|
||||
|
||||
const object OBJ_PROTO = {NULL,NULL,NULL, &_copy_object_default};
|
@ -0,0 +1,65 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <rng.h>
|
||||
|
||||
#include <rng_impl.h>
|
||||
|
||||
RNG rng_new_impl(const struct rng_algo *from)
|
||||
{
|
||||
RNG algo = malloc(sizeof(struct rng_algo));
|
||||
memcpy(algo, from, sizeof(struct rng_algo));
|
||||
if(algo->construct!=NULL)
|
||||
algo->construct();
|
||||
return algo;
|
||||
}
|
||||
|
||||
RNG rng_new(RNG (*instantiate)(void))
|
||||
{
|
||||
return instantiate();
|
||||
}
|
||||
|
||||
void rng_free(RNG algo)
|
||||
{
|
||||
if(algo->destruct!=NULL)
|
||||
algo->destruct();
|
||||
free(algo);
|
||||
}
|
||||
|
||||
void rng_seed(RNG algo, void* seed)
|
||||
{
|
||||
if(algo->seed!=NULL)
|
||||
algo->seed(seed);
|
||||
}
|
||||
|
||||
double rng_next_double(RNG algo)
|
||||
{
|
||||
return algo->sample();
|
||||
}
|
||||
|
||||
int rng_next_int_bounded(RNG algo, int min, int max)
|
||||
{
|
||||
return (int)floor(algo->sample() * (double)(max-min))+min;
|
||||
}
|
||||
|
||||
int rng_next_int(RNG algo, int max)
|
||||
{
|
||||
return (int)floor(algo->sample() * (double)max);
|
||||
}
|
||||
|
||||
void* rng_next(RNG algo, void* data, int len)
|
||||
{
|
||||
uint8_t *buffer = data;
|
||||
for(register int i=0;i<len;i++)
|
||||
{
|
||||
buffer[i] = (uint8_t)rng_next_int(algo, 255);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
int rng_chance(RNG algo, double d)
|
||||
{
|
||||
if(d<=0) return 0;
|
||||
return algo->sample()<=d;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
#include <rng_impl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Written in 2016-2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
||||
|
||||
To the extent possible under law, the author has dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
||||
|
||||
static inline uint64_t rotl(const uint64_t x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
_Atomic static uint64_t s[2];
|
||||
|
||||
static uint64_t next(void) {
|
||||
const uint64_t s0 = s[0];
|
||||
uint64_t s1 = s[1];
|
||||
const uint64_t result = s0 + s1;
|
||||
|
||||
s1 ^= s0;
|
||||
s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
|
||||
s[1] = rotl(s1, 37); // c
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void jump(void) {
|
||||
static const uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
|
||||
|
||||
uint64_t s0 = 0;
|
||||
uint64_t s1 = 0;
|
||||
for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
|
||||
for(int b = 0; b < 64; b++) {
|
||||
if (JUMP[i] & UINT64_C(1) << b) {
|
||||
s0 ^= s[0];
|
||||
s1 ^= s[1];
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
s[0] = s0;
|
||||
s[1] = s1;
|
||||
}
|
||||
|
||||
static void long_jump(void) {
|
||||
static const uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
|
||||
|
||||
uint64_t s0 = 0;
|
||||
uint64_t s1 = 0;
|
||||
for(int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
|
||||
for(int b = 0; b < 64; b++) {
|
||||
if (LONG_JUMP[i] & UINT64_C(1) << b) {
|
||||
s0 ^= s[0];
|
||||
s1 ^= s[1];
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
s[0] = s0;
|
||||
s[1] = s1;
|
||||
}
|
||||
|
||||
static void seed(uint64_t s0, uint64_t s1) {
|
||||
s[0] = s0;
|
||||
s[1] = s1;
|
||||
}
|
||||
|
||||
void _seed(const void* from)
|
||||
{
|
||||
const uint64_t *ptr = from;
|
||||
seed(ptr[0], ptr[1]);
|
||||
}
|
||||
|
||||
double _sample()
|
||||
{
|
||||
return (next() & ((1L << 53) - 1)) * (1.00 / (1L << 53));
|
||||
}
|
||||
|
||||
RNG_IMPL_DEFINITION(xoroshiro128plus)
|
||||
{
|
||||
struct rng_algo algo;
|
||||
algo.sample = &_sample;
|
||||
algo.seed = &_seed;
|
||||
|
||||
algo.construct=NULL;
|
||||
algo.destruct=NULL;
|
||||
|
||||
return rng_new_impl(&algo);
|
||||
}
|
||||
|
||||
void xoro_jump()
|
||||
{
|
||||
jump();
|
||||
}
|
||||
|
||||
void xoro_long_jump()
|
||||
{
|
||||
long_jump();
|
||||
}
|
Loading…
Reference in new issue