|
1 | 1 | isorthogonal(::AbstractQ) = true |
2 | 2 | isorthogonal(q) = q'q ≈ I |
3 | 3 |
|
| 4 | +convert_eltype(Q::AbstractMatrix, ::Type{T}) where {T} = convert(AbstractMatrix{T}, Q) |
| 5 | +if !(AbstractQ <: AbstractMatrix) |
| 6 | + convert_eltype(Q::AbstractQ, ::Type{T}) where {T} = convert(AbstractQ{T}, Q) |
| 7 | +end |
| 8 | + |
4 | 9 | """ |
5 | 10 | QLHessenberg(factors, q) |
6 | 11 |
|
7 | 12 | represents a Hessenberg QL factorization where factors contains L in its |
8 | 13 | lower triangular components and q is a vector of 2x2 orthogonal transformations |
9 | 14 | whose product gives Q. |
10 | 15 | """ |
11 | | -struct QLHessenberg{T,S<:AbstractMatrix{T},QT<:AbstractVector{<:AbstractMatrix{T}}} <: Factorization{T} |
| 16 | +struct QLHessenberg{T,S<:AbstractMatrix{T},QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} <: Factorization{T} |
12 | 17 | factors::S |
13 | 18 | q::QT |
14 | 19 |
|
15 | | - function QLHessenberg{T,S,QT}(factors, q) where {T,S<:AbstractMatrix{T},QT<:AbstractVector{<:AbstractMatrix{T}}} |
| 20 | + function QLHessenberg{T,S,QT}(factors, q) where {T,S<:AbstractMatrix{T},QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} |
16 | 21 | require_one_based_indexing(factors) |
17 | 22 | new{T,S,QT}(factors, q) |
18 | 23 | end |
19 | 24 | end |
20 | 25 |
|
21 | | -QLHessenberg(factors::AbstractMatrix{T}, q::AbstractVector{<:AbstractMatrix{T}}) where {T} = QLHessenberg{T,typeof(factors),typeof(q)}(factors, q) |
| 26 | +QLHessenberg(factors::AbstractMatrix{T}, q::AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}) where {T} = |
| 27 | + QLHessenberg{T,typeof(factors),typeof(q)}(factors, q) |
22 | 28 | QLHessenberg{T}(factors::AbstractMatrix, q::AbstractVector) where {T} = |
23 | | - QLHessenberg(convert(AbstractMatrix{T}, factors), convert.(AbstractMatrix{T}, q)) |
| 29 | + QLHessenberg(convert(AbstractMatrix{T}, factors), convert_eltype.(q, T)) |
24 | 30 |
|
25 | 31 | # iteration for destructuring into components |
26 | 32 | Base.iterate(S::QLHessenberg) = (S.Q, Val(:L)) |
27 | 33 | Base.iterate(S::QLHessenberg, ::Val{:L}) = (S.L, Val(:done)) |
28 | 34 | Base.iterate(S::QLHessenberg, ::Val{:done}) = nothing |
29 | 35 |
|
30 | | -QLHessenberg{T}(A::QLHessenberg) where {T} = QLHessenberg(convert(AbstractMatrix{T}, A.factors), convert.(AbstractMatrix{T}, A.q)) |
| 36 | +QLHessenberg{T}(A::QLHessenberg) where {T} = QLHessenberg(convert(AbstractMatrix{T}, A.factors), convert_eltype.(A.q, T)) |
31 | 37 | Factorization{T}(A::QLHessenberg{T}) where {T} = A |
32 | 38 | Factorization{T}(A::QLHessenberg) where {T} = QLHessenberg{T}(A) |
33 | 39 | AbstractMatrix(F::QLHessenberg) = F.Q * F.L |
@@ -69,16 +75,16 @@ abstract type AbstractHessenbergQ{T} <: LayoutQ{T} end |
69 | 75 |
|
70 | 76 | for Typ in (:UpperHessenbergQ, :LowerHessenbergQ) |
71 | 77 | @eval begin |
72 | | - struct $Typ{T, QT<:AbstractVector{<:AbstractMatrix{T}}} <: AbstractHessenbergQ{T} |
| 78 | + struct $Typ{T, QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} <: AbstractHessenbergQ{T} |
73 | 79 | q::QT |
74 | | - function $Typ{T,QT}(q::QT) where {T,QT<:AbstractVector{<:AbstractMatrix{T}}} |
| 80 | + function $Typ{T,QT}(q::QT) where {T,QT<:AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}} |
75 | 81 | all(isorthogonal.(q)) || throw(ArgumentError("input must be orthogonal")) |
76 | 82 | all(size.(q) .== Ref((2,2))) || throw(ArgumentError("input must be 2x2")) |
77 | 83 | new{T,QT}(q) |
78 | 84 | end |
79 | 85 | end |
80 | 86 |
|
81 | | - $Typ(q::AbstractVector{<:AbstractMatrix{T}}) where T = |
| 87 | + $Typ(q::AbstractVector{<:Union{AbstractMatrix{T},AbstractQ{T}}}) where {T} = |
82 | 88 | $Typ{T,typeof(q)}(q) |
83 | 89 | end |
84 | 90 | end |
@@ -141,13 +147,12 @@ end |
141 | 147 | # getindex |
142 | 148 | #### |
143 | 149 |
|
144 | | -function getindex(Q::UpperHessenbergQ, i::Int, j::Int) |
145 | | - y = zeros(eltype(Q), size(Q, 2)) |
146 | | - y[j] = 1 |
147 | | - lmul!(Q, y)[i] |
148 | | -end |
| 150 | +getindex(Q::UpperHessenbergQ, I::AbstractVector{Int}, J::AbstractVector{Int}) = |
| 151 | + hcat((Q[:,j][I] for j in J)...) |
149 | 152 |
|
150 | 153 | getindex(Q::LowerHessenbergQ, i::Int, j::Int) = (Q')[j,i]' |
| 154 | +getindex(Q::LowerHessenbergQ, I::AbstractVector{Int}, J::AbstractVector{Int}) = |
| 155 | + [Q[i,j] for i in I, j in J] |
151 | 156 |
|
152 | 157 |
|
153 | 158 | ### |
|
0 commit comments