Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 546 lines (476 sloc) 14.943 kb
817a62de » matz
2000-05-01 2000-05-01
1 /**********************************************************************
99d0354e » matz
1998-01-16 Initial revision
2
3 random.c -
4
5 $Author$
6 $Date$
7 created at: Fri Dec 24 16:39:21 JST 1993
8
42bc5d26 » michal
2003-01-16 Updated Copyrights of Matz to 2003.
9 Copyright (C) 1993-2003 Yukihiro Matsumoto
99d0354e » matz
1998-01-16 Initial revision
10
817a62de » matz
2000-05-01 2000-05-01
11 **********************************************************************/
99d0354e » matz
1998-01-16 Initial revision
12
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
13 /*
14 This is based on trimmed version of MT19937. To get the original version,
26a1bd70 » matz
2007-11-08 * random.c: update MT URL.[ruby-core:13305].
15 contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>.
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
16
17 The original copyright notice follows.
18
19 A C-program for MT19937, with initialization improved 2002/2/10.
20 Coded by Takuji Nishimura and Makoto Matsumoto.
21 This is a faster version by taking Shawn Cokus's optimization,
22 Matthe Bellew's simplification, Isaku Wada's real version.
23
24 Before using, initialize the state by using init_genrand(seed)
25 or init_by_array(init_key, key_length).
26
27 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
28 All rights reserved.
29
30 Redistribution and use in source and binary forms, with or without
31 modification, are permitted provided that the following conditions
32 are met:
33
34 1. Redistributions of source code must retain the above copyright
35 notice, this list of conditions and the following disclaimer.
36
37 2. Redistributions in binary form must reproduce the above copyright
38 notice, this list of conditions and the following disclaimer in the
39 documentation and/or other materials provided with the distribution.
40
41 3. The names of its contributors may not be used to endorse or promote
42 products derived from this software without specific prior written
43 permission.
44
45 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
49 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
57
58 Any feedback is very welcome.
59 http://www.math.keio.ac.jp/matumoto/emt.html
60 email: matumoto@math.keio.ac.jp
61 */
62
63 /* Period parameters */
64 #define N 624
65 #define M 397
66 #define MATRIX_A 0x9908b0dfUL /* constant vector a */
67 #define UMASK 0x80000000UL /* most significant w-r bits */
68 #define LMASK 0x7fffffffUL /* least significant r bits */
69 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
70 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
71
72 static unsigned long state[N]; /* the array for the state vector */
73 static int left = 1;
74 static int initf = 0;
75 static unsigned long *next;
76
77 /* initializes state[N] with a seed */
78 static void
79 init_genrand(s)
80 unsigned long s;
81 {
82 int j;
83 state[0]= s & 0xffffffffUL;
84 for (j=1; j<N; j++) {
85 state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
86 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
87 /* In the previous versions, MSBs of the seed affect */
88 /* only MSBs of the array state[]. */
89 /* 2002/01/09 modified by Makoto Matsumoto */
90 state[j] &= 0xffffffffUL; /* for >32 bit machines */
91 }
92 left = 1; initf = 1;
93 }
94
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
95 /* initialize by an array with array-length */
96 /* init_key is the array for initializing keys */
97 /* key_length is its length */
98 /* slight change for C++, 2004/2/26 */
99 static void
100 init_by_array(unsigned long init_key[], int key_length)
101 {
102 int i, j, k;
103 init_genrand(19650218UL);
104 i=1; j=0;
105 k = (N>key_length ? N : key_length);
106 for (; k; k--) {
107 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))
108 + init_key[j] + j; /* non linear */
109 state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
110 i++; j++;
111 if (i>=N) { state[0] = state[N-1]; i=1; }
112 if (j>=key_length) j=0;
113 }
114 for (k=N-1; k; k--) {
115 state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))
116 - i; /* non linear */
117 state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
118 i++;
119 if (i>=N) { state[0] = state[N-1]; i=1; }
120 }
121
122 state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
123 left = 1; initf = 1;
124 }
125
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
126 static void
127 next_state()
128 {
129 unsigned long *p=state;
130 int j;
131
132 /* if init_genrand() has not been called, */
133 /* a default initial seed is used */
134 if (initf==0) init_genrand(5489UL);
135
136 left = N;
137 next = state;
138
139 for (j=N-M+1; --j; p++)
140 *p = p[M] ^ TWIST(p[0], p[1]);
141
142 for (j=M; --j; p++)
143 *p = p[M-N] ^ TWIST(p[0], p[1]);
144
145 *p = p[M-N] ^ TWIST(p[0], state[0]);
146 }
147
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
148 /* generates a random number on [0,0xffffffff]-interval */
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
149 unsigned long
150 rb_genrand_int32(void)
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
151 {
152 unsigned long y;
153
154 if (--left == 0) next_state();
155 y = *next++;
156
157 /* Tempering */
158 y ^= (y >> 11);
159 y ^= (y << 7) & 0x9d2c5680UL;
160 y ^= (y << 15) & 0xefc60000UL;
161 y ^= (y >> 18);
162
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
163 return y;
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
164 }
165
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
166 /* generates a random number on [0,1) with 53-bit resolution*/
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
167 double
168 rb_genrand_real(void)
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
169 {
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
170 unsigned long a=rb_genrand_int32()>>5, b=rb_genrand_int32()>>6;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
171 return(a*67108864.0+b)*(1.0/9007199254740992.0);
172 }
173 /* These real versions are due to Isaku Wada, 2002/01/09 added */
174
af0adb13 » eban
2002-07-26 * random.c (N, M): undef for <winnt.h> on MinGW.
175 #undef N
176 #undef M
177
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
178 /* These real versions are due to Isaku Wada, 2002/01/09 added */
179
99d0354e » matz
1998-01-16 Initial revision
180 #include "ruby.h"
181
1f72ff9b » matz
1999-09-01 regexp literal (e.g. \202) match, etc.
182 #ifdef HAVE_UNISTD_H
183 #include <unistd.h>
184 #endif
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
185 #include <time.h>
49785c03 » akr
2005-01-03 * random.c (random_seed): use /dev/urandom if available.
186 #include <sys/types.h>
187 #include <sys/stat.h>
188 #ifdef HAVE_FCNTL_H
189 #include <fcntl.h>
190 #endif
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
191
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
192 static int seed_initialized = 0;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
193 static VALUE saved_seed = INT2FIX(0);
99d0354e » matz
1998-01-16 Initial revision
194
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
195 static VALUE
196 rand_init(vseed)
197 VALUE vseed;
ee08592d » matz
2000-01-08 2000-01-08
198 {
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
199 volatile VALUE seed;
200 VALUE old;
201 long len;
202 unsigned long *buf;
ee08592d » matz
2000-01-08 2000-01-08
203
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
204 seed = rb_to_int(vseed);
205 switch (TYPE(seed)) {
206 case T_FIXNUM:
207 len = sizeof(VALUE);
208 break;
209 case T_BIGNUM:
210 len = RBIGNUM(seed)->len * SIZEOF_BDIGITS;
211 if (len == 0)
212 len = 4;
213 break;
214 default:
215 rb_raise(rb_eTypeError, "failed to convert %s into Integer",
216 rb_obj_classname(vseed));
217 }
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
218 len = (len + 3) / 4; /* number of 32bit words */
12a3b06c » nobu
2005-02-12 * random.c (rand_init): suppress warning.
219 buf = ALLOC_N(unsigned long, len); /* allocate longs for init_by_array */
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
220 memset(buf, 0, len * sizeof(long));
221 if (FIXNUM_P(seed)) {
222 buf[0] = FIX2ULONG(seed) & 0xffffffff;
223 #if SIZEOF_LONG > 4
224 buf[1] = FIX2ULONG(seed) >> 32;
225 #endif
226 }
227 else {
228 int i, j;
229 for (i = RBIGNUM(seed)->len-1; 0 <= i; i--) {
230 j = i * SIZEOF_BDIGITS / 4;
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
231 #if SIZEOF_BDIGITS < 4
232 buf[j] <<= SIZEOF_BDIGITS * 8;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
233 #endif
234 buf[j] |= ((BDIGIT *)RBIGNUM(seed)->digits)[i];
235 }
236 }
237 while (1 < len && buf[len-1] == 0) {
238 len--;
239 }
240 if (len <= 1) {
241 init_genrand(buf[0]);
242 }
243 else {
244 if (buf[len-1] == 1) /* remove leading-zero-guard */
245 len--;
246 init_by_array(buf, len);
247 }
ee08592d » matz
2000-01-08 2000-01-08
248 old = saved_seed;
249 saved_seed = seed;
a529423c » akr
2005-01-07 * random.c (rand_init): use ALLOC_N instead of ALLOCA_N
250 free(buf);
ee08592d » matz
2000-01-08 2000-01-08
251 return old;
252 }
253
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
254 #define DEFAULT_SEED_LEN (4 * sizeof(long))
255
256 static void
257 fill_random_seed(ptr)
258 char *ptr;
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
259 {
260 static int n = 0;
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
261 unsigned long *seed;
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
262 struct timeval tv;
49785c03 » akr
2005-01-03 * random.c (random_seed): use /dev/urandom if available.
263 int fd;
a5392617 » akr
2005-01-03 * random.c (random_seed): don't use /dev/urandom if it is not charact…
264 struct stat statbuf;
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
265 char *buf = (char*)ptr;
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
266
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
267 seed = (unsigned long *)buf;
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
268
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
269 memset(buf, 0, DEFAULT_SEED_LEN);
49785c03 » akr
2005-01-03 * random.c (random_seed): use /dev/urandom if available.
270
a5392617 » akr
2005-01-03 * random.c (random_seed): don't use /dev/urandom if it is not charact…
271 #ifdef S_ISCHR
4f60fa31 » ocean
2005-01-06 * random.c (random_seed): O_NONBLOCK isn't defined on some
272 if ((fd = open("/dev/urandom", O_RDONLY
273 #ifdef O_NONBLOCK
274 |O_NONBLOCK
275 #endif
a5392617 » akr
2005-01-03 * random.c (random_seed): don't use /dev/urandom if it is not charact…
276 #ifdef O_NOCTTY
277 |O_NOCTTY
278 #endif
279 #ifdef O_NOFOLLOW
280 |O_NOFOLLOW
281 #endif
282 )) >= 0) {
283 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
284 read(fd, seed, DEFAULT_SEED_LEN);
a5392617 » akr
2005-01-03 * random.c (random_seed): don't use /dev/urandom if it is not charact…
285 }
49785c03 » akr
2005-01-03 * random.c (random_seed): use /dev/urandom if available.
286 close(fd);
287 }
a5392617 » akr
2005-01-03 * random.c (random_seed): don't use /dev/urandom if it is not charact…
288 #endif
49785c03 » akr
2005-01-03 * random.c (random_seed): use /dev/urandom if available.
289
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
290 gettimeofday(&tv, 0);
291 seed[0] ^= tv.tv_usec;
292 seed[1] ^= tv.tv_sec;
293 seed[2] ^= getpid() ^ (n++ << 16);
294 seed[3] ^= (unsigned long)&seed;
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
295 }
296
297 static VALUE
298 make_seed_value(char *ptr)
299 {
300 BDIGIT *digits;
301 NEWOBJ(big, struct RBignum);
302 OBJSETUP(big, rb_cBignum, T_BIGNUM);
303
304 RBIGNUM_SET_SIGN(big, 1);
305
306 digits = ALLOC_N(char, DEFAULT_SEED_LEN);
307 RBIGNUM(big)->digits = digits;
308 RBIGNUM(big)->len = DEFAULT_SEED_LEN / SIZEOF_BDIGITS;
309
310 MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
311
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
312 /* set leading-zero-guard if need. */
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
313 digits[RBIGNUM_LEN(big)-1] = digits[RBIGNUM_LEN(big)-2] <= 1 ? 1 : 0;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
314
315 return rb_big_norm((VALUE)big);
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
316 }
317
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
318 static VALUE
319 random_seed(void)
320 {
321 char buf[DEFAULT_SEED_LEN];
322 fill_random_seed(buf);
323 return make_seed_value(buf);
324 }
325
3e09bd3f » dave
2003-12-28 RDoc Struct and random
326 /*
327 * call-seq:
328 * srand(number=0) => old_seed
329 *
330 * Seeds the pseudorandom number generator to the value of
d002d25f » nahi
2007-07-11 # the previous commit should include random.c
331 * <i>number</i>.<code>to_i.abs</code>. If <i>number</i> is omitted,
332 * seeds the generator using a combination of the time, the
3e09bd3f » dave
2003-12-28 RDoc Struct and random
333 * process id, and a sequence number. (This is also the behavior if
334 * <code>Kernel::rand</code> is called without previously calling
335 * <code>srand</code>, but without the sequence.) By setting the seed
336 * to a known value, scripts can be made deterministic during testing.
337 * The previous seed value is returned. Also see <code>Kernel::rand</code>.
338 */
339
99d0354e » matz
1998-01-16 Initial revision
340 static VALUE
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
341 rb_f_srand(argc, argv, obj)
99d0354e » matz
1998-01-16 Initial revision
342 int argc;
343 VALUE *argv;
344 VALUE obj;
345 {
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
346 VALUE seed, old;
99d0354e » matz
1998-01-16 Initial revision
347
757a5f33 » matz
2000-11-14 matz
348 rb_secure(4);
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
349 if (rb_scan_args(argc, argv, "01", &seed) == 0) {
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
350 seed = random_seed();
99d0354e » matz
1998-01-16 Initial revision
351 }
ee08592d » matz
2000-01-08 2000-01-08
352 old = rand_init(seed);
99d0354e » matz
1998-01-16 Initial revision
353
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
354 return old;
355 }
356
357 static unsigned long
358 make_mask(unsigned long x)
359 {
360 x = x | x >> 1;
361 x = x | x >> 2;
362 x = x | x >> 4;
363 x = x | x >> 8;
364 x = x | x >> 16;
365 #if 4 < SIZEOF_LONG
366 x = x | x >> 32;
367 #endif
368 return x;
369 }
370
371 static unsigned long
372 limited_rand(unsigned long limit)
373 {
374 unsigned long mask = make_mask(limit);
375 int i;
376 unsigned long val;
377
378 retry:
379 val = 0;
380 for (i = SIZEOF_LONG/4-1; 0 <= i; i--) {
381 if (mask >> (i * 32)) {
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
382 val |= rb_genrand_int32() << (i * 32);
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
383 val &= mask;
384 if (limit < val)
385 goto retry;
386 }
387 }
388 return val;
389 }
390
391 static VALUE
392 limited_big_rand(struct RBignum *limit)
393 {
394 unsigned long mask, lim, rnd;
395 struct RBignum *val;
396 int i, len, boundary;
397
398 len = (limit->len * SIZEOF_BDIGITS + 3) / 4;
399 val = (struct RBignum *)rb_big_clone((VALUE)limit);
400 val->sign = 1;
401 #if SIZEOF_BDIGITS == 2
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
402 # define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[(i)*2] | \
403 ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] << 16) \
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
404 : 0))
3aa034b6 » akr
2005-01-05 * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
405 # define BIG_SET32(big,i,d) ((((BDIGIT *)(big)->digits)[(i)*2] = (d) & 0xffff), \
406 ((i)*2+1 < (big)->len ? (((BDIGIT *)(big)->digits)[(i)*2+1] = (d) >> 16) \
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
407 : 0))
408 #else
409 /* SIZEOF_BDIGITS == 4 */
410 # define BIG_GET32(big,i) (((BDIGIT *)(big)->digits)[i])
411 # define BIG_SET32(big,i,d) (((BDIGIT *)(big)->digits)[i] = (d))
412 #endif
413 retry:
414 mask = 0;
415 boundary = 1;
416 for (i = len-1; 0 <= i; i--) {
417 lim = BIG_GET32(limit, i);
418 mask = mask ? 0xffffffff : make_mask(lim);
419 if (mask) {
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
420 rnd = rb_genrand_int32() & mask;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
421 if (boundary) {
422 if (lim < rnd)
423 goto retry;
424 if (rnd < lim)
425 boundary = 0;
426 }
427 }
428 else {
429 rnd = 0;
430 }
431 BIG_SET32(val, i, rnd);
432 }
433 return rb_big_norm((VALUE)val);
99d0354e » matz
1998-01-16 Initial revision
434 }
435
3e09bd3f » dave
2003-12-28 RDoc Struct and random
436 /*
437 * call-seq:
438 * rand(max=0) => number
439 *
440 * Converts <i>max</i> to an integer using max1 =
441 * max<code>.to_i.abs</code>. If the result is zero, returns a
442 * pseudorandom floating point number greater than or equal to 0.0 and
443 * less than 1.0. Otherwise, returns a pseudorandom integer greater
444 * than or equal to zero and less than max1. <code>Kernel::srand</code>
445 * may be used to ensure repeatable sequences of random numbers between
446 * different runs of the program. Ruby currently uses a modified
b3251c5c » matz
2006-09-24 * random.c (rb_f_rand): RDoc typo fix. a patch from Frederick
447 * Mersenne Twister with a period of 2**19937-1.
3e09bd3f » dave
2003-12-28 RDoc Struct and random
448 *
449 * srand 1234 #=> 0
450 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
451 * [ rand(10), rand(1000) ] #=> [6, 817]
452 * srand 1234 #=> 1234
453 * [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
454 */
455
99d0354e » matz
1998-01-16 Initial revision
456 static VALUE
f0367359 » matz
2000-07-04 matz
457 rb_f_rand(argc, argv, obj)
458 int argc;
459 VALUE *argv;
460 VALUE obj;
99d0354e » matz
1998-01-16 Initial revision
461 {
f0367359 » matz
2000-07-04 matz
462 VALUE vmax;
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
463 long val, max;
99d0354e » matz
1998-01-16 Initial revision
464
f0367359 » matz
2000-07-04 matz
465 rb_scan_args(argc, argv, "01", &vmax);
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
466 if (!seed_initialized) {
467 rand_init(random_seed());
468 }
99d0354e » matz
1998-01-16 Initial revision
469 switch (TYPE(vmax)) {
470 case T_FLOAT:
3e6cc01c » matz
2000-11-02 matz
471 if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) {
472 max = (long)RFLOAT(vmax)->value;
bd5567f1 » matz
1999-12-06 19991206
473 break;
3e6cc01c » matz
2000-11-02 matz
474 }
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
475 if (RFLOAT(vmax)->value < 0)
476 vmax = rb_dbl2big(-RFLOAT(vmax)->value);
477 else
478 vmax = rb_dbl2big(RFLOAT(vmax)->value);
bd5567f1 » matz
1999-12-06 19991206
479 /* fall through */
134ded84 » matz
2003-01-31 * parse.y (yylex): remove EXPR_CMDARG according to the RHG book.
480 case T_BIGNUM:
481 bignum:
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
482 {
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
483 struct RBignum *limit = (struct RBignum *)vmax;
484 if (!limit->sign) {
485 limit = (struct RBignum *)rb_big_clone(vmax);
486 limit->sign = 1;
487 }
488 limit = (struct RBignum *)rb_big_minus((VALUE)limit, INT2FIX(1));
489 if (FIXNUM_P((VALUE)limit)) {
490 if (FIX2LONG((VALUE)limit) == -1)
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
491 return rb_float_new(rb_genrand_real());
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
492 return LONG2NUM(limited_rand(FIX2LONG((VALUE)limit)));
493 }
494 return limited_big_rand(limit);
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
495 }
f0367359 » matz
2000-07-04 matz
496 case T_NIL:
497 max = 0;
498 break;
499 default:
134ded84 » matz
2003-01-31 * parse.y (yylex): remove EXPR_CMDARG according to the RHG book.
500 vmax = rb_Integer(vmax);
35d0b982 » eban
2003-01-31 * random.c (rb_f_rand): type fix.
501 if (TYPE(vmax) == T_BIGNUM) goto bignum;
d002d25f » nahi
2007-07-11 # the previous commit should include random.c
502 /* fall through */
134ded84 » matz
2003-01-31 * parse.y (yylex): remove EXPR_CMDARG according to the RHG book.
503 case T_FIXNUM:
a6e49656 » matz
2004-03-15 * eval.c (rb_yield_0): should not re-submit TAG_BREAK if this
504 max = FIX2LONG(vmax);
f0367359 » matz
2000-07-04 matz
505 break;
99d0354e » matz
1998-01-16 Initial revision
506 }
507
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
508 if (max == 0) {
cbb46a58 » knu
2008-04-14 * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
509 return rb_float_new(rb_genrand_real());
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
510 }
c932081e » matz
2002-07-26 * random.c: replace with Mersenne Twister RNG.
511 if (max < 0) max = -max;
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
512 val = limited_rand(max-1);
8969c2a0 » matz
2002-04-25 * various files: macro fix-up by Michal Rokos.
513 return LONG2NUM(val);
99d0354e » matz
1998-01-16 Initial revision
514 }
515
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
516 static char initial_seed[DEFAULT_SEED_LEN];
517
99d0354e » matz
1998-01-16 Initial revision
518 void
17bff4ce » shyouhei
2011-05-23 merge revision(s) 31655:
519 rb_reset_random_seed()
99d0354e » matz
1998-01-16 Initial revision
520 {
ce500653 » shyouhei
2009-01-17 merge revision(s) 18509:
521 rand_init(random_seed());
17bff4ce » shyouhei
2011-05-23 merge revision(s) 31655:
522 }
523
524 void
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
525 Init_RandomSeed(void)
526 {
527 fill_random_seed(initial_seed);
528 init_by_array((unsigned long*)initial_seed, DEFAULT_SEED_LEN/sizeof(unsigned long));
529 seed_initialized = 1;
530 }
531
532 static void
533 Init_RandomSeed2(void)
534 {
535 saved_seed = make_seed_value(initial_seed);
536 memset(initial_seed, 0, DEFAULT_SEED_LEN);
537 }
538
539 void
17bff4ce » shyouhei
2011-05-23 merge revision(s) 31655:
540 Init_Random()
541 {
e05ee61e » shyouhei
2011-12-28 -This line, and those below, will be ignored--
542 Init_RandomSeed2();
a2af08da » matz
1999-01-20 This commit was generated by cvs2svn to compensate for changes in r372,
543 rb_define_global_function("srand", rb_f_srand, -1);
f0367359 » matz
2000-07-04 matz
544 rb_define_global_function("rand", rb_f_rand, -1);
9395191d » akr
2005-01-04 * random.c (init_by_array): imported from mt19937ar-cok.tgz.
545 rb_global_variable(&saved_seed);
99d0354e » matz
1998-01-16 Initial revision
546 }
Something went wrong with that request. Please try again.