1 /* Generate random integers.
3 Copyright (C) 2006-2024 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 3 of the License, or
8 (at your option) 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, see <https://www.gnu.org/licenses/>. */
18 /* Written by Paul Eggert. */
31 # include <inttypes.h>
35 main (int argc
, char **argv
)
38 randint n
= strtoumax (argv
[1], nullptr, 10);
39 randint choices
= strtoumax (argv
[2], nullptr, 10);
40 char const *name
= argv
[3];
41 struct randint_source
*ints
= randint_all_new (name
, SIZE_MAX
);
43 for (i
= 0; i
< n
; i
++)
44 printf ("%ju\n", randint_choose (ints
, choices
));
46 return (randint_all_free (ints
) == 0 ? EXIT_SUCCESS
: EXIT_FAILURE
);
53 /* A source of random data for generating random integers. */
56 /* The source of random bytes. */
57 struct randread_source
*source
;
59 /* RANDNUM is a buffered random integer, whose information has not
60 yet been delivered to the caller. It is uniformly distributed in
61 the range 0 <= RANDNUM <= RANDMAX. If RANDMAX is zero, then
62 RANDNUM must be zero (and in some sense it is not really
68 /* Create a new randint_source from SOURCE. */
70 struct randint_source
*
71 randint_new (struct randread_source
*source
)
73 struct randint_source
*s
= xmalloc (sizeof *s
);
75 s
->randnum
= s
->randmax
= 0;
79 /* Create a new randint_source by creating a randread_source from
80 NAME and ESTIMATED_BYTES. Return nullptr (setting errno) if
83 struct randint_source
*
84 randint_all_new (char const *name
, size_t bytes_bound
)
86 struct randread_source
*source
= randread_new (name
, bytes_bound
);
87 return (source
? randint_new (source
) : nullptr);
90 /* Return the random data source of *S. */
92 struct randread_source
*
93 randint_get_source (struct randint_source
const *s
)
98 /* HUGE_BYTES is true on hosts hosts where randint and unsigned char
99 have the same width and where shifting by the word size therefore
100 has undefined behavior. */
101 enum { HUGE_BYTES
= RANDINT_MAX
== UCHAR_MAX
};
103 /* Return X shifted left by CHAR_BIT bits. */
104 static inline randint
shift_left (randint x
)
106 return HUGE_BYTES
? 0 : x
<< CHAR_BIT
;
110 /* Consume random data from *S to generate a random number in the range
114 randint_genmax (struct randint_source
*s
, randint genmax
)
116 struct randread_source
*source
= s
->source
;
117 randint randnum
= s
->randnum
;
118 randint randmax
= s
->randmax
;
119 randint choices
= genmax
+ 1;
123 if (randmax
< genmax
)
125 /* Calculate how many input bytes will be needed, and read
129 randint rmax
= randmax
;
130 unsigned char buf
[sizeof randnum
];
134 rmax
= shift_left (rmax
) + UCHAR_MAX
;
137 while (rmax
< genmax
);
139 randread (source
, buf
, i
);
141 /* Increase RANDMAX by appending random bytes to RANDNUM and
142 UCHAR_MAX to RANDMAX until RANDMAX is no less than
143 GENMAX. This may lose up to CHAR_BIT bits of information
144 if (HUGE_BYTES ? 0 : RANDINT_MAX >> CHAR_BIT) < GENMAX,
145 but it is not worth the programming hassle of saving
146 these bits since GENMAX is rarely that large in practice. */
152 randnum
= shift_left (randnum
) + buf
[i
];
153 randmax
= shift_left (randmax
) + UCHAR_MAX
;
156 while (randmax
< genmax
);
159 if (randmax
== genmax
)
161 s
->randnum
= s
->randmax
= 0;
166 /* GENMAX < RANDMAX, so attempt to generate a random number
167 by taking RANDNUM modulo GENMAX+1. This will choose
168 fairly so long as RANDNUM falls within an integral
169 multiple of GENMAX+1; otherwise, LAST_USABLE_CHOICE < RANDNUM,
170 so discard this attempt and try again.
172 Since GENMAX cannot be RANDINT_MAX, CHOICES cannot be
173 zero and there is no need to worry about dividing by
176 randint excess_choices
= randmax
- genmax
;
177 randint unusable_choices
= excess_choices
% choices
;
178 randint last_usable_choice
= randmax
- unusable_choices
;
179 randint reduced_randnum
= randnum
% choices
;
181 if (randnum
<= last_usable_choice
)
183 s
->randnum
= randnum
/ choices
;
184 s
->randmax
= excess_choices
/ choices
;
185 return reduced_randnum
;
188 /* Retry, but retain the randomness from the fact that RANDNUM fell
189 into the range LAST_USABLE_CHOICE+1 .. RANDMAX. */
190 randnum
= reduced_randnum
;
191 randmax
= unusable_choices
- 1;
196 /* Clear *S so that it no longer contains undelivered random data. */
199 randint_free (struct randint_source
*s
)
201 explicit_bzero (s
, sizeof *s
);
205 /* Likewise, but also clear the underlying randread object. Return
206 0 if successful, -1 (setting errno) otherwise. */
209 randint_all_free (struct randint_source
*s
)
211 int r
= randread_free (s
->source
);