* coreutils.texi (mkdir invocation): Say how to set the file
[coreutils.git] / lib / randint.c
blob5ee738a506dbb1ca09da62425fcc427312fb42fb
1 /* Generate random integers.
3 Copyright (C) 2006 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU 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 Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 /* Written by Paul Eggert. */
21 #include <config.h>
23 #include "randint.h"
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
31 #if TEST
32 # include <inttypes.h>
33 # include <stdio.h>
35 int
36 main (int argc, char **argv)
38 randint i;
39 randint n = strtoumax (argv[1], NULL, 10);
40 randint choices = strtoumax (argv[2], NULL, 10);
41 char const *name = argv[3];
42 struct randint_source *ints = randint_all_new (name, SIZE_MAX);
44 for (i = 0; i < n; i++)
45 printf ("%"PRIuMAX"\n", randint_choose (ints, choices));
47 return (randint_all_free (ints) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
49 #endif
52 #include "xalloc.h"
54 #ifndef MAX
55 # define MAX(a,b) ((a) < (b) ? (b) : (a))
56 #endif
58 /* A source of random data for generating random integers. */
59 struct randint_source
61 /* The source of random bytes. */
62 struct randread_source *source;
64 /* RANDNUM is a buffered random integer, whose information has not
65 yet been delivered to the caller. It is uniformly distributed in
66 the range 0 <= RANDNUM <= RANDMAX. If RANDMAX is zero, then
67 RANDNUM must be zero (and in some sense it is not really
68 "random"). */
69 randint randnum;
70 randint randmax;
73 /* Create a new randint_source from SOURCE. */
75 struct randint_source *
76 randint_new (struct randread_source *source)
78 struct randint_source *s = xmalloc (sizeof *s);
79 s->source = source;
80 s->randnum = s->randmax = 0;
81 return s;
84 /* Create a new randint_source by creating a randread_source from
85 NAME and ESTIMATED_BYTES. Return NULL (setting errno) if
86 unsuccessful. */
88 struct randint_source *
89 randint_all_new (char const *name, size_t bytes_bound)
91 struct randread_source *source = randread_new (name, bytes_bound);
92 return (source ? randint_new (source) : NULL);
95 /* Return the random data source of *S. */
97 struct randread_source *
98 randint_get_source (struct randint_source const *s)
100 return s->source;
103 /* HUGE_BYTES is true on hosts hosts where randint and unsigned char
104 have the same width and where shifting by the word size therefore
105 has undefined behavior. */
106 enum { HUGE_BYTES = RANDINT_MAX == UCHAR_MAX };
108 /* Return X shifted left by CHAR_BIT bits. */
109 static inline randint shift_left (randint x)
111 return HUGE_BYTES ? 0 : x << CHAR_BIT;
114 /* Return X shifted right by CHAR_BIT bits. */
115 static inline randint
116 shift_right (randint x)
118 return HUGE_BYTES ? 0 : x >> CHAR_BIT;
122 /* Consume random data from *S to generate a random number in the range
123 0 .. GENMAX. */
125 randint
126 randint_genmax (struct randint_source *s, randint genmax)
128 struct randread_source *source = s->source;
129 randint randnum = s->randnum;
130 randint randmax = s->randmax;
131 randint choices = genmax + 1;
133 for (;;)
135 if (randmax < genmax)
137 /* Calculate how many input bytes will be needed, and read
138 the bytes. */
140 size_t i = 0;
141 randint rmax = randmax;
142 unsigned char buf[sizeof randnum];
146 rmax = shift_left (rmax) + UCHAR_MAX;
147 i++;
149 while (rmax < genmax);
151 randread (source, buf, i);
153 /* Increase RANDMAX by appending random bytes to RANDNUM and
154 UCHAR_MAX to RANDMAX until RANDMAX is no less than
155 GENMAX. This may lose up to CHAR_BIT bits of information
156 if shift_right (RANDINT_MAX) < GENMAX, but it is not
157 worth the programming hassle of saving these bits since
158 GENMAX is rarely that large in practice. */
160 i = 0;
164 randnum = shift_left (randnum) + buf[i];
165 randmax = shift_left (randmax) + UCHAR_MAX;
166 i++;
168 while (randmax < genmax);
171 if (randmax == genmax)
173 s->randnum = s->randmax = 0;
174 return randnum;
176 else
178 /* GENMAX < RANDMAX, so attempt to generate a random number
179 by taking RANDNUM modulo GENMAX+1. This will choose
180 fairly so long as RANDNUM falls within an integral
181 multiple of GENMAX+1; otherwise, LAST_USABLE_CHOICE < RANDNUM,
182 so discard this attempt and try again.
184 Since GENMAX cannot be RANDINT_MAX, CHOICES cannot be
185 zero and there is no need to worry about dividing by
186 zero. */
188 randint excess_choices = randmax - genmax;
189 randint unusable_choices = excess_choices % choices;
190 randint last_usable_choice = randmax - unusable_choices;
191 randint reduced_randnum = randnum % choices;
193 if (randnum <= last_usable_choice)
195 s->randnum = randnum / choices;
196 s->randmax = excess_choices / choices;
197 return reduced_randnum;
200 /* Retry, but retain the randomness from the fact that RANDNUM fell
201 into the range LAST_USABLE_CHOICE+1 .. RANDMAX. */
202 randnum = reduced_randnum;
203 randmax = unusable_choices - 1;
208 /* Clear *S so that it no longer contains undelivered random data. */
210 void
211 randint_free (struct randint_source *s)
213 memset (s, 0, sizeof *s);
214 free (s);
217 /* Likewise, but also clear the underlying randread object. Return
218 0 if successful, -1 (setting errno) otherwise. */
221 randint_all_free (struct randint_source *s)
223 int r = randread_free (s->source);
224 int e = errno;
225 randint_free (s);
226 errno = e;
227 return r;