mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	random.c: rand_random_number
* random.c (rand_random_number): add a method to return a random number like SecureRandom to Random::Formatter. * lib/securerandom.rb (random_bytes): move to Random::Formatter, the base method of the module. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									1f13a179d3
								
							
						
					
					
						commit
						b1adbd14e5
					
				
					 3 changed files with 170 additions and 70 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,11 @@
 | 
			
		|||
Sat Feb 14 12:20:01 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* random.c (rand_random_number): add a method to return a random
 | 
			
		||||
	  number like SecureRandom to Random::Formatter.
 | 
			
		||||
 | 
			
		||||
	* lib/securerandom.rb (random_bytes): move to Random::Formatter,
 | 
			
		||||
	  the base method of the module.
 | 
			
		||||
 | 
			
		||||
Sat Feb 14 12:01:32 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* random.c (random_raw_seed): extract platform dependent random
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,26 +47,6 @@ end
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
module SecureRandom
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.random_bytes generates a random binary string.
 | 
			
		||||
  #
 | 
			
		||||
  # The argument _n_ specifies the length of the result string.
 | 
			
		||||
  #
 | 
			
		||||
  # If _n_ is not specified or is nil, 16 is assumed.
 | 
			
		||||
  # It may be larger in future.
 | 
			
		||||
  #
 | 
			
		||||
  # The result may contain any byte: "\x00" - "\xff".
 | 
			
		||||
  #
 | 
			
		||||
  #   p SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
 | 
			
		||||
  #   p SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
 | 
			
		||||
  #
 | 
			
		||||
  # If a secure random number generator is not available,
 | 
			
		||||
  # +NotImplementedError+ is raised.
 | 
			
		||||
  def self.random_bytes(n=nil)
 | 
			
		||||
    n = n ? n.to_int : 16
 | 
			
		||||
    gen_random(n)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  if defined? OpenSSL::Random
 | 
			
		||||
    def self.gen_random(n)
 | 
			
		||||
      @pid = 0 unless defined?(@pid)
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +74,26 @@ module SecureRandom
 | 
			
		|||
end
 | 
			
		||||
 | 
			
		||||
module Random::Formatter
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.random_bytes generates a random binary string.
 | 
			
		||||
  #
 | 
			
		||||
  # The argument _n_ specifies the length of the result string.
 | 
			
		||||
  #
 | 
			
		||||
  # If _n_ is not specified or is nil, 16 is assumed.
 | 
			
		||||
  # It may be larger in future.
 | 
			
		||||
  #
 | 
			
		||||
  # The result may contain any byte: "\x00" - "\xff".
 | 
			
		||||
  #
 | 
			
		||||
  #   p SecureRandom.random_bytes #=> "\xD8\\\xE0\xF4\r\xB2\xFC*WM\xFF\x83\x18\xF45\xB6"
 | 
			
		||||
  #   p SecureRandom.random_bytes #=> "m\xDC\xFC/\a\x00Uf\xB2\xB2P\xBD\xFF6S\x97"
 | 
			
		||||
  #
 | 
			
		||||
  # If a secure random number generator is not available,
 | 
			
		||||
  # +NotImplementedError+ is raised.
 | 
			
		||||
  def random_bytes(n=nil)
 | 
			
		||||
    n = n ? n.to_int : 16
 | 
			
		||||
    gen_random(n)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.hex generates a random hexadecimal string.
 | 
			
		||||
  #
 | 
			
		||||
  # The argument _n_ specifies the length, in bytes, of the random number to be generated.
 | 
			
		||||
| 
						 | 
				
			
			@ -168,6 +168,7 @@ module Random::Formatter
 | 
			
		|||
    s
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
=begin
 | 
			
		||||
  # SecureRandom.random_number generates a random number.
 | 
			
		||||
  #
 | 
			
		||||
  # If a positive integer is given as _n_,
 | 
			
		||||
| 
						 | 
				
			
			@ -212,6 +213,7 @@ module Random::Formatter
 | 
			
		|||
      Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
=end
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.uuid generates a random v4 UUID (Universally Unique IDentifier).
 | 
			
		||||
  #
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +232,11 @@ module Random::Formatter
 | 
			
		|||
    ary[3] = (ary[3] & 0x3fff) | 0x8000
 | 
			
		||||
    "%08x-%04x-%04x-%04x-%04x%08x" % ary
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
  def gen_random(n)
 | 
			
		||||
    self.bytes(n)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
SecureRandom.extend(Random::Formatter)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										185
									
								
								random.c
									
										
									
									
									
								
							
							
						
						
									
										185
									
								
								random.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -196,16 +196,26 @@ genrand_int32(struct MT *mt)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* generates a random number on [0,1) with 53-bit resolution*/
 | 
			
		||||
static double int_pair_to_real_exclusive(uint32_t a, uint32_t b);
 | 
			
		||||
static double
 | 
			
		||||
genrand_real(struct MT *mt)
 | 
			
		||||
{
 | 
			
		||||
    /* mt must be initialized */
 | 
			
		||||
    unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
 | 
			
		||||
    unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
 | 
			
		||||
    return int_pair_to_real_exclusive(a, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double
 | 
			
		||||
int_pair_to_real_exclusive(uint32_t a, uint32_t b)
 | 
			
		||||
{
 | 
			
		||||
    a >>= 5;
 | 
			
		||||
    b >>= 6;
 | 
			
		||||
    return(a*67108864.0+b)*(1.0/9007199254740992.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generates a random number on [0,1] with 53-bit resolution*/
 | 
			
		||||
static double int_pair_to_real_inclusive(uint32_t a, uint32_t b);
 | 
			
		||||
#if 0
 | 
			
		||||
static double
 | 
			
		||||
genrand_real2(struct MT *mt)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +223,7 @@ genrand_real2(struct MT *mt)
 | 
			
		|||
    uint32_t a = genrand_int32(mt), b = genrand_int32(mt);
 | 
			
		||||
    return int_pair_to_real_inclusive(a, b);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* These real versions are due to Isaku Wada, 2002/01/09 added */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -839,10 +850,9 @@ rb_genrand_ulong_limited(unsigned long limit)
 | 
			
		|||
    return limited_rand(default_mt(), limit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int
 | 
			
		||||
rb_random_int32(VALUE obj)
 | 
			
		||||
static unsigned int
 | 
			
		||||
random_int32(VALUE obj, rb_random_t *rnd)
 | 
			
		||||
{
 | 
			
		||||
    rb_random_t *rnd = try_get_rnd(obj);
 | 
			
		||||
    if (!rnd) {
 | 
			
		||||
#if SIZEOF_LONG * CHAR_BIT > 32
 | 
			
		||||
	VALUE lim = ULONG2NUM(0x100000000UL);
 | 
			
		||||
| 
						 | 
				
			
			@ -856,6 +866,25 @@ rb_random_int32(VALUE obj)
 | 
			
		|||
    return genrand_int32(&rnd->mt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int
 | 
			
		||||
rb_random_int32(VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    return random_int32(obj, try_get_rnd(obj));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double
 | 
			
		||||
random_real(VALUE obj, rb_random_t *rnd, int excl)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t a = random_int32(obj, rnd);
 | 
			
		||||
    uint32_t b = random_int32(obj, rnd);
 | 
			
		||||
    if (excl) {
 | 
			
		||||
	return int_pair_to_real_exclusive(a, b);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	return int_pair_to_real_inclusive(a, b);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double
 | 
			
		||||
rb_random_real(VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -887,10 +916,9 @@ ulong_to_num_plus_1(unsigned long n)
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long
 | 
			
		||||
rb_random_ulong_limited(VALUE obj, unsigned long limit)
 | 
			
		||||
static unsigned long
 | 
			
		||||
random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
 | 
			
		||||
{
 | 
			
		||||
    rb_random_t *rnd = try_get_rnd(obj);
 | 
			
		||||
    if (!rnd) {
 | 
			
		||||
	extern int rb_num_negative_p(VALUE);
 | 
			
		||||
	VALUE lim = ulong_to_num_plus_1(limit);
 | 
			
		||||
| 
						 | 
				
			
			@ -907,6 +935,32 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
 | 
			
		|||
    return limited_rand(&rnd->mt, limit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
 | 
			
		||||
{
 | 
			
		||||
    if (!rnd) {
 | 
			
		||||
	extern int rb_num_negative_p(VALUE);
 | 
			
		||||
	VALUE lim = rb_big_plus(vmax, INT2FIX(1));
 | 
			
		||||
	VALUE v = rb_to_int(rb_funcall2(obj, id_rand, 1, &lim));
 | 
			
		||||
	if (rb_num_negative_p(v)) {
 | 
			
		||||
	    rb_raise(rb_eRangeError, "random number too small %"PRIsVALUE, v);
 | 
			
		||||
	}
 | 
			
		||||
	if (FIX2LONG(rb_big_cmp(vmax, v)) < 0) {
 | 
			
		||||
	    rb_raise(rb_eRangeError, "random number too big %"PRIsVALUE, v);
 | 
			
		||||
	}
 | 
			
		||||
	return v;
 | 
			
		||||
    }
 | 
			
		||||
    return limited_big_rand(&rnd->mt, vmax);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned long
 | 
			
		||||
rb_random_ulong_limited(VALUE obj, unsigned long limit)
 | 
			
		||||
{
 | 
			
		||||
    return random_ulong_limited(obj, try_get_rnd(obj), limit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE genrand_bytes(rb_random_t *rnd, long n);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq: prng.bytes(size) -> a_string
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -918,21 +972,16 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
 | 
			
		|||
static VALUE
 | 
			
		||||
random_bytes(VALUE obj, VALUE len)
 | 
			
		||||
{
 | 
			
		||||
    return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
 | 
			
		||||
    return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
rb_random_bytes(VALUE obj, long n)
 | 
			
		||||
static VALUE
 | 
			
		||||
genrand_bytes(rb_random_t *rnd, long n)
 | 
			
		||||
{
 | 
			
		||||
    rb_random_t *rnd = try_get_rnd(obj);
 | 
			
		||||
    VALUE bytes;
 | 
			
		||||
    char *ptr;
 | 
			
		||||
    unsigned int r, i;
 | 
			
		||||
 | 
			
		||||
    if (!rnd) {
 | 
			
		||||
	VALUE len = LONG2NUM(n);
 | 
			
		||||
	return rb_funcall2(obj, id_bytes, 1, &len);
 | 
			
		||||
    }
 | 
			
		||||
    bytes = rb_str_new(0, n);
 | 
			
		||||
    ptr = RSTRING_PTR(bytes);
 | 
			
		||||
    for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
 | 
			
		||||
| 
						 | 
				
			
			@ -953,6 +1002,17 @@ rb_random_bytes(VALUE obj, long n)
 | 
			
		|||
    return bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
rb_random_bytes(VALUE obj, long n)
 | 
			
		||||
{
 | 
			
		||||
    rb_random_t *rnd = try_get_rnd(obj);
 | 
			
		||||
    if (!rnd) {
 | 
			
		||||
	VALUE len = LONG2NUM(n);
 | 
			
		||||
	return rb_funcall2(obj, id_bytes, 1, &len);
 | 
			
		||||
    }
 | 
			
		||||
    return genrand_bytes(rnd, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -967,20 +1027,19 @@ range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
rand_int(struct MT *mt, VALUE vmax, int restrictive)
 | 
			
		||||
rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
 | 
			
		||||
{
 | 
			
		||||
    /* mt must be initialized */
 | 
			
		||||
    long max;
 | 
			
		||||
    unsigned long r;
 | 
			
		||||
 | 
			
		||||
    if (FIXNUM_P(vmax)) {
 | 
			
		||||
	max = FIX2LONG(vmax);
 | 
			
		||||
	long max = FIX2LONG(vmax);
 | 
			
		||||
	if (!max) return Qnil;
 | 
			
		||||
	if (max < 0) {
 | 
			
		||||
	    if (restrictive) return Qnil;
 | 
			
		||||
	    max = -max;
 | 
			
		||||
	}
 | 
			
		||||
	r = limited_rand(mt, (unsigned long)max - 1);
 | 
			
		||||
	r = random_ulong_limited(obj, rnd, (unsigned long)max - 1);
 | 
			
		||||
	return ULONG2NUM(r);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
| 
						 | 
				
			
			@ -992,30 +1051,37 @@ rand_int(struct MT *mt, VALUE vmax, int restrictive)
 | 
			
		|||
	}
 | 
			
		||||
	vmax = rb_big_minus(vmax, INT2FIX(1));
 | 
			
		||||
	if (FIXNUM_P(vmax)) {
 | 
			
		||||
	    max = FIX2LONG(vmax);
 | 
			
		||||
	    long max = FIX2LONG(vmax);
 | 
			
		||||
	    if (max == -1) return Qnil;
 | 
			
		||||
	    r = limited_rand(mt, max);
 | 
			
		||||
	    r = random_ulong_limited(obj, rnd, max);
 | 
			
		||||
	    return LONG2NUM(r);
 | 
			
		||||
	}
 | 
			
		||||
	ret = limited_big_rand(mt, vmax);
 | 
			
		||||
	ret = random_ulong_limited_big(obj, rnd, vmax);
 | 
			
		||||
	RB_GC_GUARD(vmax);
 | 
			
		||||
	return ret;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NORETURN(static void domain_error(void));
 | 
			
		||||
static void
 | 
			
		||||
domain_error(void)
 | 
			
		||||
{
 | 
			
		||||
    VALUE error = INT2FIX(EDOM);
 | 
			
		||||
    rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline double
 | 
			
		||||
float_value(VALUE v)
 | 
			
		||||
{
 | 
			
		||||
    double x = RFLOAT_VALUE(v);
 | 
			
		||||
    if (isinf(x) || isnan(x)) {
 | 
			
		||||
	VALUE error = INT2FIX(EDOM);
 | 
			
		||||
	rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
 | 
			
		||||
	domain_error();
 | 
			
		||||
    }
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
rand_range(struct MT* mt, VALUE range)
 | 
			
		||||
rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
 | 
			
		||||
{
 | 
			
		||||
    VALUE beg = Qundef, end = Qundef, vmax, v;
 | 
			
		||||
    int excl = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1029,7 +1095,7 @@ rand_range(struct MT* mt, VALUE range)
 | 
			
		|||
	if (FIXNUM_P(vmax)) {
 | 
			
		||||
	  fixnum:
 | 
			
		||||
	    if ((max = FIX2LONG(vmax) - excl) >= 0) {
 | 
			
		||||
		unsigned long r = limited_rand(mt, (unsigned long)max);
 | 
			
		||||
		unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
 | 
			
		||||
		v = ULONG2NUM(r);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1039,7 +1105,7 @@ rand_range(struct MT* mt, VALUE range)
 | 
			
		|||
		excl = 0;
 | 
			
		||||
		goto fixnum;
 | 
			
		||||
	    }
 | 
			
		||||
	    v = limited_big_rand(mt, vmax);
 | 
			
		||||
	    v = random_ulong_limited_big(obj, rnd, vmax);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1052,17 +1118,12 @@ rand_range(struct MT* mt, VALUE range)
 | 
			
		|||
	    mid = max + min;
 | 
			
		||||
	    max -= min;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    float_value(v);
 | 
			
		||||
	else if (isnan(max)) {
 | 
			
		||||
	    domain_error();
 | 
			
		||||
	}
 | 
			
		||||
	v = Qnil;
 | 
			
		||||
	if (max > 0.0) {
 | 
			
		||||
	    if (excl) {
 | 
			
		||||
		r = genrand_real(mt);
 | 
			
		||||
	    }
 | 
			
		||||
	    else {
 | 
			
		||||
		r = genrand_real2(mt);
 | 
			
		||||
	    }
 | 
			
		||||
	    r = random_real(obj, rnd, excl);
 | 
			
		||||
	    if (scale > 1) {
 | 
			
		||||
		return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
 | 
			
		||||
	    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1095,7 +1156,7 @@ rand_range(struct MT* mt, VALUE range)
 | 
			
		|||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE rand_random(int argc, VALUE *argv, rb_random_t *rnd);
 | 
			
		||||
static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq:
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,16 +1190,17 @@ static VALUE rand_random(int argc, VALUE *argv, rb_random_t *rnd);
 | 
			
		|||
static VALUE
 | 
			
		||||
random_rand(int argc, VALUE *argv, VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    return rand_random(argc, argv, get_rnd(obj));
 | 
			
		||||
    return rand_random(argc, argv, obj, get_rnd(obj));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
rand_random(int argc, VALUE *argv, rb_random_t *rnd)
 | 
			
		||||
rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
 | 
			
		||||
{
 | 
			
		||||
    VALUE vmax, v;
 | 
			
		||||
    double max = 0.0;
 | 
			
		||||
 | 
			
		||||
    if (argc == 0) {
 | 
			
		||||
	return rb_float_new(genrand_real(&rnd->mt));
 | 
			
		||||
	goto float_rand;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	rb_check_arity(argc, 0, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,16 +1210,26 @@ rand_random(int argc, VALUE *argv, rb_random_t *rnd)
 | 
			
		|||
	v = Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
 | 
			
		||||
	v = rand_int(&rnd->mt, v, 1);
 | 
			
		||||
	v = rand_int(obj, rnd, 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));
 | 
			
		||||
	else
 | 
			
		||||
	max = float_value(v);
 | 
			
		||||
	if (max < 0.0) {
 | 
			
		||||
	    v = Qnil;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    uint32_t a, b;
 | 
			
		||||
	    double r;
 | 
			
		||||
 | 
			
		||||
	  float_rand:
 | 
			
		||||
	    a = random_int32(obj, rnd);
 | 
			
		||||
	    b = random_int32(obj, rnd);
 | 
			
		||||
	    r = int_pair_to_real_exclusive(a, b);
 | 
			
		||||
	    if (max > 0.0) r *= max;;
 | 
			
		||||
	    v = rb_float_new(r);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
 | 
			
		||||
    else if ((v = rand_range(obj, rnd, vmax)) != Qfalse) {
 | 
			
		||||
	/* nothing to do */
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1171,6 +1243,13 @@ rand_random(int argc, VALUE *argv, rb_random_t *rnd)
 | 
			
		|||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
rand_random_number(int argc, VALUE *argv, VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    if (argc == 1 && argv[0] == INT2FIX(0)) --argc;
 | 
			
		||||
    return rand_random(argc, argv, obj, try_get_rnd(obj));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * call-seq:
 | 
			
		||||
 *   prng1 == prng2 -> true or false
 | 
			
		||||
| 
						 | 
				
			
			@ -1244,18 +1323,18 @@ static VALUE
 | 
			
		|||
rb_f_rand(int argc, VALUE *argv, VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    VALUE v, vmax, r;
 | 
			
		||||
    struct MT *mt = default_mt();
 | 
			
		||||
    rb_random_t *rnd = rand_start(&default_rand);
 | 
			
		||||
 | 
			
		||||
    if (argc == 0) goto zero_arg;
 | 
			
		||||
    rb_scan_args(argc, argv, "01", &vmax);
 | 
			
		||||
    if (NIL_P(vmax)) goto zero_arg;
 | 
			
		||||
    if ((v = rand_range(mt, vmax)) != Qfalse) {
 | 
			
		||||
    if ((v = rand_range(Qnil, rnd, vmax)) != Qfalse) {
 | 
			
		||||
	return v;
 | 
			
		||||
    }
 | 
			
		||||
    vmax = rb_to_int(vmax);
 | 
			
		||||
    if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
 | 
			
		||||
    if (vmax == INT2FIX(0) || NIL_P(r = rand_int(Qnil, rnd, vmax, 0))) {
 | 
			
		||||
      zero_arg:
 | 
			
		||||
	return DBL2NUM(genrand_real(mt));
 | 
			
		||||
	return DBL2NUM(genrand_real(&rnd->mt));
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1271,7 +1350,7 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
 | 
			
		|||
static VALUE
 | 
			
		||||
random_s_rand(int argc, VALUE *argv, VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    return rand_random(argc, argv, rand_start(&default_rand));
 | 
			
		||||
    return rand_random(argc, argv, Qnil, rand_start(&default_rand));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SIP_HASH_STREAMING 0
 | 
			
		||||
| 
						 | 
				
			
			@ -1430,6 +1509,12 @@ InitVM_Random(void)
 | 
			
		|||
    rb_define_singleton_method(rb_cRandom, "raw_seed", random_raw_seed, 1);
 | 
			
		||||
    rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
 | 
			
		||||
    rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
	VALUE m = rb_define_module_under(rb_cRandom, "Formatter");
 | 
			
		||||
	rb_include_module(rb_cRandom, m);
 | 
			
		||||
	rb_define_method(m, "random_number", rand_random_number, -1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef rb_intern
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue