1998-01-16 07:13:05 -05:00
|
|
|
/************************************************
|
|
|
|
|
|
|
|
random.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
$Date$
|
|
|
|
created at: Fri Dec 24 16:39:21 JST 1993
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
Copyright (C) 1993-1999 Yukihiro Matsumoto
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
************************************************/
|
|
|
|
|
|
|
|
#include "ruby.h"
|
|
|
|
|
1999-09-01 05:48:03 -04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
1999-01-19 23:59:39 -05:00
|
|
|
#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 */
|
1999-08-13 01:45:20 -04:00
|
|
|
#define RANDOM_NUMBER (((double)RANDOM())/((double)RANDOM_MAX+1))
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
#endif /* not HAVE_DRAND48 */
|
|
|
|
|
|
|
|
#ifdef HAVE_RANDOM
|
1998-01-16 07:13:05 -05:00
|
|
|
static int first = 1;
|
|
|
|
static char state[256];
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
static VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_f_srand(argc, argv, obj)
|
1998-01-16 07:13:05 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE seed;
|
|
|
|
int old;
|
1998-01-16 07:13:05 -05:00
|
|
|
static int saved_seed;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &seed) == 0) {
|
1999-09-16 05:40:33 -04:00
|
|
|
static int n = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
gettimeofday(&tv, 0);
|
1999-09-16 05:40:33 -04:00
|
|
|
seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
seed = NUM2UINT(seed);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_RANDOM
|
|
|
|
if (first == 1) {
|
|
|
|
initstate(1, state, sizeof state);
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setstate(state);
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
SRANDOM(seed);
|
1998-01-16 07:13:05 -05:00
|
|
|
old = saved_seed;
|
|
|
|
saved_seed = seed;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
return rb_int2inum(old);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_f_rand(obj, vmax)
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE obj, vmax;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
long val, max;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
switch (TYPE(vmax)) {
|
|
|
|
case T_BIGNUM:
|
1999-01-19 23:59:39 -05:00
|
|
|
return rb_big_rand(vmax);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case T_FLOAT:
|
|
|
|
if (RFLOAT(vmax)->value > LONG_MAX || RFLOAT(vmax)->value < LONG_MIN)
|
1999-01-19 23:59:39 -05:00
|
|
|
return rb_big_rand(rb_dbl2big(RFLOAT(vmax)->value));
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
max = NUM2LONG(vmax);
|
|
|
|
if (max == 0) {
|
|
|
|
return rb_float_new(RANDOM_NUMBER);
|
|
|
|
}
|
|
|
|
val = max*RANDOM_NUMBER;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
if (val < 0) val = -val;
|
1999-01-19 23:59:39 -05:00
|
|
|
return rb_int2inum(val);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Init_Random()
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_global_function("srand", rb_f_srand, -1);
|
|
|
|
rb_define_global_function("rand", rb_f_rand, 1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|