Skip to content

Commit

Permalink
Merge pull request #15198 from JuliaLang/anj/similar
Browse files Browse the repository at this point in the history
Use Matrix for similar(SpecialMatrix, shape) instead of throwing
  • Loading branch information
andreasnoack committed Feb 24, 2016
2 parents 86f42bc + e696f0a commit 4d8f5bf
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 28 deletions.
2 changes: 1 addition & 1 deletion base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ end
## Constructors ##

# default arguments to similar()
similar{T}(a::AbstractArray{T}) = similar(a, T, size(a))
similar{T}(a::AbstractArray{T}) = similar(a, T)
similar( a::AbstractArray, T::Type) = similar(a, T, size(a))
similar{T}(a::AbstractArray{T}, dims::DimsInteger) = similar(a, T, dims)
similar{T}(a::AbstractArray{T}, dims::Integer...) = similar(a, T, dims)
Expand Down
4 changes: 3 additions & 1 deletion base/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type Bidiagonal{T} <: AbstractMatrix{T}
dv::Vector{T} # diagonal
ev::Vector{T} # sub/super diagonal
isupper::Bool # is upper bidiagonal (true) or lower (false)
function Bidiagonal{T}(dv::Vector{T}, ev::Vector{T}, isupper::Bool)
function Bidiagonal(dv::Vector{T}, ev::Vector{T}, isupper::Bool)
if length(ev) != length(dv)-1
throw(DimensionMismatch("length of diagonal vector is $(length(dv)), length of off-diagonal vector is $(length(ev))"))
end
Expand Down Expand Up @@ -101,6 +101,8 @@ convert{Tnew,Told}(::Type{AbstractMatrix{Tnew}}, A::Bidiagonal{Told}) = convert(

big(B::Bidiagonal) = Bidiagonal(big(B.dv), big(B.ev), B.isupper)

similar{T}(B::Bidiagonal, ::Type{T}) = Bidiagonal{T}(similar(B.dv, T), similar(B.ev, T), B.isupper)

###################
# LAPACK routines #
###################
Expand Down
7 changes: 2 additions & 5 deletions base/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ convert{T}(::Type{AbstractMatrix{T}}, D::Diagonal) = convert(Diagonal{T}, D)
convert{T}(::Type{UpperTriangular}, A::Diagonal{T}) = UpperTriangular(A)
convert{T}(::Type{LowerTriangular}, A::Diagonal{T}) = LowerTriangular(A)

function similar{T}(D::Diagonal, ::Type{T}, d::Tuple{Int,Int})
if d[1] != d[2]
throw(ArgumentError("diagonal matrix must be square"))
end
return Diagonal{T}(Array(T,d[1]))
function similar{T}(D::Diagonal, ::Type{T})
return Diagonal{T}(similar(D.diag, T))
end

copy!(D1::Diagonal, D2::Diagonal) = (copy!(D1.diag, D2.diag); D1)
Expand Down
12 changes: 12 additions & 0 deletions base/linalg/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ end
@inbounds r = (A.uplo == 'U') == (i < j) ? A.data[i, j] : conj(A.data[j, i])
r
end

similar{T}(A::Symmetric, ::Type{T}) = Symmetric(similar(A.data, T))
# Hermitian version can be simplified when check for imaginary part of
# diagonal in Hermitian has been removed
function similar{T}(A::Hermitian, ::Type{T})
B = similar(A.data, T)
for i = 1:size(A,1)
B[i,i] = 0
end
return Hermitian(B)
end

full(A::Symmetric) = copytri!(copy(A.data), A.uplo)
full(A::Hermitian) = copytri!(copy(A.data), A.uplo, true)
parent(A::HermOrSym) = A.data
Expand Down
10 changes: 2 additions & 8 deletions base/linalg/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular,
convert{Tnew,Told,S}(::Type{AbstractMatrix{Tnew}}, A::$t{Told,S}) = convert($t{Tnew}, A)
convert{T,S}(::Type{Matrix}, A::$t{T,S}) = convert(Matrix{T}, A)

function similar{T,S,Tnew}(A::$t{T,S}, ::Type{Tnew}, dims::Dims)
if length(dims) != 2
throw(ArgumentError("Triangular matrix must have two dimensions"))
end
if dims[1] != dims[2]
throw(ArgumentError("Triangular matrix must be square"))
end
B = similar(A.data, Tnew, dims)
function similar{T,S,Tnew}(A::$t{T,S}, ::Type{Tnew})
B = similar(A.data, Tnew)
return $t(B)
end

Expand Down
9 changes: 4 additions & 5 deletions base/linalg/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ function size(A::SymTridiagonal, d::Integer)
end
end

similar{T}(S::SymTridiagonal, ::Type{T}) = SymTridiagonal{T}(similar(S.dv, T), similar(S.ev, T))

#Elementary operations
for func in (:conj, :copy, :round, :trunc, :floor, :ceil, :abs, :real, :imag)
@eval ($func)(M::SymTridiagonal) = SymTridiagonal(($func)(M.dv), ($func)(M.ev))
Expand Down Expand Up @@ -361,11 +363,8 @@ function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T})
A
end
convert{T}(::Type{Matrix}, M::Tridiagonal{T}) = convert(Matrix{T}, M)
function similar(M::Tridiagonal, T, dims::Dims)
if length(dims) != 2 || dims[1] != dims[2]
throw(DimensionMismatch("Tridiagonal matrices must be square"))
end
Tridiagonal{T}(similar(M.dl), similar(M.d), similar(M.du), similar(M.du2))
function similar{T}(M::Tridiagonal, ::Type{T})
Tridiagonal{T}(similar(M.dl, T), similar(M.d, T), similar(M.du, T), similar(M.du2, T))
end

# Operations on Tridiagonal matrices
Expand Down
5 changes: 4 additions & 1 deletion test/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ for relty in (Int, Float32, Float64, BigFloat), elty in (relty, Complex{relty})
@test_throws DimensionMismatch Bidiagonal(dv,ones(elty,n),true)
@test_throws ArgumentError Bidiagonal(dv,ev)

debug && println("getindex, setindex!, and size")
debug && println("getindex, setindex!, size, and similar")
BD = Bidiagonal(dv, ev, true)
@test_throws BoundsError BD[n+1,1]
@test BD[2,2] == dv[2]
Expand All @@ -44,6 +44,9 @@ for relty in (Int, Float32, Float64, BigFloat), elty in (relty, Complex{relty})
@test BD == cBD
@test_throws ArgumentError size(BD,0)
@test size(BD,3) == 1
@test isa(similar(BD), Bidiagonal{elty})
@test isa(similar(BD, Int), Bidiagonal{Int})
@test isa(similar(BD, Int, (3,2)), Matrix{Int})

debug && println("show")
dstring = sprint(Base.print_matrix,BD.dv')
Expand Down
6 changes: 4 additions & 2 deletions test/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,10 @@ for relty in (Float32, Float64, BigFloat), elty in (relty, Complex{relty})
end

#similar
@test_throws ArgumentError similar(D, eltype(D), (n,n+1))
@test length(diag(similar(D, eltype(D), (n,n)))) == n
@test isa(similar(D), Diagonal{elty})
@test isa(similar(D, Int), Diagonal{Int})
@test isa(similar(D, (3,2)), Matrix{elty})
@test isa(similar(D, Int, (3,2)), Matrix{Int})

#10036
@test issym(D2)
Expand Down
10 changes: 10 additions & 0 deletions test/linalg/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ let n=10

debug && println("\ntype of a: ", eltya, "\n")

# similar
@test isa(similar(Symmetric(asym)), Symmetric{eltya})
@test isa(similar(Hermitian(asym)), Hermitian{eltya})
@test isa(similar(Symmetric(asym), Int), Symmetric{Int})
@test isa(similar(Hermitian(asym), Int), Hermitian{Int})
@test isa(similar(Symmetric(asym), (3,2)), Matrix{eltya})
@test isa(similar(Hermitian(asym), (3,2)), Matrix{eltya})
@test isa(similar(Symmetric(asym), Int, (3,2)), Matrix{Int})
@test isa(similar(Hermitian(asym), Int, (3,2)), Matrix{Int})

# full
@test asym == full(Hermitian(asym))

Expand Down
8 changes: 6 additions & 2 deletions test/linalg/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@ for elty1 in (Float32, Float64, BigFloat, Complex64, Complex128, Complex{BigFloa

# similar
@test isa(similar(A1), t1)
@test_throws ArgumentError similar(A1,typeof(A1),(n,n+1))
@test_throws ArgumentError similar(A1,typeof(A1),(n,n,n))
@test eltype(similar(A1)) == elty1
@test isa(similar(A1, Int), t1)
@test eltype(similar(A1, Int)) == Int
@test isa(similar(A1, (3,2)), Matrix{elty1})
@test isa(similar(A1, Int, (3,2)), Matrix{Int})

# getindex
## Linear indexing
for i = 1:length(A1)
@test A1[i] == full(A1)[i]
end
@test isa(A1[2:4,1], Vector)

## Cartesian indexing
for i = 1:size(A1, 1)
Expand Down
11 changes: 8 additions & 3 deletions test/linalg/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ for elty in (Float32, Float64, Complex64, Complex128, Int)
@test_approx_eq x invFsv
@test_approx_eq full(full(Tldlt)) Fs
end

# similar
@test isa(similar(Ts), SymTridiagonal{elty})
@test isa(similar(Ts, Int), SymTridiagonal{Int})
@test isa(similar(Ts, Int, (3,2)), Matrix{Int})
end

# eigenvalues/eigenvectors of symmetric tridiagonal
Expand Down Expand Up @@ -365,9 +370,9 @@ let n = 12 #Size of matrix problem to test
@test size(B) == size(A)
copy!(B,A)
@test B == A
@test_throws DimensionMismatch similar(A,(n,n,2))
@test_throws DimensionMismatch similar(A,(n+1,n))
@test_throws DimensionMismatch similar(A,(n,n+1))
@test isa(similar(A), Tridiagonal{elty})
@test isa(similar(A, Int), Tridiagonal{Int})
@test isa(similar(A, Int, (3,2)), Matrix{Int})
@test size(A,3) == 1
@test_throws ArgumentError size(A,0)

Expand Down

0 comments on commit 4d8f5bf

Please sign in to comment.