Skip to content

Commit 62027cd

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 db90ac0 commit 62027cd

File tree

4 files changed

+62
-8
lines changed

4 files changed

+62
-8
lines changed

base/linalg/generic.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,19 +547,22 @@ 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<:AbstractFloat}(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(T)))
559562

560563
if nrm δ #Safe to multiply with inverse
561564
invnrm = inv(nrm)
562-
scale!(v, invrm)
565+
scale!(v, invnrm)
563566

564567
else #Divide by norm; slower but more correct
565568
#Note 2015-10-19: As of Julia 0.4, @simd does not vectorize floating
@@ -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/generic.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,17 @@ let
157157
w = normalize(v)
158158
@test w == [0.6, 0.8]
159159
@test norm(w) === 1.0
160-
@test normalize!(v) == w
160+
@test norm(normalize!(v) - w, Inf) < eps()
161161
end
162162

163163
#Test potential overflow in normalize!
164164
let
165-
δ = inv(prevfloat(typemax(float(nrm))))
165+
δ = inv(prevfloat(typemax(Float64)))
166166
v = [δ, -δ]
167167

168168
@test norm(v) === 7.866824069956793e-309
169169
w = normalize(v)
170-
@test norm(w) === 1.0
171170
@test w [1/√2, -1/√2]
172-
@test normalize!(v) == w
171+
@test norm(w) === 1.0
172+
@test norm(normalize!(v) - w, Inf) < eps()
173173
end

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)