diff --git random.c random.c index 15a7f51..10c9fe6 100644 --- random.c +++ random.c @@ -1025,39 +1025,14 @@ float_value(VALUE v) return x; } -/* - * call-seq: - * prng.rand -> float - * prng.rand(limit) -> number - * - * When the argument is an +Integer+ or a +Bignum+, it returns a - * random integer greater than or equal to zero and less than the - * argument. Unlike Random.rand, when the argument is a negative - * integer or zero, it raises an ArgumentError. - * - * When the argument is a +Float+, it returns a random floating point - * number between 0.0 and _max_, including 0.0 and excluding _max_. - * - * When the argument _limit_ is a +Range+, it returns a random - * number where range.member?(number) == true. - * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] - * prng.rand(5...9) #=> one of [5, 6, 7, 8] - * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 - * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 - * - * +begin+/+end+ of the range have to have subtract and add methods. - * - * Otherwise, it raises an ArgumentError. - */ static VALUE -random_rand(int argc, VALUE *argv, VALUE obj) +random_rand_get(int argc, VALUE *argv, struct MT *mt) { - rb_random_t *rnd = get_rnd(obj); VALUE vmax, beg = Qundef, end = Qundef, v; int excl = 0; if (argc == 0) { - return rb_float_new(genrand_real(&rnd->mt)); + return rb_float_new(genrand_real(mt)); } else if (argc != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc); @@ -1067,12 +1042,12 @@ random_rand(int argc, VALUE *argv, VALUE obj) v = Qnil; } else if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) { - v = rand_int(&rnd->mt, v, 1); + v = rand_int(mt, v, 1); } else if (v = rb_check_to_float(vmax), !NIL_P(v)) { double max = float_value(v); if (max > 0.0) - v = rb_float_new(max * genrand_real(&rnd->mt)); + v = rb_float_new(max * genrand_real(mt)); else v = Qnil; } @@ -1085,7 +1060,7 @@ random_rand(int argc, VALUE *argv, VALUE obj) if (FIXNUM_P(vmax)) { fixnum: if ((max = FIX2LONG(vmax) - excl) >= 0) { - unsigned long r = limited_rand(&rnd->mt, (unsigned long)max); + unsigned long r = limited_rand(mt, (unsigned long)max); v = ULONG2NUM(r); } } @@ -1095,7 +1070,7 @@ random_rand(int argc, VALUE *argv, VALUE obj) excl = 0; goto fixnum; } - v = limited_big_rand(&rnd->mt, RBIGNUM(vmax)); + v = limited_big_rand(mt, RBIGNUM(vmax)); } } else if (v = rb_check_to_float(vmax), !NIL_P(v)) { @@ -1114,10 +1089,10 @@ random_rand(int argc, VALUE *argv, VALUE obj) v = Qnil; if (max > 0.0) { if (excl) { - r = genrand_real(&rnd->mt); + r = genrand_real(mt); } else { - r = genrand_real2(&rnd->mt); + r = genrand_real2(mt); } if (scale > 1) { return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid); @@ -1160,6 +1135,36 @@ random_rand(int argc, VALUE *argv, VALUE obj) /* * call-seq: + * prng.rand -> float + * prng.rand(limit) -> number + * + * When the argument is an +Integer+ or a +Bignum+, it returns a + * random integer greater than or equal to zero and less than the + * argument. Unlike Random.rand, when the argument is a negative + * integer or zero, it raises an ArgumentError. + * + * When the argument is a +Float+, it returns a random floating point + * number between 0.0 and _max_, including 0.0 and excluding _max_. + * + * When the argument _limit_ is a +Range+, it returns a random + * number where range.member?(number) == true. + * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] + * prng.rand(5...9) #=> one of [5, 6, 7, 8] + * prng.rand(5.0..9.0) #=> between 5.0 and 9.0, including 9.0 + * prng.rand(5.0...9.0) #=> between 5.0 and 9.0, excluding 9.0 + * + * +begin+/+end+ of the range have to have subtract and add methods. + * + * Otherwise, it raises an ArgumentError. + */ +static VALUE +random_rand(int argc, VALUE *argv, VALUE obj) +{ + return random_rand_get(argc,argv,&(get_rnd(obj)->mt)); +} + +/* + * call-seq: * prng1 == prng2 -> true or false * * Returns true if the generators' states equal. @@ -1180,39 +1185,35 @@ random_equal(VALUE self, VALUE other) /* * call-seq: - * rand(max=0) -> number + * rand(limit) -> number * - * Converts max to an integer using max1 = - * max.to_i.abs. If _max_ is +nil+ the result is zero, returns a - * pseudorandom floating point number greater than or equal to 0.0 and - * less than 1.0. Otherwise, returns a pseudorandom integer greater - * than or equal to zero and less than max1. Kernel::srand - * may be used to ensure repeatable sequences of random numbers between - * different runs of the program. Ruby currently uses a modified - * Mersenne Twister with a period of 2**19937-1. + * When the argument is an +Integer+ or a +Bignum+, it returns a + * random integer greater than or equal to zero and less than the + * argument. Unlike Random.rand, when the argument is a negative + * integer or zero, it raises an ArgumentError. * - * srand 1234 #=> 0 - * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] - * [ rand(10), rand(1000) ] #=> [6, 817] - * srand 1234 #=> 1234 - * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136] + * When the argument _limit_ is a +Range+, it returns a random + * number where range.member?(number) == true. + * prng.rand(5..9) #=> one of [5, 6, 7, 8, 9] + * prng.rand(5...9) #=> one of [5, 6, 7, 8] + * + * +begin+/+end+ of the range have to have subtract and add methods. + * + * When the argument is not an +Integer+, a +Bignum+ or a +Range+ and it + * can convert to interger, it'll be converted to integer and use as + * an +Integer+. + * + * Otherwise, it raises an ArgumentError. */ static VALUE rb_f_rand(int argc, VALUE *argv, VALUE obj) { - VALUE vmax, r; - struct MT *mt = default_mt(); + VALUE v; + if(argc == 1 && (v = rb_check_to_integer(argv[0], "to_int"), !NIL_P(v))) + argv[0] = v; - if (argc == 0) goto zero_arg; - rb_scan_args(argc, argv, "01", &vmax); - if (NIL_P(vmax)) goto zero_arg; - vmax = rb_to_int(vmax); - if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) { - zero_arg: - return DBL2NUM(genrand_real(mt)); - } - return r; + return random_rand_get(argc,argv,default_mt()); } static st_index_t hashseed;