lean
Avril 5 years ago
parent 01f12fba2e
commit 61a90a9faa
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1,27 @@
#ifndef _ARRAY_H
#define _ARRAY_H
#include <ptr_store.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct array* array_t;
array_t ar_create_file(S_LEXENV, FILE* from, size_t element_size, int owns_stream);
array_t ar_create_memory_from(S_LEXENV, const void* from, size_t element_size, size_t count);
array_t ar_create_memory(S_LEXENV, size_t size, size_t count, int init0);
const void* ar_get(const array_t this, long i);
void ar_set(array_t this, long i, const void* obj);
long ar_size(const array_t this);
long ar_full_size(const array_t this);
long ar_type(const array_t this);
int ar_get_into(const array_t this, long i, void* buffer);
void ar_swap(array_t from, long i, long j);
void ar_reinterpret(array_t from, size_t element);
int ar_dump(const array_t from, void* buffer, size_t offset, size_t count);
int ar_ndump(const array_t from, void* buffer, size_t bufsize, size_t offset, size_t count);
#define ar_get_v(this, type, i) (*((const type*)ar_get(this, i)))
#define ar_set_v(this, i, value) ar_set(this, i, &value)
#endif /* _ARRAY_H */

@ -40,6 +40,7 @@ extern const object OBJ_PROTO;
#define strack _store_first_empty(__internal_store, 0)->ptr = #define strack _store_first_empty(__internal_store, 0)->ptr =
#define strack_obj _store_first_empty(__internal_store, 1)->ptr = #define strack_obj _store_first_empty(__internal_store, 1)->ptr =
#define S_NAMED_LEXENV(n) store_t* n
#define S_LEXENV store_t* __internal_store #define S_LEXENV store_t* __internal_store
#define S_LEXCALL(f, ...) f(__internal_store, __VA_ARGS__) #define S_LEXCALL(f, ...) f(__internal_store, __VA_ARGS__)
#define LEXENV __internal_store #define LEXENV __internal_store
@ -51,8 +52,25 @@ extern const object OBJ_PROTO;
#define MANAGED(var) { \ #define MANAGED(var) { \
store_t * __internal_store = new_store(); \ store_t * __internal_store = new_store(); \
var; \ var; \
goto __internal_breakpoint; /*to suppress unused warning*/ \
__internal_breakpoint: \
destroy_store(__internal_store); \ destroy_store(__internal_store); \
} }
#define MANAGED_RETURNABLE(type, var) { \
type __internal_retval; \
int __internal_has_set_return =0; \
store_t * __internal_store = new_store(); \
var; \
goto __internal_breakpoint; /*to suppress unused warning*/ \
__internal_breakpoint: \
destroy_store(__internal_store); \
if(__internal_has_set_return) return __internal_retval; \
}
#define MANAGED_RETURN(value) __internal_retval = value; \
__internal_has_set_return = 1; \
MANAGED_BREAK
#define MANAGED_BREAK goto __internal_breakpoint
#define STORE_LEXBIND(type, name) type name = *((type*)store_malloc(__internal_store, sizeof(type))); #define STORE_LEXBIND(type, name) type name = *((type*)store_malloc(__internal_store, sizeof(type)));

@ -0,0 +1,241 @@
#include <ptr_store.h>
#include <array.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct array {
object* base;
size_t size;
size_t element;
size_t full_size;
void *tl_state;
void* state;
int (*dump)(const array_t this, void* buffer, size_t buffermax, size_t offset, size_t count);
void* (*get)(struct array* this, long i);
void (*set)(struct array* this, long i, const void* item);
unsigned char data[];
};
static void* _ar_memory_get(struct array* this, long i)
{
if(i< 0|| i>= this->size) return NULL;
return &this->data[i*this->element];
}
static const void _ar_memory_set(struct array* this, long i, const void* item)
{
if(i<0 || i>= this->size) return;
memcpy(this->data+(i*this->element), item, this->element);
}
static int _ar_memory_dump(const array_t this, void* buffer, size_t bufsize, size_t offset, size_t count)
{
if(offset+count > this->size) return 0;
#define min(x, y) (x<y?x:y)
long fsz = count*this->element;
long wsz = min(fsz, bufsize);
memcpy(buffer, this->data+(offset*this->element), wsz);
return (wsz==fsz);
#undef min
}
static void _ar_memory_destructor(object* this)
{
free(this->state);
this->state=NULL;
}
array_t ar_create_memory(S_LEXENV, size_t size, size_t count, int init0)
{
array_t mem = malloc(sizeof(struct array)+(size*count));
memset(mem,0,sizeof(struct array));
if(init0)
memset(mem->data, 0, size*count);
mem->size = count;
mem->element = size;
mem->full_size = size*count;
mem->get = &_ar_memory_get;
mem->set = &_ar_memory_set;
mem->dump = &_ar_memory_dump;
object obj = OBJ_PROTO;
obj.state= mem;
obj.destructor = &_ar_memory_destructor;
return snew_obj(obj)->state;
}
array_t ar_create_memory_from(S_LEXENV, const void* from, size_t element_size, size_t count)
{
array_t mem = ar_create_memory(LEXENV, element_size, count, 0);
memcpy(mem->data, from, element_size*count);
return mem;
}
static inline size_t filesize(FILE* file)
{
size_t from = ftell(file);
fseek(file,0,SEEK_END);
size_t ret = ftell(file);
fseek(file,from, SEEK_SET);
return ret;
}
static void* _ar_file_get(struct array* this, long i)
{
if(i<0 || i>=this->size) return NULL;
fseek(this->state, i*this->element, SEEK_SET);
if(this->tl_state != NULL)
free(this->tl_state);
void* buffer = malloc(this->element);
this->tl_state = buffer;
fread(buffer, this->element, 1, this->state);
return buffer;
}
static void _ar_file_set(struct array* this, long i, const void* from)
{
if(i<0 || i>=this->size) return;
fseek(this->state, i*this->element, SEEK_SET);
fwrite(from, this->element, 1, this->state);
}
static void _ar_file_destructor(object* _this)
{
array_t this = _this->state;
if(this->tl_state!=NULL)
free(this->tl_state);
if(this->data[0])
fclose(this->state);
this->state=NULL;
this->tl_state=NULL;
free(this);
}
array_t ar_create_file(S_LEXENV, FILE* from, size_t element_size, int owns_stream)
{
array_t mem = malloc(sizeof(struct array)+1);
memset(mem,0, sizeof(struct array));
mem->data[0] = (unsigned char)owns_stream;
mem->state = from;
mem->element = element_size;
mem->full_size = filesize(from);
mem->size = mem->full_size/element_size;
mem->get = &_ar_file_get;
mem->set = &_ar_file_set;
object obj = OBJ_PROTO;
obj.state = mem;
obj.destructor = &_ar_file_destructor;
return snew_obj(obj)->state;
}
///Generic accessor functions
const void* ar_get(const array_t this, long i)
{
return this->get(this, i);
}
void ar_set(array_t this, long i, const void* obj)
{
this->set(this, i, obj);
}
long ar_size(const array_t this)
{
return this->size;
}
long ar_full_size(const array_t this)
{
return this->full_size;
}
long ar_type(const array_t this)
{
return this->element;
}
int ar_get_into(const array_t this, long i, void* buffer)
{
const void* ptr = ar_get(this, i);
if(!ptr) return 0;
memcpy(buffer,ptr,this->element);
return 1;
}
void ar_swap(array_t from, long i, long j)
{
unsigned char temp[from->element];
ar_get_into(from, i, temp);
ar_set(from, i, ar_get(from, j));
ar_set(from, j, temp);
}
void ar_reinterpret(array_t from, size_t element)
{
long fsz = from->full_size;
from->element = element;
from->size = fsz/element;
}
int ar_dump(const array_t from, void* buffer, size_t offset, size_t count)
{
if(from->dump)
return from->dump(from, buffer, from->full_size, offset,count);
else {
unsigned char* buf = buffer;
for(int i=0;i<count;i++)
{
if(!ar_get_into(from, offset+i, buf)) return 0;
buf+=from->element;
}
return 1;
}
}
int ar_ndump(const array_t from, void* buffer, size_t bufsize, size_t offset, size_t count)
{
if(from->dump)
return from->dump(from, buffer, bufsize, offset,count);
else {
unsigned char* buf = buffer;
unsigned char* maxbuf = buf+bufsize;
for(int i=0;i<count;i++)
{
if(buf>=maxbuf) return 0;
if(!ar_get_into(from, offset+i, buf)) return 0;
buf+= from->element;
}
return 1;
}
}

@ -7,6 +7,7 @@ double vec[2];
static void _seed(const void* from) static void _seed(const void* from)
{ {
memcpy(vec, from, sizeof(double)*2); memcpy(vec, from, sizeof(double)*2);
} }
double fract(double x) double fract(double x)

@ -5,6 +5,7 @@
#include <rng.h> #include <rng.h>
#include <rng_algos.h> #include <rng_algos.h>
#include <ptr_store.h> #include <ptr_store.h>
#include <array.h>
/*void test_destructor(object* ptr) /*void test_destructor(object* ptr)
{ {
@ -23,78 +24,111 @@ RNG rng_object(S_LEXENV, RNG rng)
return snew_obj(proto)->state; return snew_obj(proto)->state;
} }
void shuffle_longs(RNG with, long *data, int n) void shuffle(RNG with, array_t data)
{ {
register long temp; printf(" -> shuffling %d objects...", (int)ar_size(data));
for(register int i= n-1;i>0;i--) for(int i=ar_size(data)-1;i>0;i--)
{ {
int j = rng_next_int(with, i); int j = rng_next_int(with, i);
temp = data[i]; ar_swap(data, i, j);
data[i] = data[j];
data[j] = temp;
} }
printf(" Okay\n");
} }
void shuffle_floats(RNG with, float* data, int n) void unshuffle(RNG with, array_t data)
{ {
register float temp; int rng_values[ar_size(data)-1];
for(register int i=n-1;i>0;i--) int k=0;
printf(" -> unshuffling %d objects...", (int)ar_size(data));
for(int i=ar_size(data)-1;i>0;i--)
rng_values[k++] = rng_next_int(with, i);
for(int i=1;i<ar_size(data);i++)
{ {
int j = rng_next_int(with,i); ar_swap(data, i, rng_values[--k]);
temp = data[i];
data[i] = data[j];
data[j] = temp;
} }
printf(" Okay\n");
} }
void shuffle_bytes(RNG with, unsigned char* data, int n) void minmax_longs(long* min, long* max, const array_t data)
{ {
register unsigned char temp; for(register int i=0;i<ar_size(data);i++)
for(int i=n-1;i>0;i--)
{ {
int j = rng_next_int(with, i); if(ar_get_v(data, long, i) > *max) *max = ar_get_v(data, long, i);
temp = data[i]; if(ar_get_v(data, long, i) < *min) *min = ar_get_v(data, long, i);
data[i] = data[j];
data[j] = temp;
} }
} }
int valid_float(float f)
{
return !( (f!=f) || (f< -FLT_MAX || f> FLT_MAX));
void minmax_longs(long* min, long* max, const long* data, int n) }
void minmax_floats(float* min, float* max, const array_t data)
{ {
for(register int i=0;i<n;i++) for(register int i=0;i<ar_size(data);i++)
{ {
if(data[i] > *max) *max = data[i]; if(!valid_float(ar_get_v(data,float,i))) continue;
if(data[i] < *min) *min = data[i]; if(ar_get_v(data, float, i) > *max) *max = ar_get_v(data, float, i);
if(ar_get_v(data, float, i) < *min) *min = ar_get_v(data, float, i);
} }
} }
void minmax_floats(float* min, float* max, const float* data, int n) void minmax_sbytes(signed char* min, signed char* max, const array_t data)
{ {
for(register int i=0;i<n;i++) for(register int i=0;i<ar_size(data);i++)
{ {
if(data[i] > *max) *max = data[i]; if(ar_get_v(data, signed char, i) > *max) *max = ar_get_v(data, signed char, i);
if(data[i] < *min) *min = data[i]; if(ar_get_v(data, signed char, i) < *min) *min = ar_get_v(data, signed char, i);
} }
} }
void minmax_sbytes(signed char* min, signed char* max, const signed char* data,int n) void print_array(const array_t data)
{ {
for(register int i=0;i<n;i++) printf("---%d elements---\n", (int)ar_size(data));
{ for(register int i=0;i<ar_size(data);i++)
if(data[i] > *max) *max = data[i]; printf("%d ", (int)ar_get_v(data, unsigned char, i));
if(data[i] < *min) *min = data[i]; printf("\n---\n");
}
} }
void print_array(unsigned char* data, int len) void unshuffle3(S_LEXENV, array_t data)
{ {
for(register int i=0;i<len;i++) if(ar_type(data)!=sizeof(signed char))
printf("%d ", (int)data[i]); ar_reinterpret(data, sizeof(signed char));
printf("\n"); 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)));
signed char bmax = INT8_MIN;
signed char bmin = INT8_MAX;
minmax_sbytes(&bmin, &bmax, data);
unsigned int seed = (0xfffa << 16) | (bmin<<8) | bmax;
rng_seed(drng, &seed);
unshuffle(drng, data);
void shuffle3(S_LEXENV, void* data, int raw_len) float fmin = (float)DBL_MAX;
float fmax = (float)-DBL_MAX;
ar_reinterpret(data, sizeof(float));
minmax_floats(&fmin, &fmax, data);
double fseed[2];
fseed[0] = fmin;
fseed[1] = fmax;
rng_seed(frng, fseed);
unshuffle(frng, data);
long min = INT64_MAX;
long max = INT64_MIN;
ar_reinterpret(data, sizeof(long));
minmax_longs(&min, &max, data);
uint64_t xseed[2];
xseed[0] = min;
xseed[1] = max;
rng_seed(xoro, xseed);
unshuffle(xoro, data);
}
void shuffle3(S_LEXENV, array_t data)
{ {
if(ar_type(data)!=sizeof(long))
ar_reinterpret(data, sizeof(long));
RNG xoro = S_LEXCALL(rng_object, rng_new(RNG_ALGO(xoroshiro128plus))); RNG xoro = S_LEXCALL(rng_object, rng_new(RNG_ALGO(xoroshiro128plus)));
RNG frng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(frng))); RNG frng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(frng)));
RNG drng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(drng))); RNG drng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(drng)));
@ -108,52 +142,140 @@ void shuffle3(S_LEXENV, void* data, int raw_len)
signed char bmax = INT8_MIN; signed char bmax = INT8_MIN;
signed char bmin = INT8_MAX; signed char bmin = INT8_MAX;
minmax_longs(&min, &max, data, raw_len/sizeof(long)); minmax_longs(&min, &max, data);
uint64_t xseed[2]; uint64_t xseed[2];
xseed[0] = min; xseed[0] = min;
xseed[1] = max; xseed[1] = max;
rng_seed(xoro, xseed); rng_seed(xoro, xseed);
shuffle_longs(xoro, data, raw_len/sizeof(long)); shuffle(xoro, data);
ar_reinterpret(data, sizeof(float));
minmax_floats(&fmin, &fmax, data);
minmax_floats(&fmin, &fmax, data, raw_len/sizeof(float));
double fseed[2]; double fseed[2];
fseed[0] = fmin; fseed[0] = fmin;
fseed[1] = fmax; fseed[1] = fmax;
rng_seed(frng, fseed); rng_seed(frng, fseed);
shuffle_floats(frng, data, raw_len/sizeof(float)); shuffle(frng, data);
minmax_sbytes(&bmin, &bmax, data, raw_len); ar_reinterpret(data,sizeof(signed char));
minmax_sbytes(&bmin, &bmax, data);
unsigned int seed = (0xfffa << 16) | (bmin<<8) | bmax; unsigned int seed = (0xfffa << 16) | (bmin<<8) | bmax;
rng_seed(drng, &seed); rng_seed(drng, &seed);
shuffle_bytes(drng, data, raw_len); shuffle(drng, data);
} }
int main() void print_usage(char** argv)
{ {
printf("Usage: %s -[b]s <file> [<outfile>]\nUsage: %s -[b]u <file> [<outfile>]\n", argv[0], argv[0]);
printf(" <file>\t\tFile to shuffle\n");
printf(" <outfile>\tOutput file (only valid for buffered mode)\n");
printf("\ts\tShuffle\n");
printf("\tu\tReverse shuffle\n");
printf("\n\tb\tUse buffered mode instead of shuffling in place (must specify output file)\n");
}
array_t read_whole_file(S_NAMED_LEXENV(base), FILE* fp)
{
fseek(fp,0,SEEK_END);
long sz = ftell(fp);
fseek(fp,0,SEEK_SET);
array_t ar;
MANAGED({ MANAGED({
void * data = smalloc(255); void* buf = smalloc(sz);
int raw_len = 255; fread(buf, 1, sz, fp);
for(int i=0;i<raw_len;i++) ar = ar_create_memory_from(base, buf, 1, sz);
((unsigned char*)data)[i] = i; });
return ar;
}
int main(int argc, char** argv)
{
int is_buffered=0;
int i=1;
int is_unshuffling =0;
if(!argv[1] || !argv[2] || argv[1][0] != '-')
{
print_usage(argv);
return 1;
}
else {
do_switch:
switch(argv[1][i])
{
case 'b':
if(is_buffered)
{
print_usage(argv);
return 1;
}
is_buffered = 1;
i+=1;
goto do_switch;
case 'u':
is_unshuffling=1;
break;
case 's':
break;
default:
print_usage(argv);
return 1;
}
}
if(is_buffered && !argv[3])
{
printf("Buffered option requires an output file\n");
return 1;
}
print_array(data,raw_len); MANAGED_RETURNABLE(int ,{
array_t array;
shuffle3(LEXENV, data, raw_len); if(is_buffered)
{
FILE* infile = fopen(argv[2], "rb");
if(!infile)
{
printf("! could not open file for reading\n");
MANAGED_RETURN(1);
}
array = read_whole_file(LEXENV, infile);
fclose(infile);
printf(" buffered file (%ld bytes)\n", ar_size(array));
}
else {
FILE* infile = fopen(argv[2], "r+b");
if(!infile)
{
printf("! could not open file for reading+writing\n");
MANAGED_RETURN(1);
}
array = ar_create_file(LEXENV, infile, 1, 1);
}
print_array(data,raw_len); //print_array(array);
/*char* buffer = smalloc(32); if(is_unshuffling) unshuffle3(LEXENV, array);
int* nw = snew(int); else shuffle3(LEXENV, array);
object proto = OBJ_PROTO;
proto.destructor = &test_destructor; if(is_buffered)
proto.constructor = &test_destructor; {
object* obj = snew_obj(proto); FILE* outfile = fopen(argv[3], "wb");
*nw=22; if(!outfile)
sprintf(buffer, "hello %d\n", *nw); {
sdelete(nw); printf("! could not open outfile for writing\n");
sdelete(obj); MANAGED_RETURN(1);
printf("%s", buffer);*/ }
void* wbuf = smalloc(ar_full_size(array));
if(!ar_ndump(array, wbuf, ar_full_size(array), 0, ar_size(array)))
printf("W memory dump failed, continuing anyway\n");
fwrite(wbuf, 1, ar_full_size(array), outfile);
fclose(outfile);
printf(" write completed (%d bytes)\n", (int)ar_size(array));
}
}); });
return 0; return 0;
} }

@ -45,7 +45,8 @@ int rng_next_int_bounded(RNG algo, int min, int max)
int rng_next_int(RNG algo, int max) int rng_next_int(RNG algo, int max)
{ {
return (int)floor(algo->sample() * (double)max); double sample = algo->sample();
return (int)floor(sample * (double)max);
} }
void* rng_next(RNG algo, void* data, int len) void* rng_next(RNG algo, void* data, int len)

Loading…
Cancel
Save