*** empty log message ***
[bpt/guile.git] / libguile / random.c
CommitLineData
e7a72986
MD
1/* Copyright (C) 1999 Free Software Foundation, Inc.
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
e7a72986
MD
47#include "_scm.h"
48
7f146094 49#include <stdio.h>
e7a72986
MD
50#include <math.h>
51#include "genio.h"
52#include "smob.h"
53#include "numbers.h"
54#include "feature.h"
55
b6791b2e 56#include "validate.h"
e7a72986
MD
57#include "random.h"
58
59\f
60/*
61 * A plugin interface for RNGs
62 *
63 * Using this interface, it is possible for the application to tell
64 * libguile to use a different RNG. This is desirable if it is
65 * necessary to use the same RNG everywhere in the application in
66 * order to prevent interference, if the application uses RNG
67 * hardware, or if the application has special demands on the RNG.
68 *
69 * Look in random.h and how the default generator is "plugged in" in
70 * scm_init_random().
71 */
72
73scm_rng scm_the_rng;
74
75\f
76/*
77 * The prepackaged RNG
78 *
79 * This is the MWC (Multiply With Carry) random number generator
80 * described by George Marsaglia at the Department of Statistics and
81 * Supercomputer Computations Research Institute, The Florida State
82 * University (http://stat.fsu.edu/~geo).
83 *
84 * It uses 64 bits, has a period of 4578426017172946943 (4.6e18), and
85 * passes all tests in the DIEHARD test suite
86 * (http://stat.fsu.edu/~geo/diehard.html)
87 */
88
89#define A 2131995753UL
90
91#if SIZEOF_LONG > 4
92#if SIZEOF_INT > 4
93#define LONG32 unsigned short
94#else
95#define LONG32 unsigned int
96#endif
97#define LONG64 unsigned long
98#else
99#define LONG32 unsigned long
100#define LONG64 unsigned long long
101#endif
102
103#if SIZEOF_LONG > 4 || defined (HAVE_LONG_LONGS)
104
105unsigned long
106scm_i_uniform32 (scm_i_rstate *state)
107{
108 LONG64 x = (LONG64) A * state->w + state->c;
109 LONG32 w = x & 0xffffffffUL;
110 state->w = w;
111 state->c = x >> 32L;
112 return w;
113}
114
115#else
116
117/* ww This is a portable version of the same RNG without 64 bit
118 * * aa arithmetic.
119 * ----
120 * xx It is only intended to provide identical behaviour on
121 * xx platforms without 8 byte longs or long longs until
122 * xx someone has implemented the routine in assembler code.
123 * xxcc
124 * ----
125 * ccww
126 */
127
128#define L(x) ((x) & 0xffff)
129#define H(x) ((x) >> 16)
130
131unsigned long
132scm_i_uniform32 (scm_i_rstate *state)
133{
134 LONG32 x1 = L (A) * L (state->w);
135 LONG32 x2 = L (A) * H (state->w);
136 LONG32 x3 = H (A) * L (state->w);
137 LONG32 w = L (x1) + L (state->c);
138 LONG32 m = H (x1) + L (x2) + L (x3) + H (state->c) + H (w);
139 LONG32 x4 = H (A) * H (state->w);
140 state->w = w = (L (m) << 16) + L (w);
141 state->c = H (x2) + H (x3) + x4 + H (m);
142 return w;
143}
144
145#endif
146
147void
148scm_i_init_rstate (scm_i_rstate *state, char *seed, int n)
149{
150 LONG32 w = 0L;
151 LONG32 c = 0L;
152 int i, m;
153 for (i = 0; i < n; ++i)
154 {
155 m = i % 8;
156 if (m < 4)
157 w += seed[i] << (8 * m);
158 else
159 c += seed[i] << (8 * (m - 4));
160 }
161 if ((w == 0 && c == 0) || (w == 0xffffffffUL && c == A - 1))
162 ++c;
163 state->w = w;
164 state->c = c;
165}
166
167scm_i_rstate *
168scm_i_copy_rstate (scm_i_rstate *state)
169{
170 scm_rstate *new_state = malloc (scm_the_rng.rstate_size);
171 if (new_state == 0)
172 scm_wta (SCM_MAKINUM (scm_the_rng.rstate_size),
173 (char *) SCM_NALLOC, "rstate");
174 return memcpy (new_state, state, scm_the_rng.rstate_size);
175}
176
177\f
178/*
179 * Random number library functions
180 */
181
5ee11b7c 182scm_rstate *
9b741bb6 183scm_c_make_rstate (char *seed, int n)
5ee11b7c
MD
184{
185 scm_rstate *state = malloc (scm_the_rng.rstate_size);
186 if (state == 0)
187 scm_wta (SCM_MAKINUM (scm_the_rng.rstate_size),
188 (char *) SCM_NALLOC,
189 "rstate");
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
332long scm_tc16_rstate;
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
341free_rstate (SCM rstate)
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"
363 "`seed->andom-state'. It defaults to the value of the variable\n"
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"
366 "effect of the random operation.\n"
367 "")
1bbd0b84 368#define FUNC_NAME s_scm_random
e7a72986
MD
369{
370 if (SCM_UNBNDP (state))
371 state = SCM_CDR (scm_var_random_state);
3b3b36dd 372 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
373 if (SCM_INUMP (n))
374 {
375 unsigned long m = SCM_INUM (n);
1bbd0b84 376 SCM_ASSERT_RANGE (1,n,m > 0);
9b741bb6 377 return SCM_MAKINUM (scm_c_random (SCM_RSTATE (state), m));
e7a72986 378 }
6b5a304f 379 SCM_VALIDATE_NIM (1,n);
e7a72986 380 if (SCM_REALP (n))
9b741bb6 381 return scm_makdbl (SCM_REALPART (n) * scm_c_uniform01 (SCM_RSTATE (state)),
e7a72986 382 0.0);
1bbd0b84 383 SCM_VALIDATE_SMOB (1,n,bigpos);
9b741bb6 384 return scm_c_random_bignum (SCM_RSTATE (state), n);
e7a72986 385}
1bbd0b84 386#undef FUNC_NAME
e7a72986 387
a1ec6916 388SCM_DEFINE (scm_copy_random_state, "copy-random-state", 0, 1, 0,
1bbd0b84 389 (SCM state),
d928e0b4 390 "Return a copy of the random state STATE.")
1bbd0b84 391#define FUNC_NAME s_scm_copy_random_state
e7a72986
MD
392{
393 if (SCM_UNBNDP (state))
5ee11b7c 394 state = SCM_CDR (scm_var_random_state);
3b3b36dd 395 SCM_VALIDATE_RSTATE (1,state);
e7a72986
MD
396 return make_rstate (scm_the_rng.copy_rstate (SCM_RSTATE (state)));
397}
1bbd0b84 398#undef FUNC_NAME
e7a72986 399
a1ec6916 400SCM_DEFINE (scm_seed_to_random_state, "seed->random-state", 1, 0, 0,
1bbd0b84 401 (SCM seed),
d928e0b4 402 "Return a new random state using SEED.")
1bbd0b84 403#define FUNC_NAME s_scm_seed_to_random_state
5ee11b7c
MD
404{
405 if (SCM_NUMBERP (seed))
406 seed = scm_number_to_string (seed, SCM_UNDEFINED);
3b3b36dd 407 SCM_VALIDATE_STRING (1,seed);
9b741bb6 408 return make_rstate (scm_c_make_rstate (SCM_ROCHARS (seed),
5ee11b7c
MD
409 SCM_LENGTH (seed)));
410}
1bbd0b84 411#undef FUNC_NAME
5ee11b7c 412
a1ec6916 413SCM_DEFINE (scm_random_uniform, "random:uniform", 0, 1, 0,
1bbd0b84 414 (SCM state),
d928e0b4 415 "Returns a uniformly distributed inexact real random number in [0,1).")
1bbd0b84 416#define FUNC_NAME s_scm_random_uniform
e7a72986
MD
417{
418 if (SCM_UNBNDP (state))
419 state = SCM_CDR (scm_var_random_state);
3b3b36dd 420 SCM_VALIDATE_RSTATE (1,state);
9b741bb6 421 return scm_makdbl (scm_c_uniform01 (SCM_RSTATE (state)), 0.0);
e7a72986 422}
1bbd0b84 423#undef FUNC_NAME
e7a72986 424
a1ec6916 425SCM_DEFINE (scm_random_normal, "random:normal", 0, 1, 0,
1bbd0b84 426 (SCM state),
d928e0b4
GB
427 "Returns an inexact real in a normal distribution.\n"
428 "The distribution used has mean 0 and standard deviation 1.\n"
429 "For a normal distribution with mean m and standard deviation\n"
430 "d use @code{(+ m (* d (random:normal)))}.\n"
431 "")
1bbd0b84 432#define FUNC_NAME s_scm_random_normal
afe5177e
GH
433{
434 if (SCM_UNBNDP (state))
435 state = SCM_CDR (scm_var_random_state);
3b3b36dd 436 SCM_VALIDATE_RSTATE (1,state);
afe5177e
GH
437 return scm_makdbl (scm_c_normal01 (SCM_RSTATE (state)), 0.0);
438}
1bbd0b84 439#undef FUNC_NAME
afe5177e
GH
440
441#ifdef HAVE_ARRAYS
442
e7a72986
MD
443static void
444vector_scale (SCM v, double c)
445{
446 int n = SCM_LENGTH (v);
447 if (SCM_VECTORP (v))
448 while (--n >= 0)
449 SCM_REAL (SCM_VELTS (v)[n]) *= c;
450 else
451 while (--n >= 0)
452 ((double *) SCM_VELTS (v))[n] *= c;
453}
454
455static double
456vector_sum_squares (SCM v)
457{
458 double x, sum = 0.0;
459 int n = SCM_LENGTH (v);
460 if (SCM_VECTORP (v))
461 while (--n >= 0)
462 {
463 x = SCM_REAL (SCM_VELTS (v)[n]);
464 sum += x * x;
465 }
466 else
467 while (--n >= 0)
468 {
469 x = ((double *) SCM_VELTS (v))[n];
470 sum += x * x;
471 }
472 return sum;
473}
474
e7a72986
MD
475/* For the uniform distribution on the solid sphere, note that in
476 * this distribution the length r of the vector has cumulative
477 * distribution r^n; i.e., u=r^n is uniform [0,1], so r can be
478 * generated as r=u^(1/n).
479 */
a1ec6916 480SCM_DEFINE (scm_random_solid_sphere_x, "random:solid-sphere!", 1, 1, 0,
1bbd0b84 481 (SCM v, SCM state),
d928e0b4
GB
482 "Fills vect with inexact real random numbers\n"
483 "the sum of whose squares is less than 1.0.\n"
484 "Thinking of vect as coordinates in space of \n"
485 "dimension n = (vector-length vect), the coordinates \n"
486 "are uniformly distributed within the unit n-shere.\n"
487 "The sum of the squares of the numbers is returned.\n"
488 "")
1bbd0b84 489#define FUNC_NAME s_scm_random_solid_sphere_x
e7a72986 490{
3b3b36dd 491 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
492 if (SCM_UNBNDP (state))
493 state = SCM_CDR (scm_var_random_state);
3b3b36dd 494 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
495 scm_random_normal_vector_x (v, state);
496 vector_scale (v,
9b741bb6 497 pow (scm_c_uniform01 (SCM_RSTATE (state)),
e7a72986
MD
498 1.0 / SCM_LENGTH (v))
499 / sqrt (vector_sum_squares (v)));
500 return SCM_UNSPECIFIED;
501}
1bbd0b84 502#undef FUNC_NAME
e7a72986 503
a1ec6916 504SCM_DEFINE (scm_random_hollow_sphere_x, "random:hollow-sphere!", 1, 1, 0,
1bbd0b84 505 (SCM v, SCM state),
d928e0b4
GB
506 "Fills vect with inexact real random numbers\n"
507 "the sum of whose squares is equal to 1.0.\n"
508 "Thinking of vect as coordinates in space of \n"
509 "dimension n = (vector-length vect), the coordinates\n"
510 "are uniformly distributed over the surface of the \n"
511 "unit n-shere.\n"
512 "")
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"
530 "(i.e., with mean 0 and variance 1).\n"
531 "")
1bbd0b84 532#define FUNC_NAME s_scm_random_normal_vector_x
e7a72986
MD
533{
534 int n;
3b3b36dd 535 SCM_VALIDATE_VECTOR_OR_DVECTOR (1,v);
e7a72986
MD
536 if (SCM_UNBNDP (state))
537 state = SCM_CDR (scm_var_random_state);
3b3b36dd 538 SCM_VALIDATE_RSTATE (2,state);
e7a72986
MD
539 n = SCM_LENGTH (v);
540 if (SCM_VECTORP (v))
541 while (--n >= 0)
9b741bb6 542 SCM_VELTS (v)[n] = scm_makdbl (scm_c_normal01 (SCM_RSTATE (state)), 0.0);
e7a72986
MD
543 else
544 while (--n >= 0)
9b741bb6 545 ((double *) SCM_VELTS (v))[n] = scm_c_normal01 (SCM_RSTATE (state));
e7a72986
MD
546 return SCM_UNSPECIFIED;
547}
1bbd0b84 548#undef FUNC_NAME
e7a72986 549
afe5177e
GH
550#endif /* HAVE_ARRAYS */
551
a1ec6916 552SCM_DEFINE (scm_random_exp, "random:exp", 0, 1, 0,
1bbd0b84 553 (SCM state),
d928e0b4
GB
554 "Returns an inexact real in an exponential distribution with mean 1.\n"
555 "For an exponential distribution with mean u use (* u (random:exp)).\n"
556 "")
1bbd0b84 557#define FUNC_NAME s_scm_random_exp
e7a72986
MD
558{
559 if (SCM_UNBNDP (state))
560 state = SCM_CDR (scm_var_random_state);
3b3b36dd 561 SCM_VALIDATE_RSTATE (1,state);
9b741bb6 562 return scm_makdbl (scm_c_exp1 (SCM_RSTATE (state)), 0.0);
e7a72986 563}
1bbd0b84 564#undef FUNC_NAME
e7a72986
MD
565
566void
567scm_init_random ()
568{
569 int i, m;
570 /* plug in default RNG */
571 scm_rng rng =
572 {
573 sizeof (scm_i_rstate),
574 (unsigned long (*)()) scm_i_uniform32,
575 (void (*)()) scm_i_init_rstate,
576 (scm_rstate *(*)()) scm_i_copy_rstate
577 };
578 scm_the_rng = rng;
579
23a62151
MD
580 scm_tc16_rstate = scm_make_smob_type_mfpe ("random-state", 0,
581 NULL, free_rstate, NULL, NULL);
e7a72986
MD
582
583 for (m = 1; m <= 0x100; m <<= 1)
584 for (i = m >> 1; i < m; ++i)
585 scm_masktab[i] = m - 1;
586
587#include "random.x"
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}