3 * Generic interface to random number generators
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28 /*----- Header files ------------------------------------------------------*/
32 #include <mLib/bits.h>
36 /*----- Default operations ------------------------------------------------*/
38 /* --- @grand_defaultbyte@ --- *
40 * Arguments: @grand *r@ = pointet to generic generator
42 * Returns: A uniformly-distributed pseudorandom integer in the interval
45 * Use: Default @byte@ output method. This calls the @range@ method
46 * to return a uniform random value between 0 and 255.
49 octet
grand_defaultbyte(grand
*r
)
50 { return (r
->ops
->range(r
, 256)); }
52 /* --- @grand_defaultword@ --- *
54 * Arguments: @grand *r@ = pointet to generic generator
56 * Returns: A uniformly-distributed pseudorandom integer in the interval
59 * Use: Default @word@ output method. This calls the @fill@ method
60 * to fill a 4-octet buffer with uniform random bytes, and then
61 * converts them to an integer.
64 uint32
grand_defaultword(grand
*r
)
65 { octet buf
[4]; r
->ops
->fill(r
, buf
, sizeof(buf
)); return (LOAD32(buf
)); }
67 /* --- @grand_defaultrange@ --- *
69 * Arguments: @grand *r@ = pointet to generic generator
70 * @uint32 l@ = limit for acceptable results
72 * Returns: A uniformly-distributed pseudorandom integer in the interval
75 * Use: Default @range@ output method. This falls back to either
76 * @word@ (if the generator's @max@ is zero, or if @max < l@) or
77 * @raw@ (otherwise). This might recurse via @fill@ and @byte@,
78 * but this is safe because of the constraint on the @raw@
82 uint32
grand_defaultrange(grand
*r
, uint32 l
)
85 uint32 (*w
)(grand */
*r*/
);
88 /* --- Decide where to get data from --- *
90 * The choice of %$2^{32} - 1$% as a limit when using @grand_word@ isn't
91 * wonderful, but working with %$2^{32}$% is awkward and the loss of a few
92 * return values isn't significant. The algorithm below still successfully
93 * returns uniformly distributed results.
95 * If there's a raw generator, and it can cope with the limit, then use it;
96 * otherwise use the @word@ generator, which may recurse via @fill@ and
97 * @byte@, but by that point it must be able to satisfy us.
101 if (r
->ops
->max
&& r
->ops
->max
>= l
) {
105 assert(!r
->ops
->max
|| r
->ops
->max
>= 256);
110 /* --- Work out maximum acceptable return value --- *
112 * This will be the highest multiple of @l@ less than @m@.
117 /* --- Generate numbers until something acceptable is found --- *
119 * This will require an expected number of attempts less than 2.
122 do x
= w(r
); while (x
>= z
);
126 /* --- @grand_defaultfill@ --- *
128 * Arguments: @grand *r@ = pointet to generic generator
129 * @void *p@ = pointer to a buffer
130 * @size_t sz@ = size of the buffer
134 * Use: Fills a buffer with uniformly distributed pseudorandom bytes.
135 * This calls the @byte@ method repeatedly to fill in the output
139 void grand_defaultfill(grand
*r
, void *p
, size_t sz
)
140 { octet
*q
= p
; while (sz
--) *q
++ = r
->ops
->byte(r
); }
142 /*----- Main code ---------------------------------------------------------*/
144 /* --- @grand_byte@ --- *
146 * Arguments: @grand *r@ = pointet to generic generator
148 * Returns: A uniformly-distributed pseudorandom integer in the interval
152 octet
grand_byte(grand
*r
)
154 if (r
->ops
->byte
== grand_byte
) return (grand_defaultbyte(r
));
155 else return (r
->ops
->byte(r
));
158 /* --- @grand_word@ --- *
160 * Arguments: @grand *r@ = pointet to generic generator
162 * Returns: A uniformly-distributed pseudorandom integer in the interval
166 uint32
grand_word(grand
*r
)
168 if (r
->ops
->word
== grand_word
) return (grand_defaultword(r
));
169 else return (r
->ops
->word(r
));
172 /* --- @grand_range@ --- *
174 * Arguments: @grand *r@ = pointet to generic generator
175 * @uint32 l@ = limit for acceptable results
177 * Returns: A uniformly-distributed pseudorandom integer in the interval
181 uint32
grand_range(grand
*r
, uint32 l
)
183 if (r
->ops
->range
== grand_range
) return (grand_defaultrange(r
, l
));
184 else return (r
->ops
->range(r
, l
));
187 /* --- @grand_fill@ --- *
189 * Arguments: @grand *r@ = pointet to generic generator
190 * @void *p@ = pointer to a buffer
191 * @size_t sz@ = size of the buffer
195 * Use: Fills a buffer with uniformly distributed pseudorandom bytes
196 * (see @grand_byte@).
199 void grand_fill(grand
*r
, void *p
, size_t sz
)
201 if (r
->ops
->fill
== grand_fill
) grand_defaultfill(r
, p
, sz
);
202 else r
->ops
->fill(r
, p
, sz
);
205 /*----- That's all, folks -------------------------------------------------*/