* scheme-options.texi, scheme-procedures.texi,
[bpt/guile.git] / libguile / random.c
CommitLineData
2ade72d7 1/* Copyright (C) 1999,2000,2001 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
2ade72d7 195
9b741bb6
MD
196scm_rstate *
197scm_c_default_rstate ()
2ade72d7 198#define FUNC_NAME "scm_c_default_rstate"
9b741bb6
MD
199{
200 SCM state = SCM_CDR (scm_var_random_state);
2ade72d7
DH
201 if (!SCM_RSTATEP (state))
202 SCM_MISC_ERROR ("*random-state* contains bogus random state", SCM_EOL);
9b741bb6
MD
203 return SCM_RSTATE (state);
204}
2ade72d7
DH
205#undef FUNC_NAME
206
9b741bb6 207
e7a72986 208inline double
9b741bb6 209scm_c_uniform01 (scm_rstate *state)
e7a72986 210{
5a92ddfd 211 double x = (double) scm_the_rng.random_bits (state) / (double) 0xffffffffUL;
e7a72986 212 return ((x + (double) scm_the_rng.random_bits (state))
5a92ddfd 213 / (double) 0xffffffffUL);
e7a72986
MD
214}
215
216double
9b741bb6 217scm_c_normal01 (scm_rstate *state)
e7a72986
MD
218{
219 if (state->reserved0)
220 {
221 state->reserved0 = 0;
222 return state->reserved1;
223 }
224 else
225 {
226 double r, a, n;
e7a72986 227
9b741bb6
MD
228 r = sqrt (-2.0 * log (scm_c_uniform01 (state)));
229 a = 2.0 * M_PI * scm_c_uniform01 (state);
e7a72986
MD
230
231 n = r * sin (a);
232 state->reserved1 = r * cos (a);
5a92ddfd 233 state->reserved0 = 1;
e7a72986
MD
234
235 return n;
236 }
237}
238
239double
9b741bb6 240scm_c_exp1 (scm_rstate *state)
e7a72986 241{
9b741bb6 242 return - log (scm_c_uniform01 (state));
e7a72986
MD
243}
244
245unsigned char scm_masktab[256];
246
247unsigned long
9b741bb6 248scm_c_random (scm_rstate *state, unsigned long m)
e7a72986
MD
249{
250 unsigned int r, mask;
251 mask = (m < 0x100
252 ? scm_masktab[m]
253 : (m < 0x10000
5a92ddfd 254 ? scm_masktab[m >> 8] << 8 | 0xff
e7a72986 255 : (m < 0x1000000
5a92ddfd
MD
256 ? scm_masktab[m >> 16] << 16 | 0xffff
257 : scm_masktab[m >> 24] << 24 | 0xffffff)));
e7a72986
MD
258 while ((r = scm_the_rng.random_bits (state) & mask) >= m);
259 return r;
260}
261
262SCM
9b741bb6 263scm_c_random_bignum (scm_rstate *state, SCM m)
e7a72986
MD
264{
265 SCM b;
a7e7ea3e
MD
266 int i, nd;
267 LONG32 *bits, mask, w;
268 nd = SCM_NUMDIGS (m);
269 /* calculate mask for most significant digit */
e7a72986
MD
270#if SIZEOF_INT == 4
271 /* 16 bit digits */
a7e7ea3e 272 if (nd & 1)
e7a72986
MD
273 {
274 /* fix most significant 16 bits */
a7e7ea3e 275 unsigned short s = SCM_BDIGITS (m)[nd - 1];
5a92ddfd 276 mask = s < 0x100 ? scm_masktab[s] : scm_masktab[s >> 8] << 8 | 0xff;
e7a72986
MD
277 }
278 else
279#endif
280 {
281 /* fix most significant 32 bits */
96e263d6 282#if SIZEOF_INT == 4
2a0279c9
MD
283 w = SCM_BDIGITS (m)[nd - 1] << 16 | SCM_BDIGITS (m)[nd - 2];
284#else
96e263d6 285 w = SCM_BDIGITS (m)[nd - 1];
2a0279c9 286#endif
e7a72986
MD
287 mask = (w < 0x10000
288 ? (w < 0x100
289 ? scm_masktab[w]
5a92ddfd 290 : scm_masktab[w >> 8] << 8 | 0xff)
e7a72986 291 : (w < 0x1000000
5a92ddfd
MD
292 ? scm_masktab[w >> 16] << 16 | 0xffff
293 : scm_masktab[w >> 24] << 24 | 0xffffff));
e7a72986 294 }
a7e7ea3e
MD
295 b = scm_mkbig (nd, 0);
296 bits = (LONG32 *) SCM_BDIGITS (b);
297 do
e7a72986 298 {
a7e7ea3e
MD
299 i = nd;
300 /* treat most significant digit specially */
301#if SIZEOF_INT == 4
302 /* 16 bit digits */
303 if (i & 1)
304 {
305 ((SCM_BIGDIG*) bits)[i - 1] = scm_the_rng.random_bits (state) & mask;
306 i /= 2;
307 }
308 else
309#endif
310 {
311 /* fix most significant 32 bits */
96e263d6 312#if SIZEOF_INT == 4
2a0279c9 313 w = scm_the_rng.random_bits (state) & mask;
96e263d6
MD
314 ((SCM_BIGDIG*) bits)[i - 2] = w & 0xffff;
315 ((SCM_BIGDIG*) bits)[i - 1] = w >> 16;
316 i = i / 2 - 1;
2a0279c9 317#else
96e263d6 318 i /= 2;
a7e7ea3e 319 bits[--i] = scm_the_rng.random_bits (state) & mask;
2a0279c9 320#endif
a7e7ea3e
MD
321 }
322 /* now fill up the rest of the bignum */
323 while (i)
324 bits[--i] = scm_the_rng.random_bits (state);
325 b = scm_normbig (b);
326 if (SCM_INUMP (b))
327 return b;
328 } while (scm_bigcomp (b, m) <= 0);
329 return b;
e7a72986
MD
330}
331
332/*
333 * Scheme level representation of random states.
334 */
335
e841c3e0 336scm_bits_t scm_tc16_rstate;
e7a72986
MD
337
338static SCM
339make_rstate (scm_rstate *state)
340{
23a62151 341 SCM_RETURN_NEWSMOB (scm_tc16_rstate, state);
e7a72986
MD
342}
343
344static scm_sizet
e841c3e0 345rstate_free (SCM rstate)
e7a72986
MD
346{
347 free (SCM_RSTATE (rstate));
348 return scm_the_rng.rstate_size;
349}
350
e7a72986
MD
351/*
352 * Scheme level interface.
353 */
354
5ee11b7c 355SCM_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 356
a1ec6916 357SCM_DEFINE (scm_random, "random", 1, 1, 0,
1bbd0b84 358 (SCM n, SCM state),
d928e0b4
GB
359 "Return a number in [0,N).\n"
360 "\n"
361 "Accepts a positive integer or real n and returns a \n"
362 "number of the same type between zero (inclusive) and \n"
363 "N (exclusive). The values returned have a uniform \n"
364 "distribution.\n"
365 "\n"
3b644514
MG
366 "The optional argument @var{state} must be of the type produced\n"
367 "by @code{seed->random-state}. It defaults to the value of the\n"
368 "variable @var{*random-state*}. This object is used to maintain\n"
369 "the state of the pseudo-random-number generator and is altered\n"
370 "as a side effect of the random operation.")
1bbd0b84 371#define FUNC_NAME s_scm_random
e7a72986
MD
372{
373 if (SCM_UNBNDP (state))
374 state = SCM_CDR (scm_var_random_state);
3b3b36dd 375 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
376 if (SCM_INUMP (n))
377 {
378 unsigned long m = SCM_INUM (n);
1bbd0b84 379 SCM_ASSERT_RANGE (1,n,m > 0);
9b741bb6 380 return SCM_MAKINUM (scm_c_random (SCM_RSTATE (state), m));
e7a72986 381 }
6b5a304f 382 SCM_VALIDATE_NIM (1,n);
e7a72986 383 if (SCM_REALP (n))
f8de44c1
DH
384 return scm_make_real (SCM_REAL_VALUE (n)
385 * scm_c_uniform01 (SCM_RSTATE (state)));
950cc72b 386 SCM_VALIDATE_SMOB (1, n, big);
9b741bb6 387 return scm_c_random_bignum (SCM_RSTATE (state), n);
e7a72986 388}
1bbd0b84 389#undef FUNC_NAME
e7a72986 390
a1ec6916 391SCM_DEFINE (scm_copy_random_state, "copy-random-state", 0, 1, 0,
1bbd0b84 392 (SCM state),
3b644514 393 "Return a copy of the random state @var{state}.")
1bbd0b84 394#define FUNC_NAME s_scm_copy_random_state
e7a72986
MD
395{
396 if (SCM_UNBNDP (state))
5ee11b7c 397 state = SCM_CDR (scm_var_random_state);
3b3b36dd 398 SCM_VALIDATE_RSTATE (1,state);
e7a72986
MD
399 return make_rstate (scm_the_rng.copy_rstate (SCM_RSTATE (state)));
400}
1bbd0b84 401#undef FUNC_NAME
e7a72986 402
a1ec6916 403SCM_DEFINE (scm_seed_to_random_state, "seed->random-state", 1, 0, 0,
1bbd0b84 404 (SCM seed),
3b644514 405 "Return a new random state using @var{seed}.")
1bbd0b84 406#define FUNC_NAME s_scm_seed_to_random_state
5ee11b7c
MD
407{
408 if (SCM_NUMBERP (seed))
409 seed = scm_number_to_string (seed, SCM_UNDEFINED);
3b3b36dd 410 SCM_VALIDATE_STRING (1,seed);
34f0f2b8 411 return make_rstate (scm_c_make_rstate (SCM_STRING_CHARS (seed),
b7ead2ae 412 SCM_STRING_LENGTH (seed)));
5ee11b7c 413}
1bbd0b84 414#undef FUNC_NAME
5ee11b7c 415
a1ec6916 416SCM_DEFINE (scm_random_uniform, "random:uniform", 0, 1, 0,
1bbd0b84 417 (SCM state),
d928e0b4 418 "Returns a uniformly distributed inexact real random number in [0,1).")
1bbd0b84 419#define FUNC_NAME s_scm_random_uniform
e7a72986
MD
420{
421 if (SCM_UNBNDP (state))
422 state = SCM_CDR (scm_var_random_state);
3b3b36dd 423 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 424 return scm_make_real (scm_c_uniform01 (SCM_RSTATE (state)));
e7a72986 425}
1bbd0b84 426#undef FUNC_NAME
e7a72986 427
a1ec6916 428SCM_DEFINE (scm_random_normal, "random:normal", 0, 1, 0,
1bbd0b84 429 (SCM state),
d928e0b4
GB
430 "Returns an inexact real in a normal distribution.\n"
431 "The distribution used has mean 0 and standard deviation 1.\n"
432 "For a normal distribution with mean m and standard deviation\n"
64ba8e85 433 "d use @code{(+ m (* d (random:normal)))}.")
1bbd0b84 434#define FUNC_NAME s_scm_random_normal
afe5177e
GH
435{
436 if (SCM_UNBNDP (state))
437 state = SCM_CDR (scm_var_random_state);
3b3b36dd 438 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 439 return scm_make_real (scm_c_normal01 (SCM_RSTATE (state)));
afe5177e 440}
1bbd0b84 441#undef FUNC_NAME
afe5177e
GH
442
443#ifdef HAVE_ARRAYS
444
e7a72986
MD
445static void
446vector_scale (SCM v, double c)
447{
b7ead2ae 448 int n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
449 if (SCM_VECTORP (v))
450 while (--n >= 0)
eb42e2f0 451 SCM_REAL_VALUE (SCM_VELTS (v)[n]) *= c;
e7a72986
MD
452 else
453 while (--n >= 0)
454 ((double *) SCM_VELTS (v))[n] *= c;
455}
456
457static double
458vector_sum_squares (SCM v)
459{
460 double x, sum = 0.0;
b7ead2ae 461 int n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
462 if (SCM_VECTORP (v))
463 while (--n >= 0)
464 {
eb42e2f0 465 x = SCM_REAL_VALUE (SCM_VELTS (v)[n]);
e7a72986
MD
466 sum += x * x;
467 }
468 else
469 while (--n >= 0)
470 {
471 x = ((double *) SCM_VELTS (v))[n];
472 sum += x * x;
473 }
474 return sum;
475}
476
e7a72986
MD
477/* For the uniform distribution on the solid sphere, note that in
478 * this distribution the length r of the vector has cumulative
479 * distribution r^n; i.e., u=r^n is uniform [0,1], so r can be
480 * generated as r=u^(1/n).
481 */
a1ec6916 482SCM_DEFINE (scm_random_solid_sphere_x, "random:solid-sphere!", 1, 1, 0,
1bbd0b84 483 (SCM v, SCM state),
d928e0b4
GB
484 "Fills vect with inexact real random numbers\n"
485 "the sum of whose squares is less than 1.0.\n"
486 "Thinking of vect as coordinates in space of \n"
487 "dimension n = (vector-length vect), the coordinates \n"
488 "are uniformly distributed within the unit n-shere.\n"
64ba8e85 489 "The sum of the squares of the numbers is returned.")
1bbd0b84 490#define FUNC_NAME s_scm_random_solid_sphere_x
e7a72986 491{
3b3b36dd 492 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
493 if (SCM_UNBNDP (state))
494 state = SCM_CDR (scm_var_random_state);
3b3b36dd 495 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
496 scm_random_normal_vector_x (v, state);
497 vector_scale (v,
9b741bb6 498 pow (scm_c_uniform01 (SCM_RSTATE (state)),
b7ead2ae 499 1.0 / SCM_INUM (scm_uniform_vector_length (v)))
e7a72986
MD
500 / sqrt (vector_sum_squares (v)));
501 return SCM_UNSPECIFIED;
502}
1bbd0b84 503#undef FUNC_NAME
e7a72986 504
a1ec6916 505SCM_DEFINE (scm_random_hollow_sphere_x, "random:hollow-sphere!", 1, 1, 0,
1bbd0b84 506 (SCM v, SCM state),
d928e0b4
GB
507 "Fills vect with inexact real random numbers\n"
508 "the sum of whose squares is equal to 1.0.\n"
509 "Thinking of vect as coordinates in space of \n"
510 "dimension n = (vector-length vect), the coordinates\n"
511 "are uniformly distributed over the surface of the \n"
64ba8e85 512 "unit n-shere.")
1bbd0b84 513#define FUNC_NAME s_scm_random_hollow_sphere_x
e7a72986 514{
3b3b36dd 515 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
516 if (SCM_UNBNDP (state))
517 state = SCM_CDR (scm_var_random_state);
3b3b36dd 518 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
519 scm_random_normal_vector_x (v, state);
520 vector_scale (v, 1 / sqrt (vector_sum_squares (v)));
521 return SCM_UNSPECIFIED;
522}
1bbd0b84 523#undef FUNC_NAME
e7a72986 524
1bbd0b84 525
a1ec6916 526SCM_DEFINE (scm_random_normal_vector_x, "random:normal-vector!", 1, 1, 0,
1bbd0b84 527 (SCM v, SCM state),
d928e0b4
GB
528 "Fills vect with inexact real random numbers that are\n"
529 "independent and standard normally distributed\n"
64ba8e85 530 "(i.e., with mean 0 and variance 1).")
1bbd0b84 531#define FUNC_NAME s_scm_random_normal_vector_x
e7a72986
MD
532{
533 int n;
3b3b36dd 534 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
535 if (SCM_UNBNDP (state))
536 state = SCM_CDR (scm_var_random_state);
3b3b36dd 537 SCM_VALIDATE_RSTATE (2,state);
b7ead2ae 538 n = SCM_INUM (scm_uniform_vector_length (v));
e7a72986
MD
539 if (SCM_VECTORP (v))
540 while (--n >= 0)
f8de44c1 541 SCM_VELTS (v)[n] = scm_make_real (scm_c_normal01 (SCM_RSTATE (state)));
e7a72986
MD
542 else
543 while (--n >= 0)
9b741bb6 544 ((double *) SCM_VELTS (v))[n] = scm_c_normal01 (SCM_RSTATE (state));
e7a72986
MD
545 return SCM_UNSPECIFIED;
546}
1bbd0b84 547#undef FUNC_NAME
e7a72986 548
afe5177e
GH
549#endif /* HAVE_ARRAYS */
550
a1ec6916 551SCM_DEFINE (scm_random_exp, "random:exp", 0, 1, 0,
1bbd0b84 552 (SCM state),
d928e0b4 553 "Returns an inexact real in an exponential distribution with mean 1.\n"
64ba8e85 554 "For an exponential distribution with mean u use (* u (random:exp)).")
1bbd0b84 555#define FUNC_NAME s_scm_random_exp
e7a72986
MD
556{
557 if (SCM_UNBNDP (state))
558 state = SCM_CDR (scm_var_random_state);
3b3b36dd 559 SCM_VALIDATE_RSTATE (1,state);
f8de44c1 560 return scm_make_real (scm_c_exp1 (SCM_RSTATE (state)));
e7a72986 561}
1bbd0b84 562#undef FUNC_NAME
e7a72986
MD
563
564void
565scm_init_random ()
566{
567 int i, m;
568 /* plug in default RNG */
569 scm_rng rng =
570 {
571 sizeof (scm_i_rstate),
572 (unsigned long (*)()) scm_i_uniform32,
573 (void (*)()) scm_i_init_rstate,
574 (scm_rstate *(*)()) scm_i_copy_rstate
575 };
576 scm_the_rng = rng;
577
e841c3e0
KN
578 scm_tc16_rstate = scm_make_smob_type ("random-state", 0);
579 scm_set_smob_free (scm_tc16_rstate, rstate_free);
e7a72986
MD
580
581 for (m = 1; m <= 0x100; m <<= 1)
582 for (i = m >> 1; i < m; ++i)
583 scm_masktab[i] = m - 1;
584
8dc9439f 585#ifndef SCM_MAGIC_SNARFER
a0599745 586#include "libguile/random.x"
8dc9439f 587#endif
e7a72986 588
2a0279c9
MD
589 /* Check that the assumptions about bits per bignum digit are correct. */
590#if SIZEOF_INT == 4
591 m = 16;
592#else
593 m = 32;
594#endif
595 if (m != SCM_BITSPERDIG)
596 {
597 fprintf (stderr, "Internal inconsistency: Confused about bignum digit size in random.c\n");
598 exit (1);
599 }
600
e7a72986
MD
601 scm_add_feature ("random");
602}
89e00824
ML
603
604/*
605 Local Variables:
606 c-file-style: "gnu"
607 End:
608*/