diff --git a/src/qr.jl b/src/qr.jl index 5c59ab60..ffe369b6 100644 --- a/src/qr.jl +++ b/src/qr.jl @@ -148,7 +148,8 @@ Base.iterate(S::QRCompactWY, ::Val{:done}) = nothing # function _triuppers_qr(T) blocksize, cols = size(T) - return Iterators.map(0:div(cols - 1, blocksize)) do i + nblocks = iszero(cols) || iszero(blocksize) ? 0 : cld(cols, blocksize) + return Iterators.map(range(0, length=nblocks)) do i n = min(blocksize, cols - i * blocksize) return UpperTriangular(view(T, 1:n, (1:n) .+ i * blocksize)) end @@ -158,9 +159,11 @@ function Base.hash(F::QRCompactWY, h::UInt) return hash(F.factors, foldr(hash, _triuppers_qr(F.T); init=hash(QRCompactWY, h))) end function Base.:(==)(A::QRCompactWY, B::QRCompactWY) + size(A.T) == size(B.T) || return false return A.factors == B.factors && all(splat(==), zip(_triuppers_qr.((A.T, B.T))...)) end function Base.isequal(A::QRCompactWY, B::QRCompactWY) + size(A.T) == size(B.T) || return false return isequal(A.factors, B.factors) && all(zip(_triuppers_qr.((A.T, B.T))...)) do (a, b) isequal(a, b)::Bool end diff --git a/test/qr.jl b/test/qr.jl index 0ad61a7a..cc397efe 100644 --- a/test/qr.jl +++ b/test/qr.jl @@ -517,7 +517,7 @@ end # this should have worked before, Q is square, and R is 0 × 0: A_zero_cols = rand(F, dimA, 0) qr_zero_cols = qr(A_zero_cols) - @test size(qr_zero_cols.Q) == (dimA, dimA) + @test size(qr_zero_cols.Q) == (dimA, dimA) @test size(qr_zero_cols.R) == (0, 0) @test qr_zero_cols.Q == LinearAlgebra.I(dimA) @@ -542,4 +542,23 @@ end @test rank(qr([1.0 2.0 3.0; 4.0 5.0 6.0 ; 7.0 8.0 9.0], ColumnNorm())) == 2 end +@testset "QRCompactWY equality/hash" begin + @testset "$(size(A))" for A in (zeros(0, 0), zeros(0, 3), zeros(3, 0)) + F, G = qr(A), qr(A) + @test F == G + @test isequal(F, G) + @test hash(F) == hash(G) + end + + @testset "QRCompactWY equality checks T shape" begin + # This is a contrived example, but ensures that we don't violate the hash contract + F = LinearAlgebra.QRCompactWY(zeros(1, 1), reshape([1.0], 1, 1)) + G = LinearAlgebra.QRCompactWY(zeros(1, 1), reshape([1.0 99.0], 1, 2)) + + @test F != G + @test !isequal(F, G) + @test hash(F) != hash(G) + end +end + end # module TestQR