Skip to content

Commit 78d3ff4

Browse files
authored
Use dot and views in QR code (#38973)
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.
1 parent ad513ca commit 78d3ff4

File tree

2 files changed

+15
-30
lines changed

2 files changed

+15
-30
lines changed

stdlib/LinearAlgebra/src/generic.jl

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,21 +1487,17 @@ end
14871487

14881488
# Elementary reflection similar to LAPACK. The reflector is not Hermitian but
14891489
# ensures that tridiagonalization of Hermitian matrices become real. See lawn72
1490-
@inline function reflector!(x::AbstractVector)
1490+
@inline function reflector!(x::AbstractVector{T}) where {T}
14911491
require_one_based_indexing(x)
14921492
n = length(x)
14931493
n == 0 && return zero(eltype(x))
14941494
@inbounds begin
14951495
ξ1 = x[1]
1496-
normu = abs2(ξ1)
1497-
for i = 2:n
1498-
normu += abs2(x[i])
1499-
end
1496+
normu = norm(x)
15001497
if iszero(normu)
15011498
return zero(ξ1/normu)
15021499
end
1503-
normu = sqrt(normu)
1504-
ν = copysign(normu, real(ξ1))
1500+
ν = T(copysign(normu, real(ξ1)))
15051501
ξ1 += ν
15061502
x[1] = -ν
15071503
for i = 2:n
@@ -1512,29 +1508,18 @@ end
15121508
end
15131509

15141510
# apply reflector from left
1515-
@inline function reflectorApply!(x::AbstractVector, τ::Number, A::StridedMatrix)
1511+
@inline function reflectorApply!(x::AbstractVector, τ::Number, A::AbstractMatrix)
15161512
require_one_based_indexing(x)
15171513
m, n = size(A)
15181514
if length(x) != m
15191515
throw(DimensionMismatch("reflector has length $(length(x)), which must match the first dimension of matrix A, $m"))
15201516
end
15211517
m == 0 && return A
1522-
@inbounds begin
1523-
for j = 1:n
1524-
# dot
1525-
vAj = A[1, j]
1526-
for i = 2:m
1527-
vAj += x[i]'*A[i, j]
1528-
end
1529-
1530-
vAj = conj(τ)*vAj
1531-
1532-
# ger
1533-
A[1, j] -= vAj
1534-
for i = 2:m
1535-
A[i, j] -= x[i]*vAj
1536-
end
1537-
end
1518+
@inbounds for j = 1:n
1519+
Aj, xj = view(A, 2:m, j), view(x, 2:m)
1520+
vAj = conj(τ)*(A[1, j] + dot(xj, Aj))
1521+
A[1, j] -= vAj
1522+
axpy!(-vAj, xj, Aj)
15381523
end
15391524
return A
15401525
end

stdlib/LinearAlgebra/src/qr.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ function qrfactUnblocked!(A::AbstractMatrix{T}) where {T}
198198
end
199199

200200
# Find index for columns with largest two norm
201-
function indmaxcolumn(A::StridedMatrix)
201+
function indmaxcolumn(A::AbstractMatrix)
202202
mm = norm(view(A, :, 1))
203203
ii = 1
204204
for i = 2:size(A, 2)
@@ -211,7 +211,7 @@ function indmaxcolumn(A::StridedMatrix)
211211
return ii
212212
end
213213

214-
function qrfactPivotedUnblocked!(A::StridedMatrix)
214+
function qrfactPivotedUnblocked!(A::AbstractMatrix)
215215
m, n = size(A)
216216
piv = Vector(UnitRange{BlasInt}(1,n))
217217
τ = Vector{eltype(A)}(undef, min(m,n))
@@ -287,14 +287,14 @@ julia> a = [1 2; 3 4]
287287
3 4
288288
289289
julia> qr!(a)
290-
ERROR: InexactError: Int64(-3.1622776601683795)
290+
ERROR: InexactError: Int64(3.1622776601683795)
291291
Stacktrace:
292292
[...]
293293
```
294294
"""
295-
qr!(A::StridedMatrix, ::Val{false}) = qrfactUnblocked!(A)
296-
qr!(A::StridedMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A)
297-
qr!(A::StridedMatrix) = qr!(A, Val(false))
295+
qr!(A::AbstractMatrix, ::Val{false}) = qrfactUnblocked!(A)
296+
qr!(A::AbstractMatrix, ::Val{true}) = qrfactPivotedUnblocked!(A)
297+
qr!(A::AbstractMatrix) = qr!(A, Val(false))
298298

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

0 commit comments

Comments
 (0)