Skip to content

Commit 57bd2b7

Browse files
committed
make RandIntGen stop handling "full range" random generation
The rand(T) function is already the normal way of generating random values spanning "full range" of T. So let's make RandIntGen less powerful in the name of orthogonality and simplicity. Also tried to clarify a bit the `maxmultiple` comments.
1 parent 9d0282e commit 57bd2b7

File tree

1 file changed

+12
-16
lines changed

1 file changed

+12
-16
lines changed

base/random.jl

+12-16
Original file line numberDiff line numberDiff line change
@@ -148,21 +148,17 @@ rand{T<:Number}(::Type{T}, dims::Int...) = rand(T, dims)
148148

149149
## Generate random integer within a range 1:n
150150

151-
# remainder function according to Knuth, where rem_knuth(a, 0) = a
152-
rem_knuth(a::Uint, b::Uint) = a % (b + (b == 0)) + a * (b == 0)
153-
rem_knuth{T<:Unsigned}(a::T, b::T) = b != 0 ? a % b : a
154-
155-
# maximum multiple of k <= 2^bits(T) decremented by one,
156-
# that is 0xFFFFFFFF if k = typemax(T) - typemin(T) with intentional underflow
157-
maxmultiple(k::Uint32) = itrunc(Uint32, div(0x0000000100000000,k + (k == 0))*k - 1)
158-
maxmultiple(k::Uint64) = itrunc(Uint64, div(0x00000000000000010000000000000000, k + (k == 0))*k - 1)
159-
# maximum multiple of k within 1:typemax(Uint128)
160-
maxmultiple(k::Uint128) = div(typemax(Uint128), k + (k == 0))*k - 1
161-
# maximum multiple of k within 1:2^32 or 1:2^64, depending on size
162-
maxmultiplemix(k::Uint64) = itrunc(Uint64, div((k >> 32 != 0)*0x0000000000000000FFFFFFFF00000000 + 0x0000000100000000, k + (k == 0))*k - 1)
151+
# maxmultiple: precondition: k>0
152+
# maximum multiple of k <= 2^numbits(k), decremented by one
153+
maxmultiple(k::Uint32) = itrunc(Uint32, div(0x0000000100000000, k)*k - 1)
154+
maxmultiple(k::Uint64) = itrunc(Uint64, div(0x00000000000000010000000000000000, k)*k - 1)
155+
# maximum multiple of k <= typemax(Uint128), decremented by one
156+
maxmultiple(k::Uint128) = div(typemax(Uint128), k)*k - 1
157+
# 32 or 64 bits version depending on size
158+
maxmultiplemix(k::Uint64) = k >> 32 == 0 ? uint64(maxmultiple(itrunc(Uint32, k))) : maxmultiple(k)
163159

164160
immutable RandIntGen{T<:Integer, U<:Unsigned}
165-
k::U # range length (or zero for full range)
161+
k::U # range length
166162
u::U # rejection threshold
167163
end
168164
# generators with 32, 128 bits entropy
@@ -179,7 +175,7 @@ for (T, U) in [(Uint8, Uint32), (Uint16, Uint32),
179175
(Int8, Uint32), (Int16, Uint32), (Int32, Uint32), (Int64, Uint64), (Int128, Uint128),
180176
(Bool, Uint32), (Char, Uint32)]
181177

182-
@eval randintgen(k::$T) = k<1 ? error("range must be non-empty") : RandIntGen($T, convert($U, k)) # overflow ok
178+
@eval randintgen(k::$T) = k<1 ? error("range must be non-empty") : RandIntGen($T, convert($U, k))
183179
end
184180

185181
# this function uses 32 bit entropy for small ranges of length <= typemax(Uint32) + 1
@@ -197,15 +193,15 @@ function rand{T<:Union(Uint64, Int64)}(g::RandIntGen{T,Uint64})
197193
x = rand(Uint64)
198194
end
199195
end
200-
return reinterpret(T, one(Uint64) + rem_knuth(x, g.k))
196+
return reinterpret(T, one(Uint64) + x % g.k)
201197
end
202198

203199
function rand{T<:Integer, U<:Unsigned}(g::RandIntGen{T,U})
204200
x = rand(U)
205201
while x > g.u
206202
x = rand(U)
207203
end
208-
itrunc(T, one(U) + rem_knuth(x, g.k))
204+
itrunc(T, one(U) + x % g.k)
209205
end
210206

211207

0 commit comments

Comments
 (0)