1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* random.c (random_rand): get rid of overflow.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29843 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2010-11-20 03:04:59 +00:00
parent c62c8f725d
commit 99aaee351e
2 changed files with 21 additions and 4 deletions

View file

@ -964,11 +964,12 @@ rb_random_bytes(VALUE obj, long n)
}
static VALUE
range_values(VALUE vmax, VALUE *begp, int *exclp)
range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
{
VALUE end, r;
if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
if (endp) *endp = end;
if (!rb_respond_to(end, id_minus)) return Qfalse;
r = rb_funcall2(end, id_minus, 1, begp);
if (NIL_P(r)) return Qfalse;
@ -1052,7 +1053,7 @@ static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
VALUE vmax, beg = Qundef, v;
VALUE vmax, beg = Qundef, end, v;
int excl = 0;
if (argc == 0) {
@ -1075,7 +1076,7 @@ random_rand(int argc, VALUE *argv, VALUE obj)
else
v = Qnil;
}
else if ((v = range_values(vmax, &beg, &excl)) != Qfalse) {
else if ((v = range_values(vmax, &beg, &end, &excl)) != Qfalse) {
vmax = v;
if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
long max;
@ -1098,7 +1099,18 @@ random_rand(int argc, VALUE *argv, VALUE obj)
}
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
double max = float_value(v), r;
int scale = 1;
double max = RFLOAT_VALUE(v), mid = 0.5, r;
if (isinf(max)) {
double min = float_value(rb_to_float(beg)) / 2.0;
max = float_value(rb_to_float(end)) / 2.0;
scale = 2;
mid = max + min;
max -= min;
}
else {
float_value(v);
}
v = Qnil;
if (max > 0.0) {
if (excl) {
@ -1107,6 +1119,9 @@ random_rand(int argc, VALUE *argv, VALUE obj)
else {
r = genrand_real2(&rnd->mt);
}
if (scale > 1) {
return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
}
v = rb_float_new(r * max);
}
else if (max == 0.0 && !excl) {

View file

@ -379,6 +379,8 @@ END
assert_in_delta(1.7151893663724195, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]')
assert_in_delta(7.027633760716439, r.rand(1.0...11.0), 0.0001, '[ruby-core:24655]')
assert_in_delta(3.0897663659937937, r.rand(2.0...4.0), 0.0001, '[ruby-core:24655]')
assert_nothing_raised {r.rand(-Float::MAX..Float::MAX)}
end
def test_random_equal