From f44b16341cd376c2fdc21b5ca804e77981d7793c Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 19 Jun 2012 09:00:26 +0530 Subject: [PATCH 1/4] Make sparse(Matrix) work again. Implementation is simpler and should be faster. Fix speye as well. --- extras/sparse.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/extras/sparse.jl b/extras/sparse.jl index acb18f484f42b..30741e308c8d7 100644 --- a/extras/sparse.jl +++ b/extras/sparse.jl @@ -19,6 +19,10 @@ function SparseMatrixCSC(Tv::Type, m::Int, n::Int, numnz::Integer) SparseMatrixCSC{Tv,Ti}(m, n, colptr, rowval, nzval) end +function SparseMatrixCSC(m::Int32, n::Int32, colptr, rowval, nzval) + return SparseMatrixCSC(int(m), int(n), colptr, rowval, nzval) +end + issparse(A::AbstractArray) = false issparse(S::SparseMatrixCSC) = true @@ -140,8 +144,10 @@ full{T}(S::SparseMatrixCSC{T}) = convert(Matrix{T}, S) function sparse(A::Matrix) m, n = size(A) - I, J, V = findn_nzs(A) - _jl_sparse(int32(I), int32(J), V, m, n) + colptr = [int32(1):int32(m):int32(m*n+1)] + rowval = repmat([int32(1):int32(m)], 1, n)[:] + nzval = A[:] + return SparseMatrixCSC(m, n, colptr, rowval, nzval) end # _jl_sparse_sortbased uses sort to rearrange the input and construct the sparse matrix @@ -388,8 +394,8 @@ speye(m::Int, n::Int) = speye(Float64, m, n) function speye(T::Type, m::Int, n::Int) x = int32(min(m,n)) - rowval = linspace(int32(1), x, x) - colptr = [rowval, int32(x+1)*ones(Int32, n+1-x)] + rowval = [int32(1):x] + colptr = [rowval, int32((x+1)*ones(Int32, n+1-x))] nzval = ones(T, x) return SparseMatrixCSC(m, n, colptr, rowval, nzval) end From d906da9112acdd639febcdb88420e7beffecf094 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 18 Jun 2012 23:39:44 -0400 Subject: [PATCH 2/4] Revert "fix elementwise operators on boolean arrays" This reverts commit fe2ad5bb4b02b63604c2cf36e52bc3f3a3fe12d5. --- base/array.jl | 25 ++++++++++++++++++------- test/bitarray.jl | 10 +++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/base/array.jl b/base/array.jl index a6f3527222b60..71867350ff357 100644 --- a/base/array.jl +++ b/base/array.jl @@ -653,15 +653,26 @@ end for f in (:+, :-, :.*, :div, :mod, :&, :|, :$) @eval begin - function ($f)(x::Number, y::AbstractArray) - reshape([ ($f)(x, y[i]) for i=1:numel(y) ], size(y)) + function ($f){S,T}(A::AbstractArray{S}, B::AbstractArray{T}) + F = Array(promote_type(S,T), promote_shape(size(A),size(B))) + for i=1:numel(A) + F[i] = ($f)(A[i], B[i]) + end + return F end - function ($f)(x::AbstractArray, y::Number) - reshape([ ($f)(x[i], y) for i=1:numel(x) ], size(x)) + function ($f){T}(A::Number, B::AbstractArray{T}) + F = similar(B, promote_type(typeof(A),T)) + for i=1:numel(B) + F[i] = ($f)(A, B[i]) + end + return F end - function ($f)(x::AbstractArray, y::AbstractArray) - shp = promote_shape(size(x),size(y)) - reshape([ ($f)(x[i], y[i]) for i=1:numel(x) ], shp) + function ($f){T}(A::AbstractArray{T}, B::Number) + F = similar(A, promote_type(T,typeof(B))) + for i=1:numel(A) + F[i] = ($f)(A[i], B) + end + return F end end end diff --git a/test/bitarray.jl b/test/bitarray.jl index eac994b04107a..7b3a6e82d3688 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -228,14 +228,14 @@ b2 = bitrand(TT, n1, n2) @check_bit_operation (&) BitArray{TT} (b1, b2) @check_bit_operation (|) BitArray{TT} (b1, b2) @check_bit_operation ($) BitArray{TT} (b1, b2) -@check_bit_operation (-) Array{Uint} (b1, b2) +@check_bit_operation (-) Array{TT} (b1, b2) @check_bit_operation (.*) BitArray{TT} (b1, b2) @check_bit_operation (./) Array{Float64} (b1, b2) @check_bit_operation (.^) Array{Float64} (b1, b2) b2 = bitones(TT, n1, n2) -@check_bit_operation div Array{Uint} (b1, b2) -@check_bit_operation mod Array{Uint} (b1, b2) +@check_bit_operation div Array{TT} (b1, b2) +@check_bit_operation mod Array{TT} (b1, b2) while true global b1 @@ -259,8 +259,8 @@ b2 = randi(10, n1, n2) @check_bit_operation (.*) Array{S} (b1, b2) @check_bit_operation (./) Array{Float64} (b1, b2) @check_bit_operation (.^) Array{Float64} (b1, b2) -@check_bit_operation div Array{Uint} (b1, b2) -@check_bit_operation mod Array{Int} (b1, b2) +@check_bit_operation div Array{S} (b1, b2) +@check_bit_operation mod Array{S} (b1, b2) while true global b1 From ac47a4930d83dd25ddaa9ec94a4d64c476ea1d40 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 19 Jun 2012 10:07:49 +0530 Subject: [PATCH 3/4] Revert the sparse(Matrix) implementation to the original, as it could return a sparse matrix with zeros. find(sparse) now has the same behaviour as that of dense matrices. Implement findn and find_nzs for sparse. NOTE: Code depending on the current behaviour of find(sparse) will have to be changed to use findn or find_nzs. --- extras/sparse.jl | 62 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/extras/sparse.jl b/extras/sparse.jl index 30741e308c8d7..71bb0344bf643 100644 --- a/extras/sparse.jl +++ b/extras/sparse.jl @@ -144,23 +144,19 @@ full{T}(S::SparseMatrixCSC{T}) = convert(Matrix{T}, S) function sparse(A::Matrix) m, n = size(A) - colptr = [int32(1):int32(m):int32(m*n+1)] - rowval = repmat([int32(1):int32(m)], 1, n)[:] - nzval = A[:] - return SparseMatrixCSC(m, n, colptr, rowval, nzval) + (I, J, V) = findn_nzs(A) + return _jl_sparse_sorted!(I,J,V,m,n,+) end -# _jl_sparse_sortbased uses sort to rearrange the input and construct the sparse matrix - -_jl_sparse_sortbased(I,J,V) = _jl_sparse_sortbased(I, J, V, int(max(I)), int(max(J)), +) +# _jl_sparse_sort uses sort to rearrange the input and construct the sparse matrix -_jl_sparse_sortbased(I,J,V,m,n) = _jl_sparse_sortbased(I, J, V, m, n, +) +_jl_sparse_sort(I,J,V) = _jl_sparse_sort(I, J, V, int(max(I)), int(max(J)), +) -_jl_sparse_sortbased(I,J,V,m,n,combine) = _jl_sparse_sortbased(I, J, V, m, n, combine) +_jl_sparse_sort(I,J,V,m,n) = _jl_sparse_sort(I, J, V, m, n, +) -function _jl_sparse_sortbased{Ti<:Union(Int32,Int64)}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, - V::Union(Number, AbstractVector), - m::Int, n::Int, combine::Function) +function _jl_sparse_sort{Ti<:Union(Int32,Int64)}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, + V::Union(Number, AbstractVector), + m::Int, n::Int, combine::Function) if length(I) == 0; return spzeros(eltype(V),m,n); end @@ -190,6 +186,15 @@ function _jl_sparse_sortbased{Ti<:Union(Int32,Int64)}(I::AbstractVector{Ti}, J:: if isa(V, Number); V = fill(V, length(I)); end + return _jl_sparse_sorted!(I,J,V,m,n,combine) +end + +_jl_sparse_sorted!(I,J,V,m,n) = _jl_sparse_sorted!(I,J,V,m,n,+) + +function _jl_sparse_sorted!{Ti<:Union(Int32,Int64)}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, + V::AbstractVector, + m::Int, n::Int, combine::Function) + cols = zeros(Ti, n+1) cols[1] = 1 # For cumsum purposes cols[J[1] + 1] = 1 @@ -336,8 +341,37 @@ function sparse{Tv,Ti<:Union(Int32,Int64)}(I::AbstractVector{Ti}, J::AbstractVec return SparseMatrixCSC(nrow, ncol, RpT, RiT, RxT) end +function find(S::SparseMatrixCSC) + sz = size(S) + I, J = findn(S) + return sub2ind(sz, I, J) +end + +function findn{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) + numnz = nnz(S) + I = Array(Ti, numnz) + J = Array(Ti, numnz) + + count = 1 + for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1) + if S.nzval[k] != 0 + I[count] = S.rowval[k] + J[count] = col + count += 1 + else + println("Warning: sparse matrix contains explicit stored zeros.") + end + end + + if numnz != count-1 + I = I[1:count] + J = J[1:count] + end + + return (I, J) +end -function find{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function findn_nzs{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) numnz = nnz(S) I = Array(Ti, numnz) J = Array(Ti, numnz) @@ -351,7 +385,7 @@ function find{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) V[count] = S.nzval[k] count += 1 else - println("Warning: sparse matrix has explicit stored zeros.") + println("Warning: sparse matrix contains explicit stored zeros.") end end From dcb8a4507a3a689bf24aa04fd74154f03081d91a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 19 Jun 2012 00:38:26 -0400 Subject: [PATCH 4/4] better fix for bool elementwise ops --- base/array.jl | 16 ++++++++++++++++ base/darray.jl | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/base/array.jl b/base/array.jl index 71867350ff357..2d780b4915044 100644 --- a/base/array.jl +++ b/base/array.jl @@ -677,6 +677,22 @@ for f in (:+, :-, :.*, :div, :mod, :&, :|, :$) end end +# functions that should give an Int result for Bool arrays +for f in (:+, :-, :div) + @eval begin + function ($f)(x::Bool, y::Array{Bool}) + reshape([ ($f)(x, y[i]) for i=1:numel(y) ], size(y)) + end + function ($f)(x::Array{Bool}, y::Bool) + reshape([ ($f)(x[i], y) for i=1:numel(x) ], size(x)) + end + function ($f)(x::Array{Bool}, y::Array{Bool}) + shp = promote_shape(size(x),size(y)) + reshape([ ($f)(x[i], y[i]) for i=1:numel(x) ], shp) + end + end +end + ## promotion to complex ## function complex{S<:Real,T<:Real}(A::Array{S}, B::Array{T}) diff --git a/base/darray.jl b/base/darray.jl index 100737bf60088..5267ea68065e4 100644 --- a/base/darray.jl +++ b/base/darray.jl @@ -798,12 +798,12 @@ end for f in (:+, :-, :.*, :./, :.^, :&, :|, :$) @eval begin function ($f){T}(A::Number, B::SubOrDArray{T}) - S = typeof(($f)(one(A),one(T))) + S = eltype(($f)([one(A)],[one(T)])) darray((T,lsz,da)->($f)(A, localize(B, da)), S, size(B), distdim(B), procs(B)) end function ($f){T}(A::SubOrDArray{T}, B::Number) - S = typeof(($f)(one(T),one(B))) + S = eltype(($f)([one(T)],[one(B)])) darray((T,lsz,da)->($f)(localize(A, da), B), S, size(A), distdim(A), procs(A)) end @@ -811,7 +811,7 @@ for f in (:+, :-, :.*, :./, :.^, :&, :|, :$) if size(A) != size(B) error("argument dimensions must match") end - R = typeof(($f)(one(T), one(S))) + R = eltype(($f)([one(T)],[one(S)])) darray((T,lsz,da)->($f)(localize(A, da), localize(B, da)), R, size(A), distdim(A), procs(A)) end