diff options
-rw-r--r-- | km-rand.c | 33 | ||||
-rw-r--r-- | km-set.c | 47 | ||||
-rw-r--r-- | km.h | 13 |
3 files changed, 91 insertions, 2 deletions
@@ -12,6 +12,16 @@ km_rand_fill( return rs->cbs->fill(rs, num_floats, floats); } +// fill buffer with N random size_ts +bool +km_rand_fill_sizes( + km_rand_t * const rs, + const size_t num_sizes, + size_t * const sizes +) { + return rs->cbs->fill_sizes(rs, num_sizes, sizes); +} + // finalize random source void km_rand_fini( @@ -40,11 +50,30 @@ system_on_fill( return true; } +// fill sizes callback for system random source +static bool +system_on_fill_sizes( + km_rand_t * const rs, + const size_t num_sizes, + size_t * const sizes +) { + UNUSED(rs); + + // generate random size_ts + for (size_t i = 0; i < num_sizes; i++) { + sizes[i] = rand(); + } + + // return success + return true; +} + // system random source callbacks static const km_rand_cbs_t SYSTEM_CBS = { - .fill = system_on_fill, - .fini = NULL, + .fill = system_on_fill, + .fill_sizes = system_on_fill_sizes, + .fini = NULL, }; // init system random source (uses system rand()) @@ -301,3 +301,50 @@ km_set_init_rand_clusters( // add data, return result return km_set_push(cs, num_clusters, floats, ints); } + +// init a set with num_clusters clusters of shape num_floats by picking +// random initial points from the set +bool +km_set_init_rand_points( + km_set_t * const cs, + const km_set_t * const set, + const size_t num_clusters, + km_rand_t * const rs +) { + const size_t num_floats = set->shape.num_floats, + stride = sizeof(float) * num_floats; + + // init cluster shape + const km_shape_t shape = { + .num_floats = num_floats, + .num_ints = 1, + }; + + // get random row offsets + size_t rows[num_clusters]; + if (!km_rand_fill_sizes(rs, num_clusters, rows)) { + // return failure + return false; + } + + // generate random cluster centers + float floats[num_floats * num_clusters]; + for (size_t i = 0; i < num_clusters; i++) { + const size_t row_num = rows[i] % set->num_rows; + const float * const row_floats = km_set_get_row(set, row_num); + memcpy(floats + i * num_floats, row_floats, stride); + } + + // FIXME: should probably be heap-allocated + int ints[num_clusters]; + memset(ints, 0, sizeof(ints)); + + // init cluster set + if (!km_set_init(cs, &shape, num_clusters)) { + // return failure + return false; + } + + // add data, return result + return km_set_push(cs, num_clusters, floats, ints); +} @@ -11,6 +11,7 @@ typedef struct km_rand_t_ km_rand_t; // random number source callbacks typedef struct { _Bool (*fill)(km_rand_t * const, const size_t, float * const); + _Bool (*fill_sizes)(km_rand_t * const, const size_t, size_t * const); void (*fini)(km_rand_t * const); } km_rand_cbs_t; @@ -23,6 +24,9 @@ struct km_rand_t_ { // fill buffer with N random floats _Bool km_rand_fill(km_rand_t * const, const size_t, float * const); +// fill buffer with N random size_ts +_Bool km_rand_fill_sizes(km_rand_t * const, const size_t, size_t * const); + // finalize random source void km_rand_fini(km_rand_t * const); @@ -82,6 +86,15 @@ _Bool km_set_init_rand_clusters( km_rand_t * ); +// init a set with num_clusters clusters of random points from the +// given set +_Bool km_set_init_rand_points( + km_set_t * const, + const km_set_t * const, + const size_t, + km_rand_t * +); + typedef struct { float d2; size_t cluster; |