diff --git a/base/random.jl b/base/random.jl index 8cd4d712dbbff2..c852c1ed0c3964 100644 --- a/base/random.jl +++ b/base/random.jl @@ -180,6 +180,27 @@ for (T, U) in [(Uint8, Uint32), (Uint16, Uint32), @eval RandIntGen(r::UnitRange{$T}) = isempty(r) ? error("range must be non-empty") : RandIntGen(first(r), convert($U, last(r) - first(r) + 1)) # overflow ok end + +# generator for BigInt +immutable RandIntGenBigInt + a::BigInt # first + m::BigInt # range length - 1 + nlimbs::Int # number of limbs in generated BigInt's + mask::Culong # applied to the highest limb +end + +function RandIntGen(r::UnitRange{BigInt}) + isempty(r) && error("range must be non-empty") + m = last(r) - first(r) + # mpz_sizeinbase is exact in this case, so this is faster than calling ndigits(m,2) + nd = int(ccall((:__gmpz_sizeinbase,:libgmp), Culong, (Ptr{BigInt}, Int32), &m, 2)) + nlimbs, highbits = divrem(nd, 8*sizeof(Culong)) + highbits > 0 && (nlimbs += 1) + mask = highbits == 0 ? ~zero(Culong) : one(Culong)<