• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38187

17 Aug 2025 03:51PM UTC coverage: 77.005% (-1.2%) from 78.205%
#38187

push

local

web-flow
openlibm 0.8.7 (#59312)

Released 3 June 2025
https://github.com/JuliaMath/openlibm/releases/tag/v0.8.7

47659 of 61891 relevant lines covered (77.0%)

9074775.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.21
/stdlib/Random/src/misc.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
## rand!(::BitArray) && bitrand
4

5
function rand!(rng::AbstractRNG, B::BitArray, ::SamplerType{Bool})
6
    isempty(B) && return B
137,872✔
7
    Bc = B.chunks
134,913✔
8
    rand!(rng, Bc)
134,913✔
9
    Bc[end] &= Base._msk_end(B)
134,913✔
10
    return B
134,913✔
11
end
12

13
"""
14
    bitrand([rng=default_rng()], [dims...])
15

16
Generate a `BitArray` of random boolean values.
17

18
# Examples
19
```jldoctest
20
julia> bitrand(Xoshiro(123), 10)
21
10-element BitVector:
22
 0
23
 1
24
 0
25
 1
26
 0
27
 1
28
 0
29
 0
30
 1
31
 1
32
```
33
"""
34
bitrand(r::AbstractRNG, dims::Dims)   = rand!(r, BitArray(undef, dims))
×
35
bitrand(r::AbstractRNG, dims::Integer...) = rand!(r, BitArray(undef, convert(Dims, dims)))
×
36

37
bitrand(dims::Dims)   = rand!(BitArray(undef, dims))
41✔
38
bitrand(dims::Integer...) = rand!(BitArray(undef, convert(Dims, dims)))
86,003✔
39

40

41
## randstring (often useful for temporary filenames/dirnames)
42

43
"""
44
    randstring([rng=default_rng()], [chars], [len=8])
45

46
Create a random string of length `len`, consisting of characters from
47
`chars`, which defaults to the set of upper- and lower-case letters
48
and the digits 0-9. The optional `rng` argument specifies a random
49
number generator, see [Random Numbers](@ref).
50

51
# Examples
52
```jldoctest
53
julia> Random.seed!(3); randstring()
54
"Lxz5hUwn"
55

56
julia> randstring(Xoshiro(3), 'a':'z', 6)
57
"iyzcsm"
58

59
julia> randstring("ACGT")
60
"TGCTCCTC"
61
```
62

63
!!! note
64
    `chars` can be any collection of characters, of type `Char` or
65
    `UInt8` (more efficient), provided [`rand`](@ref) can randomly
66
    pick characters from it.
67
"""
68
function randstring end
69

70
let b = UInt8['0':'9';'A':'Z';'a':'z']
71
    global randstring
72

73
    function randstring(r::AbstractRNG, chars=b, n::Integer=8)
1,101✔
74
        T = eltype(chars)
105,804✔
75
        if T === UInt8
105,804✔
76
            str = Base._string_n(n)
105,856✔
77
            GC.@preserve str rand!(r, UnsafeView(pointer(str), n), chars)
105,856✔
78
            return str
105,726✔
79
        else
80
            v = Vector{T}(undef, n)
1,100✔
81
            rand!(r, v, chars)
1,100✔
82
            return String(v)
1,100✔
83
        end
84
    end
85

86
    randstring(r::AbstractRNG, n::Integer) = randstring(r, b, n)
1,100✔
87
    randstring(chars=b, n::Integer=8) = randstring(default_rng(), chars, n)
200,278✔
88
    randstring(n::Integer) = randstring(default_rng(), b, n)
4,614✔
89
end
90

91

92
## randsubseq & randsubseq!
93

94
# Fill S (resized as needed) with a random subsequence of A, where
95
# each element of A is included in S with independent probability p.
96
# (Note that this is different from the problem of finding a random
97
#  size-m subset of A where m is fixed!)
98
function randsubseq!(r::AbstractRNG, S::AbstractArray, A::AbstractArray, p::Real)
1,961✔
99
    require_one_based_indexing(S, A)
1,961✔
100
    0 <= p <= 1 || _throw_argerror(LazyString("probability ", p, " not in [0,1]"))
1,961✔
101
    n = length(A)
1,961✔
102
    p == 1 && return copyto!(resize!(S, n), A)
1,961✔
103
    empty!(S)
1,939✔
104
    p == 0 && return S
1,939✔
105
    nexpected = p * length(A)
1,930✔
106
    sizehint!(S, round(Int,nexpected + 5*sqrt(nexpected)))
1,930✔
107
    if p > 0.15 # empirical threshold for trivial O(n) algorithm to be better
1,930✔
108
        for i = 1:n
1,776✔
109
            rand(r) <= p && push!(S, A[i])
40,635,341✔
110
        end
81,268,906✔
111
    else
112
        # Skip through A, in order, from each element i to the next element i+s
113
        # included in S. The probability that the next included element is
114
        # s==k (k > 0) is (1-p)^(k-1) * p, and hence the probability (CDF) that
115
        # s is in {1,...,k} is 1-(1-p)^k = F(k).   Thus, we can draw the skip s
116
        # from this probability distribution via the discrete inverse-transform
117
        # method: s = ceil(F^{-1}(u)) where u = rand(), which is simply
118
        # s = ceil(log(rand()) / log1p(-p)).
119
        # -log(rand()) is an exponential variate, so can use randexp().
120
        L = -1 / log1p(-p) # L > 0
154✔
121
        i = 0
154✔
122
        while true
228,791✔
123
            s = randexp(r) * L
228,791✔
124
            s >= n - i && return S # compare before ceil to avoid overflow
228,791✔
125
            push!(S, A[i += ceil(Int,s)])
228,637✔
126
        end
228,637✔
127
        # [This algorithm is similar in spirit to, but much simpler than,
128
        #  the one by Vitter for a related problem in "Faster methods for
129
        #  random sampling," Comm. ACM Magazine 7, 703-718 (1984).]
130
    end
131
    return S
1,776✔
132
end
133

134
"""
135
    randsubseq!([rng=default_rng(),] S, A, p)
136

137
Like [`randsubseq`](@ref), but the results are stored in `S`
138
(which is resized as needed).
139

140
# Examples
141
```jldoctest
142
julia> S = Int64[];
143

144
julia> randsubseq!(Xoshiro(123), S, 1:8, 0.3)
145
2-element Vector{Int64}:
146
 4
147
 7
148

149
julia> S
150
2-element Vector{Int64}:
151
 4
152
 7
153
```
154
"""
155
randsubseq!(S::AbstractArray, A::AbstractArray, p::Real) = randsubseq!(default_rng(), S, A, p)
×
156

157
randsubseq(r::AbstractRNG, A::AbstractArray{T}, p::Real) where {T} =
1,961✔
158
    randsubseq!(r, T[], A, p)
159

160
"""
161
    randsubseq([rng=default_rng(),] A, p) -> Vector
162

163
Return a vector consisting of a random subsequence of the given array `A`, where each
164
element of `A` is included (in order) with independent probability `p`. (Complexity is
165
linear in `p*length(A)`, so this function is efficient even if `p` is small and `A` is
166
large.) Technically, this process is known as "Bernoulli sampling" of `A`.
167

168
# Examples
169
```jldoctest
170
julia> randsubseq(Xoshiro(123), 1:8, 0.3)
171
2-element Vector{Int64}:
172
 4
173
 7
174
```
175
"""
176
randsubseq(A::AbstractArray, p::Real) = randsubseq(default_rng(), A, p)
1,101✔
177

178

179
## rand Less Than Masked 52 bits (helper function)
180

181
"Return a sampler generating a random `Int` (masked with `mask`) in ``[0, n)``, when `n <= 2^52`."
182
ltm52(n::Int, mask::Int=nextpow(2, n)-1) = LessThan(n-1, Masked(mask, UInt52Raw(Int)))
53,488✔
183

184
## shuffle & shuffle!
185

186
function shuffle(rng::AbstractRNG, tup::NTuple{N}) where {N}
×
187
    # `@inline` and `@inbounds` are here to help escape analysis eliminate the `Memory` allocation
188
    #
189
    # * `@inline` might be necessary because escape analysis relies on everything
190
    #   touching the `Memory` being inlined because there's no interprocedural escape
191
    #   analysis yet, relevant WIP PR: https://github.com/JuliaLang/julia/pull/56849
192
    #
193
    # * `@inbounds` might be necessary because escape analysis requires any throws of
194
    #   `BoundsError` to be eliminated as dead code, because `BoundsError` stores the
195
    #   array itself, making the throw escape the array from the function, relevant
196
    #   WIP PR: https://github.com/JuliaLang/julia/pull/56167
197
    @inline let
×
198
        # use a narrow integer type to save stack space and prevent heap allocation
199
        Ind = if N ≤ typemax(UInt8)
×
200
            UInt8
×
201
        elseif N ≤ typemax(UInt16)
×
202
            UInt16
×
203
        else
204
            UInt
×
205
        end
206
        mem = @inbounds randperm!(rng, Memory{Ind}(undef, N))
×
207
        function closure(i::Int)
×
208
            @inbounds tup[mem[i]]
×
209
        end
210
        ntuple(closure, Val{N}())
×
211
    end
212
end
213

214
"""
215
    shuffle!([rng=default_rng(),] v::AbstractArray)
216

217
In-place version of [`shuffle`](@ref): randomly permute `v` in-place,
218
optionally supplying the random-number generator `rng`.
219

220
# Examples
221
```jldoctest
222
julia> shuffle!(Xoshiro(123), Vector(1:10))
223
10-element Vector{Int64}:
224
  5
225
  4
226
  2
227
  3
228
  6
229
 10
230
  8
231
  1
232
  9
233
  7
234
```
235
"""
236
function shuffle!(r::AbstractRNG, a::AbstractArray)
2,007✔
237
    # keep it consistent with `randperm!` and `randcycle!` if possible
238
    require_one_based_indexing(a)
2,007✔
239
    n = length(a)
2,007✔
240
    @assert n <= Int64(2)^52
2,007✔
241
    n == 0 && return a
2,007✔
242
    mask = 3
2,007✔
243
    @inbounds for i = 2:n
2,007✔
244
        j = 1 + rand(r, ltm52(i, mask))
19,103✔
245
        a[i], a[j] = a[j], a[i]
19,103✔
246
        i == 1 + mask && (mask = 2 * mask + 1)
19,103✔
247
    end
36,199✔
248
    return a
2,007✔
249
end
250

251
function shuffle!(r::AbstractRNG, a::AbstractArray{Bool})
×
252
    old_count = count(a)
×
253
    len = length(a)
×
254
    uncommon_value = 2old_count <= len
×
255
    fuel = uncommon_value ? old_count : len - old_count
×
256
    fuel == 0 && return a
×
257
    a .= !uncommon_value
×
258
    while fuel > 0
×
259
        k = rand(r, eachindex(a))
×
260
        fuel -= a[k] != uncommon_value
×
261
        a[k] = uncommon_value
×
262
    end
×
263
    a
×
264
end
265

266
shuffle!(a::AbstractArray) = shuffle!(default_rng(), a)
2,003✔
267

268
"""
269
    shuffle([rng=default_rng(),] v::Union{NTuple,AbstractArray})
270

271
Return a randomly permuted copy of `v`. The optional `rng` argument specifies a random
272
number generator (see [Random Numbers](@ref)).
273
To permute `v` in-place, see [`shuffle!`](@ref). To obtain randomly permuted
274
indices, see [`randperm`](@ref).
275

276
!!! compat "Julia 1.13"
277
    Shuffling an `NTuple` value requires Julia v1.13 or above.
278

279
# Examples
280
```jldoctest
281
julia> shuffle(Xoshiro(123), Vector(1:10))
282
10-element Vector{Int64}:
283
  5
284
  4
285
  2
286
  3
287
  6
288
 10
289
  8
290
  1
291
  9
292
  7
293
```
294
"""
295
function shuffle end
296

297
shuffle(r::AbstractRNG, a::AbstractArray) = shuffle!(r, copymutable(a))
5✔
298
shuffle(a::Union{NTuple, AbstractArray}) = shuffle(default_rng(), a)
5✔
299

300
shuffle(r::AbstractRNG, a::Base.OneTo) = randperm(r, last(a))
×
301

302
## randperm & randperm!
303

304
"""
305
    randperm([rng=default_rng(),] n::Integer)
306

307
Construct a random permutation of length `n`. The optional `rng`
308
argument specifies a random number generator (see [Random
309
Numbers](@ref)). The element type of the result is the same as the type
310
of `n`.
311

312
To randomly permute an arbitrary vector, see [`shuffle`](@ref) or
313
[`shuffle!`](@ref).
314

315
!!! compat "Julia 1.1"
316
    In Julia 1.1 `randperm` returns a vector `v` with `eltype(v) == typeof(n)`
317
    while in Julia 1.0 `eltype(v) == Int`.
318

319
# Examples
320
```jldoctest
321
julia> randperm(Xoshiro(123), 4)
322
4-element Vector{Int64}:
323
 1
324
 4
325
 2
326
 3
327
```
328
"""
329
randperm(r::AbstractRNG, n::T) where {T <: Integer} = randperm!(r, Vector{T}(undef, n))
51✔
330
randperm(n::Integer) = randperm(default_rng(), n)
51✔
331

332
"""
333
    randperm!([rng=default_rng(),] A::AbstractArray{<:Integer})
334

335
Construct in `A` a random permutation of length `length(A)`. The
336
optional `rng` argument specifies a random number generator (see
337
[Random Numbers](@ref)). To randomly permute an arbitrary vector, see
338
[`shuffle`](@ref) or [`shuffle!`](@ref).
339

340
!!! compat "Julia 1.13"
341
    `A isa Array` was required prior to Julia v1.13.
342

343
# Examples
344
```jldoctest
345
julia> randperm!(Xoshiro(123), Vector{Int}(undef, 4))
346
4-element Vector{Int64}:
347
 1
348
 4
349
 2
350
 3
351
```
352
"""
353
function randperm!(r::AbstractRNG, a::AbstractArray{<:Integer})
51✔
354
    # keep it consistent with `shuffle!` and `randcycle!` if possible
355
    Base.require_one_based_indexing(a)
51✔
356
    n = length(a)
51✔
357
    @assert n <= Int64(2)^52
51✔
358
    n == 0 && return a
51✔
359
    a[1] = 1
51✔
360
    mask = 3
51✔
361
    @inbounds for i = 2:n
51✔
362
        j = 1 + rand(r, ltm52(i, mask))
34,187✔
363
        if i != j # a[i] is undef (and could be #undef)
34,187✔
364
            a[i] = a[j]
34,054✔
365
        end
366
        a[j] = i
34,187✔
367
        i == 1 + mask && (mask = 2 * mask + 1)
34,187✔
368
    end
68,323✔
369
    return a
51✔
370
end
371

372
randperm!(a::AbstractArray{<:Integer}) = randperm!(default_rng(), a)
×
373

374

375
## randcycle & randcycle!
376

377
"""
378
    randcycle([rng=default_rng(),] n::Integer)
379

380
Construct a random cyclic permutation of length `n`. The optional `rng`
381
argument specifies a random number generator, see [Random Numbers](@ref).
382
The element type of the result is the same as the type of `n`.
383

384
Here, a "cyclic permutation" means that all of the elements lie within
385
a single cycle.  If `n > 0`, there are ``(n-1)!`` possible cyclic permutations,
386
which are sampled uniformly.  If `n == 0`, `randcycle` returns an empty vector.
387

388
[`randcycle!`](@ref) is an in-place variant of this function.
389

390
!!! compat "Julia 1.1"
391
    In Julia 1.1 and above, `randcycle` returns a vector `v` with
392
    `eltype(v) == typeof(n)` while in Julia 1.0 `eltype(v) == Int`.
393

394
# Examples
395
```jldoctest
396
julia> randcycle(Xoshiro(123), 6)
397
6-element Vector{Int64}:
398
 5
399
 4
400
 2
401
 6
402
 3
403
 1
404
```
405
"""
406
randcycle(r::AbstractRNG, n::T) where {T <: Integer} = randcycle!(r, Vector{T}(undef, n))
19✔
407
randcycle(n::Integer) = randcycle(default_rng(), n)
19✔
408

409
"""
410
    randcycle!([rng=default_rng(),] A::AbstractArray{<:Integer})
411

412
Construct in `A` a random cyclic permutation of length `n = length(A)`.
413
The optional `rng` argument specifies a random number generator, see
414
[Random Numbers](@ref).
415

416
Here, a "cyclic permutation" means that all of the elements lie within a single cycle.
417
If `A` is nonempty (`n > 0`), there are ``(n-1)!`` possible cyclic permutations,
418
which are sampled uniformly.  If `A` is empty, `randcycle!` leaves it unchanged.
419

420
[`randcycle`](@ref) is a variant of this function that allocates a new vector.
421

422
!!! compat "Julia 1.13"
423
    `A isa Array` was required prior to Julia v1.13.
424

425
# Examples
426
```jldoctest
427
julia> randcycle!(Xoshiro(123), Vector{Int}(undef, 6))
428
6-element Vector{Int64}:
429
 5
430
 4
431
 2
432
 6
433
 3
434
 1
435
```
436
"""
437
function randcycle!(r::AbstractRNG, a::AbstractArray{<:Integer})
19✔
438
    # keep it consistent with `shuffle!` and `randperm!` if possible
439
    Base.require_one_based_indexing(a)
19✔
440
    n = length(a)
19✔
441
    @assert n <= Int64(2)^52
19✔
442
    n == 0 && return a
19✔
443
    a[1] = 1
19✔
444
    mask = 3
19✔
445
    # Sattolo's algorithm:
446
    @inbounds for i = 2:n
19✔
447
        j = 1 + rand(r, ltm52(i-1, mask))
198✔
448
        a[i] = a[j]
198✔
449
        a[j] = i
198✔
450
        i == 1 + mask && (mask = 2 * mask + 1)
198✔
451
    end
377✔
452
    return a
19✔
453
end
454

455
randcycle!(a::AbstractArray{<:Integer}) = randcycle!(default_rng(), a)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc