Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parametrize Tridiagonal on the wrapped vector type #23154

Merged
merged 1 commit into from
Aug 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ This section lists changes that do not have deprecation warnings.
longer present. Use `first(R)` and `last(R)` to obtain
start/stop. ([#20974])

* The `Diagonal`, `Bidiagonal` and `SymTridiagonal` type definitions have changed from
`Diagonal{T}`, `Bidiagonal{T}` and `SymTridiagonal{T}` to `Diagonal{T,V<:AbstractVector{T}}`,
`Bidiagonal{T,V<:AbstractVector{T}}` and `SymTridiagonal{T,V<:AbstractVector{T}}`
respectively ([#22718], [#22925], [#23035]).
* The `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` type definitions have
changed from `Diagonal{T}`, `Bidiagonal{T}`, `Tridiagonal{T}` and `SymTridiagonal{T}`
to `Diagonal{T,V<:AbstractVector{T}}`, `Bidiagonal{T,V<:AbstractVector{T}}`,
`Tridiagonal{T,V<:AbstractVector{T}}` and `SymTridiagonal{T,V<:AbstractVector{T}}`
respectively ([#22718], [#22925], [#23035], [#23154]).

* `isapprox(x,y)` now tests `norm(x-y) <= max(atol, rtol*max(norm(x), norm(y)))`
rather than `norm(x-y) <= atol + ...`, and `rtol` defaults to zero
Expand Down Expand Up @@ -196,9 +197,10 @@ Library improvements

* `Char`s can now be concatenated with `String`s and/or other `Char`s using `*` ([#22532]).

* `Diagonal`, `Bidiagonal` and `SymTridiagonal` are now parameterized on the type of the
wrapped vectors, allowing `Diagonal`, `Bidiagonal` and `SymTridiagonal` matrices with
arbitrary `AbstractVector`s ([#22718], [#22925], [#23035]).
* `Diagonal`, `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` are now parameterized on
the type of the wrapped vectors, allowing `Diagonal`, `Bidiagonal`, `Tridiagonal` and
`SymTridiagonal` matrices with arbitrary `AbstractVector`s
([#22718], [#22925], [#23035], [#23154]).

* Mutating versions of `randperm` and `randcycle` have been added:
`randperm!` and `randcycle!` ([#22723]).
Expand Down Expand Up @@ -261,8 +263,9 @@ Deprecated or removed
* `Bidiagonal` constructors now use a `Symbol` (`:U` or `:L`) for the upper/lower
argument, instead of a `Bool` or a `Char` ([#22703]).

* `Bidiagonal` and `SymTridiagonal` constructors that automatically converted the input
vectors to the same type are deprecated in favor of explicit conversion ([#22925], [#23035]).
* `Bidiagonal`, `Tridiagonal` and `SymTridiagonal` constructors that automatically
converted the input vectors to the same type are deprecated in favor of explicit
conversion ([#22925], [#23035], [#23154].

* Calling `nfields` on a type to find out how many fields its instances have is deprecated.
Use `fieldcount` instead. Use `nfields` only to get the number of fields in a specific object ([#22350]).
Expand Down
8 changes: 8 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,14 @@ function SymTridiagonal(dv::AbstractVector{T}, ev::AbstractVector{S}) where {T,S
SymTridiagonal(convert(Vector{R}, dv), convert(Vector{R}, ev))
end

# PR #23154
# also uncomment constructor tests in test/linalg/tridiag.jl
function Tridiagonal(dl::AbstractVector{Tl}, d::AbstractVector{Td}, du::AbstractVector{Tu}) where {Tl,Td,Tu}
depwarn(string("Tridiagonal(dl::AbstractVector{Tl}, d::AbstractVector{Td}, du::AbstractVector{Tu}) ",
"where {Tl, Td, Tu} is deprecated; convert all vectors to the same type instead."), :Tridiagonal)
Tridiagonal(map(v->convert(Vector{promote_type(Tl,Td,Tu)}, v), (dl, d, du))...)
end

# PR #23092
@eval LibGit2 begin
function prompt(msg::AbstractString; default::AbstractString="", password::Bool=false)
Expand Down
6 changes: 4 additions & 2 deletions base/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ promote_rule(::Type{Matrix{T}}, ::Type{Bidiagonal{S}}) where {T,S} = Matrix{prom
#Converting from Bidiagonal to Tridiagonal
Tridiagonal(M::Bidiagonal{T}) where {T} = convert(Tridiagonal{T}, M)
function convert(::Type{Tridiagonal{T}}, A::Bidiagonal) where T
z = zeros(T, size(A)[1]-1)
A.uplo == 'U' ? Tridiagonal(z, convert(Vector{T},A.dv), convert(Vector{T},A.ev)) : Tridiagonal(convert(Vector{T},A.ev), convert(Vector{T},A.dv), z)
dv = convert(AbstractVector{T}, A.dv)
ev = convert(AbstractVector{T}, A.ev)
z = fill!(similar(ev), zero(T))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To check my understanding, converting a Bidiagonal over Ranges to a Tridiagonal should fail?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right..., Yea I guess that’s a consequence of this series of PR's? 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're converting from Diagonal or Bidiagonal or SymTridiagonal that have fewer diagonal vectors and they already have to be a consistent type within those structs, can't we use that same parameter to know which new diagonal vector type to fill in when converting to Tridiagonal?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of a Range: You can not create a Range of a given length with only zeros, right? That is the only failure case here I think...
Using Ranges results in other problems as well, so I guess you will just have to convert to a vector format that supports a larger set of functions.

A.uplo == 'U' ? Tridiagonal(z, dv, ev) : Tridiagonal(ev, dv, z)
end
promote_rule(::Type{Tridiagonal{T}}, ::Type{Bidiagonal{S}}) where {T,S} = Tridiagonal{promote_type(T,S)}

Expand Down
2 changes: 1 addition & 1 deletion base/linalg/bunchkaufman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ julia> A = [1 2 3; 2 1 2; 3 2 1]
julia> F = bkfact(Symmetric(A, :L))
Base.LinAlg.BunchKaufman{Float64,Array{Float64,2}}
D factor:
3×3 Tridiagonal{Float64}:
3×3 Tridiagonal{Float64,Array{Float64,1}}:
1.0 3.0 ⋅
3.0 1.0 0.0
⋅ 0.0 -1.0
Expand Down
27 changes: 14 additions & 13 deletions base/linalg/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,14 @@ end
# Tridiagonal

# See dgttrf.f
function lufact!(A::Tridiagonal{T}, pivot::Union{Val{false}, Val{true}} = Val(true)) where T
function lufact!(A::Tridiagonal{T,V}, pivot::Union{Val{false}, Val{true}} = Val(true)) where {T,V}
n = size(A, 1)
info = 0
ipiv = Vector{BlasInt}(n)
dl = A.dl
d = A.d
du = A.du
du2 = A.du2
du2 = fill!(similar(d, n-2), 0)::V

@inbounds begin
for i = 1:n
Expand Down Expand Up @@ -389,12 +389,13 @@ function lufact!(A::Tridiagonal{T}, pivot::Union{Val{false}, Val{true}} = Val(tr
end
end
end
LU{T,Tridiagonal{T}}(A, ipiv, convert(BlasInt, info))
B = Tridiagonal{T,V}(dl, d, du, du2)
LU{T,Tridiagonal{T,V}}(B, ipiv, convert(BlasInt, info))
end

factorize(A::Tridiagonal) = lufact(A)

function getindex(F::Base.LinAlg.LU{T,Tridiagonal{T}}, d::Symbol) where T
function getindex(F::LU{T,Tridiagonal{T,V}}, d::Symbol) where {T,V}
m, n = size(F)
if d == :L
L = Array(Bidiagonal(ones(T, n), F.factors.dl, d))
Expand All @@ -419,7 +420,7 @@ function getindex(F::Base.LinAlg.LU{T,Tridiagonal{T}}, d::Symbol) where T
end

# See dgtts2.f
function A_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T
function A_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V}
n = size(A,1)
if n != size(B,1)
throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows"))
Expand Down Expand Up @@ -450,7 +451,7 @@ function A_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T
return B
end

function At_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T
function At_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V}
n = size(A,1)
if n != size(B,1)
throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows"))
Expand Down Expand Up @@ -485,7 +486,7 @@ function At_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T
end

# Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where {T<:Real} = At_ldiv_B!(A,B)
function Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T
function Ac_ldiv_B!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V}
n = size(A,1)
if n != size(B,1)
throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows"))
Expand Down Expand Up @@ -528,7 +529,7 @@ convert(::Type{Matrix}, F::LU) = convert(Array, convert(AbstractArray, F))
convert(::Type{Array}, F::LU) = convert(Matrix, F)
full(F::LU) = convert(AbstractArray, F)

function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where T
function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T,V}}) where {T,V}
n = size(F, 1)

dl = copy(F.factors.dl)
Expand Down Expand Up @@ -562,12 +563,12 @@ function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where
end
return Tridiagonal(dl, d, du)
end
convert(::Type{AbstractMatrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} =
convert(::Type{AbstractMatrix}, F::LU{T,Tridiagonal{T,V}}) where {T,V} =
convert(Tridiagonal, F)
convert(::Type{AbstractArray}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} =
convert(::Type{AbstractArray}, F::LU{T,Tridiagonal{T,V}}) where {T,V} =
convert(AbstractMatrix, F)
convert(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} =
convert(::Type{Matrix}, F::LU{T,Tridiagonal{T,V}}) where {T,V} =
convert(Array, convert(AbstractArray, F))
convert(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} =
convert(::Type{Array}, F::LU{T,Tridiagonal{T,V}}) where {T,V} =
convert(Matrix, F)
full(F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(AbstractArray, F)
full(F::LU{T,Tridiagonal{T,V}}) where {T,V} = convert(AbstractArray, F)
100 changes: 43 additions & 57 deletions base/linalg/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -399,71 +399,58 @@ function setindex!(A::SymTridiagonal, x, i::Integer, j::Integer)
end

## Tridiagonal matrices ##
struct Tridiagonal{T} <: AbstractMatrix{T}
dl::Vector{T} # sub-diagonal
d::Vector{T} # diagonal
du::Vector{T} # sup-diagonal
du2::Vector{T} # supsup-diagonal for pivoting
struct Tridiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T}
dl::V # sub-diagonal
d::V # diagonal
du::V # sup-diagonal
du2::V # supsup-diagonal for pivoting in LU
function Tridiagonal{T}(dl::V, d::V, du::V) where {T,V<:AbstractVector{T}}
n = length(d)
if (length(dl) != n-1 || length(du) != n-1)
throw(ArgumentError(string("cannot construct Tridiagonal from incompatible ",
"lengths of subdiagonal, diagonal and superdiagonal: ",
"($(length(dl)), $(length(d)), $(length(du)))")))
end
new{T,V}(dl, d, du)
end
# constructor used in lufact!
function Tridiagonal{T,V}(dl::V, d::V, du::V, du2::V) where {T,V<:AbstractVector{T}}
new{T,V}(dl, d, du, du2)
end
end

"""
Tridiagonal(dl, d, du)
Tridiagonal(dl::V, d::V, du::V) where V <: AbstractVector
Construct a tridiagonal matrix from the first subdiagonal, diagonal, and first superdiagonal,
respectively. The result is of type `Tridiagonal` and provides efficient specialized linear
respectively. The result is of type `Tridiagonal` and provides efficient specialized linear
solvers, but may be converted into a regular matrix with
[`convert(Array, _)`](@ref) (or `Array(_)` for short).
The lengths of `dl` and `du` must be one less than the length of `d`.
# Examples
```jldoctest
julia> dl = [1; 2; 3]
3-element Array{Int64,1}:
1
2
3
julia> dl = [1, 2, 3];
julia> du = [4; 5; 6]
3-element Array{Int64,1}:
4
5
6
julia> du = [4, 5, 6];
julia> d = [7; 8; 9; 0]
4-element Array{Int64,1}:
7
8
9
0
julia> d = [7, 8, 9, 0];
julia> Tridiagonal(dl, d, du)
4×4 Tridiagonal{Int64}:
4×4 Tridiagonal{Int64,Array{Int64,1}}:
7 4 ⋅ ⋅
1 8 5 ⋅
⋅ 2 9 6
⋅ ⋅ 3 0
```
"""
# Basic constructor takes in three dense vectors of same type
function Tridiagonal(dl::Vector{T}, d::Vector{T}, du::Vector{T}) where T
n = length(d)
if (length(dl) != n-1 || length(du) != n-1)
throw(ArgumentError("cannot make Tridiagonal from incompatible lengths of subdiagonal, diagonal and superdiagonal: ($(length(dl)), $(length(d)), $(length(du))"))
end
Tridiagonal(dl, d, du, zeros(T,n-2))
end

# Construct from diagonals of any abstract vector, any eltype
function Tridiagonal(dl::AbstractVector{Tl}, d::AbstractVector{Td}, du::AbstractVector{Tu}) where {Tl,Td,Tu}
Tridiagonal(map(v->convert(Vector{promote_type(Tl,Td,Tu)}, v), (dl, d, du))...)
end
Tridiagonal(dl::V, d::V, du::V) where {T,V<:AbstractVector{T}} = Tridiagonal{T}(dl, d, du)

# Provide a constructor Tridiagonal(A) similar to the triangulars, diagonal, symmetric
"""
Tridiagonal(A)
returns a `Tridiagonal` array based on (abstract) matrix `A`, using its first lower diagonal,
main diagonal, and first upper diagonal.
Construct a tridiagonal matrix from the first sub-diagonal,
diagonal and first super-diagonal of the matrix `A`.
# Examples
```jldoctest
Expand All @@ -475,16 +462,14 @@ julia> A = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4]
1 2 3 4
julia> Tridiagonal(A)
4×4 Tridiagonal{Int64}:
4×4 Tridiagonal{Int64,Array{Int64,1}}:
1 2 ⋅ ⋅
1 2 3 ⋅
⋅ 2 3 4
⋅ ⋅ 3 4
```
"""
function Tridiagonal(A::AbstractMatrix)
return Tridiagonal(diag(A,-1), diag(A), diag(A,+1))
end
Tridiagonal(A::AbstractMatrix) = Tridiagonal(diag(A,-1), diag(A,0), diag(A,1))

size(M::Tridiagonal) = (length(M.d), length(M.d))
function size(M::Tridiagonal, d::Integer)
Expand Down Expand Up @@ -512,31 +497,31 @@ convert(::Type{Matrix}, M::Tridiagonal{T}) where {T} = convert(Matrix{T}, M)
convert(::Type{Array}, M::Tridiagonal) = convert(Matrix, M)
full(M::Tridiagonal) = convert(Array, M)
function similar(M::Tridiagonal, ::Type{T}) where T
Tridiagonal{T}(similar(M.dl, T), similar(M.d, T), similar(M.du, T), similar(M.du2, T))
Tridiagonal{T}(similar(M.dl, T), similar(M.d, T), similar(M.du, T))
end

# Operations on Tridiagonal matrices
copy!(dest::Tridiagonal, src::Tridiagonal) = Tridiagonal(copy!(dest.dl, src.dl), copy!(dest.d, src.d), copy!(dest.du, src.du), copy!(dest.du2, src.du2))
copy!(dest::Tridiagonal, src::Tridiagonal) = (copy!(dest.dl, src.dl); copy!(dest.d, src.d); copy!(dest.du, src.du); dest)

#Elementary operations
broadcast(::typeof(abs), M::Tridiagonal) = Tridiagonal(abs.(M.dl), abs.(M.d), abs.(M.du), abs.(M.du2))
broadcast(::typeof(round), M::Tridiagonal) = Tridiagonal(round.(M.dl), round.(M.d), round.(M.du), round.(M.du2))
broadcast(::typeof(trunc), M::Tridiagonal) = Tridiagonal(trunc.(M.dl), trunc.(M.d), trunc.(M.du), trunc.(M.du2))
broadcast(::typeof(floor), M::Tridiagonal) = Tridiagonal(floor.(M.dl), floor.(M.d), floor.(M.du), floor.(M.du2))
broadcast(::typeof(ceil), M::Tridiagonal) = Tridiagonal(ceil.(M.dl), ceil.(M.d), ceil.(M.du), ceil.(M.du2))
broadcast(::typeof(abs), M::Tridiagonal) = Tridiagonal(abs.(M.dl), abs.(M.d), abs.(M.du))
broadcast(::typeof(round), M::Tridiagonal) = Tridiagonal(round.(M.dl), round.(M.d), round.(M.du))
broadcast(::typeof(trunc), M::Tridiagonal) = Tridiagonal(trunc.(M.dl), trunc.(M.d), trunc.(M.du))
broadcast(::typeof(floor), M::Tridiagonal) = Tridiagonal(floor.(M.dl), floor.(M.d), floor.(M.du))
broadcast(::typeof(ceil), M::Tridiagonal) = Tridiagonal(ceil.(M.dl), ceil.(M.d), ceil.(M.du))
for func in (:conj, :copy, :real, :imag)
@eval function ($func)(M::Tridiagonal)
Tridiagonal(($func)(M.dl), ($func)(M.d), ($func)(M.du), ($func)(M.du2))
Tridiagonal(($func)(M.dl), ($func)(M.d), ($func)(M.du))
end
end
broadcast(::typeof(round), ::Type{T}, M::Tridiagonal) where {T<:Integer} =
Tridiagonal(round.(T, M.dl), round.(T, M.d), round.(T, M.du), round.(T, M.du2))
Tridiagonal(round.(T, M.dl), round.(T, M.d), round.(T, M.du))
broadcast(::typeof(trunc), ::Type{T}, M::Tridiagonal) where {T<:Integer} =
Tridiagonal(trunc.(T, M.dl), trunc.(T, M.d), trunc.(T, M.du), trunc.(T, M.du2))
Tridiagonal(trunc.(T, M.dl), trunc.(T, M.d), trunc.(T, M.du))
broadcast(::typeof(floor), ::Type{T}, M::Tridiagonal) where {T<:Integer} =
Tridiagonal(floor.(T, M.dl), floor.(T, M.d), floor.(T, M.du), floor.(T, M.du2))
Tridiagonal(floor.(T, M.dl), floor.(T, M.d), floor.(T, M.du))
broadcast(::typeof(ceil), ::Type{T}, M::Tridiagonal) where {T<:Integer} =
Tridiagonal(ceil.(T, M.dl), ceil.(T, M.d), ceil.(T, M.du), ceil.(T, M.du2))
Tridiagonal(ceil.(T, M.dl), ceil.(T, M.d), ceil.(T, M.du))

transpose(M::Tridiagonal) = Tridiagonal(M.du, M.d, M.dl)
ctranspose(M::Tridiagonal) = conj(transpose(M))
Expand Down Expand Up @@ -646,7 +631,8 @@ end
inv(A::Tridiagonal) = inv_usmani(A.dl, A.d, A.du)
det(A::Tridiagonal) = det_usmani(A.dl, A.d, A.du)

convert(::Type{Tridiagonal{T}},M::Tridiagonal) where {T} = Tridiagonal(convert(Vector{T}, M.dl), convert(Vector{T}, M.d), convert(Vector{T}, M.du), convert(Vector{T}, M.du2))
convert(::Type{Tridiagonal{T}},M::Tridiagonal) where {T} =
Tridiagonal(convert(AbstractVector{T}, M.dl), convert(AbstractVector{T}, M.d), convert(AbstractVector{T}, M.du))
convert(::Type{AbstractMatrix{T}},M::Tridiagonal) where {T} = convert(Tridiagonal{T}, M)
convert(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) where {T} = Tridiagonal(M)
function convert(::Type{SymTridiagonal{T}}, M::Tridiagonal) where T
Expand Down
7 changes: 7 additions & 0 deletions test/linalg/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,17 @@ B = randn(n,2)
@test ST == Matrix(ST)
@test ST.dv === x
@test ST.ev === y
TT = (Tridiagonal(y, x, y))::Tridiagonal{elty, typeof(x)}
@test TT == Matrix(TT)
@test TT.dl === y
@test TT.d === x
@test TT.du === y
end
# enable when deprecations for 0.7 are dropped
# @test_throws MethodError SymTridiagonal(dv, GenericArray(ev))
# @test_throws MethodError SymTridiagonal(GenericArray(dv), ev)
# @test_throws MethodError Tridiagonal(GenericArray(ev), dv, GenericArray(ev))
# @test_throws MethodError Tridiagonal(ev, GenericArray(dv), ev)
end

@testset "size and Array" begin
Expand Down
2 changes: 1 addition & 1 deletion test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ A = reshape(1:16,4,4)
@test replstr(Bidiagonal(A,:U)) == "4×4 Bidiagonal{$(Int),Array{$(Int),1}}:\n 1 5 ⋅ ⋅\n ⋅ 6 10 ⋅\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
@test replstr(Bidiagonal(A,:L)) == "4×4 Bidiagonal{$(Int),Array{$(Int),1}}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n ⋅ 7 11 ⋅\n ⋅ ⋅ 12 16"
@test replstr(SymTridiagonal(A+A')) == "4×4 SymTridiagonal{$(Int),Array{$(Int),1}}:\n 2 7 ⋅ ⋅\n 7 12 17 ⋅\n ⋅ 17 22 27\n ⋅ ⋅ 27 32"
@test replstr(Tridiagonal(diag(A,-1),diag(A),diag(A,+1))) == "4×4 Tridiagonal{$Int}:\n 1 5 ⋅ ⋅\n 2 6 10 ⋅\n ⋅ 7 11 15\n ⋅ ⋅ 12 16"
@test replstr(Tridiagonal(diag(A,-1),diag(A),diag(A,+1))) == "4×4 Tridiagonal{$(Int),Array{$(Int),1}}:\n 1 5 ⋅ ⋅\n 2 6 10 ⋅\n ⋅ 7 11 15\n ⋅ ⋅ 12 16"
@test replstr(UpperTriangular(copy(A))) == "4×4 UpperTriangular{$Int,Array{$Int,2}}:\n 1 5 9 13\n ⋅ 6 10 14\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
@test replstr(LowerTriangular(copy(A))) == "4×4 LowerTriangular{$Int,Array{$Int,2}}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n 3 7 11 ⋅\n 4 8 12 16"

Expand Down