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

154 lines
2.7 KiB
C
Raw Normal View History

/************************************************
random.c -
$Author$
$Date$
created at: Fri Dec 24 16:39:21 JST 1993
Copyright (C) 1993-1999 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 */
#ifdef HAVE_RANDOM
static int first = 1;
static char state[256];
#endif
static VALUE
rb_f_srand(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
VALUE seed;
int old;
static int saved_seed;
if (rb_scan_args(argc, argv, "01", &seed) == 0) {
static int n = 0;
struct timeval tv;
gettimeofday(&tv, 0);
seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
}
else {
seed = NUM2UINT(seed);
}
#ifdef HAVE_RANDOM
if (first == 1) {
initstate(1, state, sizeof state);
first = 0;
}
else {
setstate(state);
}
#endif
SRANDOM(seed);
old = saved_seed;
saved_seed = seed;
return rb_int2inum(old);
}
static VALUE
rb_f_rand(obj, vmax)
VALUE obj, vmax;
{
long val, max;
switch (TYPE(vmax)) {
case T_BIGNUM:
return rb_big_rand(vmax);
case T_FLOAT:
if (RFLOAT(vmax)->value > LONG_MAX || RFLOAT(vmax)->value < LONG_MIN)
return rb_big_rand(rb_dbl2big(RFLOAT(vmax)->value));
break;
}
max = NUM2LONG(vmax);
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);
}