Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1427 lines (1285 sloc) 36.088 kb
fedf489 2000-05-01
matz authored
1 /**********************************************************************
3db12e8 Initial revision
matz authored
2
3 random.c -
4
5 $Author$
6 created at: Fri Dec 24 16:39:21 JST 1993
7
a25fbe3 * encoding.c: provide basic features for M17N.
matz authored
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
3db12e8 Initial revision
matz authored
9
fedf489 2000-05-01
matz authored
10 **********************************************************************/
3db12e8 Initial revision
matz authored
11
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
12 /*
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
13 This is based on trimmed version of MT19937. To get the original version,
9099eab * random.c: update MT URL.[ruby-core:13305].
matz authored
14 contact <http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html>.
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
15
16 The original copyright notice follows.
17
18 A C-program for MT19937, with initialization improved 2002/2/10.
19 Coded by Takuji Nishimura and Makoto Matsumoto.
20 This is a faster version by taking Shawn Cokus's optimization,
21 Matthe Bellew's simplification, Isaku Wada's real version.
22
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
23 Before using, initialize the state by using init_genrand(mt, seed)
24 or init_by_array(mt, init_key, key_length).
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
25
26 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
27 All rights reserved.
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
28
29 Redistribution and use in source and binary forms, with or without
30 modification, are permitted provided that the following conditions
31 are met:
32
33 1. Redistributions of source code must retain the above copyright
34 notice, this list of conditions and the following disclaimer.
35
36 2. Redistributions in binary form must reproduce the above copyright
37 notice, this list of conditions and the following disclaimer in the
38 documentation and/or other materials provided with the distribution.
39
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
40 3. The names of its contributors may not be used to endorse or promote
41 products derived from this software without specific prior written
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
42 permission.
43
44 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
47 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
48 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
49 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
50 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
52 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
53 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
54 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55
56
57 Any feedback is very welcome.
58 http://www.math.keio.ac.jp/matumoto/emt.html
59 email: matumoto@math.keio.ac.jp
60 */
61
46a4000 NARUSE, Yui * random.c: change include order; ruby.h should be at first.
nurse authored
62 #include "ruby/ruby.h"
63
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
64 #include <limits.h>
46a4000 NARUSE, Yui * random.c: change include order; ruby.h should be at first.
nurse authored
65 #ifdef HAVE_UNISTD_H
66 #include <unistd.h>
67 #endif
68 #include <time.h>
69 #include <sys/types.h>
70 #include <sys/stat.h>
71 #ifdef HAVE_FCNTL_H
72 #include <fcntl.h>
73 #endif
74 #include <math.h>
75 #include <errno.h>
76
77 #ifdef _WIN32
78 # if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0400
79 # undef _WIN32_WINNT
80 # define _WIN32_WINNT 0x400
81 # undef __WINCRYPT_H__
82 # endif
83 #include <wincrypt.h>
84 #endif
85
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
86 typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
87
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
88 /* Period parameters */
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
89 #define N 624
90 #define M 397
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
91 #define MATRIX_A 0x9908b0dfU /* constant vector a */
92 #define UMASK 0x80000000U /* most significant w-r bits */
93 #define LMASK 0x7fffffffU /* least significant r bits */
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
94 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
0c232be akr * random.c: parenthesize macro arguments.
akr authored
95 #define TWIST(u,v) ((MIXBITS((u),(v)) >> 1) ^ ((v)&1U ? MATRIX_A : 0U))
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
96
97 enum {MT_MAX_STATE = N};
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
98
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
99 struct MT {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
100 /* assume int is enough to store 32bits */
101 unsigned int state[N]; /* the array for the state vector */
102 unsigned int *next;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
103 int left;
104 };
105
106 #define genrand_initialized(mt) ((mt)->next != 0)
107 #define uninit_genrand(mt) ((mt)->next = 0)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
108
109 /* initializes state[N] with a seed */
110 static void
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
111 init_genrand(struct MT *mt, unsigned int s)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
112 {
113 int j;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
114 mt->state[0] = s & 0xffffffffU;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
115 for (j=1; j<N; j++) {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
116 mt->state[j] = (1812433253U * (mt->state[j-1] ^ (mt->state[j-1] >> 30)) + j);
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
117 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
118 /* In the previous versions, MSBs of the seed affect */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
119 /* only MSBs of the array state[]. */
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
120 /* 2002/01/09 modified by Makoto Matsumoto */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
121 mt->state[j] &= 0xffffffff; /* for >32 bit machines */
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
122 }
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
123 mt->left = 1;
fe22f83 Yusuke Endoh * random.c (init_genrand): ensure invariant of mt->next and mt->left.
mame authored
124 mt->next = mt->state + N;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
125 }
126
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
127 /* initialize by an array with array-length */
128 /* init_key is the array for initializing keys */
129 /* key_length is its length */
130 /* slight change for C++, 2004/2/26 */
131 static void
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
132 init_by_array(struct MT *mt, unsigned int init_key[], int key_length)
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
133 {
134 int i, j, k;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
135 init_genrand(mt, 19650218U);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
136 i=1; j=0;
137 k = (N>key_length ? N : key_length);
138 for (; k; k--) {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
139 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1664525U))
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
140 + init_key[j] + j; /* non linear */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
141 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
142 i++; j++;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
143 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
144 if (j>=key_length) j=0;
145 }
146 for (k=N-1; k; k--) {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
147 mt->state[i] = (mt->state[i] ^ ((mt->state[i-1] ^ (mt->state[i-1] >> 30)) * 1566083941U))
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
148 - i; /* non linear */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
149 mt->state[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
150 i++;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
151 if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
152 }
153
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
154 mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
155 }
156
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
157 static void
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
158 next_state(struct MT *mt)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
159 {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
160 unsigned int *p = mt->state;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
161 int j;
162
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
163 mt->left = N;
164 mt->next = mt->state;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
165
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
166 for (j=N-M+1; --j; p++)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
167 *p = p[M] ^ TWIST(p[0], p[1]);
168
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
169 for (j=M; --j; p++)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
170 *p = p[M-N] ^ TWIST(p[0], p[1]);
171
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
172 *p = p[M-N] ^ TWIST(p[0], mt->state[0]);
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
173 }
174
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
175 /* generates a random number on [0,0xffffffff]-interval */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
176 static unsigned int
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
177 genrand_int32(struct MT *mt)
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
178 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
179 /* mt must be initialized */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
180 unsigned int y;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
181
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
182 if (--mt->left <= 0) next_state(mt);
183 y = *mt->next++;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
184
185 /* Tempering */
186 y ^= (y >> 11);
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
187 y ^= (y << 7) & 0x9d2c5680;
188 y ^= (y << 15) & 0xefc60000;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
189 y ^= (y >> 18);
190
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
191 return y;
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
192 }
193
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
194 /* generates a random number on [0,1) with 53-bit resolution*/
30f1eb1 akr * include/ruby/intern.h, random.c, array.c:
akr authored
195 static double
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
196 genrand_real(struct MT *mt)
197 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
198 /* mt must be initialized */
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
199 unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
200 return(a*67108864.0+b)*(1.0/9007199254740992.0);
201 }
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
202
203 /* generates a random number on [0,1] with 53-bit resolution*/
204 static double int_pair_to_real_inclusive(unsigned int a, unsigned int b);
205 static double
206 genrand_real2(struct MT *mt)
207 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
208 /* mt must be initialized */
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
209 unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
210 return int_pair_to_real_inclusive(a, b);
211 }
212
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
213 /* These real versions are due to Isaku Wada, 2002/01/09 added */
214
e301edc eban * random.c (N, M): undef for <winnt.h> on MinGW.
eban authored
215 #undef N
216 #undef M
217
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
218 typedef struct {
219 VALUE seed;
220 struct MT mt;
221 } rb_random_t;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
222
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
223 #define DEFAULT_SEED_CNT 4
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
224
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
225 static rb_random_t default_rand;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
226
1bf3ca4 NARUSE, Yui * random.c (rb_reset_random_seed): set seed in this. [ruby-core:28655]
nurse authored
227 static VALUE rand_init(struct MT *mt, VALUE vseed);
228 static VALUE random_seed(void);
229
8554e16 Nobuyoshi Nakada * array.c (rb_ary_{shuffle_bang,sample}): use Random class object.
nobu authored
230 static rb_random_t *
231 rand_start(rb_random_t *r)
1bf3ca4 NARUSE, Yui * random.c (rb_reset_random_seed): set seed in this. [ruby-core:28655]
nurse authored
232 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
233 struct MT *mt = &r->mt;
234 if (!genrand_initialized(mt)) {
235 r->seed = rand_init(mt, random_seed());
236 }
8554e16 Nobuyoshi Nakada * array.c (rb_ary_{shuffle_bang,sample}): use Random class object.
nobu authored
237 return r;
238 }
239
240 static struct MT *
241 default_mt(void)
242 {
243 return &rand_start(&default_rand)->mt;
1bf3ca4 NARUSE, Yui * random.c (rb_reset_random_seed): set seed in this. [ruby-core:28655]
nurse authored
244 }
245
f3d0225 Nobuyoshi Nakada * random.c (rb_random_{int32,real,bytes,int}): added functions for
nobu authored
246 unsigned int
30f1eb1 akr * include/ruby/intern.h, random.c, array.c:
akr authored
247 rb_genrand_int32(void)
248 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
249 struct MT *mt = default_mt();
1bf3ca4 NARUSE, Yui * random.c (rb_reset_random_seed): set seed in this. [ruby-core:28655]
nurse authored
250 return genrand_int32(mt);
30f1eb1 akr * include/ruby/intern.h, random.c, array.c:
akr authored
251 }
252
253 double
254 rb_genrand_real(void)
255 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
256 struct MT *mt = default_mt();
1bf3ca4 NARUSE, Yui * random.c (rb_reset_random_seed): set seed in this. [ruby-core:28655]
nurse authored
257 return genrand_real(mt);
30f1eb1 akr * include/ruby/intern.h, random.c, array.c:
akr authored
258 }
259
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
260 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
261 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
262 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
003fa83 Nobuyoshi Nakada * random.c (DIGSPERINT): fix for LP64.
nobu authored
263 #define DIGSPERINT (SIZEOF_INT/SIZEOF_BDIGITS)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
264 #define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
0c232be akr * random.c: parenthesize macro arguments.
akr authored
265 #define BIGDN(x) RSHIFT((x),BITSPERDIG)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
266 #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
267 #define BDIGMAX ((BDIGIT)-1)
268
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
269 #define roomof(n, m) (int)(((n)+(m)-1) / (m))
270 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
271 #define SIZEOF_INT32 (31/CHAR_BIT + 1)
272
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
273 static double
274 int_pair_to_real_inclusive(unsigned int a, unsigned int b)
275 {
276 VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1);
277 VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1);
278 BDIGIT *xd = BDIGITS(x);
279 int i = 0;
280 double r;
281
282 xd[i++] = (BDIGIT)b;
283 #if BITSPERDIG < 32
284 xd[i++] = (BDIGIT)(b >> BITSPERDIG);
285 #endif
286 xd[i++] = (BDIGIT)a;
287 #if BITSPERDIG < 32
288 xd[i++] = (BDIGIT)(a >> BITSPERDIG);
289 #endif
290 xd = BDIGITS(m);
291 #if BITSPERDIG < 53
292 MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1);
293 #endif
294 xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG;
295 xd[0] |= 1;
296 x = rb_big_mul(x, m);
297 if (FIXNUM_P(x)) {
298 #if CHAR_BIT * SIZEOF_LONG > 64
299 r = (double)(FIX2ULONG(x) >> 64);
300 #else
301 return 0.0;
302 #endif
303 }
304 else {
305 #if 64 % BITSPERDIG == 0
306 long len = RBIGNUM_LEN(x);
307 xd = BDIGITS(x);
308 MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG);
309 MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG);
310 r = rb_big2dbl(x);
311 #else
312 x = rb_big_rshift(x, INT2FIX(64));
313 if (FIXNUM_P(x)) {
314 r = (double)FIX2ULONG(x);
315 }
316 else {
317 r = rb_big2dbl(x);
318 }
319 #endif
320 }
321 return ldexp(r, -53);
322 }
323
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
324 VALUE rb_cRandom;
325 #define id_minus '-'
326 #define id_plus '+'
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
327 static ID id_rand, id_bytes;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
328
329 /* :nodoc: */
330 static void
331 random_mark(void *ptr)
332 {
333 rb_gc_mark(((rb_random_t *)ptr)->seed);
334 }
335
a4c0f7d Nobuyoshi Nakada * random.c (Init_Random): add Random::DEFAULT.
nobu authored
336 static void
337 random_free(void *ptr)
338 {
339 if (ptr != &default_rand)
340 xfree(ptr);
341 }
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
342
343 static size_t
b46cd0e Nobuyoshi Nakada * include/ruby/ruby.h (rb_data_type_struct): constified dsize.
nobu authored
344 random_memsize(const void *ptr)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
345 {
346 return ptr ? sizeof(rb_random_t) : 0;
347 }
348
349 static const rb_data_type_t random_data_type = {
350 "random",
25b9eb5 Nobuyoshi Nakada * include/ruby/ruby.h (rb_data_type_t): restructured. [ruby-dev:41862]
nobu authored
351 {
352 random_mark,
353 random_free,
354 random_memsize,
355 },
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
356 };
357
358 static rb_random_t *
359 get_rnd(VALUE obj)
360 {
361 rb_random_t *ptr;
362 TypedData_Get_Struct(obj, rb_random_t, &random_data_type, ptr);
363 return ptr;
364 }
365
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
366 static rb_random_t *
367 try_get_rnd(VALUE obj)
368 {
8554e16 Nobuyoshi Nakada * array.c (rb_ary_{shuffle_bang,sample}): use Random class object.
nobu authored
369 if (obj == rb_cRandom) {
370 return rand_start(&default_rand);
371 }
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
372 if (!rb_typeddata_is_kind_of(obj, &random_data_type)) return NULL;
373 return DATA_PTR(obj);
374 }
375
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
376 /* :nodoc: */
377 static VALUE
378 random_alloc(VALUE klass)
379 {
380 rb_random_t *rnd;
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
381 VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_data_type, rnd);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
382 rnd->seed = INT2FIX(0);
383 return obj;
384 }
385
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
386 static VALUE
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
387 rand_init(struct MT *mt, VALUE vseed)
a69b9bc 2000-01-08
matz authored
388 {
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
389 volatile VALUE seed;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
390 long blen = 0;
f571492 Nobuyoshi Nakada * random.c (rand_init): ignore higher bits if all they are same as
nobu authored
391 long fixnum_seed;
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
392 int i, j, len;
393 unsigned int buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;
a69b9bc 2000-01-08
matz authored
394
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
395 seed = rb_to_int(vseed);
396 switch (TYPE(seed)) {
397 case T_FIXNUM:
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
398 len = 1;
f571492 Nobuyoshi Nakada * random.c (rand_init): ignore higher bits if all they are same as
nobu authored
399 fixnum_seed = FIX2LONG(seed);
19afeac akr * random.c (rand_init): use the absolute value of seed to
akr authored
400 if (fixnum_seed < 0)
401 fixnum_seed = -fixnum_seed;
f571492 Nobuyoshi Nakada * random.c (rand_init): ignore higher bits if all they are same as
nobu authored
402 buf[0] = (unsigned int)(fixnum_seed & 0xffffffff);
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
403 #if SIZEOF_LONG > SIZEOF_INT32
25eebc3 NARUSE, Yui * random.c (rand_init): This checks the value is in 32bit or not,
nurse authored
404 if ((long)(int32_t)fixnum_seed != fixnum_seed) {
f571492 Nobuyoshi Nakada * random.c (rand_init): ignore higher bits if all they are same as
nobu authored
405 if ((buf[1] = (unsigned int)(fixnum_seed >> 32)) != 0) ++len;
406 }
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
407 #endif
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
408 break;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
409 case T_BIGNUM:
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
410 blen = RBIGNUM_LEN(seed);
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
411 if (blen == 0) {
412 len = 1;
413 }
414 else {
4516f62 Yusuke Endoh * random.c (rand_init): array length of random seed was broken, which
mame authored
415 if (blen > MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS)
b259e44 NARUSE, Yui * random.c (rand_init): remove useless assignment.
nurse authored
416 blen = MT_MAX_STATE * SIZEOF_INT32 / SIZEOF_BDIGITS;
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
417 len = roomof((int)blen * SIZEOF_BDIGITS, SIZEOF_INT32);
418 }
419 /* allocate ints for init_by_array */
420 if (len > numberof(buf0)) buf = ALLOC_N(unsigned int, len);
421 memset(buf, 0, len * sizeof(*buf));
422 len = 0;
423 for (i = (int)(blen-1); 0 <= i; i--) {
424 j = i * SIZEOF_BDIGITS / SIZEOF_INT32;
425 #if SIZEOF_BDIGITS < SIZEOF_INT32
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
426 buf[j] <<= BITSPERDIG;
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
427 #endif
428 buf[j] |= RBIGNUM_DIGITS(seed)[i];
429 if (!len && buf[j]) len = j;
430 }
431 ++len;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
432 break;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
433 default:
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
434 rb_raise(rb_eTypeError, "failed to convert %s into Integer",
435 rb_obj_classname(vseed));
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
436 }
437 if (len <= 1) {
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
438 init_genrand(mt, buf[0]);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
439 }
440 else {
441 if (buf[len-1] == 1) /* remove leading-zero-guard */
442 len--;
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
443 init_by_array(mt, buf, len);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
444 }
17c1e45 Nobuyoshi Nakada * random.c (rand_init): use fixed buffer for small numbers.
nobu authored
445 if (buf != buf0) xfree(buf);
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
446 return seed;
a69b9bc 2000-01-08
matz authored
447 }
448
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
449 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
450 * call-seq:
451 * Random.new() -> prng
452 * Random.new(seed) -> prng
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
453 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
454 * Creates a new PRNG using +seed+ to set the initial state. If +seed+ is
455 * omitted, the generator is initialized with Random.new_seed.
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
456 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
457 * See Random.srand for more information on the use of seed values.
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
458 */
459 static VALUE
460 random_init(int argc, VALUE *argv, VALUE obj)
461 {
462 VALUE vseed;
463 rb_random_t *rnd = get_rnd(obj);
464
465 if (argc == 0) {
466 vseed = random_seed();
467 }
468 else {
469 rb_scan_args(argc, argv, "01", &vseed);
470 }
471 rnd->seed = rand_init(&rnd->mt, vseed);
472 return obj;
473 }
474
79dfc60 Nobuyoshi Nakada * random.c (DEFAULT_SEED_LEN): suppress a warning.
nobu authored
475 #define DEFAULT_SEED_LEN (DEFAULT_SEED_CNT * (int)sizeof(int))
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
476
ed52949 Nobuyoshi Nakada * random.c (fill_random_seed): /dev/urandom is not available on
nobu authored
477 #if defined(S_ISCHR) && !defined(DOSISH)
478 # define USE_DEV_URANDOM 1
479 #else
480 # define USE_DEV_URANDOM 0
481 #endif
482
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
483 static void
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
484 fill_random_seed(unsigned int seed[DEFAULT_SEED_CNT])
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
485 {
486 static int n = 0;
487 struct timeval tv;
ed52949 Nobuyoshi Nakada * random.c (fill_random_seed): /dev/urandom is not available on
nobu authored
488 #if USE_DEV_URANDOM
e5abd52 akr * random.c (random_seed): use /dev/urandom if available.
akr authored
489 int fd;
1b27958 akr * random.c (random_seed): don't use /dev/urandom if it is not character ...
akr authored
490 struct stat statbuf;
b12c5a8 Nobuyoshi Nakada * random.c (fill_random_seed): use cryptographic service on Windows.
nobu authored
491 #elif defined(_WIN32)
4c7c46b unak * random.c: workaround for VC++ 6.0.
unak authored
492 HCRYPTPROV prov;
383b905 Nobuyoshi Nakada * random.c (fill_random_seed): enclosed conditionally used
nobu authored
493 #endif
8728b3f akr * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
akr authored
494
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
495 memset(seed, 0, DEFAULT_SEED_LEN);
e5abd52 akr * random.c (random_seed): use /dev/urandom if available.
akr authored
496
ed52949 Nobuyoshi Nakada * random.c (fill_random_seed): /dev/urandom is not available on
nobu authored
497 #if USE_DEV_URANDOM
da74bc7 akr * process.c (ruby_setsid): use rb_cloexec_open.
akr authored
498 if ((fd = rb_cloexec_open("/dev/urandom", O_RDONLY
8531657 * random.c (random_seed): O_NONBLOCK isn't defined on some
ocean authored
499 #ifdef O_NONBLOCK
500 |O_NONBLOCK
501 #endif
1b27958 akr * random.c (random_seed): don't use /dev/urandom if it is not character ...
akr authored
502 #ifdef O_NOCTTY
503 |O_NOCTTY
504 #endif
da74bc7 akr * process.c (ruby_setsid): use rb_cloexec_open.
akr authored
505 , 0)) >= 0) {
506 rb_update_max_fd(fd);
1b27958 akr * random.c (random_seed): don't use /dev/urandom if it is not character ...
akr authored
507 if (fstat(fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
52aa6ab Nobuyoshi Nakada * process.c (rb_fork_err): suppress gcc 4.4 warnings.
nobu authored
508 if (read(fd, seed, DEFAULT_SEED_LEN) < DEFAULT_SEED_LEN) {
509 /* abandon */;
510 }
1b27958 akr * random.c (random_seed): don't use /dev/urandom if it is not character ...
akr authored
511 }
e5abd52 akr * random.c (random_seed): use /dev/urandom if available.
akr authored
512 close(fd);
513 }
b12c5a8 Nobuyoshi Nakada * random.c (fill_random_seed): use cryptographic service on Windows.
nobu authored
514 #elif defined(_WIN32)
515 if (CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
8195282 Nobuyoshi Nakada * random.c (fill_random_seed): needs wincrypt.h.
nobu authored
516 CryptGenRandom(prov, DEFAULT_SEED_LEN, (void *)seed);
b12c5a8 Nobuyoshi Nakada * random.c (fill_random_seed): use cryptographic service on Windows.
nobu authored
517 CryptReleaseContext(prov, 0);
518 }
1b27958 akr * random.c (random_seed): don't use /dev/urandom if it is not character ...
akr authored
519 #endif
e5abd52 akr * random.c (random_seed): use /dev/urandom if available.
akr authored
520
8728b3f akr * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
akr authored
521 gettimeofday(&tv, 0);
522 seed[0] ^= tv.tv_usec;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
523 seed[1] ^= (unsigned int)tv.tv_sec;
524 #if SIZEOF_TIME_T > SIZEOF_INT
3622071 Nobuyoshi Nakada * random.c (fill_random_seed): suppress a warning.
nobu authored
525 seed[0] ^= (unsigned int)((time_t)tv.tv_sec >> SIZEOF_INT * CHAR_BIT);
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
526 #endif
8728b3f akr * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
akr authored
527 seed[2] ^= getpid() ^ (n++ << 16);
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
528 seed[3] ^= (unsigned int)(VALUE)&seed;
529 #if SIZEOF_VOIDP > SIZEOF_INT
530 seed[2] ^= (unsigned int)((VALUE)&seed >> SIZEOF_INT * CHAR_BIT);
531 #endif
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
532 }
533
534 static VALUE
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
535 make_seed_value(const void *ptr)
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
536 {
5d8c8b4 Nobuyoshi Nakada * random.c (make_seed_value): fix leading-zero-guard condition on
nobu authored
537 const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS;
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
538 BDIGIT *digits;
539 NEWOBJ(big, struct RBignum);
540 OBJSETUP(big, rb_cBignum, T_BIGNUM);
541
542 RBIGNUM_SET_SIGN(big, 1);
5d8c8b4 Nobuyoshi Nakada * random.c (make_seed_value): fix leading-zero-guard condition on
nobu authored
543 rb_big_resize((VALUE)big, len + 1);
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
544 digits = RBIGNUM_DIGITS(big);
545
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
546 MEMCPY(digits, ptr, char, DEFAULT_SEED_LEN);
8728b3f akr * random.c (limited_big_rand): didn't work if SIZEOF_BDIGITS == 2.
akr authored
547
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
548 /* set leading-zero-guard if need. */
5d8c8b4 Nobuyoshi Nakada * random.c (make_seed_value): fix leading-zero-guard condition on
nobu authored
549 digits[len] =
550 #if SIZEOF_INT32 / SIZEOF_BDIGITS > 1
551 digits[len-2] <= 1 && digits[len-1] == 0
552 #else
553 digits[len-1] <= 1
554 #endif
555 ? 1 : 0;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
556
557 return rb_big_norm((VALUE)big);
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
558 }
559
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
560 /*
373ed88 akr fix rdoc.
akr authored
561 * call-seq: Random.new_seed -> integer
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
562 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
563 * Returns an arbitrary seed value. This is used by Random.new
564 * when no seed value is specified as an argument.
565 *
566 * Random.new_seed #=> 115032730400174366788466674494640623225
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
567 */
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
568 static VALUE
569 random_seed(void)
570 {
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
571 unsigned int buf[DEFAULT_SEED_CNT];
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
572 fill_random_seed(buf);
573 return make_seed_value(buf);
574 }
575
8d32798 RDoc Struct and random
dave authored
576 /*
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
577 * call-seq: prng.seed -> integer
578 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
579 * Returns the seed value used to initialize the generator. This may be used to
580 * initialize another generator with the same state at a later time, causing it
581 * to produce the same sequence of numbers.
582 *
583 * prng1 = Random.new(1234)
584 * prng1.seed #=> 1234
585 * prng1.rand(100) #=> 47
586 *
587 * prng2 = Random.new(prng1.seed)
588 * prng2.rand(100) #=> 47
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
589 */
590 static VALUE
591 random_get_seed(VALUE obj)
592 {
593 return get_rnd(obj)->seed;
594 }
595
596 /* :nodoc: */
597 static VALUE
598 random_copy(VALUE obj, VALUE orig)
599 {
600 rb_random_t *rnd1 = get_rnd(obj);
601 rb_random_t *rnd2 = get_rnd(orig);
602 struct MT *mt = &rnd1->mt;
603
604 *rnd1 = *rnd2;
605 mt->next = mt->state + numberof(mt->state) - mt->left + 1;
606 return obj;
607 }
608
609 static VALUE
610 mt_state(const struct MT *mt)
611 {
612 VALUE bigo = rb_big_new(sizeof(mt->state) / sizeof(BDIGIT), 1);
613 BDIGIT *d = RBIGNUM_DIGITS(bigo);
614 int i;
615
616 for (i = 0; i < numberof(mt->state); ++i) {
617 unsigned int x = mt->state[i];
618 #if SIZEOF_BDIGITS < SIZEOF_INT32
619 int j;
620 for (j = 0; j < SIZEOF_INT32 / SIZEOF_BDIGITS; ++j) {
621 *d++ = BIGLO(x);
622 x = BIGDN(x);
623 }
624 #else
625 *d++ = (BDIGIT)x;
626 #endif
627 }
628 return rb_big_norm(bigo);
629 }
630
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
631 /* :nodoc: */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
632 static VALUE
633 random_state(VALUE obj)
634 {
635 rb_random_t *rnd = get_rnd(obj);
636 return mt_state(&rnd->mt);
637 }
638
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
639 /* :nodoc: */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
640 static VALUE
641 random_s_state(VALUE klass)
642 {
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
643 return mt_state(&default_rand.mt);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
644 }
645
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
646 /* :nodoc: */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
647 static VALUE
648 random_left(VALUE obj)
649 {
650 rb_random_t *rnd = get_rnd(obj);
651 return INT2FIX(rnd->mt.left);
652 }
653
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
654 /* :nodoc: */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
655 static VALUE
656 random_s_left(VALUE klass)
657 {
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
658 return INT2FIX(default_rand.mt.left);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
659 }
660
661 /* :nodoc: */
662 static VALUE
663 random_dump(VALUE obj)
664 {
665 rb_random_t *rnd = get_rnd(obj);
666 VALUE dump = rb_ary_new2(3);
667
668 rb_ary_push(dump, mt_state(&rnd->mt));
669 rb_ary_push(dump, INT2FIX(rnd->mt.left));
670 rb_ary_push(dump, rnd->seed);
671
672 return dump;
673 }
674
675 /* :nodoc: */
676 static VALUE
677 random_load(VALUE obj, VALUE dump)
678 {
679 rb_random_t *rnd = get_rnd(obj);
680 struct MT *mt = &rnd->mt;
681 VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
682 VALUE *ary;
683 unsigned long x;
684
685 Check_Type(dump, T_ARRAY);
686 ary = RARRAY_PTR(dump);
687 switch (RARRAY_LEN(dump)) {
688 case 3:
689 seed = ary[2];
690 case 2:
691 left = ary[1];
692 case 1:
693 state = ary[0];
694 break;
695 default:
696 rb_raise(rb_eArgError, "wrong dump data");
697 }
698 memset(mt->state, 0, sizeof(mt->state));
699 if (FIXNUM_P(state)) {
700 x = FIX2ULONG(state);
701 mt->state[0] = (unsigned int)x;
702 #if SIZEOF_LONG / SIZEOF_INT >= 2
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
703 mt->state[1] = (unsigned int)(x >> BITSPERDIG);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
704 #endif
705 #if SIZEOF_LONG / SIZEOF_INT >= 3
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
706 mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
707 #endif
708 #if SIZEOF_LONG / SIZEOF_INT >= 4
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
709 mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
710 #endif
711 }
712 else {
713 BDIGIT *d;
714 long len;
715 Check_Type(state, T_BIGNUM);
716 len = RBIGNUM_LEN(state);
717 if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) {
718 len = roomof(sizeof(mt->state), SIZEOF_BDIGITS);
719 }
720 #if SIZEOF_BDIGITS < SIZEOF_INT
721 else if (len % DIGSPERINT) {
722 d = RBIGNUM_DIGITS(state) + len;
723 # if DIGSPERINT == 2
724 --len;
725 x = *--d;
726 # else
727 x = 0;
728 do {
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
729 x = (x << BITSPERDIG) | *--d;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
730 } while (--len % DIGSPERINT);
731 # endif
732 mt->state[len / DIGSPERINT] = (unsigned int)x;
733 }
734 #endif
735 if (len > 0) {
736 d = BDIGITS(state) + len;
737 do {
738 --len;
739 x = *--d;
740 # if DIGSPERINT == 2
741 --len;
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
742 x = (x << BITSPERDIG) | *--d;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
743 # elif SIZEOF_BDIGITS < SIZEOF_INT
744 do {
ebbe19e Nobuyoshi Nakada * random.c (rand_init, random_load): use already defined macro.
nobu authored
745 x = (x << BITSPERDIG) | *--d;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
746 } while (--len % DIGSPERINT);
003fa83 Nobuyoshi Nakada * random.c (DIGSPERINT): fix for LP64.
nobu authored
747 # endif
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
748 mt->state[len / DIGSPERINT] = (unsigned int)x;
749 } while (len > 0);
750 }
751 }
752 x = NUM2ULONG(left);
753 if (x > numberof(mt->state)) {
754 rb_raise(rb_eArgError, "wrong value");
755 }
756 mt->left = (unsigned int)x;
757 mt->next = mt->state + numberof(mt->state) - x + 1;
758 rnd->seed = rb_to_int(seed);
759
760 return obj;
761 }
762
763 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
764 * call-seq:
765 * srand(number=0) -> old_seed
766 *
767 * Seeds the system pseudo-random number generator, Random::DEFAULT, with
768 * +number+. The previous seed value is returned.
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
769 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
770 * If +number+ is omitted, seeds the generator using a source of entropy
771 * provided by the operating system, if available (/dev/urandom on Unix systems
772 * or the RSA cryptographic provider on Windows), which is then combined with
773 * the time, the process id, and a sequence number.
774 *
775 * srand may be used to ensure repeatable sequences of pseudo-random numbers
776 * between different runs of the program. By setting the seed to a known value,
777 * programs can be made deterministic during testing.
778 *
779 * srand 1234 # => 268519324636777531569100071560086917274
780 * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
781 * [ rand(10), rand(1000) ] # => [4, 664]
782 * srand 1234 # => 1234
783 * [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
8d32798 RDoc Struct and random
dave authored
784 */
785
3db12e8 Initial revision
matz authored
786 static VALUE
dda5dc0 * array.c: moved to ANSI function style from K&R function style.
ocean authored
787 rb_f_srand(int argc, VALUE *argv, VALUE obj)
3db12e8 Initial revision
matz authored
788 {
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
789 VALUE seed, old;
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
790 rb_random_t *r = &default_rand;
3db12e8 Initial revision
matz authored
791
46620a8 matz
matz authored
792 rb_secure(4);
39787ea * numeric.c (fix_to_s): avoid rb_scan_args() when no argument
matz authored
793 if (argc == 0) {
7194b66 * random.c: replace with Mersenne Twister RNG.
matz authored
794 seed = random_seed();
3db12e8 Initial revision
matz authored
795 }
39787ea * numeric.c (fix_to_s): avoid rb_scan_args() when no argument
matz authored
796 else {
797 rb_scan_args(argc, argv, "01", &seed);
798 }
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
799 old = r->seed;
800 r->seed = rand_init(&r->mt, seed);
3db12e8 Initial revision
matz authored
801
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
802 return old;
803 }
804
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
805 static unsigned long
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
806 make_mask(unsigned long x)
807 {
808 x = x | x >> 1;
809 x = x | x >> 2;
810 x = x | x >> 4;
811 x = x | x >> 8;
812 x = x | x >> 16;
813 #if 4 < SIZEOF_LONG
814 x = x | x >> 32;
815 #endif
816 return x;
817 }
818
819 static unsigned long
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
820 limited_rand(struct MT *mt, unsigned long limit)
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
821 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
822 /* mt must be initialized */
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
823 int i;
31875e9 Nobuyoshi Nakada * random.c (random_rand): fixed for edge cases of ranges.
nobu authored
824 unsigned long val, mask;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
825
31875e9 Nobuyoshi Nakada * random.c (random_rand): fixed for edge cases of ranges.
nobu authored
826 if (!limit) return 0;
827 mask = make_mask(limit);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
828 retry:
829 val = 0;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
830 for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) {
a88589c Nobuyoshi Nakada * random.c (limited_rand): expands to long before shift so that
nobu authored
831 if ((mask >> (i * 32)) & 0xffffffff) {
832 val |= (unsigned long)genrand_int32(mt) << (i * 32);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
833 val &= mask;
834 if (limit < val)
835 goto retry;
836 }
837 }
838 return val;
839 }
840
841 static VALUE
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
842 limited_big_rand(struct MT *mt, struct RBignum *limit)
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
843 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
844 /* mt must be initialized */
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
845 unsigned long mask, lim, rnd;
846 struct RBignum *val;
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
847 long i, len;
848 int boundary;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
849
2c8e7a5 akr * include/ruby/ruby.h (struct RBignum): embed digits in RBignum for
akr authored
850 len = (RBIGNUM_LEN(limit) * SIZEOF_BDIGITS + 3) / 4;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
851 val = (struct RBignum *)rb_big_clone((VALUE)limit);
2c8e7a5 akr * include/ruby/ruby.h (struct RBignum): embed digits in RBignum for
akr authored
852 RBIGNUM_SET_SIGN(val, 1);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
853 #if SIZEOF_BDIGITS == 2
b5fdd1b akr * random.c (limited_big_rand): fix buffer overflow when SIZEOF_BDIGITS
akr authored
854 # define BIG_GET32(big,i) \
855 (RBIGNUM_DIGITS(big)[(i)*2] | \
856 ((i)*2+1 < RBIGNUM_LEN(big) ? \
857 (RBIGNUM_DIGITS(big)[(i)*2+1] << 16) : \
858 0))
859 # define BIG_SET32(big,i,d) \
860 ((RBIGNUM_DIGITS(big)[(i)*2] = (d) & 0xffff), \
861 ((i)*2+1 < RBIGNUM_LEN(big) ? \
862 (RBIGNUM_DIGITS(big)[(i)*2+1] = (d) >> 16) : \
863 0))
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
864 #else
865 /* SIZEOF_BDIGITS == 4 */
0c232be akr * random.c: parenthesize macro arguments.
akr authored
866 # define BIG_GET32(big,i) (RBIGNUM_DIGITS(big)[(i)])
867 # define BIG_SET32(big,i,d) (RBIGNUM_DIGITS(big)[(i)] = (d))
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
868 #endif
869 retry:
870 mask = 0;
871 boundary = 1;
872 for (i = len-1; 0 <= i; i--) {
873 lim = BIG_GET32(limit, i);
874 mask = mask ? 0xffffffff : make_mask(lim);
875 if (mask) {
21b00e0 Nobuyoshi Nakada * random.c (struct MT): packed Mersenne Twister staffs.
nobu authored
876 rnd = genrand_int32(mt) & mask;
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
877 if (boundary) {
878 if (lim < rnd)
879 goto retry;
880 if (rnd < lim)
881 boundary = 0;
882 }
883 }
884 else {
885 rnd = 0;
886 }
234485d Nobuyoshi Nakada * random.c (struct MT): ruby already assumes int has 32bit at
nobu authored
887 BIG_SET32(val, i, (BDIGIT)rnd);
943e67e akr * random.c (init_by_array): imported from mt19937ar-cok.tgz.
akr authored
888 }
889 return rb_big_norm((VALUE)val);
3db12e8 Initial revision
matz authored
890 }
891
493f721 NARUSE, Yui * random.c (rb_genrand_ulong_limited): renamed from
nurse authored
892 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
893 * Returns random unsigned long value in [0, +limit+].
493f721 NARUSE, Yui * random.c (rb_genrand_ulong_limited): renamed from
nurse authored
894 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
895 * Note that +limit+ is included, and the range of the argument and the
493f721 NARUSE, Yui * random.c (rb_genrand_ulong_limited): renamed from
nurse authored
896 * return value depends on environments.
897 */
19f45f8 Yusuke Endoh * bignum.c (rb_big_mul): faster multiplication by Karatsuba method and
mame authored
898 unsigned long
493f721 NARUSE, Yui * random.c (rb_genrand_ulong_limited): renamed from
nurse authored
899 rb_genrand_ulong_limited(unsigned long limit)
19f45f8 Yusuke Endoh * bignum.c (rb_big_mul): faster multiplication by Karatsuba method and
mame authored
900 {
493f721 NARUSE, Yui * random.c (rb_genrand_ulong_limited): renamed from
nurse authored
901 return limited_rand(default_mt(), limit);
19f45f8 Yusuke Endoh * bignum.c (rb_big_mul): faster multiplication by Karatsuba method and
mame authored
902 }
903
f3d0225 Nobuyoshi Nakada * random.c (rb_random_{int32,real,bytes,int}): added functions for
nobu authored
904 unsigned int
905 rb_random_int32(VALUE obj)
906 {
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
907 rb_random_t *rnd = try_get_rnd(obj);
908 if (!rnd) {
8554e16 Nobuyoshi Nakada * array.c (rb_ary_{shuffle_bang,sample}): use Random class object.
nobu authored
909 #if SIZEOF_LONG * CHAR_BIT > 32
910 VALUE lim = ULONG2NUM(0x100000000);
911 #elif defined HAVE_LONG_LONG
912 VALUE lim = ULL2NUM((LONG_LONG)0xffffffff+1);
913 #else
914 VALUE lim = rb_big_plus(ULONG2NUM(0xffffffff), INT2FIX(1));
915 #endif
0eb31be Nobuyoshi Nakada * random.c (rb_random_int32): suppress warning on LP64 platforms.
nobu authored
916 return (unsigned int)NUM2ULONG(rb_funcall2(obj, id_rand, 1, &lim));
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
917 }
f3d0225 Nobuyoshi Nakada * random.c (rb_random_{int32,real,bytes,int}): added functions for
nobu authored
918 return genrand_int32(&rnd->mt);
919 }
920
921 double
922 rb_random_real(VALUE obj)
923 {
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
924 rb_random_t *rnd = try_get_rnd(obj);
925 if (!rnd) {
926 VALUE v = rb_funcall2(obj, id_rand, 0, 0);
8554e16 Nobuyoshi Nakada * array.c (rb_ary_{shuffle_bang,sample}): use Random class object.
nobu authored
927 double d = NUM2DBL(v);
928 if (d < 0.0 || d >= 1.0) {
929 rb_raise(rb_eRangeError, "random number too big %g", d);
930 }
931 return d;
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
932 }
f3d0225 Nobuyoshi Nakada * random.c (rb_random_{int32,real,bytes,int}): added functions for
nobu authored
933 return genrand_real(&rnd->mt);
934 }
935
8d32798 RDoc Struct and random
dave authored
936 /*
3f5e567 Marc-André Lafortune * random.c: Documentation fix for Random#bytes
marcandre authored
937 * call-seq: prng.bytes(size) -> a_string
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
938 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
939 * Returns a random binary string containing +size+ bytes.
940 *
941 * random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO"
942 * random_string.size # => 10
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
943 */
944 static VALUE
945 random_bytes(VALUE obj, VALUE len)
946 {
6937a3e Yusuke Endoh * random.c (random_bytes): use NUM2LONG instead of FIX2LONG because
mame authored
947 return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
f3d0225 Nobuyoshi Nakada * random.c (rb_random_{int32,real,bytes,int}): added functions for
nobu authored
948 }
949
950 VALUE
951 rb_random_bytes(VALUE obj, long n)
952 {
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
953 rb_random_t *rnd = try_get_rnd(obj);
954 VALUE bytes;
955 char *ptr;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
956 unsigned int r, i;
957
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
958 if (!rnd) {
959 VALUE len = LONG2NUM(n);
960 return rb_funcall2(obj, id_bytes, 1, &len);
961 }
962 bytes = rb_str_new(0, n);
963 ptr = RSTRING_PTR(bytes);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
964 for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
965 r = genrand_int32(&rnd->mt);
966 i = SIZEOF_INT32;
967 do {
968 *ptr++ = (char)r;
969 r >>= CHAR_BIT;
970 } while (--i);
971 }
972 if (n > 0) {
973 r = genrand_int32(&rnd->mt);
974 do {
975 *ptr++ = (char)r;
976 r >>= CHAR_BIT;
977 } while (--n);
978 }
979 return bytes;
980 }
981
982 static VALUE
99aaee3 Nobuyoshi Nakada * random.c (random_rand): get rid of overflow.
nobu authored
983 range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
984 {
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
985 VALUE end, r;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
986
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
987 if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
99aaee3 Nobuyoshi Nakada * random.c (random_rand): get rid of overflow.
nobu authored
988 if (endp) *endp = end;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
989 if (!rb_respond_to(end, id_minus)) return Qfalse;
990 r = rb_funcall2(end, id_minus, 1, begp);
991 if (NIL_P(r)) return Qfalse;
992 return r;
993 }
994
995 static VALUE
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
996 rand_int(struct MT *mt, VALUE vmax, int restrictive)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
997 {
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
998 /* mt must be initialized */
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
999 long max;
1000 unsigned long r;
1001
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1002 if (FIXNUM_P(vmax)) {
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1003 max = FIX2LONG(vmax);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1004 if (!max) return Qnil;
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1005 if (max < 0) {
1006 if (restrictive) return Qnil;
1007 max = -max;
1008 }
1009 r = limited_rand(mt, (unsigned long)max - 1);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1010 return ULONG2NUM(r);
1011 }
1012 else {
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1013 VALUE ret;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1014 if (rb_bigzero_p(vmax)) return Qnil;
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1015 if (!RBIGNUM_SIGN(vmax)) {
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1016 if (restrictive) return Qnil;
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1017 vmax = rb_big_clone(vmax);
1018 RBIGNUM_SET_SIGN(vmax, 1);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1019 }
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1020 vmax = rb_big_minus(vmax, INT2FIX(1));
1021 if (FIXNUM_P(vmax)) {
1022 max = FIX2LONG(vmax);
1023 if (max == -1) return Qnil;
1024 r = limited_rand(mt, max);
1025 return LONG2NUM(r);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1026 }
e626e0b Nobuyoshi Nakada * random.c (rand_int): prevent from GC.
nobu authored
1027 ret = limited_big_rand(mt, RBIGNUM(vmax));
1028 RB_GC_GUARD(vmax);
1029 return ret;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1030 }
1031 }
1032
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1033 static inline double
1034 float_value(VALUE v)
1035 {
1036 double x = RFLOAT_VALUE(v);
1037 if (isinf(x) || isnan(x)) {
1038 VALUE error = INT2FIX(EDOM);
1039 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
1040 }
1041 return x;
1042 }
1043
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1044 static inline VALUE
1045 rand_range(struct MT* mt, VALUE range)
1046 {
1047 VALUE beg = Qundef, end = Qundef, vmax, v;
1048 int excl = 0;
1049
1050 if ((v = vmax = range_values(range, &beg, &end, &excl)) == Qfalse)
1051 return Qfalse;
8e6e8e6 Nobuyoshi Nakada * use RB_TYPE_P which is optimized for constant types, instead of
nobu authored
1052 if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1053 long max;
1054 vmax = v;
1055 v = Qnil;
1056 if (FIXNUM_P(vmax)) {
1057 fixnum:
1058 if ((max = FIX2LONG(vmax) - excl) >= 0) {
1059 unsigned long r = limited_rand(mt, (unsigned long)max);
1060 v = ULONG2NUM(r);
1061 }
1062 }
1063 else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
1064 vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
1065 if (FIXNUM_P(vmax)) {
1066 excl = 0;
1067 goto fixnum;
1068 }
1069 v = limited_big_rand(mt, RBIGNUM(vmax));
1070 }
1071 }
1072 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
1073 int scale = 1;
1074 double max = RFLOAT_VALUE(v), mid = 0.5, r;
1075 if (isinf(max)) {
1076 double min = float_value(rb_to_float(beg)) / 2.0;
1077 max = float_value(rb_to_float(end)) / 2.0;
1078 scale = 2;
1079 mid = max + min;
1080 max -= min;
1081 }
1082 else {
1083 float_value(v);
1084 }
1085 v = Qnil;
1086 if (max > 0.0) {
1087 if (excl) {
1088 r = genrand_real(mt);
1089 }
1090 else {
1091 r = genrand_real2(mt);
1092 }
1093 if (scale > 1) {
1094 return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
1095 }
1096 v = rb_float_new(r * max);
1097 }
1098 else if (max == 0.0 && !excl) {
1099 v = rb_float_new(0.0);
1100 }
1101 }
1102
1103 if (FIXNUM_P(beg) && FIXNUM_P(v)) {
1104 long x = FIX2LONG(beg) + FIX2LONG(v);
1105 return LONG2NUM(x);
1106 }
1107 switch (TYPE(v)) {
1108 case T_NIL:
1109 break;
1110 case T_BIGNUM:
1111 return rb_big_plus(v, beg);
1112 case T_FLOAT: {
1113 VALUE f = rb_check_to_float(beg);
1114 if (!NIL_P(f)) {
1115 RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
1116 return v;
1117 }
1118 }
1119 default:
1120 return rb_funcall2(beg, id_plus, 1, &v);
1121 }
1122
1123 return v;
1124 }
1125
4243778 Nobuyoshi Nakada * random.c (Init_Random): removed rb_Random_DEFAULT and register as
nobu authored
1126 static VALUE rand_random(int argc, VALUE *argv, rb_random_t *rnd);
1127
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1128 /*
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1129 * call-seq:
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1130 * prng.rand -> float
1131 * prng.rand(max) -> number
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1132 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1133 * When +max+ is an Integer, +rand+ returns a random integer greater than
1134 * or equal to zero and less than +max+. Unlike Kernel.rand, when +max+
1135 * is a negative integer or zero, +rand+ raises an ArgumentError.
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1136 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1137 * prng = Random.new
1138 * prng.rand(100) # => 42
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1139 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1140 * When +max+ is a Float, +rand+ returns a random floating point number
1141 * between 0.0 and +max+, including 0.0 and excluding +max+.
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1142 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1143 * prng.rand(1.5) # => 1.4600282860034115
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1144 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1145 * When +max+ is a Range, +rand+ returns a random number where
1146 * range.member?(number) == true.
1147 *
1148 * prng.rand(5..9) # => one of [5, 6, 7, 8, 9]
1149 * prng.rand(5...9) # => one of [5, 6, 7, 8]
1150 * prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0
1151 * prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0
1152 *
1153 * Both the beginning and ending values of the range must respond to subtract
1154 * (<tt>-</tt>) and add (<tt>+</tt>)methods, or rand will raise an
1155 * ArgumentError.
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1156 */
1157 static VALUE
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1158 random_rand(int argc, VALUE *argv, VALUE obj)
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1159 {
4243778 Nobuyoshi Nakada * random.c (Init_Random): removed rb_Random_DEFAULT and register as
nobu authored
1160 return rand_random(argc, argv, get_rnd(obj));
1161 }
1162
1163 static VALUE
1164 rand_random(int argc, VALUE *argv, rb_random_t *rnd)
1165 {
63f39fc NARUSE, Yui * random.c (random_rand): remove unused variables.
nurse authored
1166 VALUE vmax, v;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1167
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1168 if (argc == 0) {
1169 return rb_float_new(genrand_real(&rnd->mt));
1170 }
7316302 Marc-André Lafortune * include/ruby/intern.h: Add rb_check_arity, rb_error_arity [#6085]
marcandre authored
1171 else {
1172 rb_check_arity(argc, 0, 1);
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1173 }
1174 vmax = argv[0];
1175 if (NIL_P(vmax)) {
6decf41 Nobuyoshi Nakada * random.c (random_rand): raise ArgumentError on nil, as the
nobu authored
1176 v = Qnil;
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1177 }
8e6e8e6 Nobuyoshi Nakada * use RB_TYPE_P which is optimized for constant types, instead of
nobu authored
1178 else if (!RB_TYPE_P(vmax, T_FLOAT) && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
b259e44 NARUSE, Yui * random.c (rand_init): remove useless assignment.
nurse authored
1179 v = rand_int(&rnd->mt, v, 1);
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1180 }
1181 else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
1182 double max = float_value(v);
1183 if (max > 0.0)
1184 v = rb_float_new(max * genrand_real(&rnd->mt));
1185 else
1186 v = Qnil;
1187 }
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1188 else if ((v = rand_range(&rnd->mt, vmax)) != Qfalse) {
1189 /* nothing to do */
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1190 }
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1191 else {
2981448 Nobuyoshi Nakada * random.c (random_rand): refined error message.
nobu authored
1192 v = Qnil;
7175a90 NARUSE, Yui * class.c, compile.c, dir.c, file.c, iseq.c, parse.y, random.c:
nurse authored
1193 (void)NUM2LONG(vmax);
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1194 }
2981448 Nobuyoshi Nakada * random.c (random_rand): refined error message.
nobu authored
1195 if (NIL_P(v)) {
1196 VALUE mesg = rb_str_new_cstr("invalid argument - ");
1197 rb_str_append(mesg, rb_obj_as_string(argv[0]));
1198 rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
1199 }
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1200
1201 return v;
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1202 }
1203
1204 /*
115c220 Nobuyoshi Nakada * random.c (random_equal): new method Random#==.
nobu authored
1205 * call-seq:
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1206 * prng1 == prng2 -> true or false
1207 *
1208 * Returns true if the two generators have the same internal state, otherwise
1209 * false. Equivalent generators will return the same sequence of
1210 * pseudo-random numbers. Two generators will generally have the same state
1211 * only if they were initialized with the same seed
115c220 Nobuyoshi Nakada * random.c (random_equal): new method Random#==.
nobu authored
1212 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1213 * Random.new == Random.new # => false
1214 * Random.new(1234) == Random.new(1234) # => true
1215 *
1216 * and have the same invocation history.
1217 *
1218 * prng1 = Random.new(1234)
1219 * prng2 = Random.new(1234)
1220 * prng1 == prng2 # => true
1221 *
1222 * prng1.rand # => 0.1915194503788923
1223 * prng1 == prng2 # => false
1224 *
1225 * prng2.rand # => 0.1915194503788923
1226 * prng1 == prng2 # => true
115c220 Nobuyoshi Nakada * random.c (random_equal): new method Random#==.
nobu authored
1227 */
1228 static VALUE
1229 random_equal(VALUE self, VALUE other)
1230 {
1231 rb_random_t *r1, *r2;
1232 if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
1233 r1 = get_rnd(self);
1234 r2 = get_rnd(other);
1235 if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse;
1236 if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
1237 if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
1238 if (r1->mt.left != r2->mt.left) return Qfalse;
1239 return Qtrue;
1240 }
1241
1242 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1243 * call-seq:
1244 * rand(max=0) -> number
1245 *
1246 * If called without an argument, or if <tt>max.to_i.abs == 0</tt>, rand
1247 * returns a pseudo-random floating point number between 0.0 and 1.0,
1248 * including 0.0 and excluding 1.0.
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
1249 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1250 * rand #=> 0.2725926052826416
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1251 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1252 * When <tt>max.abs</tt> is greater than or equal to 1, +rand+ returns a
1253 * pseudo-random integer greater than or equal to 0 and less than
1254 * <tt>max.to_i.abs</tt>.
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1255 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1256 * rand(100) #=> 12
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1257 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1258 * Negative or floating point values for +max+ are allowed, but may give
1259 * surprising results.
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1260 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1261 * rand(-100) # => 87
1262 * rand(-0.5) # => 0.8130921818028143
1263 * rand(1.9) # equivalent to rand(1), which is always 0
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1264 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1265 * Kernel.srand may be used to ensure that sequences of random numbers are
1266 * reproducible between different runs of a program.
12d2c8b Nobuyoshi Nakada stripped trailing spaces.
nobu authored
1267 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1268 * See also Random.rand.
8d32798 RDoc Struct and random
dave authored
1269 */
1270
3db12e8 Initial revision
matz authored
1271 static VALUE
dda5dc0 * array.c: moved to ANSI function style from K&R function style.
ocean authored
1272 rb_f_rand(int argc, VALUE *argv, VALUE obj)
3db12e8 Initial revision
matz authored
1273 {
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1274 VALUE v, vmax, r;
d188e1a Nobuyoshi Nakada * random.c (next_state): no initialization here.
nobu authored
1275 struct MT *mt = default_mt();
3db12e8 Initial revision
matz authored
1276
6bbd76a * random.c (rb_f_rand): type check simplified. strings are no
matz authored
1277 if (argc == 0) goto zero_arg;
1278 rb_scan_args(argc, argv, "01", &vmax);
1279 if (NIL_P(vmax)) goto zero_arg;
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1280 if ((v = rand_range(mt, vmax)) != Qfalse) {
1281 return v;
1282 }
6bbd76a * random.c (rb_f_rand): type check simplified. strings are no
matz authored
1283 vmax = rb_to_int(vmax);
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1284 if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
6bbd76a * random.c (rb_f_rand): type check simplified. strings are no
matz authored
1285 zero_arg:
31b6ea6 * include/ruby/ruby.h (DBL2NUM): renamed from DOUBLE2NUM.
matz authored
1286 return DBL2NUM(genrand_real(mt));
210367e This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
1287 }
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1288 return r;
3db12e8 Initial revision
matz authored
1289 }
1290
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1291 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1292 * call-seq:
1293 * Random.rand -> float
1294 * Random.rand(max) -> number
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1295 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1296 * Alias of Random::DEFAULT.rand.
b5909ef Shota Fukumori * random.c (rb_f_rand, random_s_rand): RDocs for them.
sorah authored
1297 */
1298
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1299 static VALUE
1300 random_s_rand(int argc, VALUE *argv, VALUE obj)
1301 {
4243778 Nobuyoshi Nakada * random.c (Init_Random): removed rb_Random_DEFAULT and register as
nobu authored
1302 return rand_random(argc, argv, rand_start(&default_rand));
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1303 }
1304
f41eaf8 Nobuyoshi Nakada * random.c (rb_hash_start): moved from string.c.
nobu authored
1305 static st_index_t hashseed;
1306
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
1307 static VALUE
1308 init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT])
1309 {
1310 VALUE seed;
1311 fill_random_seed(initial);
1312 init_by_array(mt, initial, DEFAULT_SEED_CNT);
1313 seed = make_seed_value(initial);
1314 memset(initial, 0, DEFAULT_SEED_LEN);
1315 return seed;
1316 }
1317
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1318 void
1319 Init_RandomSeed(void)
1320 {
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
1321 rb_random_t *r = &default_rand;
1322 unsigned int initial[DEFAULT_SEED_CNT];
1323 struct MT *mt = &r->mt;
1324 VALUE seed = init_randomseed(mt, initial);
f41eaf8 Nobuyoshi Nakada * random.c (rb_hash_start): moved from string.c.
nobu authored
1325
1326 hashseed = genrand_int32(mt);
1327 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
1328 hashseed <<= 32;
1329 hashseed |= genrand_int32(mt);
1330 #endif
1331 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
1332 hashseed <<= 32;
1333 hashseed |= genrand_int32(mt);
1334 #endif
1335 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8
1336 hashseed <<= 32;
1337 hashseed |= genrand_int32(mt);
1338 #endif
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
1339
1340 rb_global_variable(&r->seed);
1341 r->seed = seed;
f41eaf8 Nobuyoshi Nakada * random.c (rb_hash_start): moved from string.c.
nobu authored
1342 }
1343
1344 st_index_t
1345 rb_hash_start(st_index_t h)
1346 {
1347 return st_hash_start(hashseed + h);
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1348 }
1349
79bb49b Nobuyoshi Nakada * random.c (Init_RandomSeed2): should be void.
nobu authored
1350 static void
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1351 Init_RandomSeed2(void)
1352 {
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
1353 VALUE seed = default_rand.seed;
1354
1355 if (RB_TYPE_P(seed, T_BIGNUM)) {
1356 RBASIC(seed)->klass = rb_cBignum;
1357 }
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1358 }
1359
1360 void
1361 rb_reset_random_seed(void)
1362 {
21c7d36 Nobuyoshi Nakada * random.c (default_rand): removed initial buffer.
nobu authored
1363 rb_random_t *r = &default_rand;
1364 uninit_genrand(&r->mt);
1365 r->seed = INT2FIX(0);
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1366 }
1367
9654a4c Eric Hodel * random.c (Init_Random): Add a top-level comment for Random. Patch
drbrain authored
1368 /*
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1369 * Document-class: Random
1370 *
1371 * Random provides an interface to Ruby's pseudo-random number generator, or
1372 * PRNG. The PRNG produces a deterministic sequence of bits which approximate
1373 * true randomness. The sequence may be represented by integers, floats, or
1374 * binary strings.
1375 *
1376 * The generator may be initialized with either a system-generated or
1377 * user-supplied seed value by using Random.srand.
1378 *
1379 * The class method Random.rand provides the base functionality of Kernel.rand
1380 * along with better handling of floating point values. These are both
1381 * interfaces to Random::DEFAULT, the Ruby system PRNG.
1382 *
1383 * Random.new will create a new PRNG with a state independent of
1384 * Random::DEFAULT, allowing multiple generators with different seed values or
1385 * sequence positions to exist simultaneously. Random objects can be
1386 * marshaled, allowing sequences to be saved and resumed.
9654a4c Eric Hodel * random.c (Init_Random): Add a top-level comment for Random. Patch
drbrain authored
1387 *
f365f19 Eric Hodel * random.c: Improve documentation of Random. Patch by Gregory
drbrain authored
1388 * PRNGs are currently implemented as a modified Mersenne Twister with a period
1389 * of 2**19937-1.
9654a4c Eric Hodel * random.c (Init_Random): Add a top-level comment for Random. Patch
drbrain authored
1390 */
1391
3db12e8 Initial revision
matz authored
1392 void
dda5dc0 * array.c: moved to ANSI function style from K&R function style.
ocean authored
1393 Init_Random(void)
3db12e8 Initial revision
matz authored
1394 {
04739ba akr * string.c (rb_memhash): randomize hash to avoid algorithmic
akr authored
1395 Init_RandomSeed2();
210367e This commit was generated by cvs2svn to compensate for changes in r372,
matz authored
1396 rb_define_global_function("srand", rb_f_srand, -1);
4f51d81 matz
matz authored
1397 rb_define_global_function("rand", rb_f_rand, -1);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1398
1399 rb_cRandom = rb_define_class("Random", rb_cObject);
1400 rb_define_alloc_func(rb_cRandom, random_alloc);
1401 rb_define_method(rb_cRandom, "initialize", random_init, -1);
9676023 Nobuyoshi Nakada * random.c (random_rand): unified random_int and random_float.
nobu authored
1402 rb_define_method(rb_cRandom, "rand", random_rand, -1);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1403 rb_define_method(rb_cRandom, "bytes", random_bytes, 1);
1404 rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
1405 rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
1406 rb_define_method(rb_cRandom, "marshal_dump", random_dump, 0);
1407 rb_define_method(rb_cRandom, "marshal_load", random_load, 1);
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
1408 rb_define_private_method(rb_cRandom, "state", random_state, 0);
1409 rb_define_private_method(rb_cRandom, "left", random_left, 0);
115c220 Nobuyoshi Nakada * random.c (random_equal): new method Random#==.
nobu authored
1410 rb_define_method(rb_cRandom, "==", random_equal, 1);
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1411
4243778 Nobuyoshi Nakada * random.c (Init_Random): removed rb_Random_DEFAULT and register as
nobu authored
1412 {
1413 VALUE rand_default = TypedData_Wrap_Struct(rb_cRandom, &random_data_type, &default_rand);
1414 rb_gc_register_mark_object(rand_default);
1415 rb_define_const(rb_cRandom, "DEFAULT", rand_default);
1416 }
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1417
1418 rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
2aeb3b4 Kenta Murata * random.c (random_s_rand, Init_Random): Random.rand should behave as
mrkn authored
1419 rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
eb9bc2d Nobuyoshi Nakada * random.c (rb_random_t): objectified. [EXPERIMENTAL]
nobu authored
1420 rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
f8faa5e Nobuyoshi Nakada * random.c (random_{state,left}): internal/debug use.
nobu authored
1421 rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
1422 rb_define_private_method(CLASS_OF(rb_cRandom), "left", random_s_left, 0);
2f6c0e3 Nobuyoshi Nakada * array.c (rb_ary_shuffle_bang, rb_ary_sample): add optional
nobu authored
1423
1424 id_rand = rb_intern("rand");
1425 id_bytes = rb_intern("bytes");
3db12e8 Initial revision
matz authored
1426 }
Something went wrong with that request. Please try again.