X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a..HEAD:/math/mprand.c diff --git a/math/mprand.c b/math/mprand.c index eb779cb8..5805e6ed 100644 --- a/math/mprand.c +++ b/math/mprand.c @@ -49,17 +49,27 @@ * uniformly distributed in the interval %$[2^{b - 1}, 2^b)$%. * The result is then ORred with the given @or@ value. This * will often be 1, to make the result odd. + * + * The length @b@ may be zero; but %$\texttt{or} \ge 2^b$% is + * not permitted. */ mp *mprand(mp *d, unsigned b, grand *r, mpw or) { size_t sz = (b + 7) >> 3; arena *a = (d && (d->f & MP_BURN)) ? arena_secure : arena_global; - octet *v = x_alloc(a, sz); + octet *v; unsigned m; + assert(b >= MPW_BITS || !(or >> b)); + + /* --- Special case --- */ + + if (!b) return (MP_ZERO); + /* --- Fill buffer with random data --- */ + v = x_alloc(a, sz); r->ops->fill(r, v, sz); /* --- Force into the correct range --- * @@ -74,7 +84,11 @@ mp *mprand(mp *d, unsigned b, grand *r, mpw or) /* --- Mask, load and return --- */ d = mp_loadb(d, v, sz); - d->v[0] |= or; + if (or) { + assert(d->sz); + if (!MP_LEN(d)) d->vl = d->v + 1; + d->v[0] |= or; + } memset(v, 0, sz); x_free(a, v); return (d); @@ -91,7 +105,7 @@ mp *mprand(mp *d, unsigned b, grand *r, mpw or) * interval %$[0, l)$%. * * Use: Generates a uniformly-distributed pseudorandom number in the - * appropriate range. + * appropriate range. We must have %$l > 0$%. */ mp *mprand_range(mp *d, mp *l, grand *r, mpw or) @@ -119,6 +133,7 @@ mp *mprand_range(mp *d, mp *l, grand *r, mpw or) * As usual, the number of iterations expected is two. */ + assert(MP_POSP(l)); b = ((b - 1) & 7) + 1; m = (1 << b) - 1; do {