diff options
| author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2016-05-07 11:51:14 +0900 |
|---|---|---|
| committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-09-07 20:08:01 +0900 |
| commit | af5e87ab218c5f4e34c6cdb54ae119a7f0f9033f (patch) | |
| tree | e050cf7f7af91f1b990287f6e17d26bc27b6171d /ext/-test-/random/loop.c | |
| parent | f4d5273989ae8d6569a62b126b2774706b86fbf5 (diff) | |
separate rb_random_t
* random.c: separate abstract rb_random_t and rb_random_mt_t for
Mersenne Twister implementation.
* include/ruby/random.h: the interface for extensions of Random
class.
* DLL imported symbol reference is not constant on Windows.
* check if properly initialized.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3024
Diffstat (limited to 'ext/-test-/random/loop.c')
| -rw-r--r-- | ext/-test-/random/loop.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c new file mode 100644 index 0000000000..92af1a9b18 --- /dev/null +++ b/ext/-test-/random/loop.c @@ -0,0 +1,100 @@ +#include "ruby/random.h" + +static const uint32_t max_seeds = 1024; + +typedef struct { + rb_random_t base; + uint32_t num, idx, *buf; +} rand_loop_t; + +RB_RANDOM_INTERFACE_DECLARE(loop) +static const rb_random_interface_t random_loop_if = { + 32, + RB_RANDOM_INTERFACE_DEFINE(loop) +}; + +static size_t +random_loop_memsize(const void *ptr) +{ + const rand_loop_t *r = ptr; + return sizeof(*r) + r->num * sizeof(r->buf[0]); +} + +static rb_random_data_type_t random_loop_type = { + "random/loop", + { + rb_random_mark, + RUBY_TYPED_DEFAULT_FREE, + random_loop_memsize, + }, + RB_RANDOM_PARENT, + (void *)&random_loop_if, + RUBY_TYPED_FREE_IMMEDIATELY +}; + + +static VALUE +loop_alloc(VALUE klass) +{ + rand_loop_t *rnd; + VALUE obj = TypedData_Make_Struct(klass, rand_loop_t, &random_loop_type, rnd); + rnd->base.seed = INT2FIX(0); + return obj; +} + +static void +loop_init(rb_random_t *rnd, const uint32_t *buf, size_t len) +{ + rand_loop_t *r = (rand_loop_t *)rnd; + + if (len > max_seeds) len = max_seeds; + + REALLOC_N(r->buf, uint32_t, len); + MEMCPY(r->buf, buf, uint32_t, (r->num = (uint32_t)len)); +} + +static void +loop_get_bytes(rb_random_t *rnd, void *p, size_t n) +{ + uint8_t *buf = p; + while (n > 0) { + uint32_t x = loop_get_int32(rnd); + switch (n % 4) { + case 0: + *buf++ = (uint8_t)x; + n--; + case 3: + *buf++ = (uint8_t)x; + n--; + case 2: + *buf++ = (uint8_t)x; + n--; + case 1: + *buf++ = (uint8_t)x; + n--; + } + } +} + +static uint32_t +loop_get_int32(rb_random_t *rnd) +{ + rand_loop_t *r = (rand_loop_t *)rnd; + if (r->idx < r->num) { + uint32_t x = r->buf[r->idx++]; + if (r->idx >= r->num) r->idx = 0; + return x; + } + else if (r->num) { + return r->buf[r->idx = 0]; + } + return 0; +} + +void +Init_random_loop(VALUE mod, VALUE base) +{ + VALUE c = rb_define_class_under(mod, "Loop", base); + rb_define_alloc_func(c, loop_alloc); + RB_RANDOM_DATA_INIT_PARENT(random_loop_type); +} |
