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_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_LEXCALL(f, ...) f(__internal_store, __VA_ARGS__)
#define LEXENV __internal_store
@ -51,8 +52,25 @@ extern const object OBJ_PROTO;
#define MANAGED(var) { \
store_t * __internal_store = new_store(); \
var; \
goto __internal_breakpoint; /*to suppress unused warning*/ \
__internal_breakpoint: \
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)));

@ -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)
{
memcpy(vec, from, sizeof(double)*2);
}
double fract(double x)

@ -5,6 +5,7 @@
#include <rng.h>
#include <rng_algos.h>
#include <ptr_store.h>
#include <array.h>
/*void test_destructor(object* ptr)
{
@ -23,78 +24,111 @@ RNG rng_object(S_LEXENV, RNG rng)
return snew_obj(proto)->state;
}
void shuffle_longs(RNG with, long *data, int n)
void shuffle(RNG with, array_t data)
{
register long temp;
for(register int i= n-1;i>0;i--)
printf(" -> shuffling %d objects...", (int)ar_size(data));
for(int i=ar_size(data)-1;i>0;i--)
{
int j = rng_next_int(with, i);
temp = data[i];
data[i] = data[j];
data[j] = temp;
ar_swap(data, i, j);
}
printf(" Okay\n");
}
void shuffle_floats(RNG with, float* data, int n)
void unshuffle(RNG with, array_t data)
{
register float temp;
for(register int i=n-1;i>0;i--)
int rng_values[ar_size(data)-1];
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);
temp = data[i];
data[i] = data[j];
data[j] = temp;
ar_swap(data, i, rng_values[--k]);
}
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(int i=n-1;i>0;i--)
for(register int i=0;i<ar_size(data);i++)
{
int j = rng_next_int(with, i);
temp = data[i];
data[i] = data[j];
data[j] = temp;
if(ar_get_v(data, long, i) > *max) *max = ar_get_v(data, long, i);
if(ar_get_v(data, long, i) < *min) *min = ar_get_v(data, long, i);
}
}
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(data[i] < *min) *min = data[i];
if(!valid_float(ar_get_v(data,float,i))) continue;
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(data[i] < *min) *min = data[i];
if(ar_get_v(data, signed char, i) > *max) *max = ar_get_v(data, signed char, 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++)
{
if(data[i] > *max) *max = data[i];
if(data[i] < *min) *min = data[i];
}
printf("---%d elements---\n", (int)ar_size(data));
for(register int i=0;i<ar_size(data);i++)
printf("%d ", (int)ar_get_v(data, unsigned char, 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++)
printf("%d ", (int)data[i]);
printf("\n");
}
if(ar_type(data)!=sizeof(signed char))
ar_reinterpret(data, sizeof(signed char));
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)));
void shuffle3(S_LEXENV, void* data, int raw_len)
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);
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 frng = S_LEXCALL(rng_object, rng_new(RNG_ALGO(frng)));
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 bmin = INT8_MAX;
minmax_longs(&min, &max, data, raw_len/sizeof(long));
minmax_longs(&min, &max, data);
uint64_t xseed[2];
xseed[0] = min;
xseed[1] = max;
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];
fseed[0] = fmin;
fseed[1] = fmax;
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;
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({
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);*/
void* buf = smalloc(sz);
fread(buf, 1, sz, fp);
ar = ar_create_memory_from(base, buf, 1, sz);
});
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;
}
MANAGED_RETURNABLE(int ,{
array_t array;
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(array);
if(is_unshuffling) unshuffle3(LEXENV, array);
else shuffle3(LEXENV, array);
if(is_buffered)
{
FILE* outfile = fopen(argv[3], "wb");
if(!outfile)
{
printf("! could not open outfile for writing\n");
MANAGED_RETURN(1);
}
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;
}

@ -45,7 +45,8 @@ int rng_next_int_bounded(RNG algo, int min, 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)

Loading…
Cancel
Save