199 lines
7.8 KiB
Julia
199 lines
7.8 KiB
Julia
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||
|
||
debug = false
|
||
using Base.Test
|
||
|
||
using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted
|
||
|
||
n = 10
|
||
|
||
# Split n into 2 parts for tests needing two matrices
|
||
n1 = div(n, 2)
|
||
n2 = 2*n1
|
||
|
||
srand(1234321)
|
||
|
||
areal = randn(n,n)/2
|
||
aimg = randn(n,n)/2
|
||
a2real = randn(n,n)/2
|
||
a2img = randn(n,n)/2
|
||
breal = randn(n,2)/2
|
||
bimg = randn(n,2)/2
|
||
|
||
for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int)
|
||
a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal)
|
||
a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real)
|
||
asym = a'+a # symmetric indefinite
|
||
apd = a'*a # symmetric positive-definite
|
||
ε = εa = eps(abs(float(one(eltya))))
|
||
|
||
for eltyb in (Float32, Float64, Complex64, Complex128, Int)
|
||
b = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal)
|
||
εb = eps(abs(float(one(eltyb))))
|
||
ε = max(εa,εb)
|
||
|
||
α = rand(eltyb)
|
||
aα = fill(α,1,1)
|
||
@test qrfact(α)[:Q]*qrfact(α)[:R] ≈ qrfact(aα)[:Q]*qrfact(aα)[:R]
|
||
@test abs(qrfact(α)[:Q][1,1]) ≈ one(eltyb)
|
||
tab = promote_type(eltya,eltyb)
|
||
|
||
debug && println("\ntype of a: ", eltya, " type of b: ", eltyb, "\n")
|
||
debug && println("QR decomposition (without pivoting)")
|
||
for i = 1:2
|
||
let a = i == 1 ? a : view(a, 1:n - 1, 1:n - 1), b = i == 1 ? b : view(b, 1:n - 1), n = i == 1 ? n : n - 1
|
||
qra = @inferred qrfact(a)
|
||
@inferred qr(a)
|
||
q, r = qra[:Q], qra[:R]
|
||
@test_throws KeyError qra[:Z]
|
||
@test q'*full(q, thin=false) ≈ eye(n)
|
||
@test q*full(q, thin=false)' ≈ eye(n)
|
||
@test q'*eye(n)' ≈ full(q, thin=false)'
|
||
@test full(q, thin=false)'q ≈ eye(n)
|
||
@test eye(n)'q' ≈ full(q, thin=false)'
|
||
@test q*r ≈ a
|
||
@test a*(qra\b) ≈ b atol=3000ε
|
||
@test full(qra) ≈ a
|
||
@test A_mul_Bc(eye(eltyb,size(q.factors,2)),q)*full(q,thin=false) ≈ eye(n) atol=5000ε
|
||
if eltya != Int
|
||
@test eye(eltyb,n)*q ≈ convert(AbstractMatrix{tab},q)
|
||
ac = copy(a)
|
||
@test qrfact!(a[:, 1:5])\b == qrfact!(view(ac, :, 1:5))\b
|
||
end
|
||
rstring = sprint(show,r)
|
||
qstring = sprint(show,q)
|
||
@test sprint(show,qra) == "$(typeof(qra)) with factors Q and R:\n$qstring\n$rstring"
|
||
|
||
debug && println("Thin QR decomposition (without pivoting)")
|
||
qra = @inferred qrfact(a[:,1:n1], Val{false})
|
||
@inferred qr(a[:,1:n1], Val{false})
|
||
q,r = qra[:Q], qra[:R]
|
||
@test_throws KeyError qra[:Z]
|
||
@test q'*full(q, thin=false) ≈ eye(n)
|
||
@test q'*full(q) ≈ eye(n,n1)
|
||
@test q*r ≈ a[:,1:n1]
|
||
@test q*b[1:n1] ≈ full(q)*b[1:n1] atol=100ε
|
||
@test q*b ≈ full(q,thin=false)*b atol=100ε
|
||
@test_throws DimensionMismatch q*b[1:n1 + 1]
|
||
@test_throws DimensionMismatch b[1:n1 + 1]*q'
|
||
@test A_mul_Bc(UpperTriangular(eye(eltyb,size(q.factors,2))),q)*full(q,thin=false) ≈ eye(n1,n) atol=5000ε
|
||
if eltya != Int
|
||
@test eye(eltyb,n)*q ≈ convert(AbstractMatrix{tab},q)
|
||
end
|
||
|
||
debug && println("(Automatic) Fat (pivoted) QR decomposition")
|
||
@inferred qrfact(a, Val{true})
|
||
@inferred qr(a, Val{true})
|
||
|
||
qrpa = factorize(a[1:n1,:])
|
||
q,r = qrpa[:Q], qrpa[:R]
|
||
@test_throws KeyError qrpa[:Z]
|
||
p = qrpa[:p]
|
||
@test q'*full(q, thin=false) ≈ eye(n1)
|
||
@test q*full(q, thin=false)' ≈ eye(n1)
|
||
@test (UpperTriangular(eye(eltya,size(q,2)))*q')*full(q, thin=false) ≈ eye(n1)
|
||
@test q*r ≈ (isa(qrpa,QRPivoted) ? a[1:n1,p] : a[1:n1,:])
|
||
@test q*r[:,invperm(p)] ≈ a[1:n1,:]
|
||
@test q*r*qrpa[:P].' ≈ a[1:n1,:]
|
||
@test a[1:n1,:]*(qrpa\b[1:n1]) ≈ b[1:n1] atol=5000ε
|
||
@test full(qrpa) ≈ a[1:5,:]
|
||
@test_throws DimensionMismatch q*b[1:n1+1]
|
||
@test_throws DimensionMismatch b[1:n1+1]*q'
|
||
if eltya != Int
|
||
@test eye(eltyb,n1)*q ≈ convert(AbstractMatrix{tab},q)
|
||
end
|
||
|
||
debug && println("(Automatic) Thin (pivoted) QR decomposition")
|
||
qrpa = factorize(a[:,1:n1])
|
||
q,r = qrpa[:Q], qrpa[:R]
|
||
@test_throws KeyError qrpa[:Z]
|
||
p = qrpa[:p]
|
||
@test q'*full(q, thin=false) ≈ eye(n)
|
||
@test q*full(q, thin=false)' ≈ eye(n)
|
||
@test q*r ≈ a[:,p]
|
||
@test q*r[:,invperm(p)] ≈ a[:,1:n1]
|
||
@test full(qrpa) ≈ a[:,1:5]
|
||
@test_throws DimensionMismatch q*b[1:n1+1]
|
||
@test_throws DimensionMismatch b[1:n1+1]*q'
|
||
@test A_mul_Bc(UpperTriangular(eye(eltyb,size(q.factors,2))),q)*full(q,thin=false) ≈ eye(n1,n) atol=5000ε
|
||
if eltya != Int
|
||
@test eye(eltyb,n)*q ≈ convert(AbstractMatrix{tab},q)
|
||
end
|
||
end
|
||
end
|
||
|
||
debug && println("Matmul with QR factorizations")
|
||
if eltya != Int
|
||
qrpa = factorize(a[:,1:n1])
|
||
q, r = qrpa[:Q], qrpa[:R]
|
||
@test A_mul_B!(full(q, thin=false)',q) ≈ eye(n)
|
||
@test_throws DimensionMismatch A_mul_B!(eye(eltya,n+1),q)
|
||
@test A_mul_Bc!(full(q, thin=false),q) ≈ eye(n)
|
||
@test_throws DimensionMismatch A_mul_Bc!(eye(eltya,n+1),q)
|
||
@test_throws BoundsError size(q,-1)
|
||
@test_throws DimensionMismatch Base.LinAlg.A_mul_B!(q,zeros(eltya,n1+1))
|
||
@test_throws DimensionMismatch Base.LinAlg.Ac_mul_B!(q,zeros(eltya,n1+1))
|
||
|
||
qra = qrfact(a[:,1:n1], Val{false})
|
||
q, r = qra[:Q], qra[:R]
|
||
@test A_mul_B!(full(q, thin=false)',q) ≈ eye(n)
|
||
@test_throws DimensionMismatch A_mul_B!(eye(eltya,n+1),q)
|
||
@test A_mul_Bc!(full(q, thin=false),q) ≈ eye(n)
|
||
@test_throws DimensionMismatch A_mul_Bc!(eye(eltya,n+1),q)
|
||
@test_throws BoundsError size(q,-1)
|
||
@test_throws DimensionMismatch q * eye(Int8,n+4)
|
||
end
|
||
end
|
||
end
|
||
|
||
# Because transpose(x) == x
|
||
@test_throws ErrorException transpose(qrfact(randn(3,3)))
|
||
@test_throws ErrorException ctranspose(qrfact(randn(3,3)))
|
||
@test_throws ErrorException transpose(qrfact(randn(3,3), Val{false}))
|
||
@test_throws ErrorException ctranspose(qrfact(randn(3,3), Val{false}))
|
||
@test_throws ErrorException transpose(qrfact(big.(randn(3,3))))
|
||
@test_throws ErrorException ctranspose(qrfact(big.(randn(3,3))))
|
||
|
||
# Issue 7304
|
||
let
|
||
A = [-√.5 -√.5; -√.5 √.5]
|
||
Q = full(qrfact(A)[:Q])
|
||
@test vecnorm(A-Q) < eps()
|
||
end
|
||
|
||
let
|
||
debug && println("qr on AbstractVector")
|
||
|
||
vr = [3.0, 4.0]
|
||
for Tr in (Float32, Float64)
|
||
for T in (Tr, Complex{Tr})
|
||
v = convert(Vector{T}, vr)
|
||
nv, nm = qr(v)
|
||
@test norm(nv - [0.6, 0.8], Inf) < eps(Tr)
|
||
@test nm == 5.0
|
||
end
|
||
end
|
||
end
|
||
|
||
@test qr(Int[]) == (Int[],1)
|
||
@test Base.LinAlg.qr!(Int[1]) == (Int[1],1)
|
||
|
||
B = rand(7,2)
|
||
@test (1:7)\B ≈ collect(1:7)\B
|
||
|
||
# Issue 16520
|
||
@test_throws DimensionMismatch ones(3,2)\(1:5)
|
||
|
||
# Issue 22810
|
||
let
|
||
A = zeros(1, 2)
|
||
B = zeros(1, 1)
|
||
@test A \ B == zeros(2, 1)
|
||
@test qrfact(A, Val{true}) \ B == zeros(2, 1)
|
||
end
|
||
|
||
@testset "Issue 24107" begin
|
||
A = rand(200,2)
|
||
@test A \ linspace(0,1,200) == A \ collect(linspace(0,1,200))
|
||
end
|