1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
32 /* Random number generator. */
35 /* RC4-based random bytes. */
39 /* Normal distribution. */
43 /* Creates a new random number generator, seeds it based on
44 the current time, and returns it. */
51 rng = xmalloc (sizeof *rng);
56 rng_seed (rng, &t, sizeof t);
57 rng->next_normal = NOT_DOUBLE;
63 rng_destroy (struct rng *rng)
70 swap_byte (uint8_t *a, uint8_t *b)
77 /* Seeds RNG based on the SIZE bytes in BUF.
78 At most the first 256 bytes of BUF are used. */
80 rng_seed (struct rng *rng, const void *key_, size_t size)
82 const uint8_t *key = key_;
91 for (i = 0; i < 256; i++)
93 for (key_idx = 0, i = j = 0; i < 256; i++)
95 j = (j + s[i] + key[key_idx]) & 255;
96 swap_byte (s + i, s + j);
97 if (++key_idx >= size)
102 /* Reads SIZE random bytes from RNG into BUF. */
104 rng_get_bytes (struct rng *rng, void *buf_, size_t size)
119 swap_byte (s + i, s + j);
120 *buf++ = s[(s[i] + s[j]) & 255];
126 /* Returns a random int in the range [0, INT_MAX]. */
128 rng_get_int (struct rng *rng)
134 rng_get_bytes (rng, &value, sizeof value);
142 /* Returns a random unsigned in the range [0, UINT_MAX]. */
144 rng_get_unsigned (struct rng *rng)
148 rng_get_bytes (rng, &value, sizeof value);
152 /* Returns a random number from the uniform distribution with
155 rng_get_double (struct rng *rng)
159 rng_get_bytes (rng, &value, sizeof value);
160 return value / ULONG_MAX;
163 /* Returns a random number from the distribution with mean 0 and
164 standard deviation 1. (Multiply the result by the desired
165 standard deviation, then add the desired mean.) */
167 rng_get_double_normal (struct rng *rng)
169 /* Knuth, _The Art of Computer Programming_, Vol. 2, 3.4.1C,
173 if (rng->next_normal != NOT_DOUBLE)
175 this_normal = rng->next_normal;
176 rng->next_normal = NOT_DOUBLE;
184 double u1 = rng_get_double (rng);
185 double u2 = rng_get_double (rng);
188 s = v1 * v1 + v2 * v2;
192 this_normal = v1 * sqrt (-2. * log (s) / s);
193 rng->next_normal = v2 * sqrt (-2. * log (s) / s);
199 /* Gets an initialized RNG for use in PSPP transformations and
204 static struct rng *rng;