mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1039 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			181 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**********************************************************************
 | 
						|
 | 
						|
  random.c -
 | 
						|
 | 
						|
  $Author$
 | 
						|
  $Date$
 | 
						|
  created at: Fri Dec 24 16:39:21 JST 1993
 | 
						|
 | 
						|
  Copyright (C) 1993-2000 Yukihiro Matsumoto
 | 
						|
 | 
						|
**********************************************************************/
 | 
						|
 | 
						|
#include "ruby.h"
 | 
						|
 | 
						|
#ifdef HAVE_UNISTD_H
 | 
						|
#include <unistd.h>
 | 
						|
#endif
 | 
						|
#include <time.h>
 | 
						|
#ifndef NT
 | 
						|
#ifdef HAVE_SYS_TIME_H
 | 
						|
# include <sys/time.h>
 | 
						|
#else
 | 
						|
struct timeval {
 | 
						|
        long    tv_sec;         /* seconds */
 | 
						|
        long    tv_usec;        /* and microseconds */
 | 
						|
};
 | 
						|
#endif
 | 
						|
#endif /* NT */
 | 
						|
 | 
						|
#ifdef HAVE_STDLIB_H
 | 
						|
# include <stdlib.h>
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Prefer to use drand48, otherwise use random, or rand as a last resort.
 | 
						|
 */
 | 
						|
#ifdef HAVE_DRAND48
 | 
						|
 | 
						|
#ifndef HAVE_DRAND48_DECL
 | 
						|
double drand48 _((void));
 | 
						|
void srand48 _((long));
 | 
						|
#endif
 | 
						|
 | 
						|
#define SRANDOM(s)	srand48((long)(s))
 | 
						|
#define RANDOM_NUMBER	drand48()
 | 
						|
 | 
						|
#else /* not HAVE_DRAND48 */
 | 
						|
 | 
						|
/*
 | 
						|
 * The largest number returned by the random number generator is
 | 
						|
 * RANDOM_MAX.  If we're using `rand' it's RAND_MAX, but if we're
 | 
						|
 * using `random' it's 2^31-1.
 | 
						|
 */
 | 
						|
#ifndef RANDOM_MAX
 | 
						|
# ifndef HAVE_RANDOM
 | 
						|
#  define RANDOM_MAX	RAND_MAX
 | 
						|
# else
 | 
						|
#  define RANDOM_MAX	2147483647.0
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef HAVE_RANDOM
 | 
						|
 | 
						|
#define RANDOM	random
 | 
						|
#define SRANDOM	srandom
 | 
						|
 | 
						|
#else /* HAVE_RANDOM */
 | 
						|
 | 
						|
#define RANDOM	rand
 | 
						|
#define SRANDOM	srand
 | 
						|
 | 
						|
#endif /* HAVE_RANDOM */
 | 
						|
 | 
						|
/* 0 <= RANDOM_NUMBER < 1 */
 | 
						|
#define RANDOM_NUMBER (((double)RANDOM())/((double)RANDOM_MAX+1))
 | 
						|
 | 
						|
#endif /* not HAVE_DRAND48 */
 | 
						|
 | 
						|
static int first = 1;
 | 
						|
#ifdef HAVE_RANDOM
 | 
						|
static char state[256];
 | 
						|
#endif
 | 
						|
 | 
						|
static int
 | 
						|
rand_init(seed)
 | 
						|
    long seed;
 | 
						|
{
 | 
						|
    int old;
 | 
						|
    static unsigned int saved_seed;
 | 
						|
 | 
						|
#ifdef HAVE_RANDOM
 | 
						|
    if (first == 1) {
 | 
						|
	initstate(1, state, sizeof state);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	setstate(state);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    first = 0;
 | 
						|
 | 
						|
    SRANDOM(seed);
 | 
						|
    old = saved_seed;
 | 
						|
    saved_seed = seed;
 | 
						|
 | 
						|
    return old;
 | 
						|
}
 | 
						|
 | 
						|
static VALUE
 | 
						|
rb_f_srand(argc, argv, obj)
 | 
						|
    int argc;
 | 
						|
    VALUE *argv;
 | 
						|
    VALUE obj;
 | 
						|
{
 | 
						|
    VALUE a;
 | 
						|
    unsigned int seed, old;
 | 
						|
 | 
						|
    rb_secure(4);
 | 
						|
    if (rb_scan_args(argc, argv, "01", &a) == 0) {
 | 
						|
	static int n = 0;
 | 
						|
	struct timeval tv;
 | 
						|
 | 
						|
	gettimeofday(&tv, 0);
 | 
						|
	seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	seed = NUM2UINT(a);
 | 
						|
    }
 | 
						|
    old = rand_init(seed);
 | 
						|
 | 
						|
    return rb_uint2inum(old);
 | 
						|
}
 | 
						|
 | 
						|
static VALUE
 | 
						|
rb_f_rand(argc, argv, obj)
 | 
						|
    int argc;
 | 
						|
    VALUE *argv;
 | 
						|
    VALUE obj;
 | 
						|
{
 | 
						|
    VALUE vmax;
 | 
						|
    long val, max;
 | 
						|
 | 
						|
    rb_scan_args(argc, argv, "01", &vmax);
 | 
						|
    if (first) {
 | 
						|
	struct timeval tv;
 | 
						|
 | 
						|
	gettimeofday(&tv, 0);
 | 
						|
	rand_init(tv.tv_sec ^ tv.tv_usec ^ getpid());
 | 
						|
    }
 | 
						|
    switch (TYPE(vmax)) {
 | 
						|
      case T_FLOAT:
 | 
						|
	if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) {
 | 
						|
	    max = (long)RFLOAT(vmax)->value;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	vmax = rb_dbl2big(RFLOAT(vmax)->value);
 | 
						|
	/* fall through */
 | 
						|
      case T_BIGNUM:
 | 
						|
	return rb_big_rand(vmax, RANDOM_NUMBER);
 | 
						|
      case T_NIL:
 | 
						|
	max = 0;
 | 
						|
	break;
 | 
						|
      default:
 | 
						|
	max = NUM2LONG(vmax);
 | 
						|
	break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (max == 0) {
 | 
						|
	return rb_float_new(RANDOM_NUMBER);
 | 
						|
    }
 | 
						|
    val = max*RANDOM_NUMBER;
 | 
						|
 | 
						|
    if (val < 0) val = -val;
 | 
						|
    return rb_int2inum(val);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
Init_Random()
 | 
						|
{
 | 
						|
    rb_define_global_function("srand", rb_f_srand, -1);
 | 
						|
    rb_define_global_function("rand", rb_f_rand, -1);
 | 
						|
}
 |