Skip to content

Commit 47d02b7

Browse files
jishnubstevengj
andauthored
Specialize norm-related functions for Diagonal (#1457)
For banded matrices such as `Diagonal`, we may skip the non-stored elements in computing the norm, as the contribution of these would be zero. This improves performance. On master ```julia julia> D1 = Diagonal(rand(1000)); julia> D2 = Diagonal(rand(1000)); julia> @Btime norm($D1); 2.668 ms (0 allocations: 0 bytes) julia> @Btime isapprox($D1, $D2); 8.007 ms (3 allocations: 7.88 KiB) ``` vs this PR ```julia julia> @Btime norm($D1); 247.196 ns (0 allocations: 0 bytes) julia> @Btime isapprox($D1, $D2); 1.696 μs (0 allocations: 0 bytes) ``` --------- Co-authored-by: Steven G. Johnson <[email protected]>
1 parent e367ff1 commit 47d02b7

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/diagonal.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,23 @@ end
11111111
/(u::AdjointAbsVec, D::Diagonal) = (D' \ u')'
11121112
/(u::TransposeAbsVec, D::Diagonal) = transpose(transpose(D) \ transpose(u))
11131113

1114+
# norm
1115+
function generic_normMinusInf(D::Diagonal)
1116+
norm_diag = norm(D.diag, -Inf)
1117+
return size(D,1) > 1 ? min(norm_diag, zero(norm_diag)) : norm_diag
1118+
end
1119+
generic_normInf(D::Diagonal) = norm(D.diag, Inf)
1120+
generic_norm1(D::Diagonal) = norm(D.diag, 1)
1121+
generic_norm2(D::Diagonal) = norm(D.diag)
1122+
function generic_normp(D::Diagonal, p)
1123+
v = norm(D.diag, p)
1124+
if size(D,1) > 1 && p < 0
1125+
v = norm(zero(v), p)
1126+
end
1127+
return v
1128+
end
1129+
norm_x_minus_y(D1::Diagonal, D2::Diagonal) = norm_x_minus_y(D1.diag, D2.diag)
1130+
11141131
_opnorm1(A::Diagonal) = maximum(norm(x) for x in A.diag)
11151132
_opnormInf(A::Diagonal) = maximum(norm(x) for x in A.diag)
11161133
_opnorm12Inf(A::Diagonal, p) = maximum(opnorm(x, p) for x in A.diag)

test/diagonal.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,4 +1576,23 @@ end
15761576
@test D == D2
15771577
end
15781578

1579+
@testset "norm" begin
1580+
# test x ≈ y but also ensure that the types are identical
1581+
function test_isapprox_and_type(x::T, y::T) where {T}
1582+
@test x y
1583+
end
1584+
@testset "size(D,1) = $(size(D,1))" for D in ( Diagonal(1:3), Diagonal(1:1), Diagonal(1:0) )
1585+
A = Array(D)
1586+
@testset for p in -2:2
1587+
p == 0 && continue
1588+
s = sum(float.(abs.(D)).^p)^(1/p)
1589+
test_isapprox_and_type(norm(D, p), isempty(D) ? zero(s) : s)
1590+
test_isapprox_and_type(norm(D, p), norm(A, p))
1591+
end
1592+
test_isapprox_and_type(norm(D, Inf), norm(A, Inf))
1593+
test_isapprox_and_type(norm(D, -Inf), norm(A, -Inf))
1594+
test_isapprox_and_type(norm(D, 0), norm(A, 0))
1595+
end
1596+
end
1597+
15791598
end # module TestDiagonal

0 commit comments

Comments
 (0)