diff options
author | Paul Duncan <pabs@pablotron.org> | 2019-02-04 15:33:35 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2019-02-04 15:33:35 -0500 |
commit | 159c42498365913f6ed400e13c77798d041a7d43 (patch) | |
tree | 96cc3b14bbbbd44dc5173e89b85cd2c8228e86e4 /km-rand-path.c | |
parent | f4a38b43d43f9395d6042d234a5e0ada7455ace1 (diff) | |
download | kmeans-159c42498365913f6ed400e13c77798d041a7d43.tar.bz2 kmeans-159c42498365913f6ed400e13c77798d041a7d43.zip |
add rand-{path,erand48}, minor fixes
Diffstat (limited to 'km-rand-path.c')
-rw-r--r-- | km-rand-path.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/km-rand-path.c b/km-rand-path.c new file mode 100644 index 0000000..6597038 --- /dev/null +++ b/km-rand-path.c @@ -0,0 +1,152 @@ +#include <stdbool.h> // bool +#include <string.h> // memset() +#include <stdio.h> // fopen() +#include "util.h" +#include "km.h" + +#define MAX_BUF_ITEMS (1 << 20) + +typedef struct { + FILE *fh; + size_t ofs; + uint64_t buf[MAX_BUF_ITEMS]; +} ctx_t; + +static inline bool +refill( + ctx_t * const ctx +) { + ctx->ofs = 0; + // D("reading %zu bytes", sizeof(ctx->buf)); + return !!fread(ctx->buf, sizeof(ctx->buf), 1, ctx->fh); +} + +static bool +next( + ctx_t * const ctx, + uint64_t * const r +) { + if ((ctx->ofs >= MAX_BUF_ITEMS - 1) && !refill(ctx)) { + // return failure + return false; + } + + // get next value, increment offset + *r = ctx->buf[ctx->ofs]; + ctx->ofs++; + + // return success + return true; +} + +// get N get_floats +static bool +on_get_floats( + km_rand_t * const rs, + const size_t num_vals, + float * const vals +) { + ctx_t * const ctx = rs->data; + + // generate results + for (size_t i = 0; i < num_vals; i++) { + uint64_t v; + + if (!next(ctx, &v)) { + // return failure + return false; + } + + // add value + vals[i] = 1.0 * v / RAND_MAX; + } + + // return success + return true; +} + +// fill sizes callback for system random source +static bool +on_get_sizes( + km_rand_t * const rs, + const size_t num_vals, + size_t * const vals +) { + ctx_t * const ctx = rs->data; + + // generate results + for (size_t i = 0; i < num_vals; i++) { + uint64_t v; + + if (!next(ctx, &v)) { + // return failure + return false; + } + + // add value + vals[i] = v; + } + + // return success + return true; +} + +static void +on_fini( + km_rand_t * const rs +) { + ctx_t * const ctx = rs->data; + + // close file + fclose(ctx->fh); + + // free context + free(ctx); + + rs->data = NULL; +} + +// path random source callbacks +static const km_rand_cbs_t +PATH_RAND_CBS = { + .get_floats = on_get_floats, + .get_sizes = on_get_sizes, + .fini = on_fini, +}; + +// init system random source (uses system rand()) +bool +km_rand_init_path( + km_rand_t * const rs, + const char * const path +) { + // open file + FILE *fh = fopen(path, "rb"); + if (!fh) { + // return failure + return false; + } + + // alloc context + ctx_t * const ctx = malloc(sizeof(ctx_t)); + if (!ctx) { + // return failure + return false; + } + + // populate context + ctx->fh = fh; + + // fill buffer + if (!refill(ctx)) { + // return failure + return false; + } + + // populate random source + rs->cbs = &PATH_RAND_CBS; + rs->data = ctx; + + // return success + return true; +} |