diff --git a/include/array.h b/include/array.h new file mode 100644 index 0000000..9f0d4d2 --- /dev/null +++ b/include/array.h @@ -0,0 +1,27 @@ +#ifndef _ARRAY_H +#define _ARRAY_H +#include +#include +#include + +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 */ diff --git a/include/ptr_store.h b/include/ptr_store.h index a90875c..ca41d40 100644 --- a/include/ptr_store.h +++ b/include/ptr_store.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))); diff --git a/src/array.c b/src/array.c new file mode 100644 index 0000000..046da45 --- /dev/null +++ b/src/array.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include + +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) (xelement; + 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;ielement; + } + 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=maxbuf) return 0; + if(!ar_get_into(from, offset+i, buf)) return 0; + buf+= from->element; + } + return 1; + } +} diff --git a/src/frng.c b/src/frng.c index 0177a02..9ddc150 100644 --- a/src/frng.c +++ b/src/frng.c @@ -7,6 +7,7 @@ double vec[2]; static void _seed(const void* from) { memcpy(vec, from, sizeof(double)*2); + } double fract(double x) diff --git a/src/main.c b/src/main.c index 63b2bcb..ed17d47 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include #include #include +#include /*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;i0;i--) + for(register int i=0;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 *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 *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 *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 []\nUsage: %s -[b]u []\n", argv[0], argv[0]); + printf(" \t\tFile to shuffle\n"); + printf(" \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;isample() * (double)max); + double sample = algo->sample(); + return (int)floor(sample * (double)max); } void* rng_next(RNG algo, void* data, int len)