(scm_init_guile_1): Call scm_i_init_discouraged.
[bpt/guile.git] / libguile / random.c
CommitLineData
ea7f6344 1/* Copyright (C) 1999,2000,2001, 2003 Free Software Foundation, Inc.
73be1d9e
MV
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
e7a72986 6 *
73be1d9e 7 * This library is distributed in the hope that it will be useful,
e7a72986 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
e7a72986 11 *
73be1d9e
MV
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 */
e7a72986 16
1bbd0b84
GB
17
18
e7a72986
MD
19/* Author: Mikael Djurfeldt <djurfeldt@nada.kth.se> */
20
2fb8013c
RB
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
a0599745 25#include "libguile/_scm.h"
e7a72986 26
8db9cc6c 27#include <gmp.h>
7f146094 28#include <stdio.h>
e7a72986 29#include <math.h>
f34d19c7 30#include <string.h>
a0599745
MD
31#include "libguile/smob.h"
32#include "libguile/numbers.h"
33#include "libguile/feature.h"
34#include "libguile/strings.h"
e9bfab50 35#include "libguile/unif.h"
a0599745 36#include "libguile/vectors.h"
e7a72986 37
a0599745
MD
38#include "libguile/validate.h"
39#include "libguile/random.h"
e7a72986
MD
40
41\f
42/*
43 * A plugin interface for RNGs
44 *
45 * Using this interface, it is possible for the application to tell
46 * libguile to use a different RNG. This is desirable if it is
47 * necessary to use the same RNG everywhere in the application in
48 * order to prevent interference, if the application uses RNG
49 * hardware, or if the application has special demands on the RNG.
50 *
51 * Look in random.h and how the default generator is "plugged in" in
52 * scm_init_random().
53 */
54
92c2555f 55scm_t_rng scm_the_rng;
e7a72986
MD
56
57\f
58/*
59 * The prepackaged RNG
60 *
61 * This is the MWC (Multiply With Carry) random number generator
62 * described by George Marsaglia at the Department of Statistics and
63 * Supercomputer Computations Research Institute, The Florida State
64 * University (http://stat.fsu.edu/~geo).
65 *
66 * It uses 64 bits, has a period of 4578426017172946943 (4.6e18), and
67 * passes all tests in the DIEHARD test suite
68 * (http://stat.fsu.edu/~geo/diehard.html)
69 */
70
71#define A 2131995753UL
72
82893676
MG
73#ifndef M_PI
74#define M_PI 3.14159265359
75#endif
76
2fb8013c 77#ifdef SCM_HAVE_T_INT64
e7a72986
MD
78
79unsigned long
92c2555f 80scm_i_uniform32 (scm_t_i_rstate *state)
e7a72986 81{
2fb8013c
RB
82 scm_t_int64 x = (scm_t_int64) A * state->w + state->c;
83 scm_t_int32 w = x & 0xffffffffUL;
e7a72986
MD
84 state->w = w;
85 state->c = x >> 32L;
86 return w;
87}
88
89#else
90
91/* ww This is a portable version of the same RNG without 64 bit
92 * * aa arithmetic.
93 * ----
94 * xx It is only intended to provide identical behaviour on
95 * xx platforms without 8 byte longs or long longs until
96 * xx someone has implemented the routine in assembler code.
97 * xxcc
98 * ----
99 * ccww
100 */
101
102#define L(x) ((x) & 0xffff)
103#define H(x) ((x) >> 16)
104
105unsigned long
92c2555f 106scm_i_uniform32 (scm_t_i_rstate *state)
e7a72986 107{
2fb8013c
RB
108 scm_t_int32 x1 = L (A) * L (state->w);
109 scm_t_int32 x2 = L (A) * H (state->w);
110 scm_t_int32 x3 = H (A) * L (state->w);
111 scm_t_int32 w = L (x1) + L (state->c);
112 scm_t_int32 m = H (x1) + L (x2) + L (x3) + H (state->c) + H (w);
113 scm_t_int32 x4 = H (A) * H (state->w);
e7a72986
MD
114 state->w = w = (L (m) << 16) + L (w);
115 state->c = H (x2) + H (x3) + x4 + H (m);
116 return w;
117}
118
119#endif
120
121void
92c2555f 122scm_i_init_rstate (scm_t_i_rstate *state, char *seed, int n)
e7a72986 123{
2fb8013c
RB
124 scm_t_int32 w = 0L;
125 scm_t_int32 c = 0L;
e7a72986
MD
126 int i, m;
127 for (i = 0; i < n; ++i)
128 {
129 m = i % 8;
130 if (m < 4)
131 w += seed[i] << (8 * m);
132 else
133 c += seed[i] << (8 * (m - 4));
134 }
135 if ((w == 0 && c == 0) || (w == 0xffffffffUL && c == A - 1))
136 ++c;
137 state->w = w;
138 state->c = c;
139}
140
92c2555f
MV
141scm_t_i_rstate *
142scm_i_copy_rstate (scm_t_i_rstate *state)
e7a72986 143{
67329a9e 144 scm_t_rstate *new_state = scm_malloc (scm_the_rng.rstate_size);
e7a72986 145 if (new_state == 0)
2500356c 146 scm_memory_error ("rstate");
e7a72986
MD
147 return memcpy (new_state, state, scm_the_rng.rstate_size);
148}
149
150\f
151/*
152 * Random number library functions
153 */
154
92c2555f 155scm_t_rstate *
9b741bb6 156scm_c_make_rstate (char *seed, int n)
5ee11b7c 157{
67329a9e 158 scm_t_rstate *state = scm_malloc (scm_the_rng.rstate_size);
5ee11b7c 159 if (state == 0)
2500356c 160 scm_memory_error ("rstate");
5ee11b7c
MD
161 state->reserved0 = 0;
162 scm_the_rng.init_rstate (state, seed, n);
163 return state;
164}
165
2ade72d7 166
92c2555f 167scm_t_rstate *
9b741bb6 168scm_c_default_rstate ()
2ade72d7 169#define FUNC_NAME "scm_c_default_rstate"
9b741bb6 170{
c5f268f8 171 SCM state = SCM_VARIABLE_REF (scm_var_random_state);
2ade72d7
DH
172 if (!SCM_RSTATEP (state))
173 SCM_MISC_ERROR ("*random-state* contains bogus random state", SCM_EOL);
9b741bb6
MD
174 return SCM_RSTATE (state);
175}
2ade72d7
DH
176#undef FUNC_NAME
177
9b741bb6 178
e7a72986 179inline double
92c2555f 180scm_c_uniform01 (scm_t_rstate *state)
e7a72986 181{
5a92ddfd 182 double x = (double) scm_the_rng.random_bits (state) / (double) 0xffffffffUL;
e7a72986 183 return ((x + (double) scm_the_rng.random_bits (state))
5a92ddfd 184 / (double) 0xffffffffUL);
e7a72986
MD
185}
186
187double
92c2555f 188scm_c_normal01 (scm_t_rstate *state)
e7a72986
MD
189{
190 if (state->reserved0)
191 {
192 state->reserved0 = 0;
193 return state->reserved1;
194 }
195 else
196 {
197 double r, a, n;
e7a72986 198
9b741bb6
MD
199 r = sqrt (-2.0 * log (scm_c_uniform01 (state)));
200 a = 2.0 * M_PI * scm_c_uniform01 (state);
e7a72986
MD
201
202 n = r * sin (a);
203 state->reserved1 = r * cos (a);
5a92ddfd 204 state->reserved0 = 1;
e7a72986
MD
205
206 return n;
207 }
208}
209
210double
92c2555f 211scm_c_exp1 (scm_t_rstate *state)
e7a72986 212{
9b741bb6 213 return - log (scm_c_uniform01 (state));
e7a72986
MD
214}
215
216unsigned char scm_masktab[256];
217
218unsigned long
92c2555f 219scm_c_random (scm_t_rstate *state, unsigned long m)
e7a72986
MD
220{
221 unsigned int r, mask;
222 mask = (m < 0x100
223 ? scm_masktab[m]
224 : (m < 0x10000
5a92ddfd 225 ? scm_masktab[m >> 8] << 8 | 0xff
e7a72986 226 : (m < 0x1000000
5a92ddfd
MD
227 ? scm_masktab[m >> 16] << 16 | 0xffff
228 : scm_masktab[m >> 24] << 24 | 0xffffff)));
e7a72986
MD
229 while ((r = scm_the_rng.random_bits (state) & mask) >= m);
230 return r;
231}
232
ea7f6344
MD
233/*
234 SCM scm_c_random_bignum (scm_t_rstate *state, SCM m)
235
236 Takes a random state (source of random bits) and a bignum m.
237 Returns a bignum b, 0 <= b < m.
238
239 It does this by allocating a bignum b with as many base 65536 digits
240 as m, filling b with random bits (in 32 bit chunks) up to the most
241 significant 1 in m, and, finally checking if the resultant b is too
242 large (>= m). If too large, we simply repeat the process again. (It
243 is important to throw away all generated random bits if b >= m,
244 otherwise we'll end up with a distorted distribution.)
245
246*/
247
e7a72986 248SCM
92c2555f 249scm_c_random_bignum (scm_t_rstate *state, SCM m)
e7a72986 250{
969d3bd0 251 SCM result = scm_i_mkbig ();
969d3bd0
RB
252 const size_t m_bits = mpz_sizeinbase (SCM_I_BIG_MPZ (m), 2);
253 /* how many bits would only partially fill the last unsigned long? */
0d79003d 254 const size_t end_bits = m_bits % (sizeof (unsigned long) * SCM_CHAR_BIT);
969d3bd0 255 unsigned long *random_chunks = NULL;
0d79003d
RB
256 const unsigned long num_full_chunks =
257 m_bits / (sizeof (unsigned long) * SCM_CHAR_BIT);
969d3bd0
RB
258 const unsigned long num_chunks = num_full_chunks + ((end_bits) ? 1 : 0);
259
260 /* we know the result will be this big */
261 mpz_realloc2 (SCM_I_BIG_MPZ (result), m_bits);
262
263 random_chunks =
264 (unsigned long *) scm_gc_calloc (num_chunks * sizeof (unsigned long),
265 "random bignum chunks");
266
372691d8 267 do
e7a72986 268 {
969d3bd0
RB
269 unsigned long *current_chunk = random_chunks + (num_chunks - 1);
270 unsigned long chunks_left = num_chunks;
969d3bd0
RB
271
272 mpz_set_ui (SCM_I_BIG_MPZ (result), 0);
273
274 if (end_bits)
275 {
276 /* generate a mask with ones in the end_bits position, i.e. if
277 end_bits is 3, then we'd have a mask of ...0000000111 */
278 const unsigned long rndbits = scm_the_rng.random_bits (state);
0d79003d 279 int rshift = (sizeof (unsigned long) * SCM_CHAR_BIT) - end_bits;
969d3bd0
RB
280 unsigned long mask = ((unsigned long) ULONG_MAX) >> rshift;
281 unsigned long highest_bits = rndbits & mask;
282 *current_chunk-- = highest_bits;
283 chunks_left--;
284 }
285
286 while (chunks_left)
287 {
288 /* now fill in the remaining unsigned long sized chunks */
289 *current_chunk-- = scm_the_rng.random_bits (state);
290 chunks_left--;
291 }
292 mpz_import (SCM_I_BIG_MPZ (result),
293 num_chunks,
294 -1,
295 sizeof (unsigned long),
296 0,
297 0,
298 random_chunks);
372691d8
MD
299 /* if result >= m, regenerate it (it is important to regenerate
300 all bits in order not to get a distorted distribution) */
301 } while (mpz_cmp (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (m)) >= 0);
969d3bd0
RB
302 scm_gc_free (random_chunks,
303 num_chunks * sizeof (unsigned long),
304 "random bignum chunks");
8db9cc6c 305 return scm_i_normbig (result);
e7a72986
MD
306}
307
308/*
309 * Scheme level representation of random states.
310 */
311
92c2555f 312scm_t_bits scm_tc16_rstate;
e7a72986
MD
313
314static SCM
92c2555f 315make_rstate (scm_t_rstate *state)
e7a72986 316{
23a62151 317 SCM_RETURN_NEWSMOB (scm_tc16_rstate, state);
e7a72986
MD
318}
319
1be6b49c 320static size_t
e841c3e0 321rstate_free (SCM rstate)
e7a72986
MD
322{
323 free (SCM_RSTATE (rstate));
dfd71aba 324 return 0;
e7a72986
MD
325}
326
e7a72986
MD
327/*
328 * Scheme level interface.
329 */
330
86d31dfe 331SCM_GLOBAL_VARIABLE_INIT (scm_var_random_state, "*random-state*", scm_seed_to_random_state (scm_makfrom0str ("URL:http://stat.fsu.edu/~geo/diehard.html")));
e7a72986 332
a1ec6916 333SCM_DEFINE (scm_random, "random", 1, 1, 0,
1bbd0b84 334 (SCM n, SCM state),
34d19ef6 335 "Return a number in [0, N).\n"
d928e0b4 336 "\n"
9401323e
NJ
337 "Accepts a positive integer or real n and returns a\n"
338 "number of the same type between zero (inclusive) and\n"
339 "N (exclusive). The values returned have a uniform\n"
d928e0b4
GB
340 "distribution.\n"
341 "\n"
3b644514
MG
342 "The optional argument @var{state} must be of the type produced\n"
343 "by @code{seed->random-state}. It defaults to the value of the\n"
344 "variable @var{*random-state*}. This object is used to maintain\n"
345 "the state of the pseudo-random-number generator and is altered\n"
346 "as a side effect of the random operation.")
1bbd0b84 347#define FUNC_NAME s_scm_random
e7a72986
MD
348{
349 if (SCM_UNBNDP (state))
86d31dfe 350 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 351 SCM_VALIDATE_RSTATE (2, state);
e11e83f3 352 if (SCM_I_INUMP (n))
e7a72986 353 {
e11e83f3 354 unsigned long m = SCM_I_INUM (n);
34d19ef6 355 SCM_ASSERT_RANGE (1, n, m > 0);
e11e83f3 356 return scm_from_ulong (scm_c_random (SCM_RSTATE (state), m));
e7a72986 357 }
34d19ef6 358 SCM_VALIDATE_NIM (1, n);
e7a72986 359 if (SCM_REALP (n))
f8de44c1
DH
360 return scm_make_real (SCM_REAL_VALUE (n)
361 * scm_c_uniform01 (SCM_RSTATE (state)));
969d3bd0 362
a55c2b68
MV
363 if (!SCM_BIGP (n))
364 SCM_WRONG_TYPE_ARG (1, n);
9b741bb6 365 return scm_c_random_bignum (SCM_RSTATE (state), n);
e7a72986 366}
1bbd0b84 367#undef FUNC_NAME
e7a72986 368
a1ec6916 369SCM_DEFINE (scm_copy_random_state, "copy-random-state", 0, 1, 0,
1bbd0b84 370 (SCM state),
3b644514 371 "Return a copy of the random state @var{state}.")
1bbd0b84 372#define FUNC_NAME s_scm_copy_random_state
e7a72986
MD
373{
374 if (SCM_UNBNDP (state))
86d31dfe 375 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 376 SCM_VALIDATE_RSTATE (1, state);
e7a72986
MD
377 return make_rstate (scm_the_rng.copy_rstate (SCM_RSTATE (state)));
378}
1bbd0b84 379#undef FUNC_NAME
e7a72986 380
a1ec6916 381SCM_DEFINE (scm_seed_to_random_state, "seed->random-state", 1, 0, 0,
1bbd0b84 382 (SCM seed),
3b644514 383 "Return a new random state using @var{seed}.")
1bbd0b84 384#define FUNC_NAME s_scm_seed_to_random_state
5ee11b7c
MD
385{
386 if (SCM_NUMBERP (seed))
387 seed = scm_number_to_string (seed, SCM_UNDEFINED);
34d19ef6 388 SCM_VALIDATE_STRING (1, seed);
34f0f2b8 389 return make_rstate (scm_c_make_rstate (SCM_STRING_CHARS (seed),
b7ead2ae 390 SCM_STRING_LENGTH (seed)));
5ee11b7c 391}
1bbd0b84 392#undef FUNC_NAME
5ee11b7c 393
a1ec6916 394SCM_DEFINE (scm_random_uniform, "random:uniform", 0, 1, 0,
1bbd0b84 395 (SCM state),
1e6808ea
MG
396 "Return a uniformly distributed inexact real random number in\n"
397 "[0,1).")
1bbd0b84 398#define FUNC_NAME s_scm_random_uniform
e7a72986
MD
399{
400 if (SCM_UNBNDP (state))
86d31dfe 401 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 402 SCM_VALIDATE_RSTATE (1, state);
f8de44c1 403 return scm_make_real (scm_c_uniform01 (SCM_RSTATE (state)));
e7a72986 404}
1bbd0b84 405#undef FUNC_NAME
e7a72986 406
a1ec6916 407SCM_DEFINE (scm_random_normal, "random:normal", 0, 1, 0,
1bbd0b84 408 (SCM state),
1e6808ea
MG
409 "Return an inexact real in a normal distribution. The\n"
410 "distribution used has mean 0 and standard deviation 1. For a\n"
411 "normal distribution with mean m and standard deviation d use\n"
412 "@code{(+ m (* d (random:normal)))}.")
1bbd0b84 413#define FUNC_NAME s_scm_random_normal
afe5177e
GH
414{
415 if (SCM_UNBNDP (state))
86d31dfe 416 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 417 SCM_VALIDATE_RSTATE (1, state);
f8de44c1 418 return scm_make_real (scm_c_normal01 (SCM_RSTATE (state)));
afe5177e 419}
1bbd0b84 420#undef FUNC_NAME
afe5177e 421
c7ad1f89 422#if SCM_HAVE_ARRAYS
afe5177e 423
e7a72986
MD
424static void
425vector_scale (SCM v, double c)
426{
e11e83f3 427 int n = scm_to_int (scm_uniform_vector_length (v));
e7a72986
MD
428 if (SCM_VECTORP (v))
429 while (--n >= 0)
eb42e2f0 430 SCM_REAL_VALUE (SCM_VELTS (v)[n]) *= c;
e7a72986
MD
431 else
432 while (--n >= 0)
433 ((double *) SCM_VELTS (v))[n] *= c;
434}
435
436static double
437vector_sum_squares (SCM v)
438{
439 double x, sum = 0.0;
e11e83f3 440 int n = scm_to_int (scm_uniform_vector_length (v));
e7a72986
MD
441 if (SCM_VECTORP (v))
442 while (--n >= 0)
443 {
eb42e2f0 444 x = SCM_REAL_VALUE (SCM_VELTS (v)[n]);
e7a72986
MD
445 sum += x * x;
446 }
447 else
448 while (--n >= 0)
449 {
450 x = ((double *) SCM_VELTS (v))[n];
451 sum += x * x;
452 }
453 return sum;
454}
455
e7a72986
MD
456/* For the uniform distribution on the solid sphere, note that in
457 * this distribution the length r of the vector has cumulative
458 * distribution r^n; i.e., u=r^n is uniform [0,1], so r can be
459 * generated as r=u^(1/n).
460 */
a1ec6916 461SCM_DEFINE (scm_random_solid_sphere_x, "random:solid-sphere!", 1, 1, 0,
1bbd0b84 462 (SCM v, SCM state),
d928e0b4
GB
463 "Fills vect with inexact real random numbers\n"
464 "the sum of whose squares is less than 1.0.\n"
9401323e
NJ
465 "Thinking of vect as coordinates in space of\n"
466 "dimension n = (vector-length vect), the coordinates\n"
72dd0a03 467 "are uniformly distributed within the unit n-sphere.\n"
64ba8e85 468 "The sum of the squares of the numbers is returned.")
1bbd0b84 469#define FUNC_NAME s_scm_random_solid_sphere_x
e7a72986 470{
34d19ef6 471 SCM_VALIDATE_VECTOR_OR_DVECTOR (1, v);
e7a72986 472 if (SCM_UNBNDP (state))
86d31dfe 473 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 474 SCM_VALIDATE_RSTATE (2, state);
e7a72986
MD
475 scm_random_normal_vector_x (v, state);
476 vector_scale (v,
9b741bb6 477 pow (scm_c_uniform01 (SCM_RSTATE (state)),
e11e83f3 478 1.0 / scm_to_int (scm_uniform_vector_length (v)))
e7a72986
MD
479 / sqrt (vector_sum_squares (v)));
480 return SCM_UNSPECIFIED;
481}
1bbd0b84 482#undef FUNC_NAME
e7a72986 483
a1ec6916 484SCM_DEFINE (scm_random_hollow_sphere_x, "random:hollow-sphere!", 1, 1, 0,
1bbd0b84 485 (SCM v, SCM state),
d928e0b4
GB
486 "Fills vect with inexact real random numbers\n"
487 "the sum of whose squares is equal to 1.0.\n"
9401323e 488 "Thinking of vect as coordinates in space of\n"
d928e0b4 489 "dimension n = (vector-length vect), the coordinates\n"
9401323e 490 "are uniformly distributed over the surface of the\n"
72dd0a03 491 "unit n-sphere.")
1bbd0b84 492#define FUNC_NAME s_scm_random_hollow_sphere_x
e7a72986 493{
34d19ef6 494 SCM_VALIDATE_VECTOR_OR_DVECTOR (1, v);
e7a72986 495 if (SCM_UNBNDP (state))
86d31dfe 496 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 497 SCM_VALIDATE_RSTATE (2, state);
e7a72986
MD
498 scm_random_normal_vector_x (v, state);
499 vector_scale (v, 1 / sqrt (vector_sum_squares (v)));
500 return SCM_UNSPECIFIED;
501}
1bbd0b84 502#undef FUNC_NAME
e7a72986 503
1bbd0b84 504
a1ec6916 505SCM_DEFINE (scm_random_normal_vector_x, "random:normal-vector!", 1, 1, 0,
1bbd0b84 506 (SCM v, SCM state),
d928e0b4
GB
507 "Fills vect with inexact real random numbers that are\n"
508 "independent and standard normally distributed\n"
64ba8e85 509 "(i.e., with mean 0 and variance 1).")
1bbd0b84 510#define FUNC_NAME s_scm_random_normal_vector_x
e7a72986
MD
511{
512 int n;
34d19ef6 513 SCM_VALIDATE_VECTOR_OR_DVECTOR (1, v);
e7a72986 514 if (SCM_UNBNDP (state))
86d31dfe 515 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 516 SCM_VALIDATE_RSTATE (2, state);
e11e83f3 517 n = scm_to_int (scm_uniform_vector_length (v));
e7a72986
MD
518 if (SCM_VECTORP (v))
519 while (--n >= 0)
34d19ef6 520 SCM_VECTOR_SET (v, n, scm_make_real (scm_c_normal01 (SCM_RSTATE (state))));
e7a72986
MD
521 else
522 while (--n >= 0)
9b741bb6 523 ((double *) SCM_VELTS (v))[n] = scm_c_normal01 (SCM_RSTATE (state));
e7a72986
MD
524 return SCM_UNSPECIFIED;
525}
1bbd0b84 526#undef FUNC_NAME
e7a72986 527
2fb8013c 528#endif /* SCM_HAVE_ARRAYS */
afe5177e 529
a1ec6916 530SCM_DEFINE (scm_random_exp, "random:exp", 0, 1, 0,
1bbd0b84 531 (SCM state),
1e6808ea
MG
532 "Return an inexact real in an exponential distribution with mean\n"
533 "1. For an exponential distribution with mean u use (* u\n"
534 "(random:exp)).")
1bbd0b84 535#define FUNC_NAME s_scm_random_exp
e7a72986
MD
536{
537 if (SCM_UNBNDP (state))
86d31dfe 538 state = SCM_VARIABLE_REF (scm_var_random_state);
34d19ef6 539 SCM_VALIDATE_RSTATE (1, state);
f8de44c1 540 return scm_make_real (scm_c_exp1 (SCM_RSTATE (state)));
e7a72986 541}
1bbd0b84 542#undef FUNC_NAME
e7a72986
MD
543
544void
545scm_init_random ()
546{
547 int i, m;
548 /* plug in default RNG */
92c2555f 549 scm_t_rng rng =
e7a72986 550 {
92c2555f 551 sizeof (scm_t_i_rstate),
e7a72986
MD
552 (unsigned long (*)()) scm_i_uniform32,
553 (void (*)()) scm_i_init_rstate,
92c2555f 554 (scm_t_rstate *(*)()) scm_i_copy_rstate
e7a72986
MD
555 };
556 scm_the_rng = rng;
557
e841c3e0
KN
558 scm_tc16_rstate = scm_make_smob_type ("random-state", 0);
559 scm_set_smob_free (scm_tc16_rstate, rstate_free);
e7a72986
MD
560
561 for (m = 1; m <= 0x100; m <<= 1)
562 for (i = m >> 1; i < m; ++i)
563 scm_masktab[i] = m - 1;
564
a0599745 565#include "libguile/random.x"
e7a72986
MD
566
567 scm_add_feature ("random");
568}
89e00824
ML
569
570/*
571 Local Variables:
572 c-file-style: "gnu"
573 End:
574*/