summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--random.c29
-rw-r--r--test/ruby/test_rand.rb13
3 files changed, 33 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 898e7191f90..880e4d702f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Sun Aug 2 14:20:43 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * random.c (rand_int): prevent from GC.
+
Sat Aug 1 19:23:27 2009 NARUSE, Yui <naruse@ruby-lang.org>
* string.c (tr_trans): change condition of singlebyte
diff --git a/random.c b/random.c
index 4a629938641..0855a1bc789 100644
--- a/random.c
+++ b/random.c
@@ -855,27 +855,32 @@ add_to_begin(VALUE beg, VALUE offset)
static VALUE
rand_int(struct MT *mt, VALUE vmax)
{
+ long max;
+ unsigned long r;
+
if (FIXNUM_P(vmax)) {
- long max = FIX2LONG(vmax);
- unsigned long r;
+ max = FIX2LONG(vmax);
if (!max) return Qnil;
r = limited_rand(mt, (unsigned long)(max < 0 ? -max : max) - 1);
return ULONG2NUM(r);
}
else {
- struct RBignum *limit = (struct RBignum *)vmax;
+ VALUE ret;
if (rb_bigzero_p(vmax)) return Qnil;
- if (!RBIGNUM_SIGN(limit)) {
- limit = (struct RBignum *)rb_big_clone(vmax);
- RBIGNUM_SET_SIGN(limit, 1);
+ if (!RBIGNUM_SIGN(vmax)) {
+ vmax = rb_big_clone(vmax);
+ RBIGNUM_SET_SIGN(vmax, 1);
}
- limit = (struct RBignum *)rb_big_minus((VALUE)limit, INT2FIX(1));
- if (FIXNUM_P((VALUE)limit)) {
- if (FIX2LONG((VALUE)limit) == -1)
- return Qnil;
- return LONG2NUM(limited_rand(mt, FIX2LONG((VALUE)limit)));
+ vmax = rb_big_minus(vmax, INT2FIX(1));
+ if (FIXNUM_P(vmax)) {
+ max = FIX2LONG(vmax);
+ if (max == -1) return Qnil;
+ r = limited_rand(mt, max);
+ return LONG2NUM(r);
}
- return limited_big_rand(mt, limit);
+ ret = limited_big_rand(mt, RBIGNUM(vmax));
+ RB_GC_GUARD(vmax);
+ return ret;
}
}
diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb
index 2f2e772c1b0..e20cf4e317b 100644
--- a/test/ruby/test_rand.rb
+++ b/test/ruby/test_rand.rb
@@ -4,13 +4,24 @@ class TestRand < Test::Unit::TestCase
def assert_random_int(ws, m, init = 0)
srand(init)
rnds = [Random.new(init)]
- ws.each do |w|
+ rnds2 = [rnds[0].dup]
+ rnds3 = [rnds[0].dup]
+ ws.each_with_index do |w, i|
w = w.to_i
assert_equal(w, rand(m))
rnds.each do |rnd|
assert_equal(w, rnd.int(m))
end
+ rnds2.each do |rnd|
+ r=rnd.int(i...(m+i))
+ assert_equal(w+i, r)
+ end
+ rnds3.each do |rnd|
+ r=rnd.int(i..(m+i-1))
+ assert_equal(w+i, r)
+ end
rnds << Marshal.load(Marshal.dump(rnds[-1]))
+ rnds2 << Marshal.load(Marshal.dump(rnds2[-1]))
end
end