diff --git a/common.mk b/common.mk index 08f8778689..094b9abe0a 100644 --- a/common.mk +++ b/common.mk @@ -10385,6 +10385,7 @@ random.$(OBJEXT): {$(VPATH)}mt19937.c random.$(OBJEXT): {$(VPATH)}onigmo.h random.$(OBJEXT): {$(VPATH)}oniguruma.h random.$(OBJEXT): {$(VPATH)}random.c +random.$(OBJEXT): {$(VPATH)}random.h random.$(OBJEXT): {$(VPATH)}ruby_atomic.h random.$(OBJEXT): {$(VPATH)}siphash.c random.$(OBJEXT): {$(VPATH)}siphash.h diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend new file mode 100644 index 0000000000..4b4997d340 --- /dev/null +++ b/ext/-test-/random/depend @@ -0,0 +1,328 @@ +# AUTOGENERATED DEPENDENCIES START +init.o: $(RUBY_EXTCONF_H) +init.o: $(arch_hdrdir)/ruby/config.h +init.o: $(hdrdir)/ruby.h +init.o: $(hdrdir)/ruby/assert.h +init.o: $(hdrdir)/ruby/backward.h +init.o: $(hdrdir)/ruby/backward/2/assume.h +init.o: $(hdrdir)/ruby/backward/2/attributes.h +init.o: $(hdrdir)/ruby/backward/2/bool.h +init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +init.o: $(hdrdir)/ruby/backward/2/inttypes.h +init.o: $(hdrdir)/ruby/backward/2/limits.h +init.o: $(hdrdir)/ruby/backward/2/long_long.h +init.o: $(hdrdir)/ruby/backward/2/r_cast.h +init.o: $(hdrdir)/ruby/backward/2/rmodule.h +init.o: $(hdrdir)/ruby/backward/2/stdalign.h +init.o: $(hdrdir)/ruby/backward/2/stdarg.h +init.o: $(hdrdir)/ruby/defines.h +init.o: $(hdrdir)/ruby/intern.h +init.o: $(hdrdir)/ruby/internal/anyargs.h +init.o: $(hdrdir)/ruby/internal/arithmetic.h +init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +init.o: $(hdrdir)/ruby/internal/assume.h +init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +init.o: $(hdrdir)/ruby/internal/attr/artificial.h +init.o: $(hdrdir)/ruby/internal/attr/cold.h +init.o: $(hdrdir)/ruby/internal/attr/const.h +init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +init.o: $(hdrdir)/ruby/internal/attr/error.h +init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +init.o: $(hdrdir)/ruby/internal/attr/format.h +init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +init.o: $(hdrdir)/ruby/internal/attr/noalias.h +init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +init.o: $(hdrdir)/ruby/internal/attr/noinline.h +init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +init.o: $(hdrdir)/ruby/internal/attr/pure.h +init.o: $(hdrdir)/ruby/internal/attr/restrict.h +init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/warning.h +init.o: $(hdrdir)/ruby/internal/attr/weakref.h +init.o: $(hdrdir)/ruby/internal/cast.h +init.o: $(hdrdir)/ruby/internal/compiler_is.h +init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +init.o: $(hdrdir)/ruby/internal/compiler_since.h +init.o: $(hdrdir)/ruby/internal/config.h +init.o: $(hdrdir)/ruby/internal/constant_p.h +init.o: $(hdrdir)/ruby/internal/core.h +init.o: $(hdrdir)/ruby/internal/core/rarray.h +init.o: $(hdrdir)/ruby/internal/core/rbasic.h +init.o: $(hdrdir)/ruby/internal/core/rbignum.h +init.o: $(hdrdir)/ruby/internal/core/rclass.h +init.o: $(hdrdir)/ruby/internal/core/rdata.h +init.o: $(hdrdir)/ruby/internal/core/rfile.h +init.o: $(hdrdir)/ruby/internal/core/rhash.h +init.o: $(hdrdir)/ruby/internal/core/robject.h +init.o: $(hdrdir)/ruby/internal/core/rregexp.h +init.o: $(hdrdir)/ruby/internal/core/rstring.h +init.o: $(hdrdir)/ruby/internal/core/rstruct.h +init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +init.o: $(hdrdir)/ruby/internal/ctype.h +init.o: $(hdrdir)/ruby/internal/dllexport.h +init.o: $(hdrdir)/ruby/internal/dosish.h +init.o: $(hdrdir)/ruby/internal/error.h +init.o: $(hdrdir)/ruby/internal/eval.h +init.o: $(hdrdir)/ruby/internal/event.h +init.o: $(hdrdir)/ruby/internal/fl_type.h +init.o: $(hdrdir)/ruby/internal/gc.h +init.o: $(hdrdir)/ruby/internal/glob.h +init.o: $(hdrdir)/ruby/internal/globals.h +init.o: $(hdrdir)/ruby/internal/has/attribute.h +init.o: $(hdrdir)/ruby/internal/has/builtin.h +init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +init.o: $(hdrdir)/ruby/internal/has/extension.h +init.o: $(hdrdir)/ruby/internal/has/feature.h +init.o: $(hdrdir)/ruby/internal/has/warning.h +init.o: $(hdrdir)/ruby/internal/intern/array.h +init.o: $(hdrdir)/ruby/internal/intern/bignum.h +init.o: $(hdrdir)/ruby/internal/intern/class.h +init.o: $(hdrdir)/ruby/internal/intern/compar.h +init.o: $(hdrdir)/ruby/internal/intern/complex.h +init.o: $(hdrdir)/ruby/internal/intern/cont.h +init.o: $(hdrdir)/ruby/internal/intern/dir.h +init.o: $(hdrdir)/ruby/internal/intern/enum.h +init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +init.o: $(hdrdir)/ruby/internal/intern/error.h +init.o: $(hdrdir)/ruby/internal/intern/eval.h +init.o: $(hdrdir)/ruby/internal/intern/file.h +init.o: $(hdrdir)/ruby/internal/intern/gc.h +init.o: $(hdrdir)/ruby/internal/intern/hash.h +init.o: $(hdrdir)/ruby/internal/intern/io.h +init.o: $(hdrdir)/ruby/internal/intern/load.h +init.o: $(hdrdir)/ruby/internal/intern/marshal.h +init.o: $(hdrdir)/ruby/internal/intern/numeric.h +init.o: $(hdrdir)/ruby/internal/intern/object.h +init.o: $(hdrdir)/ruby/internal/intern/parse.h +init.o: $(hdrdir)/ruby/internal/intern/proc.h +init.o: $(hdrdir)/ruby/internal/intern/process.h +init.o: $(hdrdir)/ruby/internal/intern/random.h +init.o: $(hdrdir)/ruby/internal/intern/range.h +init.o: $(hdrdir)/ruby/internal/intern/rational.h +init.o: $(hdrdir)/ruby/internal/intern/re.h +init.o: $(hdrdir)/ruby/internal/intern/ruby.h +init.o: $(hdrdir)/ruby/internal/intern/select.h +init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/signal.h +init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +init.o: $(hdrdir)/ruby/internal/intern/string.h +init.o: $(hdrdir)/ruby/internal/intern/struct.h +init.o: $(hdrdir)/ruby/internal/intern/thread.h +init.o: $(hdrdir)/ruby/internal/intern/time.h +init.o: $(hdrdir)/ruby/internal/intern/variable.h +init.o: $(hdrdir)/ruby/internal/intern/vm.h +init.o: $(hdrdir)/ruby/internal/interpreter.h +init.o: $(hdrdir)/ruby/internal/iterator.h +init.o: $(hdrdir)/ruby/internal/memory.h +init.o: $(hdrdir)/ruby/internal/method.h +init.o: $(hdrdir)/ruby/internal/module.h +init.o: $(hdrdir)/ruby/internal/newobj.h +init.o: $(hdrdir)/ruby/internal/rgengc.h +init.o: $(hdrdir)/ruby/internal/scan_args.h +init.o: $(hdrdir)/ruby/internal/special_consts.h +init.o: $(hdrdir)/ruby/internal/static_assert.h +init.o: $(hdrdir)/ruby/internal/stdalign.h +init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/symbol.h +init.o: $(hdrdir)/ruby/internal/token_paste.h +init.o: $(hdrdir)/ruby/internal/value.h +init.o: $(hdrdir)/ruby/internal/value_type.h +init.o: $(hdrdir)/ruby/internal/variable.h +init.o: $(hdrdir)/ruby/internal/warning_push.h +init.o: $(hdrdir)/ruby/internal/xmalloc.h +init.o: $(hdrdir)/ruby/missing.h +init.o: $(hdrdir)/ruby/ruby.h +init.o: $(hdrdir)/ruby/st.h +init.o: $(hdrdir)/ruby/subst.h +init.o: init.c +loop.o: $(RUBY_EXTCONF_H) +loop.o: $(arch_hdrdir)/ruby/config.h +loop.o: $(hdrdir)/ruby/assert.h +loop.o: $(hdrdir)/ruby/backward.h +loop.o: $(hdrdir)/ruby/backward/2/assume.h +loop.o: $(hdrdir)/ruby/backward/2/attributes.h +loop.o: $(hdrdir)/ruby/backward/2/bool.h +loop.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +loop.o: $(hdrdir)/ruby/backward/2/inttypes.h +loop.o: $(hdrdir)/ruby/backward/2/limits.h +loop.o: $(hdrdir)/ruby/backward/2/long_long.h +loop.o: $(hdrdir)/ruby/backward/2/r_cast.h +loop.o: $(hdrdir)/ruby/backward/2/rmodule.h +loop.o: $(hdrdir)/ruby/backward/2/stdalign.h +loop.o: $(hdrdir)/ruby/backward/2/stdarg.h +loop.o: $(hdrdir)/ruby/defines.h +loop.o: $(hdrdir)/ruby/intern.h +loop.o: $(hdrdir)/ruby/internal/anyargs.h +loop.o: $(hdrdir)/ruby/internal/arithmetic.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/char.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/double.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/int.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/long.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/short.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +loop.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +loop.o: $(hdrdir)/ruby/internal/assume.h +loop.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +loop.o: $(hdrdir)/ruby/internal/attr/artificial.h +loop.o: $(hdrdir)/ruby/internal/attr/cold.h +loop.o: $(hdrdir)/ruby/internal/attr/const.h +loop.o: $(hdrdir)/ruby/internal/attr/constexpr.h +loop.o: $(hdrdir)/ruby/internal/attr/deprecated.h +loop.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +loop.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +loop.o: $(hdrdir)/ruby/internal/attr/error.h +loop.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +loop.o: $(hdrdir)/ruby/internal/attr/forceinline.h +loop.o: $(hdrdir)/ruby/internal/attr/format.h +loop.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +loop.o: $(hdrdir)/ruby/internal/attr/noalias.h +loop.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +loop.o: $(hdrdir)/ruby/internal/attr/noexcept.h +loop.o: $(hdrdir)/ruby/internal/attr/noinline.h +loop.o: $(hdrdir)/ruby/internal/attr/nonnull.h +loop.o: $(hdrdir)/ruby/internal/attr/noreturn.h +loop.o: $(hdrdir)/ruby/internal/attr/pure.h +loop.o: $(hdrdir)/ruby/internal/attr/restrict.h +loop.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +loop.o: $(hdrdir)/ruby/internal/attr/warning.h +loop.o: $(hdrdir)/ruby/internal/attr/weakref.h +loop.o: $(hdrdir)/ruby/internal/cast.h +loop.o: $(hdrdir)/ruby/internal/compiler_is.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +loop.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +loop.o: $(hdrdir)/ruby/internal/compiler_since.h +loop.o: $(hdrdir)/ruby/internal/config.h +loop.o: $(hdrdir)/ruby/internal/constant_p.h +loop.o: $(hdrdir)/ruby/internal/core.h +loop.o: $(hdrdir)/ruby/internal/core/rarray.h +loop.o: $(hdrdir)/ruby/internal/core/rbasic.h +loop.o: $(hdrdir)/ruby/internal/core/rbignum.h +loop.o: $(hdrdir)/ruby/internal/core/rclass.h +loop.o: $(hdrdir)/ruby/internal/core/rdata.h +loop.o: $(hdrdir)/ruby/internal/core/rfile.h +loop.o: $(hdrdir)/ruby/internal/core/rhash.h +loop.o: $(hdrdir)/ruby/internal/core/robject.h +loop.o: $(hdrdir)/ruby/internal/core/rregexp.h +loop.o: $(hdrdir)/ruby/internal/core/rstring.h +loop.o: $(hdrdir)/ruby/internal/core/rstruct.h +loop.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +loop.o: $(hdrdir)/ruby/internal/ctype.h +loop.o: $(hdrdir)/ruby/internal/dllexport.h +loop.o: $(hdrdir)/ruby/internal/dosish.h +loop.o: $(hdrdir)/ruby/internal/error.h +loop.o: $(hdrdir)/ruby/internal/eval.h +loop.o: $(hdrdir)/ruby/internal/event.h +loop.o: $(hdrdir)/ruby/internal/fl_type.h +loop.o: $(hdrdir)/ruby/internal/gc.h +loop.o: $(hdrdir)/ruby/internal/glob.h +loop.o: $(hdrdir)/ruby/internal/globals.h +loop.o: $(hdrdir)/ruby/internal/has/attribute.h +loop.o: $(hdrdir)/ruby/internal/has/builtin.h +loop.o: $(hdrdir)/ruby/internal/has/c_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +loop.o: $(hdrdir)/ruby/internal/has/extension.h +loop.o: $(hdrdir)/ruby/internal/has/feature.h +loop.o: $(hdrdir)/ruby/internal/has/warning.h +loop.o: $(hdrdir)/ruby/internal/intern/array.h +loop.o: $(hdrdir)/ruby/internal/intern/bignum.h +loop.o: $(hdrdir)/ruby/internal/intern/class.h +loop.o: $(hdrdir)/ruby/internal/intern/compar.h +loop.o: $(hdrdir)/ruby/internal/intern/complex.h +loop.o: $(hdrdir)/ruby/internal/intern/cont.h +loop.o: $(hdrdir)/ruby/internal/intern/dir.h +loop.o: $(hdrdir)/ruby/internal/intern/enum.h +loop.o: $(hdrdir)/ruby/internal/intern/enumerator.h +loop.o: $(hdrdir)/ruby/internal/intern/error.h +loop.o: $(hdrdir)/ruby/internal/intern/eval.h +loop.o: $(hdrdir)/ruby/internal/intern/file.h +loop.o: $(hdrdir)/ruby/internal/intern/gc.h +loop.o: $(hdrdir)/ruby/internal/intern/hash.h +loop.o: $(hdrdir)/ruby/internal/intern/io.h +loop.o: $(hdrdir)/ruby/internal/intern/load.h +loop.o: $(hdrdir)/ruby/internal/intern/marshal.h +loop.o: $(hdrdir)/ruby/internal/intern/numeric.h +loop.o: $(hdrdir)/ruby/internal/intern/object.h +loop.o: $(hdrdir)/ruby/internal/intern/parse.h +loop.o: $(hdrdir)/ruby/internal/intern/proc.h +loop.o: $(hdrdir)/ruby/internal/intern/process.h +loop.o: $(hdrdir)/ruby/internal/intern/random.h +loop.o: $(hdrdir)/ruby/internal/intern/range.h +loop.o: $(hdrdir)/ruby/internal/intern/rational.h +loop.o: $(hdrdir)/ruby/internal/intern/re.h +loop.o: $(hdrdir)/ruby/internal/intern/ruby.h +loop.o: $(hdrdir)/ruby/internal/intern/select.h +loop.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +loop.o: $(hdrdir)/ruby/internal/intern/signal.h +loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h +loop.o: $(hdrdir)/ruby/internal/intern/string.h +loop.o: $(hdrdir)/ruby/internal/intern/struct.h +loop.o: $(hdrdir)/ruby/internal/intern/thread.h +loop.o: $(hdrdir)/ruby/internal/intern/time.h +loop.o: $(hdrdir)/ruby/internal/intern/variable.h +loop.o: $(hdrdir)/ruby/internal/intern/vm.h +loop.o: $(hdrdir)/ruby/internal/interpreter.h +loop.o: $(hdrdir)/ruby/internal/iterator.h +loop.o: $(hdrdir)/ruby/internal/memory.h +loop.o: $(hdrdir)/ruby/internal/method.h +loop.o: $(hdrdir)/ruby/internal/module.h +loop.o: $(hdrdir)/ruby/internal/newobj.h +loop.o: $(hdrdir)/ruby/internal/rgengc.h +loop.o: $(hdrdir)/ruby/internal/scan_args.h +loop.o: $(hdrdir)/ruby/internal/special_consts.h +loop.o: $(hdrdir)/ruby/internal/static_assert.h +loop.o: $(hdrdir)/ruby/internal/stdalign.h +loop.o: $(hdrdir)/ruby/internal/stdbool.h +loop.o: $(hdrdir)/ruby/internal/symbol.h +loop.o: $(hdrdir)/ruby/internal/token_paste.h +loop.o: $(hdrdir)/ruby/internal/value.h +loop.o: $(hdrdir)/ruby/internal/value_type.h +loop.o: $(hdrdir)/ruby/internal/variable.h +loop.o: $(hdrdir)/ruby/internal/warning_push.h +loop.o: $(hdrdir)/ruby/internal/xmalloc.h +loop.o: $(hdrdir)/ruby/missing.h +loop.o: $(hdrdir)/ruby/random.h +loop.o: $(hdrdir)/ruby/ruby.h +loop.o: $(hdrdir)/ruby/st.h +loop.o: $(hdrdir)/ruby/subst.h +loop.o: loop.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/random/extconf.rb b/ext/-test-/random/extconf.rb new file mode 100644 index 0000000000..d786b15db9 --- /dev/null +++ b/ext/-test-/random/extconf.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: false +require_relative "../auto_ext.rb" +auto_ext(inc: true) diff --git a/ext/-test-/random/init.c b/ext/-test-/random/init.c new file mode 100644 index 0000000000..320cba0ad6 --- /dev/null +++ b/ext/-test-/random/init.c @@ -0,0 +1,11 @@ +#include "ruby.h" + +#define init(n) {void Init_random_##n(VALUE mod, VALUE base); Init_random_##n(mod, base);} + +void +Init_random(void) +{ + VALUE base = rb_const_get(rb_cRandom, rb_intern_const("Base")); + VALUE mod = rb_define_module_under(rb_define_module("Bug"), "Random"); + TEST_INIT_FUNCS(init); +} 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); +} diff --git a/include/ruby/random.h b/include/ruby/random.h new file mode 100644 index 0000000000..bb6cf73bae --- /dev/null +++ b/include/ruby/random.h @@ -0,0 +1,80 @@ +#ifndef RUBY_RANDOM_H +#define RUBY_RANDOM_H 1 +/** + * @file + * @date Sat May 7 11:51:14 JST 2016 + * @copyright 2007-2020 Yukihiro Matsumoto + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + */ + +#include "ruby/ruby.h" + +#if defined(__cplusplus) +extern "C" { +#if 0 +} /* satisfy cc-mode */ +#endif +#endif + +RUBY_SYMBOL_EXPORT_BEGIN + +typedef struct { + VALUE seed; +} rb_random_t; + +typedef void rb_random_init_func(rb_random_t *, const uint32_t *, size_t); +typedef unsigned int rb_random_get_int32_func(rb_random_t *); +typedef void rb_random_get_bytes_func(rb_random_t *, void *, size_t); + +typedef struct { + size_t default_seed_bits; + rb_random_init_func *init; + rb_random_get_int32_func *get_int32; + rb_random_get_bytes_func *get_bytes; +} rb_random_interface_t; + +#define rb_rand_if(obj) \ + ((const rb_random_interface_t *)RTYPEDDATA_TYPE(obj)->data) + +#define RB_RANDOM_INTERFACE_DECLARE(prefix) \ + static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \ + static unsigned int prefix##_get_int32(rb_random_t *); \ + static void prefix##_get_bytes(rb_random_t *, void *, size_t); \ + /* end */ + +#define RB_RANDOM_INTERFACE_DEFINE(prefix) \ + prefix##_init, \ + prefix##_get_int32, \ + prefix##_get_bytes, \ + /* end */ + +#if defined _WIN32 && !defined __CYGWIN__ +typedef rb_data_type_t rb_random_data_type_t; +# define RB_RANDOM_PARENT 0 +# define RB_RANDOM_DATA_INIT_PARENT(random_data) \ + (random_data.parent = &rb_random_data_type) +#else +typedef const rb_data_type_t rb_random_data_type_t; +# define RB_RANDOM_PARENT &rb_random_data_type +# define RB_RANDOM_DATA_INIT_PARENT(random_data) ((void)0) +#endif + +void rb_random_mark(void *ptr); +double rb_int_pair_to_real_exclusive(uint32_t a, uint32_t b); +double rb_int_pair_to_real_inclusive(uint32_t a, uint32_t b); +void rb_rand_bytes_int32(rb_random_get_int32_func *, rb_random_t *, void *, size_t); +RUBY_EXTERN const rb_data_type_t rb_random_data_type; + +RUBY_SYMBOL_EXPORT_END + +#if defined(__cplusplus) +#if 0 +{ /* satisfy cc-mode */ +#endif +} /* extern "C" { */ +#endif + +#endif /* RUBY_RANDOM_H */ diff --git a/random.c b/random.c index 2a3b0d2ebd..08c69182fb 100644 --- a/random.c +++ b/random.c @@ -62,6 +62,7 @@ #include "internal/random.h" #include "internal/sanitizers.h" #include "ruby_atomic.h" +#include "ruby/random.h" typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; @@ -113,44 +114,57 @@ genrand_real2(struct MT *mt) #undef M typedef struct { - VALUE seed; + rb_random_t base; struct MT mt; -} rb_random_t; +} rb_random_mt_t; #define DEFAULT_SEED_CNT 4 -static rb_random_t default_rand; +static rb_random_mt_t default_rand; -static VALUE rand_init(struct MT *mt, VALUE vseed); +static VALUE rand_init(const rb_random_interface_t *, rb_random_t *, VALUE); static VALUE random_seed(VALUE); +static void fill_random_seed(uint32_t *seed, size_t cnt); +static VALUE make_seed_value(uint32_t *ptr, size_t len); -static rb_random_t * -rand_start(rb_random_t *r) +RB_RANDOM_INTERFACE_DECLARE(rand_mt) +static const rb_random_interface_t random_mt_if = { + DEFAULT_SEED_CNT * 32, + RB_RANDOM_INTERFACE_DEFINE(rand_mt) +}; + +static rb_random_mt_t * +rand_mt_start(rb_random_mt_t *r) { - struct MT *mt = &r->mt; - if (!genrand_initialized(mt)) { - r->seed = rand_init(mt, random_seed(Qundef)); + if (!genrand_initialized(&r->mt)) { + r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef)); } return r; } -static struct MT * +static rb_random_t * +rand_start(rb_random_mt_t *r) +{ + return &rand_mt_start(r)->base; +} + +static rb_random_mt_t * default_mt(void) { - return &rand_start(&default_rand)->mt; + return rand_mt_start(&default_rand); } unsigned int rb_genrand_int32(void) { - struct MT *mt = default_mt(); + struct MT *mt = &default_mt()->mt; return genrand_int32(mt); } double rb_genrand_real(void) { - struct MT *mt = default_mt(); + struct MT *mt = &default_mt()->mt; return genrand_real(mt); } @@ -185,18 +199,15 @@ static ID id_rand, id_bytes; NORETURN(static void domain_error(void)); /* :nodoc: */ -static void +#define random_mark rb_random_mark + +void random_mark(void *ptr) { rb_gc_mark(((rb_random_t *)ptr)->seed); } -static void -random_free(void *ptr) -{ - if (ptr != &default_rand) - xfree(ptr); -} +#define random_free RUBY_TYPED_DEFAULT_FREE static size_t random_memsize(const void *ptr) @@ -204,8 +215,8 @@ random_memsize(const void *ptr) return sizeof(rb_random_t); } -static const rb_data_type_t random_mt_type = { - "random/MT", +const rb_data_type_t rb_random_data_type = { + "random", { random_mark, random_free, @@ -214,12 +225,49 @@ static const rb_data_type_t random_mt_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; +#define random_mt_mark rb_random_mark + +static void +random_mt_free(void *ptr) +{ + if (ptr != &default_rand) + xfree(ptr); +} + +static size_t +random_mt_memsize(const void *ptr) +{ + return sizeof(rb_random_mt_t); +} + +static const rb_data_type_t random_mt_type = { + "random/MT", + { + random_mt_mark, + random_mt_free, + random_mt_memsize, + }, + &rb_random_data_type, + (void *)&random_mt_if, + RUBY_TYPED_FREE_IMMEDIATELY +}; + static rb_random_t * get_rnd(VALUE obj) { rb_random_t *ptr; - TypedData_Get_Struct(obj, rb_random_t, &random_mt_type, ptr); - return rand_start(ptr); + TypedData_Get_Struct(obj, rb_random_t, &rb_random_data_type, ptr); + if (RTYPEDDATA_TYPE(obj) == &random_mt_type) + return rand_start((rb_random_mt_t *)ptr); + return ptr; +} + +static rb_random_mt_t * +get_rnd_mt(VALUE obj) +{ + rb_random_mt_t *ptr; + TypedData_Get_Struct(obj, rb_random_mt_t, &random_mt_type, ptr); + return ptr; } static rb_random_t * @@ -228,30 +276,61 @@ try_get_rnd(VALUE obj) if (obj == rb_cRandom) { return rand_start(&default_rand); } - if (!rb_typeddata_is_kind_of(obj, &random_mt_type)) return NULL; - return rand_start(DATA_PTR(obj)); + if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL; + if (RTYPEDDATA_TYPE(obj) == &random_mt_type) + return rand_start(DATA_PTR(obj)); + rb_random_t *rnd = DATA_PTR(obj); + if (!rnd) { + rb_raise(rb_eArgError, "uninitialized random: %s", + RTYPEDDATA_TYPE(obj)->wrap_struct_name); + } + return rnd; +} + +static const rb_random_interface_t * +try_rand_if(VALUE obj, rb_random_t *rnd) +{ + if (rnd == &default_rand.base) { + return &random_mt_if; + } + return rb_rand_if(obj); } /* :nodoc: */ static VALUE random_alloc(VALUE klass) { - rb_random_t *rnd; - VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_mt_type, rnd); - rnd->seed = INT2FIX(0); + rb_random_mt_t *rnd; + VALUE obj = TypedData_Make_Struct(klass, rb_random_mt_t, &random_mt_type, rnd); + rnd->base.seed = INT2FIX(0); return obj; } static VALUE -rand_init(struct MT *mt, VALUE seed) +rand_init_default(const rb_random_interface_t *rng, rb_random_t *rnd) { - uint32_t buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0; + VALUE seed, buf0 = 0; + size_t len = roomof(rng->default_seed_bits, 32); + uint32_t *buf = ALLOCV_N(uint32_t, buf0, len+1); + + fill_random_seed(buf, len); + rng->init(rnd, buf, len); + seed = make_seed_value(buf, len); + explicit_bzero(buf, len * sizeof(*buf)); + ALLOCV_END(buf0); + return seed; +} + +static VALUE +rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed) +{ + uint32_t *buf; + VALUE buf0 = 0; size_t len; int sign; len = rb_absint_numwords(seed, 32, NULL); - if (len > numberof(buf0)) - buf = ALLOC_N(uint32_t, len); + buf = ALLOCV_N(uint32_t, buf0, len); sign = rb_integer_pack(seed, buf, len, sizeof(uint32_t), 0, INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); if (sign < 0) @@ -260,16 +339,13 @@ rand_init(struct MT *mt, VALUE seed) buf[0] = 0; len = 1; } - if (len <= 1) { - init_genrand(mt, buf[0]); - } - else { + if (len > 1) { if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */ len--; - init_by_array(mt, buf, (int)len); } + rng->init(rnd, buf, len); explicit_bzero(buf, len * sizeof(*buf)); - if (buf != buf0) xfree(buf); + ALLOCV_END(buf0); return seed; } @@ -285,19 +361,21 @@ rand_init(struct MT *mt, VALUE seed) static VALUE random_init(int argc, VALUE *argv, VALUE obj) { - VALUE vseed; - rb_random_t *rnd = get_rnd(obj); + rb_random_t *rnd = try_get_rnd(obj); + const rb_random_interface_t *rng = rb_rand_if(obj); - if (rb_check_arity(argc, 0, 1) == 0) { - rb_check_frozen(obj); - vseed = random_seed(obj); + if (!rng) { + rb_raise(rb_eTypeError, "undefined random interface: %s", + RTYPEDDATA_TYPE(obj)->wrap_struct_name); + } + argc = rb_check_arity(argc, 0, 1); + rb_check_frozen(obj); + if (argc == 0) { + rnd->seed = rand_init_default(rng, rnd); } else { - vseed = argv[0]; - rb_check_copyable(obj, vseed); - vseed = rb_to_int(vseed); + rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0])); } - rnd->seed = rand_init(&rnd->mt, vseed); return obj; } @@ -588,15 +666,15 @@ random_get_seed(VALUE obj) /* :nodoc: */ static VALUE -random_copy(VALUE obj, VALUE orig) +rand_mt_copy(VALUE obj, VALUE orig) { - rb_random_t *rnd1, *rnd2; + rb_random_mt_t *rnd1, *rnd2; struct MT *mt; if (!OBJ_INIT_COPY(obj, orig)) return obj; - rnd1 = get_rnd(obj); - rnd2 = get_rnd(orig); + rnd1 = get_rnd_mt(obj); + rnd2 = get_rnd_mt(orig); mt = &rnd1->mt; *rnd1 = *rnd2; @@ -614,9 +692,9 @@ mt_state(const struct MT *mt) /* :nodoc: */ static VALUE -random_state(VALUE obj) +rand_mt_state(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = get_rnd_mt(obj); return mt_state(&rnd->mt); } @@ -629,9 +707,9 @@ random_s_state(VALUE klass) /* :nodoc: */ static VALUE -random_left(VALUE obj) +rand_mt_left(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = get_rnd_mt(obj); return INT2FIX(rnd->mt.left); } @@ -644,23 +722,23 @@ random_s_left(VALUE klass) /* :nodoc: */ static VALUE -random_dump(VALUE obj) +rand_mt_dump(VALUE obj) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type); VALUE dump = rb_ary_new2(3); rb_ary_push(dump, mt_state(&rnd->mt)); rb_ary_push(dump, INT2FIX(rnd->mt.left)); - rb_ary_push(dump, rnd->seed); + rb_ary_push(dump, rnd->base.seed); return dump; } /* :nodoc: */ static VALUE -random_load(VALUE obj, VALUE dump) +rand_mt_load(VALUE obj, VALUE dump) { - rb_random_t *rnd = get_rnd(obj); + rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type); struct MT *mt = &rnd->mt; VALUE state, left = INT2FIX(1), seed = INT2FIX(0); unsigned long x; @@ -687,11 +765,36 @@ random_load(VALUE obj, VALUE dump) } mt->left = (unsigned int)x; mt->next = mt->state + numberof(mt->state) - x + 1; - rnd->seed = rb_to_int(seed); + rnd->base.seed = rb_to_int(seed); return obj; } +static void +rand_mt_init(rb_random_t *rnd, const uint32_t *buf, size_t len) +{ + struct MT *mt = &((rb_random_mt_t *)rnd)->mt; + if (len <= 1) { + init_genrand(mt, buf[0]); + } + else { + init_by_array(mt, buf, (int)len); + } +} + +static unsigned int +rand_mt_get_int32(rb_random_t *rnd) +{ + struct MT *mt = &((rb_random_mt_t *)rnd)->mt; + return genrand_int32(mt); +} + +static void +rand_mt_get_bytes(rb_random_t *rnd, void *ptr, size_t n) +{ + rb_rand_bytes_int32(rand_mt_get_int32, rnd, ptr, n); +} + /* * call-seq: * srand(number = Random.new_seed) -> old_seed @@ -719,7 +822,7 @@ static VALUE rb_f_srand(int argc, VALUE *argv, VALUE obj) { VALUE seed, old; - rb_random_t *r = &default_rand; + rb_random_mt_t *r = &default_rand; if (rb_check_arity(argc, 0, 1) == 0) { seed = random_seed(obj); @@ -727,8 +830,9 @@ rb_f_srand(int argc, VALUE *argv, VALUE obj) else { seed = rb_to_int(argv[0]); } - old = r->seed; - r->seed = rand_init(&r->mt, seed); + old = r->base.seed; + rand_init(&random_mt_if, &r->base, seed); + r->base.seed = seed; return old; } @@ -748,7 +852,7 @@ make_mask(unsigned long x) } static unsigned long -limited_rand(struct MT *mt, unsigned long limit) +limited_rand(const rb_random_interface_t *rng, rb_random_t *rnd, unsigned long limit) { /* mt must be initialized */ unsigned long val, mask; @@ -763,7 +867,7 @@ limited_rand(struct MT *mt, unsigned long limit) val = 0; for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) { if ((mask >> (i * 32)) & 0xffffffff) { - val |= (unsigned long)genrand_int32(mt) << (i * 32); + val |= (unsigned long)rng->get_int32(rnd) << (i * 32); val &= mask; if (limit < val) goto retry; @@ -774,13 +878,13 @@ limited_rand(struct MT *mt, unsigned long limit) #endif do { - val = genrand_int32(mt) & mask; + val = rng->get_int32(rnd) & mask; } while (limit < val); return val; } static VALUE -limited_big_rand(struct MT *mt, VALUE limit) +limited_big_rand(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE limit) { /* mt must be initialized */ @@ -804,22 +908,19 @@ limited_big_rand(struct MT *mt, VALUE limit) mask = 0; boundary = 1; for (i = len-1; 0 <= i; i--) { - uint32_t rnd; + uint32_t r = 0; uint32_t lim = lim_array[i]; mask = mask ? 0xffffffff : (uint32_t)make_mask(lim); if (mask) { - rnd = genrand_int32(mt) & mask; + r = rng->get_int32(rnd) & mask; if (boundary) { - if (lim < rnd) + if (lim < r) goto retry; - if (rnd < lim) + if (r < lim) boundary = 0; } } - else { - rnd = 0; - } - rnd_array[i] = rnd; + rnd_array[i] = r; } val = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0, INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER); @@ -837,7 +938,8 @@ limited_big_rand(struct MT *mt, VALUE limit) unsigned long rb_genrand_ulong_limited(unsigned long limit) { - return limited_rand(default_mt(), limit); + rb_random_mt_t *mt = default_mt(); + return limited_rand(&random_mt_if, &mt->base, limit); } static VALUE @@ -857,9 +959,9 @@ obj_random_bytes(VALUE obj, void *p, long n) } static unsigned int -random_int32(rb_random_t *rnd) +random_int32(const rb_random_interface_t *rng, rb_random_t *rnd) { - return genrand_int32(&rnd->mt); + return rng->get_int32(rnd); } unsigned int @@ -871,7 +973,7 @@ rb_random_int32(VALUE obj) obj_random_bytes(obj, &x, sizeof(x)); return (unsigned int)x; } - return random_int32(rnd); + return random_int32(try_rand_if(obj, rnd), rnd); } static double @@ -886,8 +988,9 @@ random_real(VALUE obj, rb_random_t *rnd, int excl) b = x[1]; } else { - a = random_int32(rnd); - b = random_int32(rnd); + const rb_random_interface_t *rng = try_rand_if(obj, rnd); + a = random_int32(rng, rnd); + b = random_int32(rng, rnd); } if (excl) { return int_pair_to_real_exclusive(a, b); @@ -912,7 +1015,7 @@ rb_random_real(VALUE obj) } return d; } - return genrand_real(&rnd->mt); + return random_real(obj, rnd, TRUE); } static inline VALUE @@ -954,7 +1057,7 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit) } while (limit < val); return val; } - return limited_rand(&rnd->mt, limit); + return limited_rand(try_rand_if(obj, rnd), rnd, limit); } unsigned long @@ -973,7 +1076,7 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit) } return r; } - return limited_rand(&rnd->mt, limit); + return limited_rand(try_rand_if(obj, rnd), rnd, limit); } static VALUE @@ -1002,10 +1105,20 @@ random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax) ALLOCV_END(vtmp); return v; } - return limited_big_rand(&rnd->mt, vmax); + return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax); } -static VALUE genrand_bytes(rb_random_t *rnd, long n); +static VALUE +rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n) +{ + VALUE bytes; + char *ptr; + + bytes = rb_str_new(0, n); + ptr = RSTRING_PTR(bytes); + rb_rand_bytes_int32(rng->get_int32, rnd, ptr, n); + return bytes; +} /* * call-seq: prng.bytes(size) -> string @@ -1018,20 +1131,18 @@ static VALUE genrand_bytes(rb_random_t *rnd, long n); static VALUE random_bytes(VALUE obj, VALUE len) { - return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len))); + rb_random_t *rnd = try_get_rnd(obj); + return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len))); } -static VALUE -genrand_bytes(rb_random_t *rnd, long n) +void +rb_rand_bytes_int32(rb_random_get_int32_func *get_int32, + rb_random_t *rnd, void *p, size_t n) { - VALUE bytes; - char *ptr; + char *ptr = p; unsigned int r, i; - - bytes = rb_str_new(0, n); - ptr = RSTRING_PTR(bytes); for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) { - r = genrand_int32(&rnd->mt); + r = get_int32(rnd); i = SIZEOF_INT32; do { *ptr++ = (char)r; @@ -1039,13 +1150,12 @@ genrand_bytes(rb_random_t *rnd, long n) } while (--i); } if (n > 0) { - r = genrand_int32(&rnd->mt); + r = get_int32(rnd); do { *ptr++ = (char)r; r >>= CHAR_BIT; } while (--n); } - return bytes; } VALUE @@ -1055,7 +1165,7 @@ rb_random_bytes(VALUE obj, long n) if (!rnd) { return obj_random_bytes(obj, NULL, n); } - return genrand_bytes(rnd, n); + return rand_bytes(try_rand_if(obj, rnd), rnd, n); } /* @@ -1068,7 +1178,7 @@ static VALUE random_s_bytes(VALUE obj, VALUE len) { rb_random_t *rnd = rand_start(&default_rand); - return genrand_bytes(rnd, NUM2LONG(rb_to_int(len))); + return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len))); } static VALUE @@ -1268,7 +1378,7 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd); static VALUE random_rand(int argc, VALUE *argv, VALUE obj) { - VALUE v = rand_random(argc, argv, obj, get_rnd(obj)); + VALUE v = rand_random(argc, argv, obj, try_get_rnd(obj)); check_random_number(v, argv); return v; } @@ -1347,16 +1457,16 @@ rand_random_number(int argc, VALUE *argv, VALUE obj) * prng1 == prng2 # => true */ static VALUE -random_equal(VALUE self, VALUE other) +rand_mt_equal(VALUE self, VALUE other) { - rb_random_t *r1, *r2; + rb_random_mt_t *r1, *r2; if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse; - r1 = get_rnd(self); - r2 = get_rnd(other); + r1 = get_rnd_mt(self); + r2 = get_rnd_mt(other); if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse; if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse; if (r1->mt.left != r2->mt.left) return Qfalse; - return rb_equal(r1->seed, r2->seed); + return rb_equal(r1->base.seed, r2->base.seed); } /* @@ -1397,15 +1507,15 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj) rb_random_t *rnd = rand_start(&default_rand); if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) { - VALUE v = rand_range(Qnil, rnd, vmax); + VALUE v = rand_range(obj, rnd, vmax); if (v != Qfalse) return v; vmax = rb_to_int(vmax); if (vmax != INT2FIX(0)) { - v = rand_int(Qnil, rnd, vmax, 0); + v = rand_int(obj, rnd, vmax, 0); if (!NIL_P(v)) return v; } } - return DBL2NUM(genrand_real(&rnd->mt)); + return DBL2NUM(random_real(obj, rnd, TRUE)); } /* @@ -1506,14 +1616,14 @@ Init_RandomSeedCore(void) static VALUE Init_Random_default(VALUE klass) { - rb_random_t *r = &default_rand; + rb_random_mt_t *r = &default_rand; struct MT *mt = &r->mt; VALUE v = TypedData_Wrap_Struct(klass, &random_mt_type, r); rb_gc_register_mark_object(v); with_random_seed(DEFAULT_SEED_CNT, 1) { init_by_array(mt, seedbuf, DEFAULT_SEED_CNT); - r->seed = make_seed_value(seedbuf, DEFAULT_SEED_CNT); + r->base.seed = make_seed_value(seedbuf, DEFAULT_SEED_CNT); } return v; @@ -1522,9 +1632,9 @@ Init_Random_default(VALUE klass) void rb_reset_random_seed(void) { - rb_random_t *r = &default_rand; + rb_random_mt_t *r = &default_rand; uninit_genrand(&r->mt); - r->seed = INT2FIX(0); + r->base.seed = INT2FIX(0); } /* @@ -1569,13 +1679,13 @@ InitVM_Random(void) rb_define_method(base, "initialize", random_init, -1); rb_define_method(base, "rand", random_rand, -1); rb_define_method(base, "bytes", random_bytes, 1); - rb_define_method(rb_cRandom, "seed", random_get_seed, 0); - rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1); - rb_define_private_method(rb_cRandom, "marshal_dump", random_dump, 0); - rb_define_private_method(rb_cRandom, "marshal_load", random_load, 1); - rb_define_private_method(rb_cRandom, "state", random_state, 0); - rb_define_private_method(rb_cRandom, "left", random_left, 0); - rb_define_method(rb_cRandom, "==", random_equal, 1); + rb_define_method(base, "seed", random_get_seed, 0); + rb_define_method(rb_cRandom, "initialize_copy", rand_mt_copy, 1); + rb_define_private_method(rb_cRandom, "marshal_dump", rand_mt_dump, 0); + rb_define_private_method(rb_cRandom, "marshal_load", rand_mt_load, 1); + rb_define_private_method(rb_cRandom, "state", rand_mt_state, 0); + rb_define_private_method(rb_cRandom, "left", rand_mt_left, 0); + rb_define_method(rb_cRandom, "==", rand_mt_equal, 1); { /* Direct access to Ruby's Pseudorandom number generator (PRNG). */ diff --git a/test/-ext-/test_random.rb b/test/-ext-/test_random.rb new file mode 100644 index 0000000000..da716c71c0 --- /dev/null +++ b/test/-ext-/test_random.rb @@ -0,0 +1,20 @@ +require 'test/unit' + +module TestRandomExt + class TestLoop < Test::Unit::TestCase + def setup + super + assert_nothing_raised(LoadError) {require '-test-/random'} + end + + def test_bytes + rnd = Bug::Random::Loop.new(1) + assert_equal("\1", rnd.bytes(1)) + end + + def test_rand + rnd = Bug::Random::Loop.new(1) + assert_equal(1, rnd.rand(10)) + end + end +end