Skip to content

Commit

Permalink
Use dot and views in QR code (JuliaLang#38973)
Browse files Browse the repository at this point in the history
The QR-code is quite ancient, and was written without using other linalg routines because views were expensive then. This lets LinearAlgebra to use dot and norm and such, which are likely optimized for special number types.
  • Loading branch information
haampie authored and johanmon committed Jul 5, 2021
1 parent 951d8ab commit 94459d4
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 30 deletions.
33 changes: 9 additions & 24 deletions stdlib/LinearAlgebra/src/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1487,21 +1487,17 @@ end

# Elementary reflection similar to LAPACK. The reflector is not Hermitian but
# ensures that tridiagonalization of Hermitian matrices become real. See lawn72
@inline function reflector!(x::AbstractVector)
@inline function reflector!(x::AbstractVector{T}) where {T}
require_one_based_indexing(x)
n = length(x)
n == 0 && return zero(eltype(x))
@inbounds begin
ξ1 = x[1]
normu = abs2(ξ1)
for i = 2:n
normu += abs2(x[i])
end
normu = norm(x)
if iszero(normu)
return zero(ξ1/normu)
end
normu = sqrt(normu)
ν = copysign(normu, real(ξ1))
ν = T(copysign(normu, real(ξ1)))
ξ1 += ν
x[1] = -ν
for i = 2:n
Expand All @@ -1512,29 +1508,18 @@ end
end

# apply reflector from left
@inline function reflectorApply!(x::AbstractVector, τ::Number, A::StridedMatrix)
@inline function reflectorApply!(x::AbstractVector, τ::Number, A::AbstractMatrix)
require_one_based_indexing(x)
m, n = size(A)
if length(x) != m
throw(DimensionMismatch("reflector has length $(length(x)), which must match the first dimension of matrix A, $m"))
end
m == 0 && return A
@inbounds begin
for j = 1:n
# dot
vAj = A[1, j]
for i = 2:m
vAj += x[i]'*A[i, j]
end

vAj = conj(τ)*vAj

# ger
A[1, j] -= vAj
for i = 2:m
A[i, j] -= x[i]*vAj
end
end
@inbounds for j = 1:n
Aj, xj = view(A, 2:m, j), view(x, 2:m)
vAj = conj(τ)*(A[1, j] + dot(xj, Aj))
A[1, j] -= vAj
axpy!(-vAj, xj, Aj)
end
return A
end
Expand Down
12 changes: 6 additions & 6 deletions stdlib/LinearAlgebra/src/qr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function qrfactUnblocked!(A::AbstractMatrix{T}) where {T}
end

# Find index for columns with largest two norm
function indmaxcolumn(A::StridedMatrix)
function indmaxcolumn(A::AbstractMatrix)
mm = norm(view(A, :, 1))
ii = 1
for i = 2:size(A, 2)
Expand All @@ -211,7 +211,7 @@ function indmaxcolumn(A::StridedMatrix)
return ii
end

function qrfactPivotedUnblocked!(A::StridedMatrix)
function qrfactPivotedUnblocked!(A::AbstractMatrix)
m, n = size(A)
piv = Vector(UnitRange{BlasInt}(1,n))
τ = Vector{eltype(A)}(undef, min(m,n))
Expand Down Expand Up @@ -287,14 +287,14 @@ julia> a = [1 2; 3 4]
3 4
julia> qr!(a)
ERROR: InexactError: Int64(-3.1622776601683795)
ERROR: InexactError: Int64(3.1622776601683795)
Stacktrace:
[...]
```
"""
qr!(A::StridedMatrix, ::Val{false}) = qrfactUnblocked!(A)
qr!(A::StridedMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A)
qr!(A::StridedMatrix) = qr!(A, Val(false))
qr!(A::AbstractMatrix, ::Val{false}) = qrfactUnblocked!(A)
qr!(A::AbstractMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A)
qr!(A::AbstractMatrix) = qr!(A, Val(false))

_qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T))))

Expand Down

0 comments on commit 94459d4

Please sign in to comment.