|
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