@@ -110,9 +110,13 @@ rand(r::AbstractRNG, ::SamplerTrivial{UInt52Raw{UInt64}}) =
110
110
_rand52 (r:: AbstractRNG , :: Type{Float64} ) = reinterpret (UInt64, rand (r, Close1Open2 ()))
111
111
_rand52 (r:: AbstractRNG , :: Type{UInt64} ) = rand (r, UInt64)
112
112
113
- rand (r:: AbstractRNG , :: SamplerTrivial{UInt10{UInt16}} ) = rand (r, UInt10Raw ()) & 0x03ff
114
- rand (r:: AbstractRNG , :: SamplerTrivial{UInt23{UInt32}} ) = rand (r, UInt23Raw ()) & 0x007fffff
115
- rand (r:: AbstractRNG , :: SamplerTrivial{UInt52{UInt64}} ) = rand (r, UInt52Raw ()) & 0x000fffffffffffff
113
+ rand (r:: AbstractRNG , :: SamplerTrivial{UInt104Raw{UInt128}} ) =
114
+ rand (r, UInt52Raw (UInt128)) << 52 ⊻ rand_inbounds (r, UInt52Raw (UInt128))
115
+
116
+ rand (r:: AbstractRNG , :: SamplerTrivial{UInt10{UInt16}} ) = rand (r, UInt10Raw ()) & 0x03ff
117
+ rand (r:: AbstractRNG , :: SamplerTrivial{UInt23{UInt32}} ) = rand (r, UInt23Raw ()) & 0x007fffff
118
+ rand (r:: AbstractRNG , :: SamplerTrivial{UInt52{UInt64}} ) = rand (r, UInt52Raw ()) & 0x000fffffffffffff
119
+ rand (r:: AbstractRNG , :: SamplerTrivial{UInt104{UInt128}} ) = rand (r, UInt104Raw ()) & 0x000000ffffffffffffffffffffffffff
116
120
117
121
rand (r:: AbstractRNG , sp:: SamplerTrivial{<:UniformBits{T}} ) where {T} =
118
122
rand (r, uint_default (sp[])) % T
143
147
# 2) "Default" which tries to use as few entropy bits as possible, at the cost of a
144
148
# a bigger upfront price associated with the creation of the sampler
145
149
150
+ # ### helper functions
151
+
152
+ uint_sup (:: Type{<:Union{Bool,BitInteger}} ) = UInt32
153
+ uint_sup (:: Type{<:Union{Int64,UInt64}} ) = UInt64
154
+ uint_sup (:: Type{<:Union{Int128,UInt128}} ) = UInt128
155
+
146
156
# ### Fast
147
157
148
158
struct SamplerRangeFast{U<: BitUnsigned ,T<: Union{BitInteger,Bool} } <: Sampler
@@ -152,44 +162,37 @@ struct SamplerRangeFast{U<:BitUnsigned,T<:Union{BitInteger,Bool}} <: Sampler
152
162
mask:: U # mask generated values before threshold rejection
153
163
end
154
164
155
- function SamplerRangeFast (r:: AbstractUnitRange{T} ) where T<: Union{Base.BitInteger64,Bool}
156
- isempty (r) && throw (ArgumentError (" range must be non-empty" ))
157
- m = last (r) % UInt64 - first (r) % UInt64
158
- bw = (64 - leading_zeros (m)) % UInt # bit-width
159
- mask = (1 % UInt64 << bw) - (1 % UInt64)
160
- SamplerRangeFast {UInt64,T} (first (r), bw, m, mask)
161
- end
165
+ SamplerRangeFast (r:: AbstractUnitRange{T} ) where T<: Union{Bool,BitInteger} =
166
+ SamplerRangeFast (r, uint_sup (T))
162
167
163
- function SamplerRangeFast (r:: AbstractUnitRange{T} ) where T <: Union{Int128,UInt128 }
168
+ function SamplerRangeFast (r:: AbstractUnitRange{T} , :: Type{U} ) where {T,U }
164
169
isempty (r) && throw (ArgumentError (" range must be non-empty" ))
165
- m = (last (r)- first (r)) % UInt128
166
- bw = (128 - leading_zeros (m)) % UInt # bit-width
167
- mask = (1 % UInt128 << bw) - (1 % UInt128 )
168
- SamplerRangeFast {UInt128 ,T} (first (r), bw, m, mask)
170
+ m = (last (r) - first (r)) % U
171
+ bw = (sizeof (U) << 3 - leading_zeros (m)) % UInt # bit-width
172
+ mask = (1 % U << bw) - (1 % U )
173
+ SamplerRangeFast {U ,T} (first (r), bw, m, mask)
169
174
end
170
175
171
- function rand_lteq (r:: AbstractRNG , S, u:: U , mask:: U ) where U<: Integer
172
- while true
173
- x = rand (r, S) & mask
174
- x <= u && return x
175
- end
176
+ function rand (rng:: AbstractRNG , sp:: SamplerRangeFast{UInt32,T} ) where T
177
+ a, bw, m, mask = sp. a, sp. bw, sp. m, sp. mask
178
+ x = rand (rng, LessThan (m, Masked (mask, uniform (UInt32))))
179
+ (x + a % UInt32) % T
176
180
end
177
181
178
- # helper function, to turn types to values, should be removed once we can do rand(Uniform(UInt))
179
- rand (rng:: AbstractRNG , :: Val{T} ) where {T} = rand (rng, T)
180
-
181
182
function rand (rng:: AbstractRNG , sp:: SamplerRangeFast{UInt64,T} ) where T
182
183
a, bw, m, mask = sp. a, sp. bw, sp. m, sp. mask
183
- x = bw <= 52 ? rand_lteq (rng, UInt52Raw (), m, mask) :
184
- rand_lteq (rng, Val (UInt64), m, mask)
184
+ x = bw <= 52 ? rand (rng, LessThan ( m, Masked ( mask, UInt52Raw ())) ) :
185
+ rand (rng, LessThan ( m, Masked ( mask, uniform (UInt64))) )
185
186
(x + a % UInt64) % T
186
187
end
187
188
188
189
function rand (rng:: AbstractRNG , sp:: SamplerRangeFast{UInt128,T} ) where T
189
190
a, bw, m, mask = sp. a, sp. bw, sp. m, sp. mask
190
- x = bw <= 52 ? rand_lteq (rng, UInt52Raw (), m % UInt64, mask % UInt64) % UInt128 :
191
- bw <= 104 ? rand_lteq (rng, UInt104Raw (), m, mask) :
192
- rand_lteq (rng, Val (UInt128), m, mask)
191
+ x = bw <= 52 ?
192
+ rand (rng, LessThan (m % UInt64, Masked (mask % UInt64, UInt52Raw ()))) % UInt128 :
193
+ bw <= 104 ?
194
+ rand (rng, LessThan (m, Masked (mask, UInt104Raw ()))) :
195
+ rand (rng, LessThan (m, Masked (mask, uniform (UInt128))))
193
196
x % T + a
194
197
end
195
198
@@ -199,60 +202,70 @@ end
199
202
rem_knuth (a:: UInt , b:: UInt ) = a % (b + (b == 0 )) + a * (b == 0 )
200
203
rem_knuth (a:: T , b:: T ) where {T<: Unsigned } = b != 0 ? a % b : a
201
204
202
- # maximum multiple of k <= 2^bits(T) decremented by one,
203
- # that is 0xFFFF...FFFF if k = typemax(T) - typemin(T) with intentional underflow
205
+ # maximum multiple of k <= sup decremented by one,
206
+ # that is 0xFFFF...FFFF if k = (typemax(T) - typemin(T)) + 1 and sup == typemax(T) - 1
207
+ # with intentional underflow
204
208
# see http://stackoverflow.com/questions/29182036/integer-arithmetic-add-1-to-uint-max-and-divide-by-n-without-overflow
205
- maxmultiple (k:: T ) where {T<: Unsigned } =
206
- (div (typemax (T) - k + one (k), k + (k == 0 ))* k + k - one (k)):: T
207
209
208
- # serves as rejection threshold
209
- _maxmultiple (k) = maxmultiple (k)
210
+ # sup == 0 means typemax(T) + 1
211
+ maxmultiple (k:: T , sup:: T = zero (T)) where {T<: Unsigned } =
212
+ (div (sup - k, k + (k == 0 ))* k + k - one (k)):: T
210
213
211
- # maximum multiple of k within 1:2^32 or 1:2^64 decremented by one, depending on size
212
- _maxmultiple (k:: UInt64 ):: UInt64 = k >> 32 != 0 ?
213
- maxmultiple (k) :
214
- div (0x0000000100000000 , k + (k == 0 ))* k - one (k)
214
+ # similar but sup must not be equal to typemax(T)
215
+ unsafe_maxmultiple (k:: T , sup:: T ) where {T<: Unsigned } =
216
+ div (sup, k + (k == 0 ))* k - one (k)
215
217
216
218
struct SamplerRangeInt{T<: Union{Bool,Integer} ,U<: Unsigned } <: Sampler
217
- a:: T # first element of the range
218
- k:: U # range length or zero for full range
219
- u:: U # rejection threshold
219
+ a:: T # first element of the range
220
+ bw:: Int # bit width
221
+ k:: U # range length or zero for full range
222
+ u:: U # rejection threshold
220
223
end
221
224
222
- function SamplerRangeInt (a:: T , diff:: U ) where {T<: Union{Bool,Integer} ,U<: Unsigned }
223
- k = diff+ one (U)
224
- SamplerRangeInt {T,U} (a, k, _maxmultiple (k)) # overflow ok
225
- end
226
225
227
- uint_sup (:: Type{<:Union{Bool,BitInteger}} ) = UInt32
228
- uint_sup (:: Type{<:Union{Int64,UInt64}} ) = UInt64
229
- uint_sup (:: Type{<:Union{Int128,UInt128}} ) = UInt128
226
+ SamplerRangeInt (r:: AbstractUnitRange{T} ) where T<: Union{Bool,BitInteger} =
227
+ SamplerRangeInt (r, uint_sup (T))
230
228
231
- function SamplerRangeInt (r:: AbstractUnitRange{T} ) where T <: Union{Bool,BitInteger }
229
+ function SamplerRangeInt (r:: AbstractUnitRange{T} , :: Type{U} ) where {T,U }
232
230
isempty (r) && throw (ArgumentError (" range must be non-empty" ))
233
- SamplerRangeInt (first (r), (last (r) - first (r)) % uint_sup (T))
231
+ a = first (r)
232
+ m = (last (r) - first (r)) % U
233
+ k = m + one (U)
234
+ bw = (sizeof (U) << 3 - leading_zeros (m)) % Int
235
+ mult = if U === UInt32
236
+ maxmultiple (k)
237
+ elseif U === UInt64
238
+ bw <= 52 ? unsafe_maxmultiple (k, one (UInt64) << 52 ) :
239
+ maxmultiple (k)
240
+ else # U === UInt128
241
+ bw <= 52 ? unsafe_maxmultiple (k, one (UInt128) << 52 ) :
242
+ bw <= 104 ? unsafe_maxmultiple (k, one (UInt128) << 104 ) :
243
+ maxmultiple (k)
244
+ end
245
+
246
+ SamplerRangeInt {T,U} (a, bw, k, mult) # overflow ok
234
247
end
235
248
236
- Sampler (:: AbstractRNG , r:: AbstractUnitRange{T} , :: Repetition ) where {T<: Union{Bool,BitInteger} } =
237
- SamplerRangeInt (r)
249
+ Sampler (:: AbstractRNG , r:: AbstractUnitRange{T} ,
250
+ :: Repetition ) where {T<: Union{Bool,BitInteger} } = SamplerRangeInt (r)
251
+
252
+ rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,UInt32} ) where {T<: Union{Bool,BitInteger} } =
253
+ (unsigned (sp. a) + rem_knuth (rand (rng, LessThan (sp. u, uniform (UInt32))), sp. k)) % T
238
254
239
- function rand_lteq (rng:: AbstractRNG , u:: T ):: T where T
240
- while true
241
- x = rand (rng, T)
242
- x <= u && return x
243
- end
244
- end
245
255
246
- # this function uses 32 bit entropy for small ranges of length <= typemax(UInt32) + 1
256
+ # this function uses 52 bit entropy for small ranges of length <= 2^52
247
257
function rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,UInt64} ) where T<: BitInteger
248
- x:: UInt64 = (sp. k - 1 ) >> 32 == 0 ?
249
- rand_lteq (rng, sp. u % UInt32) % UInt64 :
250
- rand_lteq (rng, sp. u)
258
+ x = sp. bw <= 52 ? rand (rng, LessThan (sp. u, UInt52 ())) :
259
+ rand (rng, LessThan (sp. u, uniform (UInt64)))
251
260
return ((sp. a % UInt64) + rem_knuth (x, sp. k)) % T
252
261
end
253
262
254
- rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,U} ) where {T<: Union{Bool,BitInteger} ,U} =
255
- (unsigned (sp. a) + rem_knuth (rand_lteq (rng, sp. u), sp. k)) % T
263
+ function rand (rng:: AbstractRNG , sp:: SamplerRangeInt{T,UInt128} ) where T<: BitInteger
264
+ x = sp. bw <= 52 ? rand (rng, LessThan (sp. u, UInt52 (UInt128))) :
265
+ sp. bw <= 104 ? rand (rng, LessThan (sp. u, UInt104 (UInt128))) :
266
+ rand (rng, LessThan (sp. u, uniform (UInt128)))
267
+ return ((sp. a % UInt128) + rem_knuth (x, sp. k)) % T
268
+ end
256
269
257
270
258
271
# ## BigInt
0 commit comments