(scm_strptime, scm_mktime): Added texinfo markup.
[bpt/guile.git] / libguile / random.c
CommitLineData
950cc72b 1/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
e7a72986
MD
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2, or (at your option)
5 * any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this software; see the file COPYING. If not, write to
14 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15 * Boston, MA 02111-1307 USA
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice. */
40
1bbd0b84
GB
41/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
42 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
43
44
e7a72986
MD
45/* Author: Mikael Djurfeldt <djurfeldt@nada.kth.se> */
46
a0599745 47#include "libguile/_scm.h"
e7a72986 48
7f146094 49#include <stdio.h>
e7a72986 50#include <math.h>
f34d19c7 51#include <string.h>
a0599745
MD
52#include "libguile/smob.h"
53#include "libguile/numbers.h"
54#include "libguile/feature.h"
55#include "libguile/strings.h"
e9bfab50 56#include "libguile/unif.h"
a0599745 57#include "libguile/vectors.h"
e7a72986 58
a0599745
MD
59#include "libguile/validate.h"
60#include "libguile/random.h"
e7a72986
MD
61
62\f
63/*
64 * A plugin interface for RNGs
65 *
66 * Using this interface, it is possible for the application to tell
67 * libguile to use a different RNG. This is desirable if it is
68 * necessary to use the same RNG everywhere in the application in
69 * order to prevent interference, if the application uses RNG
70 * hardware, or if the application has special demands on the RNG.
71 *
72 * Look in random.h and how the default generator is "plugged in" in
73 * scm_init_random().
74 */
75
76scm_rng scm_the_rng;
77
78\f
79/*
80 * The prepackaged RNG
81 *
82 * This is the MWC (Multiply With Carry) random number generator
83 * described by George Marsaglia at the Department of Statistics and
84 * Supercomputer Computations Research Institute, The Florida State
85 * University (http://stat.fsu.edu/~geo).
86 *
87 * It uses 64 bits, has a period of 4578426017172946943 (4.6e18), and
88 * passes all tests in the DIEHARD test suite
89 * (http://stat.fsu.edu/~geo/diehard.html)
90 */
91
92#define A 2131995753UL
93
94#if SIZEOF_LONG > 4
95#if SIZEOF_INT > 4
96#define LONG32 unsigned short
97#else
98#define LONG32 unsigned int
99#endif
100#define LONG64 unsigned long
101#else
102#define LONG32 unsigned long
103#define LONG64 unsigned long long
104#endif
105
106#if SIZEOF_LONG > 4 || defined (HAVE_LONG_LONGS)
107
108unsigned long
109scm_i_uniform32 (scm_i_rstate *state)
110{
111 LONG64 x = (LONG64) A * state->w + state->c;
112 LONG32 w = x & 0xffffffffUL;
113 state->w = w;
114 state->c = x >> 32L;
115 return w;
116}
117
118#else
119
120/* ww This is a portable version of the same RNG without 64 bit
121 * * aa arithmetic.
122 * ----
123 * xx It is only intended to provide identical behaviour on
124 * xx platforms without 8 byte longs or long longs until
125 * xx someone has implemented the routine in assembler code.
126 * xxcc
127 * ----
128 * ccww
129 */
130
131#define L(x) ((x) & 0xffff)
132#define H(x) ((x) >> 16)
133
134unsigned long
135scm_i_uniform32 (scm_i_rstate *state)
136{
137 LONG32 x1 = L (A) * L (state->w);
138 LONG32 x2 = L (A) * H (state->w);
139 LONG32 x3 = H (A) * L (state->w);
140 LONG32 w = L (x1) + L (state->c);
141 LONG32 m = H (x1) + L (x2) + L (x3) + H (state->c) + H (w);
142 LONG32 x4 = H (A) * H (state->w);
143 state->w = w = (L (m) << 16) + L (w);
144 state->c = H (x2) + H (x3) + x4 + H (m);
145 return w;
146}
147
148#endif
149
150void
151scm_i_init_rstate (scm_i_rstate *state, char *seed, int n)
152{
153 LONG32 w = 0L;
154 LONG32 c = 0L;
155 int i, m;
156 for (i = 0; i < n; ++i)
157 {
158 m = i % 8;
159 if (m < 4)
160 w += seed[i] << (8 * m);
161 else
162 c += seed[i] << (8 * (m - 4));
163 }
164 if ((w == 0 && c == 0) || (w == 0xffffffffUL && c == A - 1))
165 ++c;
166 state->w = w;
167 state->c = c;
168}
169
170scm_i_rstate *
171scm_i_copy_rstate (scm_i_rstate *state)
172{
173 scm_rstate *new_state = malloc (scm_the_rng.rstate_size);
174 if (new_state == 0)
2500356c 175 scm_memory_error ("rstate");
e7a72986
MD
176 return memcpy (new_state, state, scm_the_rng.rstate_size);
177}
178
179\f
180/*
181 * Random number library functions
182 */
183
5ee11b7c 184scm_rstate *
9b741bb6 185scm_c_make_rstate (char *seed, int n)
5ee11b7c
MD
186{
187 scm_rstate *state = malloc (scm_the_rng.rstate_size);
188 if (state == 0)
2500356c 189 scm_memory_error ("rstate");
5ee11b7c
MD
190 state->reserved0 = 0;
191 scm_the_rng.init_rstate (state, seed, n);
192 return state;
193}
194
9b741bb6
MD
195scm_rstate *
196scm_c_default_rstate ()
197{
198 SCM state = SCM_CDR (scm_var_random_state);
0c95b57d 199 SCM_ASSERT (SCM_RSTATEP (state),
9b741bb6
MD
200 state, "*random-state* contains bogus random state", 0);
201 return SCM_RSTATE (state);
202}
203
e7a72986 204inline double
9b741bb6 205scm_c_uniform01 (scm_rstate *state)
e7a72986 206{
5a92ddfd 207 double x = (double) scm_the_rng.random_bits (state) / (double) 0xffffffffUL;
e7a72986 208 return ((x + (double) scm_the_rng.random_bits (state))
5a92ddfd 209 / (double) 0xffffffffUL);
e7a72986
MD
210}
211
212double
9b741bb6 213scm_c_normal01 (scm_rstate *state)
e7a72986
MD
214{
215 if (state->reserved0)
216 {
217 state->reserved0 = 0;
218 return state->reserved1;
219 }
220 else
221 {
222 double r, a, n;
e7a72986 223
9b741bb6
MD
224 r = sqrt (-2.0 * log (scm_c_uniform01 (state)));
225 a = 2.0 * M_PI * scm_c_uniform01 (state);
e7a72986
MD
226
227 n = r * sin (a);
228 state->reserved1 = r * cos (a);
5a92ddfd 229 state->reserved0 = 1;
e7a72986
MD
230
231 return n;
232 }
233}
234
235double
9b741bb6 236scm_c_exp1 (scm_rstate *state)
e7a72986 237{
9b741bb6 238 return - log (scm_c_uniform01 (state));
e7a72986
MD
239}
240
241unsigned char scm_masktab[256];
242
243unsigned long
9b741bb6 244scm_c_random (scm_rstate *state, unsigned long m)
e7a72986
MD
245{
246 unsigned int r, mask;
247 mask = (m < 0x100
248 ? scm_masktab[m]
249 : (m < 0x10000
5a92ddfd 250 ? scm_masktab[m >> 8] << 8 | 0xff
e7a72986 251 : (m < 0x1000000
5a92ddfd
MD
252 ? scm_masktab[m >> 16] << 16 | 0xffff
253 : scm_masktab[m >> 24] << 24 | 0xffffff)));
e7a72986
MD
254 while ((r = scm_the_rng.random_bits (state) & mask) >= m);
255 return r;
256}
257
258SCM
9b741bb6 259scm_c_random_bignum (scm_rstate *state, SCM m)
e7a72986
MD
260{
261 SCM b;
a7e7ea3e
MD
262 int i, nd;
263 LONG32 *bits, mask, w;
264 nd = SCM_NUMDIGS (m);
265 /* calculate mask for most significant digit */
e7a72986
MD
266#if SIZEOF_INT == 4
267 /* 16 bit digits */
a7e7ea3e 268 if (nd & 1)
e7a72986
MD
269 {
270 /* fix most significant 16 bits */
a7e7ea3e 271 unsigned short s = SCM_BDIGITS (m)[nd - 1];
5a92ddfd 272 mask = s < 0x100 ? scm_masktab[s] : scm_masktab[s >> 8] << 8 | 0xff;
e7a72986
MD
273 }
274 else
275#endif
276 {
277 /* fix most significant 32 bits */
96e263d6 278#if SIZEOF_INT == 4
2a0279c9
MD
279 w = SCM_BDIGITS (m)[nd - 1] << 16 | SCM_BDIGITS (m)[nd - 2];
280#else
96e263d6 281 w = SCM_BDIGITS (m)[nd - 1];
2a0279c9 282#endif
e7a72986
MD
283 mask = (w < 0x10000
284 ? (w < 0x100
285 ? scm_masktab[w]
5a92ddfd 286 : scm_masktab[w >> 8] << 8 | 0xff)
e7a72986 287 : (w < 0x1000000
5a92ddfd
MD
288 ? scm_masktab[w >> 16] << 16 | 0xffff
289 : scm_masktab[w >> 24] << 24 | 0xffffff));
e7a72986 290 }
a7e7ea3e
MD
291 b = scm_mkbig (nd, 0);
292 bits = (LONG32 *) SCM_BDIGITS (b);
293 do
e7a72986 294 {
a7e7ea3e
MD
295 i = nd;
296 /* treat most significant digit specially */
297#if SIZEOF_INT == 4
298 /* 16 bit digits */
299 if (i & 1)
300 {
301 ((SCM_BIGDIG*) bits)[i - 1] = scm_the_rng.random_bits (state) & mask;
302 i /= 2;
303 }
304 else
305#endif
306 {
307 /* fix most significant 32 bits */
96e263d6 308#if SIZEOF_INT == 4
2a0279c9 309 w = scm_the_rng.random_bits (state) & mask;
96e263d6
MD
310 ((SCM_BIGDIG*) bits)[i - 2] = w & 0xffff;
311 ((SCM_BIGDIG*) bits)[i - 1] = w >> 16;
312 i = i / 2 - 1;
2a0279c9 313#else
96e263d6 314 i /= 2;
a7e7ea3e 315 bits[--i] = scm_the_rng.random_bits (state) & mask;
2a0279c9 316#endif
a7e7ea3e
MD
317 }
318 /* now fill up the rest of the bignum */
319 while (i)
320 bits[--i] = scm_the_rng.random_bits (state);
321 b = scm_normbig (b);
322 if (SCM_INUMP (b))
323 return b;
324 } while (scm_bigcomp (b, m) <= 0);
325 return b;
e7a72986
MD
326}
327
328/*
329 * Scheme level representation of random states.
330 */
331
e841c3e0 332scm_bits_t scm_tc16_rstate;
e7a72986
MD
333
334static SCM
335make_rstate (scm_rstate *state)
336{
23a62151 337 SCM_RETURN_NEWSMOB (scm_tc16_rstate, state);
e7a72986
MD
338}
339
340static scm_sizet
e841c3e0 341rstate_free (SCM rstate)
e7a72986
MD
342{
343 free (SCM_RSTATE (rstate));
344 return scm_the_rng.rstate_size;
345}
346
e7a72986
MD
347/*
348 * Scheme level interface.
349 */
350
5ee11b7c 351SCM_GLOBAL_VCELL_INIT (scm_var_random_state, "*random-state*", scm_seed_to_random_state (scm_makfrom0str ("URL:http://stat.fsu.edu/~geo/diehard.html")));
e7a72986 352
a1ec6916 353SCM_DEFINE (scm_random, "random", 1, 1, 0,
1bbd0b84 354 (SCM n, SCM state),
d928e0b4
GB
355 "Return a number in [0,N).\n"
356 "\n"
357 "Accepts a positive integer or real n and returns a \n"
358 "number of the same type between zero (inclusive) and \n"
359 "N (exclusive). The values returned have a uniform \n"
360 "distribution.\n"
361 "\n"
362 "The optional argument STATE must be of the type produced by\n"
a401a730 363 "`seed->random-state'. It defaults to the value of the variable\n"
d928e0b4
GB
364 "*random-state*. This object is used to maintain the state of\n"
365 "the pseudo-random-number generator and is altered as a side\n"
64ba8e85 366 "effect of the random operation.")
1bbd0b84 367#define FUNC_NAME s_scm_random
e7a72986
MD
368{
369 if (SCM_UNBNDP (state))
370 state = SCM_CDR (scm_var_random_state);
3b3b36dd 371 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
372 if (SCM_INUMP (n))
373 {
374 unsigned long m = SCM_INUM (n);
1bbd0b84 375 SCM_ASSERT_RANGE (1,n,m > 0);
9b741bb6 376 return SCM_MAKINUM (scm_c_random (SCM_RSTATE (state), m));
e7a72986 377 }
6b5a304f 378 SCM_VALIDATE_NIM (1,n);
e7a72986 379 if (SCM_REALP (n))
f8de44c1
DH
380 return scm_make_real (SCM_REAL_VALUE (n)
381 * scm_c_uniform01 (SCM_RSTATE (state)));
950cc72b 382 SCM_VALIDATE_SMOB (1, n, big);
9b741bb6 383 return scm_c_random_bignum (SCM_RSTATE (state), n);
e7a72986 384}
1bbd0b84 385#undef FUNC_NAME
e7a72986 386
a1ec6916 387SCM_DEFINE (scm_copy_random_state, "copy-random-state", 0, 1, 0,
1bbd0b84 388 (SCM state),
d928e0b4 389 "Return a copy of the random state STATE.")
1bbd0b84 390#define FUNC_NAME s_scm_copy_random_state
e7a72986
MD
391{
392 if (SCM_UNBNDP (state))
5ee11b7c 393 state = SCM_CDR (scm_var_random_state);
3b3b36dd 394 SCM_VALIDATE_RSTATE (1,state);
e7a72986
MD
395 return make_rstate (scm_the_rng.copy_rstate (SCM_RSTATE (state)));
396}
1bbd0b84 397#undef FUNC_NAME
e7a72986 398
a1ec6916 399SCM_DEFINE (scm_seed_to_random_state, "seed->random-state", 1, 0, 0,
1bbd0b84 400 (SCM seed),
d928e0b4 401 "Return a new random state using SEED.")
1bbd0b84 402#define FUNC_NAME s_scm_seed_to_random_state
5ee11b7c
MD
403{
404 if (SCM_NUMBERP (seed))
405 seed = scm_number_to_string (seed, SCM_UNDEFINED);
3b3b36dd 406 SCM_VALIDATE_STRING (1,seed);
34f0f2b8 407 return make_rstate (scm_c_make_rstate (SCM_STRING_CHARS (seed),
b7ead2ae 408 SCM_STRING_LENGTH (seed)));
5ee11b7c 409}
1bbd0b84 410#undef FUNC_NAME
5ee11b7c 411
a1ec6916 412SCM_DEFINE (scm_random_uniform, "random:uniform", 0, 1, 0,
1bbd0b84 413 (SCM state),
d928e0b4 414 "Returns a uniformly distributed inexact real random number in [0,1).")
1bbd0b84 415#define FUNC_NAME s_scm_random_uniform
e7a72986
MD
416{
417 if (SCM_UNBNDP (state))
418 state = SCM_CDR (scm_var_random_state);
3b3b36dd 419 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 420 return scm_make_real (scm_c_uniform01 (SCM_RSTATE (state)));
e7a72986 421}
1bbd0b84 422#undef FUNC_NAME
e7a72986 423
a1ec6916 424SCM_DEFINE (scm_random_normal, "random:normal", 0, 1, 0,
1bbd0b84 425 (SCM state),
d928e0b4
GB
426 "Returns an inexact real in a normal distribution.\n"
427 "The distribution used has mean 0 and standard deviation 1.\n"
428 "For a normal distribution with mean m and standard deviation\n"
64ba8e85 429 "d use @code{(+ m (* d (random:normal)))}.")
1bbd0b84 430#define FUNC_NAME s_scm_random_normal
afe5177e
GH
431{
432 if (SCM_UNBNDP (state))
433 state = SCM_CDR (scm_var_random_state);
3b3b36dd 434 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 435 return scm_make_real (scm_c_normal01 (SCM_RSTATE (state)));
afe5177e 436}
1bbd0b84 437#undef FUNC_NAME
afe5177e
GH
438
439#ifdef HAVE_ARRAYS
440
e7a72986
MD
441static void
442vector_scale (SCM v, double c)
443{
b7ead2ae 444 int n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
445 if (SCM_VECTORP (v))
446 while (--n >= 0)
eb42e2f0 447 SCM_REAL_VALUE (SCM_VELTS (v)[n]) *= c;
e7a72986
MD
448 else
449 while (--n >= 0)
450 ((double *) SCM_VELTS (v))[n] *= c;
451}
452
453static double
454vector_sum_squares (SCM v)
455{
456 double x, sum = 0.0;
b7ead2ae 457 int n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
458 if (SCM_VECTORP (v))
459 while (--n >= 0)
460 {
eb42e2f0 461 x = SCM_REAL_VALUE (SCM_VELTS (v)[n]);
e7a72986
MD
462 sum += x * x;
463 }
464 else
465 while (--n >= 0)
466 {
467 x = ((double *) SCM_VELTS (v))[n];
468 sum += x * x;
469 }
470 return sum;
471}
472
e7a72986
MD
473/* For the uniform distribution on the solid sphere, note that in
474 * this distribution the length r of the vector has cumulative
475 * distribution r^n; i.e., u=r^n is uniform [0,1], so r can be
476 * generated as r=u^(1/n).
477 */
a1ec6916 478SCM_DEFINE (scm_random_solid_sphere_x, "random:solid-sphere!", 1, 1, 0,
1bbd0b84 479 (SCM v, SCM state),
d928e0b4
GB
480 "Fills vect with inexact real random numbers\n"
481 "the sum of whose squares is less than 1.0.\n"
482 "Thinking of vect as coordinates in space of \n"
483 "dimension n = (vector-length vect), the coordinates \n"
484 "are uniformly distributed within the unit n-shere.\n"
64ba8e85 485 "The sum of the squares of the numbers is returned.")
1bbd0b84 486#define FUNC_NAME s_scm_random_solid_sphere_x
e7a72986 487{
3b3b36dd 488 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
489 if (SCM_UNBNDP (state))
490 state = SCM_CDR (scm_var_random_state);
3b3b36dd 491 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
492 scm_random_normal_vector_x (v, state);
493 vector_scale (v,
9b741bb6 494 pow (scm_c_uniform01 (SCM_RSTATE (state)),
b7ead2ae 495 1.0 / SCM_INUM (scm_uniform_vector_length (v)))
e7a72986
MD
496 / sqrt (vector_sum_squares (v)));
497 return SCM_UNSPECIFIED;
498}
1bbd0b84 499#undef FUNC_NAME
e7a72986 500
a1ec6916 501SCM_DEFINE (scm_random_hollow_sphere_x, "random:hollow-sphere!", 1, 1, 0,
1bbd0b84 502 (SCM v, SCM state),
d928e0b4
GB
503 "Fills vect with inexact real random numbers\n"
504 "the sum of whose squares is equal to 1.0.\n"
505 "Thinking of vect as coordinates in space of \n"
506 "dimension n = (vector-length vect), the coordinates\n"
507 "are uniformly distributed over the surface of the \n"
64ba8e85 508 "unit n-shere.")
1bbd0b84 509#define FUNC_NAME s_scm_random_hollow_sphere_x
e7a72986 510{
3b3b36dd 511 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
512 if (SCM_UNBNDP (state))
513 state = SCM_CDR (scm_var_random_state);
3b3b36dd 514 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
515 scm_random_normal_vector_x (v, state);
516 vector_scale (v, 1 / sqrt (vector_sum_squares (v)));
517 return SCM_UNSPECIFIED;
518}
1bbd0b84 519#undef FUNC_NAME
e7a72986 520
1bbd0b84 521
a1ec6916 522SCM_DEFINE (scm_random_normal_vector_x, "random:normal-vector!", 1, 1, 0,
1bbd0b84 523 (SCM v, SCM state),
d928e0b4
GB
524 "Fills vect with inexact real random numbers that are\n"
525 "independent and standard normally distributed\n"
64ba8e85 526 "(i.e., with mean 0 and variance 1).")
1bbd0b84 527#define FUNC_NAME s_scm_random_normal_vector_x
e7a72986
MD
528{
529 int n;
3b3b36dd 530 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
531 if (SCM_UNBNDP (state))
532 state = SCM_CDR (scm_var_random_state);
3b3b36dd 533 SCM_VALIDATE_RSTATE (2,state);
b7ead2ae 534 n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
535 if (SCM_VECTORP (v))
536 while (--n >= 0)
f8de44c1 537 SCM_VELTS (v)[n] = scm_make_real (scm_c_normal01 (SCM_RSTATE (state)));
e7a72986
MD
538 else
539 while (--n >= 0)
9b741bb6 540 ((double *) SCM_VELTS (v))[n] = scm_c_normal01 (SCM_RSTATE (state));
e7a72986
MD
541 return SCM_UNSPECIFIED;
542}
1bbd0b84 543#undef FUNC_NAME
e7a72986 544
afe5177e
GH
545#endif /* HAVE_ARRAYS */
546
a1ec6916 547SCM_DEFINE (scm_random_exp, "random:exp", 0, 1, 0,
1bbd0b84 548 (SCM state),
d928e0b4 549 "Returns an inexact real in an exponential distribution with mean 1.\n"
64ba8e85 550 "For an exponential distribution with mean u use (* u (random:exp)).")
1bbd0b84 551#define FUNC_NAME s_scm_random_exp
e7a72986
MD
552{
553 if (SCM_UNBNDP (state))
554 state = SCM_CDR (scm_var_random_state);
3b3b36dd 555 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 556 return scm_make_real (scm_c_exp1 (SCM_RSTATE (state)));
e7a72986 557}
1bbd0b84 558#undef FUNC_NAME
e7a72986
MD
559
560void
561scm_init_random ()
562{
563 int i, m;
564 /* plug in default RNG */
565 scm_rng rng =
566 {
567 sizeof (scm_i_rstate),
568 (unsigned long (*)()) scm_i_uniform32,
569 (void (*)()) scm_i_init_rstate,
570 (scm_rstate *(*)()) scm_i_copy_rstate
571 };
572 scm_the_rng = rng;
573
e841c3e0
KN
574 scm_tc16_rstate = scm_make_smob_type ("random-state", 0);
575 scm_set_smob_free (scm_tc16_rstate, rstate_free);
e7a72986
MD
576
577 for (m = 1; m <= 0x100; m <<= 1)
578 for (i = m >> 1; i < m; ++i)
579 scm_masktab[i] = m - 1;
580
8dc9439f 581#ifndef SCM_MAGIC_SNARFER
a0599745 582#include "libguile/random.x"
8dc9439f 583#endif
e7a72986 584
2a0279c9
MD
585 /* Check that the assumptions about bits per bignum digit are correct. */
586#if SIZEOF_INT == 4
587 m = 16;
588#else
589 m = 32;
590#endif
591 if (m != SCM_BITSPERDIG)
592 {
593 fprintf (stderr, "Internal inconsistency: Confused about bignum digit size in random.c\n");
594 exit (1);
595 }
596
e7a72986
MD
597 scm_add_feature ("random");
598}
89e00824
ML
599
600/*
601 Local Variables:
602 c-file-style: "gnu"
603 End:
604*/