Skip to content

Commit

Permalink
Merge pull request JuliaLang#10418 from tanmaykm/sparsematrix
Browse files Browse the repository at this point in the history
SparseMatrixCSC checks for negative dimensions and fixes for maximum and minimum
  • Loading branch information
tkelman committed Mar 11, 2015
2 parents a3afed7 + c3b8ba2 commit f54ba05
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 17 deletions.
12 changes: 6 additions & 6 deletions base/sparse/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer)
end
rowval = Array(Ti, nnz)
nzval = Array(Tv, nnz)
A = SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval)
A = SparseMatrixCSC(m, n, colptr, rowval, nzval)
for col = max(k+1,1) : n
c1 = S.colptr[col]
for c2 = A.colptr[col] : A.colptr[col+1]-1
Expand Down Expand Up @@ -353,7 +353,7 @@ function tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer)
end
rowval = Array(Ti, nnz)
nzval = Array(Tv, nnz)
A = SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval)
A = SparseMatrixCSC(m, n, colptr, rowval, nzval)
for col = 1 : min(n, m+k)
c1 = S.colptr[col+1]-1
l2 = A.colptr[col+1]-1
Expand All @@ -370,7 +370,7 @@ end

function sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti})
m,n = size(S)
m > 1 || return SparseMatrixCSC{Tv,Ti}(0, n, ones(n+1), Ti[], Tv[])
m > 1 || return SparseMatrixCSC(0, n, ones(Ti,n+1), Ti[], Tv[])
colptr = Array(Ti, n+1)
numnz = 2 * nnz(S) # upper bound; will shrink later
rowval = Array(Ti, numnz)
Expand Down Expand Up @@ -405,7 +405,7 @@ function sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti})
end
deleteat!(rowval, numnz+1:length(rowval))
deleteat!(nzval, numnz+1:length(nzval))
return SparseMatrixCSC{Tv,Ti}(m-1, n, colptr, rowval, nzval)
return SparseMatrixCSC(m-1, n, colptr, rowval, nzval)
end

function sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti})
Expand All @@ -425,7 +425,7 @@ function sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti})
ptrS = 1
colptr[1] = 1

n == 0 && return SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval)
n == 0 && return SparseMatrixCSC(m, n, colptr, rowval, nzval)

startA = colptr_a[1]
stopA = colptr_a[2]
Expand Down Expand Up @@ -495,7 +495,7 @@ function sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti})
end
deleteat!(rowval, ptrS:length(rowval))
deleteat!(nzval, ptrS:length(nzval))
return SparseMatrixCSC{Tv,Ti}(m, n-1, colptr, rowval, nzval)
return SparseMatrixCSC(m, n-1, colptr, rowval, nzval)
end

diff(a::SparseMatrixCSC, dim::Integer)= dim==1 ? sparse_diff1(a) : sparse_diff2(a)
Expand Down
35 changes: 24 additions & 11 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@ type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti}
colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1)
rowval::Vector{Ti} # Row values of nonzeros
nzval::Vector{Tv} # Nonzero values
end

SparseMatrixCSC{Tv,Ti}(m::Integer, n::Integer, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv}) =
SparseMatrixCSC(Int(m), Int(n), colptr, rowval, nzval)
function SparseMatrixCSC(m::Integer, n::Integer, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv})
m < 0 && throw(ArgumentError("number of rows (m) must be ≥ 0, got $m"))
n < 0 && throw(ArgumentError("number of columns (n) must be ≥ 0, got $n"))
new(Int(m), Int(n), colptr, rowval, nzval)
end
end
function SparseMatrixCSC(m::Integer, n::Integer, colptr::Vector, rowval::Vector, nzval::Vector)
Tv = eltype(nzval)
Ti = promote_type(eltype(colptr), eltype(rowval))
SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval)
end

size(S::SparseMatrixCSC) = (S.m, S.n)
nnz(S::SparseMatrixCSC) = Int(S.colptr[end]-1)
Expand Down Expand Up @@ -60,7 +68,7 @@ function reinterpret{T,Tv,Ti}(::Type{T}, a::SparseMatrixCSC{Tv,Ti})
colptr = copy(a.colptr)
rowval = copy(a.rowval)
nzval = reinterpret(T, a.nzval)
return SparseMatrixCSC{T,Ti}(mA, nA, colptr, rowval, nzval)
return SparseMatrixCSC(mA, nA, colptr, rowval, nzval)
end

function sparse_compute_reshaped_colptr_and_rowval{Ti}(colptrS::Vector{Ti}, rowvalS::Vector{Ti}, mS::Int, nS::Int, colptrA::Vector{Ti}, rowvalA::Vector{Ti}, mA::Int, nA::Int)
Expand Down Expand Up @@ -111,7 +119,7 @@ function reinterpret{T,Tv,Ti,N}(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTup

sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA)

return SparseMatrixCSC{T,Ti}(mS, nS, colptr, rowval, nzval)
return SparseMatrixCSC(mS, nS, colptr, rowval, nzval)
end

function reshape{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{2,Int})
Expand All @@ -127,7 +135,7 @@ function reshape{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{2,Int})

sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, mS, nS, a.colptr, a.rowval, mA, nA)

return SparseMatrixCSC{Tv,Ti}(mS, nS, colptr, rowval, nzval)
return SparseMatrixCSC(mS, nS, colptr, rowval, nzval)
end

## Constructors
Expand Down Expand Up @@ -194,7 +202,7 @@ function vec{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti})
rowval = similar(S.rowval)
lS = length(S)
sparse_compute_reshaped_colptr_and_rowval(colptr, rowval, lS, 1, S.colptr, S.rowval, S.m, S.n)
SparseMatrixCSC{Tv,Ti}(lS, 1, colptr, rowval, copy(S.nzval))
SparseMatrixCSC(lS, 1, colptr, rowval, copy(S.nzval))
end

sparsevec(A::AbstractMatrix) = reshape(sparse(A), (length(A),1))
Expand Down Expand Up @@ -358,6 +366,7 @@ end

function sprand{T}(m::Integer, n::Integer, density::FloatingPoint,
rng::Function,::Type{T}=eltype(rng(1)))
((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions"))
0 <= density <= 1 || throw(ArgumentError("$density not in [0,1]"))
N = n*m
N == 0 && return spzeros(T,m,n)
Expand Down Expand Up @@ -404,10 +413,11 @@ spones{T}(S::SparseMatrixCSC{T}) =
SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), ones(T, S.colptr[end]-1))

spzeros(m::Integer, n::Integer) = spzeros(Float64, m, n)
spzeros(Tv::Type, m::Integer, n::Integer) =
SparseMatrixCSC(m, n, ones(Int, n+1), Array(Int, 0), Array(Tv, 0))
spzeros(Tv::Type, Ti::Type, m::Integer, n::Integer) =
spzeros(Tv::Type, m::Integer, n::Integer) = spzeros(Tv, Int, m, n)
function spzeros(Tv::Type, Ti::Type, m::Integer, n::Integer)
((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions"))
SparseMatrixCSC(m, n, ones(Ti, n+1), Array(Ti, 0), Array(Tv, 0))
end

speye(n::Integer) = speye(Float64, n)
speye(T::Type, n::Integer) = speye(T, n, n)
Expand All @@ -416,6 +426,7 @@ speye{T}(S::SparseMatrixCSC{T}) = speye(T, size(S, 1), size(S, 2))
eye(S::SparseMatrixCSC) = speye(S)

function speye(T::Type, m::Integer, n::Integer)
((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions"))
x = min(m,n)
rowval = [1:x;]
colptr = [rowval; fill(Int(x+1), n+1-x)]
Expand Down Expand Up @@ -753,6 +764,7 @@ end

function maximum{T}(A::SparseMatrixCSC{T})
isempty(A) && throw(ArgumentError("argument must not be empty"))
(nnz(A) == 0) && (return zero(T))
m = maximum(A.nzval)
nnz(A)!=length(A) ? max(m,zero(T)) : m
end
Expand All @@ -762,6 +774,7 @@ maximum{T}(A::SparseMatrixCSC{T}, region) =

function minimum{T}(A::SparseMatrixCSC{T})
isempty(A) && throw(ArgumentError("argument must not be empty"))
(nnz(A) == 0) && (return zero(T))
m = minimum(A.nzval)
nnz(A)!=length(A) ? min(m,zero(T)) : m
end
Expand Down Expand Up @@ -2227,7 +2240,7 @@ function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti})
end
end

return SparseMatrixCSC{Tv,Ti}(n, n, colptr, rowval, nzval)
return SparseMatrixCSC(n, n, colptr, rowval, nzval)
end

# Sort all the indices in each column of a CSC sparse matrix
Expand Down
11 changes: 11 additions & 0 deletions test/sparsedir/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -695,3 +695,14 @@ for T in (Int, Float16, Float32, Float64, BigInt, BigFloat)
@test abs2(S) == abs2(D)
end
end

# issue #10407
@test maximum(spzeros(5, 5)) == 0.0
@test minimum(spzeros(5, 5)) == 0.0

# issue #10411
for (m,n) in ((2,-2),(-2,2),(-2,-2))
@test_throws ArgumentError spzeros(m,n)
@test_throws ArgumentError speye(m,n)
@test_throws ArgumentError sprand(m,n,0.2)
end

0 comments on commit f54ba05

Please sign in to comment.