@@ -133,68 +133,57 @@ rem_knuth(a::T, b::T) where {T<:Unsigned} = b != 0 ? a % b : a
133
133
# that is 0xFFFF...FFFF if k = typemax(T) - typemin(T) with intentional underflow
134
134
# see http://stackoverflow.com/questions/29182036/integer-arithmetic-add-1-to-uint-max-and-divide-by-n-without-overflow
135
135
maxmultiple (k:: T ) where {T<: Unsigned } =
136
- (div (typemax (T) - k + oneunit (k), k + (k == 0 ))* k + k - oneunit (k)):: T
136
+ (div (typemax (T) - k + one (k), k + (k == 0 ))* k + k - one (k)):: T
137
+
138
+ # serves as rejection threshold
139
+ _maxmultiple (k) = maxmultiple (k)
137
140
138
141
# maximum multiple of k within 1:2^32 or 1:2^64 decremented by one, depending on size
139
- maxmultiplemix (k:: UInt64 ) = k >> 32 != 0 ?
142
+ _maxmultiple (k:: UInt64 ):: UInt64 = k >> 32 != 0 ?
140
143
maxmultiple (k) :
141
- ( div (0x0000000100000000 , k + (k == 0 ))* k - oneunit (k)) :: UInt64
144
+ div (0x0000000100000000 , k + (k == 0 ))* k - one (k)
142
145
143
- struct SamplerRangeInt{T<: Integer ,U<: Unsigned } <: Sampler
146
+ struct SamplerRangeInt{T<: Union{Bool, Integer} ,U<: Unsigned } <: Sampler
144
147
a:: T # first element of the range
145
148
k:: U # range length or zero for full range
146
149
u:: U # rejection threshold
147
150
end
148
151
149
- # generators with 32, 128 bits entropy
150
- SamplerRangeInt (a:: T , k:: U ) where {T,U<: Union{UInt32,UInt128} } =
151
- SamplerRangeInt {T,U} (a, k, maxmultiple (k))
152
+ function SamplerRangeInt (a:: T , diff:: U ) where {T<: Union{Bool,Integer} ,U<: Unsigned }
153
+ k = diff+ one (U)
154
+ SamplerRangeInt {T,U} (a, k, _maxmultiple (k)) # overflow ok
155
+ end
152
156
153
- # mixed 32/64 bits entropy generator
154
- SamplerRangeInt (a :: T , k :: UInt64 ) where {T} =
155
- SamplerRangeInt {T,UInt64} (a, k, maxmultiplemix (k))
157
+ uint_sup ( :: Type{<:Union{Bool,BitInteger}} ) = UInt32
158
+ uint_sup ( :: Type{<:Union{Int64, UInt64}} ) = UInt64
159
+ uint_sup ( :: Type{<:Union{Int128,UInt128}} ) = UInt128
156
160
157
- function Sampler ( :: AbstractRNG , r:: AbstractUnitRange{T} , :: Repetition ) where T<: Unsigned
161
+ function SamplerRangeInt ( r:: AbstractUnitRange{T} ) where T<: Union{Bool,BitInteger}
158
162
isempty (r) && throw (ArgumentError (" range must be non-empty" ))
159
- SamplerRangeInt (first (r), last (r) - first (r) + oneunit (T))
163
+ SamplerRangeInt (first (r), ( last (r) - first (r)) % uint_sup (T))
160
164
end
161
165
162
- for (T, U) in [(UInt8, UInt32), (UInt16, UInt32),
163
- (Int8, UInt32), (Int16, UInt32), (Int32, UInt32),
164
- (Int64, UInt64), (Int128, UInt128), (Bool, UInt32)]
166
+ Sampler (:: AbstractRNG , r:: AbstractUnitRange{T} , :: Repetition ) where {T<: Union{Bool,BitInteger} } =
167
+ SamplerRangeInt (r)
165
168
166
- @eval Sampler ( :: AbstractRNG , r :: AbstractUnitRange{$T} , :: Repetition ) = begin
167
- isempty (r) && throw ( ArgumentError ( " range must be non-empty " ))
168
- # overflow ok:
169
- SamplerRangeInt ( first (r), convert ( $ U, unsigned ( last (r) - first (r)) + one ( $ U)))
169
+ function rand_lteq (rng :: AbstractRNG , u :: T ) :: T where T
170
+ while true
171
+ x = rand (rng, T)
172
+ x <= u && return x
170
173
end
171
174
end
172
175
173
176
# this function uses 32 bit entropy for small ranges of length <= typemax(UInt32) + 1
174
- # SamplerRangeInt is responsible for providing the right value of k
175
- function rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,UInt64} ) where T<: Union{UInt64,Int64}
176
- local x:: UInt64
177
- if (sp. k - 1 ) >> 32 == 0
178
- x = rand (rng, UInt32)
179
- while x > sp. u
180
- x = rand (rng, UInt32)
181
- end
182
- else
183
- x = rand (rng, UInt64)
184
- while x > sp. u
185
- x = rand (rng, UInt64)
186
- end
187
- end
188
- return reinterpret (T, reinterpret (UInt64, sp. a) + rem_knuth (x, sp. k))
177
+ function rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,UInt64} ) where T<: BitInteger
178
+ x:: UInt64 = (sp. k - 1 ) >> 32 == 0 ?
179
+ rand_lteq (rng, sp. u % UInt32) % UInt64 :
180
+ rand_lteq (rng, sp. u)
181
+ return ((sp. a % UInt64) + rem_knuth (x, sp. k)) % T
189
182
end
190
183
191
- function rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,U} ) where {T<: Integer ,U<: Unsigned }
192
- x = rand (rng, U)
193
- while x > sp. u
194
- x = rand (rng, U)
195
- end
196
- (unsigned (sp. a) + rem_knuth (x, sp. k)) % T
197
- end
184
+ rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,U} ) where {T<: Union{Bool,BitInteger} ,U} =
185
+ (unsigned (sp. a) + rem_knuth (rand_lteq (rng, sp. u), sp. k)) % T
186
+
198
187
199
188
# ## BigInt
200
189
0 commit comments