Skip to content

Commit 1f433ce

Browse files
committed
Add qr(::AbstractVector), qr!(::AbstractVector)
Compute polar decomposition of vector `qr[!]` is equivalent to `v->(normalize[!](v), norm(v))` but is convenient for reusing the norm calculation, e.g. for Krylov subspace algorithms. Also refactors the in place normalization code to a separate routine, `__normalize!()`, so that it can be reused by `qr!`
1 parent c4c6bb6 commit 1f433ce

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

base/linalg/generic.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,15 +547,18 @@ Normalize the vector `v` in-place with respect to the `p`-norm.
547547
548548
# See also
549549
550-
`normalize`
550+
`normalize`, `qr`
551551
552552
"""
553553
function normalize!(v::AbstractVector, p::Real=2)
554554
nrm = norm(v, p)
555+
__normalize!(v, nrm)
556+
end
555557

558+
@inline function __normalize!{T}(v::AbstractVector{T}, nrm::T)
556559
#The largest positive floating point number whose inverse is less than
557560
#infinity
558-
const δ = inv(prevfloat(typemax(float(nrm))))
561+
const δ = inv(prevfloat(typemax(float(T))))
559562

560563
if nrm δ #Safe to multiply with inverse
561564
invnrm = inv(nrm)
@@ -590,7 +593,7 @@ Normalize the vector `v` with respect to the `p`-norm.
590593
591594
# See also
592595
593-
`normalize!`
596+
`normalize!`, `qr`
594597
"""
595598
normalize(v::AbstractVector, p::Real=2) = v/norm(v, p)
596599

base/linalg/qr.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,49 @@ function _qr(A::Union{Number, AbstractMatrix}, ::Type{Val{true}}; thin::Bool=tru
108108
full(getq(F), thin=thin), F[:R]::Matrix{eltype(F)}, F[:p]::Vector{BlasInt}
109109
end
110110

111+
"""
112+
qr(v::AbstractVector)
113+
114+
Computes the polar decomposition of a vector.
115+
116+
# Input
117+
- `v::AbstractVector` - vector to normalize
118+
119+
# Outputs
120+
- `w` - A unit vector in the direction of `v`
121+
- `r` - The norm of `v`
122+
123+
# See also
124+
125+
`normalize`, `normalize!`, `qr!`
126+
"""
127+
function qr(v::AbstractVector)
128+
nrm = norm(v)
129+
v/nrm, nrm
130+
end
131+
132+
"""
133+
qr!(v::AbstractVector)
134+
135+
Computes the polar decomposition of a vector.
136+
137+
# Input
138+
- `v::AbstractVector` - vector to normalize
139+
140+
# Outputs
141+
- `w` - A unit vector in the direction of `v`
142+
- `r` - The norm of `v`
143+
144+
# See also
145+
146+
`normalize`, `normalize!`, `qr`
147+
"""
148+
function qr!(v::AbstractVector)
149+
nrm = norm(v)
150+
__normalize!(v, nrm), nrm
151+
end
152+
153+
111154
convert{T}(::Type{QR{T}},A::QR) = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ))
112155
convert{T}(::Type{Factorization{T}}, A::QR) = convert(QR{T}, A)
113156
convert{T}(::Type{QRCompactWY{T}},A::QRCompactWY) = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T))

test/linalg/qr.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,11 @@ let
162162
Q=full(qrfact(A)[:Q])
163163
@test vecnorm(A-Q) < eps()
164164
end
165+
166+
let
167+
debug && println("qr on AbstractVector")
168+
169+
v = [3.0, 4.0]
170+
@test qr(v) == ([0.6, 0.8], 5.0)
171+
end
172+

0 commit comments

Comments
 (0)