diff --git a/stdlib/SparseArrays/src/sparsematrix.jl b/stdlib/SparseArrays/src/sparsematrix.jl index baac93ca15b2f..4fbfd72d82809 100644 --- a/stdlib/SparseArrays/src/sparsematrix.jl +++ b/stdlib/SparseArrays/src/sparsematrix.jl @@ -1383,34 +1383,20 @@ function _sparse_findprevnz(m::SparseMatrixCSC, i::Integer) end -function _sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, rfn) - m, n = Int(m), Int(n) - (m < 0 || n < 0) && throw(ArgumentError("invalid Array dimensions")) - 0 <= density <= 1 || throw(ArgumentError("$density not in [0,1]")) - j, colm = 1, 0 - rowval = randsubseq(r, 1:(m*n), density) - nnz = length(rowval) - colptr = Vector{Int}(undef, n + 1) - @inbounds for col = 1:n+1 - colptr[col] = j - while j <= nnz && (rowval[j] -= colm) <= m - j += 1 - end - j <= nnz && (rowval[j] += colm) - colm += m - end - return SparseMatrixCSC(m, n, colptr, rowval, rfn(nnz)) -end - """ sprand([rng],[type],m,[n],p::AbstractFloat,[rfn]) Create a random length `m` sparse vector or `m` by `n` sparse matrix, in which the probability of any element being nonzero is independently given by -`p` (and hence the mean density of nonzeros is also exactly `p`). Nonzero -values are sampled from the distribution specified by `rfn` and have the type `type`. The uniform -distribution is used in case `rfn` is not specified. The optional `rng` -argument specifies a random number generator, see [Random Numbers](@ref). +`p` (and hence the mean density of nonzeros is also exactly `p`). The +optional `rng` argument specifies a random number generator that defaults +to the global one, see [Random Numbers](@ref). + +Nonzero values are taken from the function `rfn`. `rfn(i)` should +return a vector of `i` values. In case `rfn` is not specified, +it defaults to `rnf(i)=rand(rng, i)` (uniform distribution in ``[0,1)``) or, If +the parameter `type` is specified, to `rng(i)=rand(rng, type, i)`. +The special case of `type==Bool` corresponds to `rfn(i)=fill(true, i)` # Examples ```jldoctest; setup = :(using Random; Random.seed!(1234)) @@ -1423,31 +1409,29 @@ julia> sprand(Float64, 3, 0.75) [3] = 0.298614 ``` """ -function sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(r,1))) where T - m,n = Int(m), Int(n) - N = m*n - N == 0 && return spzeros(T,m,n) - N == 1 && return rand(r) <= density ? sparse([1], [1], rfn(r,1)) : spzeros(T,1,1) - _sprand(r,m,n,density,i->rfn(r,i)) -end - -function sprand(m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(1))) where T - m,n = Int(m), Int(n) - N = m*n - N == 0 && return spzeros(T,m,n) - N == 1 && return rand() <= density ? sparse([1], [1], rfn(1)) : spzeros(T,1,1) - _sprand(GLOBAL_RNG,m,n,density,rfn) +function sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, rfn::Function = i->rand(r,i)) + m, n = Int(m), Int(n) + (m < 0 || n < 0) && throw(ArgumentError("invalid Array dimensions")) + 0 <= density <= 1 || throw(ArgumentError("$density not in [0,1]")) + j, colm = 1, 0 + rowval = randsubseq(r, 1:(m*n), density) + nnz = length(rowval) + colptr = Vector{Int}(undef, n + 1) + @inbounds for col = 1:n+1 + colptr[col] = j + while j <= nnz && (rowval[j] -= colm) <= m + j += 1 + end + j <= nnz && (rowval[j] += colm) + colm += m + end + return SparseMatrixCSC(m, n, colptr, rowval, rfn(nnz)) end -truebools(r::AbstractRNG, n::Integer) = fill(true, n) - -sprand(m::Integer, n::Integer, density::AbstractFloat) = sprand(GLOBAL_RNG,m,n,density) +sprand(m::Integer, n::Integer, density::AbstractFloat, rfn::Function = rand) = sprand(GLOBAL_RNG,m,n,density,rfn) -sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,rand,Float64) -sprand(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where {T} = sprand(r,m,n,density,(r, i) -> rand(r, T, i), T) -sprand(r::AbstractRNG, ::Type{Bool}, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density, truebools, Bool) +sprand(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where {T} = sprand(r,m,n,density, i->rand(r,T,i)) +sprand(r::AbstractRNG, ::Type{Bool}, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density, i->fill(true,i)) sprand(::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where {T} = sprand(GLOBAL_RNG, T, m, n, density) """ @@ -1469,9 +1453,9 @@ julia> sprandn(2, 2, 0.75) [2, 2] = 0.297336 ``` """ -sprandn(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,randn,Float64) +sprandn(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,i->randn(r,i)) +sprandn(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where T = sprand(r,m,n,density,i->randn(r,T,i)) sprandn(m::Integer, n::Integer, density::AbstractFloat) = sprandn(GLOBAL_RNG,m,n,density) -sprandn(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where T = sprand(r,m,n,density,(r,i) -> randn(r,T,i), T) sprandn(::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where T = sprandn(GLOBAL_RNG,T,m,n,density) LinearAlgebra.fillstored!(S::SparseMatrixCSC, x) = (fill!(nzvalview(S), x); S) diff --git a/stdlib/SparseArrays/src/sparsevector.jl b/stdlib/SparseArrays/src/sparsevector.jl index 305e93ee1a0bb..247202532a47f 100644 --- a/stdlib/SparseArrays/src/sparsevector.jl +++ b/stdlib/SparseArrays/src/sparsevector.jl @@ -492,31 +492,24 @@ copyto!(A::SparseMatrixCSC, B::SparseVector{TvB,TiB}) where {TvB,TiB} = ### Rand Construction -sprand(n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) where {T} = sprand(GLOBAL_RNG, n, p, rfn, T) -function sprand(r::AbstractRNG, n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) where T - I = randsubseq(r, 1:convert(Int, n), p) - V = rfn(r, T, length(I)) - SparseVector(n, I, V) -end - sprand(n::Integer, p::AbstractFloat, rfn::Function) = sprand(GLOBAL_RNG, n, p, rfn) function sprand(r::AbstractRNG, n::Integer, p::AbstractFloat, rfn::Function) I = randsubseq(r, 1:convert(Int, n), p) - V = rfn(r, length(I)) + V = rfn(length(I)) SparseVector(n, I, V) end sprand(n::Integer, p::AbstractFloat) = sprand(GLOBAL_RNG, n, p, rand) -sprand(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, rand) -sprand(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) where {T} = sprand(r, n, p, (r, i) -> rand(r, T, i)) -sprand(r::AbstractRNG, ::Type{Bool}, n::Integer, p::AbstractFloat) = sprand(r, n, p, truebools) +sprand(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, i->rand(r,i)) +sprand(r::AbstractRNG, ::Type{Bool}, n::Integer, p::AbstractFloat) = sprand(r, n, p, i->fill(true,i)) sprand(::Type{T}, n::Integer, p::AbstractFloat) where {T} = sprand(GLOBAL_RNG, T, n, p) +sprand(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) where T = sprand(r, n, p, i->rand(r, T, i)) sprandn(n::Integer, p::AbstractFloat) = sprand(GLOBAL_RNG, n, p, randn) -sprandn(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, randn) -sprandn(::Type{T}, n::Integer, p::AbstractFloat) where T = sprand(GLOBAL_RNG, n, p, (r, i) -> randn(r, T, i)) -sprandn(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) where T = sprand(r, n, p, (r, i) -> randn(r, T, i)) +sprandn(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, i->randn(r,i)) +sprandn(::Type{T}, n::Integer, p::AbstractFloat) where T = sprand(GLOBAL_RNG, n, p, i->randn(T, i)) +sprandn(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) where T = sprand(r, n, p, i->randn(r, T, i)) ## Indexing into Matrices can return SparseVectors diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 1c8bf76e166e5..e4e7c79bcef79 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1921,7 +1921,7 @@ end @testset "issue #16073" begin @inferred sprand(1, 1, 1.0) - @inferred sprand(1, 1, 1.0, rand, Float64) + @inferred sprand(1, 1, 1.0, rand) @inferred sprand(1, 1, 1.0, x -> round.(Int, rand(x) * 100)) end diff --git a/stdlib/SparseArrays/test/sparsevector.jl b/stdlib/SparseArrays/test/sparsevector.jl index ceee49d2940a7..1c132a296a688 100644 --- a/stdlib/SparseArrays/test/sparsevector.jl +++ b/stdlib/SparseArrays/test/sparsevector.jl @@ -179,7 +179,7 @@ end @test all(nonzeros(xr) .> 0.0) end end - let xr = sprand(1000, 0.9, rand, Float32) + let xr = sprand(1000, 0.9, i->rand(Float32,i)) @test isa(xr, SparseVector{Float32,Int}) @test length(xr) == 1000 if !isempty(nonzeros(xr))