## Lecture 13
using LinearAlgebra
""" Compute a rotation matrix such that
G = Givens(v, i, j, sigma=1)
returns an orthogonal matrix G
where
(G*v)[j] = 0
and
(G*v)[i] has sign sigma.
Also, the vector is modified so that we return G*v
"""
function Givens!(v::AbstractVector, i::Int, j::Int, sigma::Int=1)
@assert i != j "the indices must be disjoint"
v1 = v[i]
v2 = v[j]
d = sigma*sqrt(v1^2 + v2^2)
c = v1/d
s = v2/d
G = Matrix(1.0I, length(v), length(v))
G[i,i] = c
G[j,j] = c
G[i,j] = s
G[j,i] = -s
v[i] = d
v[j] = 0
return G, v
end
v = randn(10)
G, Gv = Givens!(copy(v), 9, 10)
@show norm(G*v - Gv)
##
""" Compute a QR factorization via a sequence of Givens
rotations. This is a pedagogical routine. It can be
greatly improved!
"""
function givens_qr!(A)
m,n = size(A)
Qt = Matrix(1.0I, m, m)
for j=1:n
v = @view A[:,j]
Z = @view A[:,j+1:end]
for i=m:-1:(1+j)
# rotate i to i-1
G = Givens!(v, i-1, i)[1]
Qt = G*Qt
Z .= G*Z
end
end
return copy(Qt'), A
end
A = randn(10,4)
Q, R = givens_qr!(copy(A))
## Givens least squares
function least_squares_givens(A,b)
m,n = size(A)
Q,R = givens_qr!(copy(A))
bt = Q'*b
x = R[1:n,1:n]\bt[1:n]
return x
end
A = randn(10,4)
b = randn(10)
xtrue = A\b
norm(xtrue - least_squares_givens(A,b))
##