Skip to content

Commit f567112

Browse files
committed
Port structured opnorm changes from main julia PR
Originally written by mcognetta
1 parent d406524 commit f567112

File tree

7 files changed

+141
-0
lines changed

7 files changed

+141
-0
lines changed

src/bidiag.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,18 @@ function svd(M::Bidiagonal; kw...)
248248
svd!(copy(M), kw...)
249249
end
250250

251+
###################
252+
# opnorm #
253+
###################
254+
255+
function _opnorm1Inf(B::Bidiagonal, p)
256+
size(B, 1) == 1 && return norm(first(B.dv))
257+
case = xor(p == 1, istriu(B))
258+
normd1, normdend = norm(first(B.dv)), norm(last(B.dv))
259+
normd1, normdend = case ? (zero(normd1), normdend) : (normd1, zero(normdend))
260+
return max(mapreduce(t -> sum(norm, t), max, zip(view(B.dv, (1:length(B.ev)) .+ !case), B.ev)), normdend)
261+
end
262+
251263
####################
252264
# Generic routines #
253265
####################

src/diagonal.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,18 @@ end
10381038
*(A::AbstractTriangular, D::Diagonal) = @invoke *(A::AbstractMatrix, D::Diagonal)
10391039
*(D::Diagonal, A::AbstractTriangular) = @invoke *(D::Diagonal, A::AbstractMatrix)
10401040

1041+
_opnorm1(A::Diagonal) = maximum(norm(x) for x in A.diag)
1042+
_opnormInf(A::Diagonal) = maximum(norm(x) for x in A.diag)
1043+
_opnorm12Inf(A::Diagonal, p) = maximum(opnorm(x, p) for x in A.diag)
1044+
1045+
function opnorm(A::Diagonal, p::Real=2)
1046+
if p == 1 || p == Inf || p == 2
1047+
return _opnorm12Inf(A, p)
1048+
else
1049+
throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2, Inf"))
1050+
end
1051+
end
1052+
10411053
dot(x::AbstractVector, D::Diagonal, y::AbstractVector) = _mapreduce_prod(dot, x, D, y)
10421054

10431055
dot(A::Diagonal, B::Diagonal) = dot(A.diag, B.diag)

src/special.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,15 @@ end
593593
_istril(A::LowerTriangular{<:Any, <:BandedMatrix}, k) = istril(parent(A), k)
594594
_istriu(A::UpperTriangular{<:Any, <:BandedMatrix}, k) = istriu(parent(A), k)
595595
_istriu(A::UpperHessenberg{<:Any, <:BandedMatrix}, k) = istriu(parent(A), k)
596+
# op norm for structured matrices other than diagonal
597+
# the _opnorm1Inf methods are housed in the structured type's respective files
598+
599+
function opnorm(A::Union{Bidiagonal,Tridiagonal,SymTridiagonal}, p::Real=2)
600+
if p == 2
601+
return opnorm2(A)
602+
elseif p == 1 || p == Inf
603+
return _opnorm1Inf(A, p)
604+
else
605+
throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2, Inf"))
606+
end
607+
end

src/tridiag.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,3 +1097,38 @@ function show(io::IO, S::SymTridiagonal)
10971097
show(io, S.ev)
10981098
print(io, ")")
10991099
end
1100+
1101+
###################
1102+
# opnorms #
1103+
###################
1104+
1105+
# Tridiagonal
1106+
1107+
function _opnorm1Inf(A::Tridiagonal, p)
1108+
size(A, 1) == 1 && return norm(first(A.d))
1109+
case = p == Inf
1110+
lowerrange, upperrange = case ? (1:length(A.dl)-1, 2:length(A.dl)) : (2:length(A.dl), 1:length(A.dl)-1)
1111+
normfirst, normend = case ? (norm(first(A.d))+norm(first(A.du)), norm(last(A.dl))+norm(last(A.d))) : (norm(first(A.d))+norm(first(A.dl)), norm(last(A.du))+norm(last(A.d)))
1112+
1113+
return max(
1114+
mapreduce(t -> sum(norm, t),
1115+
max,
1116+
zip(view(A.d, (2:length(A.d)-1)), view(A.dl, lowerrange), view(A.du, upperrange))
1117+
),
1118+
normfirst, normend)
1119+
end
1120+
1121+
# SymTridiagonal
1122+
1123+
function _opnorm1Inf(A::SymTridiagonal, p::Real)
1124+
size(A, 1) == 1 && return norm(first(A.dv))
1125+
lowerrange, upperrange = 1:length(A.ev)-1, 2:length(A.ev)
1126+
normfirst, normend = norm(first(A.dv))+norm(first(A.ev)), norm(last(A.ev))+norm(last(A.dv))
1127+
1128+
return max(
1129+
mapreduce(t -> sum(norm, t),
1130+
max,
1131+
zip(view(A.dv, (2:length(A.dv)-1)), view(A.ev, lowerrange), view(A.ev, upperrange))
1132+
),
1133+
normfirst, normend)
1134+
end

test/bidiag.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,4 +1138,30 @@ end
11381138
end
11391139
end
11401140

1141+
@testset "opnorms" begin
1142+
B = Bidiagonal([1,-2,3,-4], [1,2,3], 'U')
1143+
1144+
@test opnorm(B, 1) == opnorm(Matrix(B), 1)
1145+
@test opnorm(B, 2) opnorm(Matrix(B), 2)
1146+
@test opnorm(B, Inf) == opnorm(Matrix(B), Inf)
1147+
1148+
B = Bidiagonal([1,-2,3,-4], [1,2,3], 'L')
1149+
1150+
@test opnorm(B, 1) == opnorm(Matrix(B), 1)
1151+
@test opnorm(B, 2) opnorm(Matrix(B), 2)
1152+
@test opnorm(B, Inf) == opnorm(Matrix(B), Inf)
1153+
1154+
B = Bidiagonal([2], Int[], 'L')
1155+
1156+
@test opnorm(B, 1) == opnorm(Matrix(B), 1)
1157+
@test opnorm(B, 2) opnorm(Matrix(B), 2)
1158+
@test opnorm(B, Inf) == opnorm(Matrix(B), Inf)
1159+
1160+
B = Bidiagonal([2], Int[], 'U')
1161+
1162+
@test opnorm(B, 1) == opnorm(Matrix(B), 1)
1163+
@test opnorm(B, 2) opnorm(Matrix(B), 2)
1164+
@test opnorm(B, Inf) == opnorm(Matrix(B), Inf)
1165+
end
1166+
11411167
end # module TestBidiagonal

test/diagonal.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,4 +1452,24 @@ end
14521452
@test kron(D2, D) == kron(Array{eltype(D2)}(D2), D)
14531453
end
14541454

1455+
@testset "opnorms" begin
1456+
D = Diagonal([1,-2,3,-4])
1457+
1458+
@test opnorm(D, 1) == opnorm(Matrix(D), 1)
1459+
@test opnorm(D, 2) opnorm(Matrix(D), 2)
1460+
@test opnorm(D, Inf) == opnorm(Matrix(D), Inf)
1461+
1462+
D = Diagonal([-11])
1463+
@test opnorm(D, 1) == opnorm(Matrix(D), 1)
1464+
@test opnorm(D, 2) opnorm(Matrix(D), 2)
1465+
@test opnorm(D, Inf) == opnorm(Matrix(D), Inf)
1466+
1467+
# block diagonal matrices
1468+
D = Diagonal([[1 2; 3 4], [5 6; 7 8]])
1469+
A = [1 2 0 0; 3 4 0 0; 0 0 5 6; 0 0 7 8] # full matrix of D
1470+
@test opnorm(D, 1) == opnorm(A, 1)
1471+
@test opnorm(D, 2) opnorm(A, 2)
1472+
@test opnorm(D, Inf) == opnorm(A, Inf)
1473+
end
1474+
14551475
end # module TestDiagonal

test/tridiag.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,4 +1075,28 @@ end
10751075
@test all(iszero, diag(A,1))
10761076
end
10771077

1078+
@testset "opnorms" begin
1079+
T = Tridiagonal([1,2,3], [1,-2,3,-4], [1,2,3])
1080+
1081+
@test opnorm(T, 1) == opnorm(Matrix(T), 1)
1082+
@test_skip opnorm(T, 2) opnorm(Matrix(T), 2) # currently missing
1083+
@test opnorm(T, Inf) == opnorm(Matrix(T), Inf)
1084+
1085+
S = SymTridiagonal([1,-2,3,-4], [1,2,3])
1086+
1087+
@test opnorm(S, 1) == opnorm(Matrix(S), 1)
1088+
@test_skip opnorm(S, 2) opnorm(Matrix(S), 2) # currently missing
1089+
@test opnorm(S, Inf) == opnorm(Matrix(S), Inf)
1090+
1091+
T = Tridiagonal(Int[], [-5], Int[])
1092+
@test opnorm(T, 1) == opnorm(Matrix(T), 1)
1093+
@test_skip opnorm(T, 2) opnorm(Matrix(T), 2) # currently missing
1094+
@test opnorm(T, Inf) == opnorm(Matrix(T), Inf)
1095+
1096+
S = SymTridiagonal(T)
1097+
@test opnorm(S, 1) == opnorm(Matrix(S), 1)
1098+
@test_skip opnorm(S, 2) opnorm(Matrix(S), 2) # currently missing
1099+
@test opnorm(S, Inf) == opnorm(Matrix(S), Inf)
1100+
end
1101+
10781102
end # module TestTridiagonal

0 commit comments

Comments
 (0)