Skip to content

Commit

Permalink
parametrize Bidiagonal on wrapped vector type
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre committed Jul 28, 2017
1 parent fc10c8b commit 6177b3b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 42 deletions.
10 changes: 6 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ 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` type definition has changed from `Diagonal{T}` to
`Diagonal{T,V<:AbstractVector{T}}` ([#22718]).
* The `Diagonal` and `Bidiagonal` type definitions have changed from `Diagonal{T}` and
`Bidiagonal{T}` to `Diagonal{T,V<:AbstractVector{T}}` and
`Bidiagonal{T,V<:AbstractVector{T}}` respectively ([#22718], [#22925]).

* Spaces are no longer allowed between `@` and the name of a macro in a macro call ([#22868]).

Expand Down Expand Up @@ -142,8 +143,9 @@ Library improvements

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

* `Diagonal` is now parameterized on the type of the wrapped vector. This allows
for `Diagonal` matrices with arbitrary `AbstractVector`s ([#22718]).
* `Diagonal` and `Bidiagonal` are now parameterized on the type of the wrapped vectors,
allowing `Diagonal` and `Bidiagonal` matrices with arbitrary
`AbstractVector`s ([#22718], [#22925]).

* Mutating versions of `randperm` and `randcycle` have been added:
`randperm!` and `randcycle!` ([#22723]).
Expand Down
38 changes: 21 additions & 17 deletions base/linalg/bidiag.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Bidiagonal matrices
struct Bidiagonal{T} <: AbstractMatrix{T}
dv::Vector{T} # diagonal
ev::Vector{T} # sub/super diagonal
uplo::Char # upper bidiagonal ('U') or lower ('L')
function Bidiagonal{T}(dv::Vector{T}, ev::Vector{T}, uplo::Char) where T
struct Bidiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T}
dv::V # diagonal
ev::V # sub/super diagonal
uplo::Char # upper bidiagonal ('U') or lower ('L')
function Bidiagonal{T}(dv::V, ev::V, uplo::Char) where {T,V<:AbstractVector{T}}
if length(ev) != length(dv)-1
throw(DimensionMismatch("length of diagonal vector is $(length(dv)), length of off-diagonal vector is $(length(ev))"))
end
new(dv, ev, uplo)
new{T,V}(dv, ev, uplo)
end
function Bidiagonal(dv::Vector{T}, ev::Vector{T}, uplo::Char) where T
function Bidiagonal(dv::V, ev::V, uplo::Char) where {T,V<:AbstractVector{T}}
Bidiagonal{T}(dv, ev, uplo)
end
end
Expand Down Expand Up @@ -41,26 +41,30 @@ julia> ev = [7, 8, 9]
9
julia> Bu = Bidiagonal(dv, ev, :U) # ev is on the first superdiagonal
4×4 Bidiagonal{Int64}:
4×4 Bidiagonal{Int64,Array{Int64,1}}:
1 7 ⋅ ⋅
⋅ 2 8 ⋅
⋅ ⋅ 3 9
⋅ ⋅ ⋅ 4
julia> Bl = Bidiagonal(dv, ev, :L) # ev is on the first subdiagonal
4×4 Bidiagonal{Int64}:
4×4 Bidiagonal{Int64,Array{Int64,1}}:
1 ⋅ ⋅ ⋅
7 2 ⋅ ⋅
⋅ 8 3 ⋅
⋅ ⋅ 9 4
```
"""
function Bidiagonal(dv::AbstractVector{T}, ev::AbstractVector{T}, uplo::Symbol) where T
Bidiagonal{T}(collect(dv), collect(ev), char_uplo(uplo))
function Bidiagonal(dv::V, ev::V, uplo::Symbol) where {T,V<:AbstractVector{T}}
Bidiagonal{T}(dv, ev, char_uplo(uplo))
end

function Bidiagonal(dv::AbstractVector{T}, ev::AbstractVector{S}, uplo::Symbol) where {T,S}
R = promote_type(T,S)
Bidiagonal(convert(AbstractVector{R}, dv), convert(AbstractVector{R}, ev), uplo)
end

function Bidiagonal(dv::AbstractVector{Td}, ev::AbstractVector{Te}, uplo::Symbol) where {Td,Te}
T = promote_type(Td,Te)
function Bidiagonal(dv::AbstractVector{T}, ev::AbstractVector{T}, uplo::Symbol) where T
Bidiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev), uplo)
end

Expand All @@ -79,15 +83,15 @@ julia> A = [1 1 1 1; 2 2 2 2; 3 3 3 3; 4 4 4 4]
3 3 3 3
4 4 4 4
julia> Bidiagonal(A, :U) #contains the main diagonal and first superdiagonal of A
4×4 Bidiagonal{Int64}:
julia> Bidiagonal(A, :U) # contains the main diagonal and first superdiagonal of A
4×4 Bidiagonal{Int64,Array{Int64,1}}:
1 1 ⋅ ⋅
⋅ 2 2 ⋅
⋅ ⋅ 3 3
⋅ ⋅ ⋅ 4
julia> Bidiagonal(A, :L) #contains the main diagonal and first subdiagonal of A
4×4 Bidiagonal{Int64}:
julia> Bidiagonal(A, :L) # contains the main diagonal and first subdiagonal of A
4×4 Bidiagonal{Int64,Array{Int64,1}}:
1 ⋅ ⋅ ⋅
2 2 ⋅ ⋅
⋅ 3 3 ⋅
Expand Down
4 changes: 4 additions & 0 deletions base/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,10 @@ end
GenericArray{T}(args...) where {T} = GenericArray(Array{T}(args...))
GenericArray{T,N}(args...) where {T,N} = GenericArray(Array{T,N}(args...))

function Base.convert(::Type{AbstractArray{T,N}}, a::GenericArray) where {T,N}
GenericArray{T,N}(convert(Array{T,N}, a.a))
end

Base.eachindex(a::GenericArray) = eachindex(a.a)
Base.indices(a::GenericArray) = indices(a.a)
Base.length(a::GenericArray) = length(a.a)
Expand Down
71 changes: 52 additions & 19 deletions test/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ srand(1)
end

@testset "Constructors" begin
@test Bidiagonal(dv,ev,:U) != Bidiagonal(dv,ev,:L)
ubd = Bidiagonal(dv, ev, :U)
lbd = Bidiagonal(dv, ev, :L)
@test ubd != lbd
@test ubd.dv === dv
@test lbd.ev === ev
ubd = Bidiagonal{elty}(dv, ev, :U)
lbd = Bidiagonal{elty}(dv, ev, :L)
@test ubd.dv === dv
@test lbd.ev === ev
@test_throws ArgumentError Bidiagonal(dv,ev,:R)
@test_throws DimensionMismatch Bidiagonal(dv,ones(elty,n),:U)
@test_throws MethodError Bidiagonal(dv,ev)
Expand Down Expand Up @@ -97,29 +105,30 @@ srand(1)
end

@testset "triu and tril" begin
bidiagcopy(dv, ev, uplo) = Bidiagonal(copy(dv), copy(ev), uplo)
@test istril(Bidiagonal(dv,ev,:L))
@test !istril(Bidiagonal(dv,ev,:U))
@test tril!(Bidiagonal(dv,ev,:U),-1) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test tril!(Bidiagonal(dv,ev,:L),-1) == Bidiagonal(zeros(dv),ev,:L)
@test tril!(Bidiagonal(dv,ev,:U),-2) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test tril!(Bidiagonal(dv,ev,:L),-2) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test tril!(Bidiagonal(dv,ev,:U),1) == Bidiagonal(dv,ev,:U)
@test tril!(Bidiagonal(dv,ev,:L),1) == Bidiagonal(dv,ev,:L)
@test tril!(Bidiagonal(dv,ev,:U)) == Bidiagonal(dv,zeros(ev),:U)
@test tril!(Bidiagonal(dv,ev,:L)) == Bidiagonal(dv,ev,:L)
@test_throws ArgumentError tril!(Bidiagonal(dv,ev,:U),n+1)
@test tril!(bidiagcopy(dv,ev,:U),-1) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test tril!(bidiagcopy(dv,ev,:L),-1) == Bidiagonal(zeros(dv),ev,:L)
@test tril!(bidiagcopy(dv,ev,:U),-2) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test tril!(bidiagcopy(dv,ev,:L),-2) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test tril!(bidiagcopy(dv,ev,:U),1) == Bidiagonal(dv,ev,:U)
@test tril!(bidiagcopy(dv,ev,:L),1) == Bidiagonal(dv,ev,:L)
@test tril!(bidiagcopy(dv,ev,:U)) == Bidiagonal(dv,zeros(ev),:U)
@test tril!(bidiagcopy(dv,ev,:L)) == Bidiagonal(dv,ev,:L)
@test_throws ArgumentError tril!(bidiagcopy(dv,ev,:U),n+1)

@test istriu(Bidiagonal(dv,ev,:U))
@test !istriu(Bidiagonal(dv,ev,:L))
@test triu!(Bidiagonal(dv,ev,:L),1) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test triu!(Bidiagonal(dv,ev,:U),1) == Bidiagonal(zeros(dv),ev,:U)
@test triu!(Bidiagonal(dv,ev,:U),2) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test triu!(Bidiagonal(dv,ev,:L),2) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test triu!(Bidiagonal(dv,ev,:U),-1) == Bidiagonal(dv,ev,:U)
@test triu!(Bidiagonal(dv,ev,:L),-1) == Bidiagonal(dv,ev,:L)
@test triu!(Bidiagonal(dv,ev,:L)) == Bidiagonal(dv,zeros(ev),:L)
@test triu!(Bidiagonal(dv,ev,:U)) == Bidiagonal(dv,ev,:U)
@test_throws ArgumentError triu!(Bidiagonal(dv,ev,:U),n+1)
@test triu!(bidiagcopy(dv,ev,:L),1) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test triu!(bidiagcopy(dv,ev,:U),1) == Bidiagonal(zeros(dv),ev,:U)
@test triu!(bidiagcopy(dv,ev,:U),2) == Bidiagonal(zeros(dv),zeros(ev),:U)
@test triu!(bidiagcopy(dv,ev,:L),2) == Bidiagonal(zeros(dv),zeros(ev),:L)
@test triu!(bidiagcopy(dv,ev,:U),-1) == Bidiagonal(dv,ev,:U)
@test triu!(bidiagcopy(dv,ev,:L),-1) == Bidiagonal(dv,ev,:L)
@test triu!(bidiagcopy(dv,ev,:L)) == Bidiagonal(dv,zeros(ev),:L)
@test triu!(bidiagcopy(dv,ev,:U)) == Bidiagonal(dv,ev,:U)
@test_throws ArgumentError triu!(bidiagcopy(dv,ev,:U),n+1)
end

Tfull = Array(T)
Expand Down Expand Up @@ -255,7 +264,31 @@ srand(1)
end
BD = Bidiagonal(dv, ev, :U)
@test Matrix{Complex{Float64}}(BD) == BD
end

@testset "arbitrary AbstractVector in Bidiagonal" begin
S, T = Float32, Float64
R = promote_type(T, S)
dvT = rand(T, n); dvS = rand(S, n)
evT = rand(T, n-1); evS = rand(S, n-1)
GdvT = GenericArray(dvT); GdvS = GenericArray(dvS)
GevT = GenericArray(evT); GevS = GenericArray(evS)
for uplo in (:U, :L)
@test isa(Bidiagonal(dvT, evT, uplo), Bidiagonal{T,Vector{T}})
@test isa(Bidiagonal(dvT, evS, uplo), Bidiagonal{R,Vector{R}})
@test isa(Bidiagonal(dvS, evT, uplo), Bidiagonal{R,Vector{R}})
@test isa(Bidiagonal(dvS, evS, uplo), Bidiagonal{S,Vector{S}})

@test isa(Bidiagonal(GdvT, GevT, uplo), Bidiagonal{T,GenericArray{T,1}})
@test isa(Bidiagonal(GdvT, GevS, uplo), Bidiagonal{R,GenericArray{R,1}})
@test isa(Bidiagonal(GdvS, GevT, uplo), Bidiagonal{R,GenericArray{R,1}})
@test isa(Bidiagonal(GdvS, GevS, uplo), Bidiagonal{S,GenericArray{S,1}})

@test isa(Bidiagonal(GdvT, evT, uplo), Bidiagonal{T,Vector{T}})
@test isa(Bidiagonal(GdvT, evS, uplo), Bidiagonal{R,Vector{R}})
@test isa(Bidiagonal(GdvS, evT, uplo), Bidiagonal{R,Vector{R}})
@test isa(Bidiagonal(GdvS, evS, uplo), Bidiagonal{S,Vector{S}})
end
end

# Issue 10742 and similar
Expand Down
4 changes: 2 additions & 2 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,8 @@ end
# test structured zero matrix printing for select structured types
A = reshape(1:16,4,4)
@test replstr(Diagonal(A)) == "4×4 Diagonal{$(Int),Array{$(Int),1}}:\n 1 ⋅ ⋅ ⋅\n ⋅ 6 ⋅ ⋅\n ⋅ ⋅ 11 ⋅\n ⋅ ⋅ ⋅ 16"
@test replstr(Bidiagonal(A,:U)) == "4×4 Bidiagonal{$Int}:\n 1 5 ⋅ ⋅\n ⋅ 6 10 ⋅\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
@test replstr(Bidiagonal(A,:L)) == "4×4 Bidiagonal{$Int}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n ⋅ 7 11 ⋅\n ⋅ ⋅ 12 16"
@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}:\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(UpperTriangular(copy(A))) == "4×4 UpperTriangular{$Int,Array{$Int,2}}:\n 1 5 9 13\n ⋅ 6 10 14\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
Expand Down

0 comments on commit 6177b3b

Please sign in to comment.