Skip to content

Commit dccd6f8

Browse files
authored
Fix empty Tridiagonal broadcast (#1324)
Fixes ```julia julia> T = Tridiagonal(1:0, 1:0, 1:0) 0×0 Tridiagonal{Int64, UnitRange{Int64}} julia> T .+ T ERROR: ArgumentError: invalid GenericMemory size: the number of elements is either negative or too large for system address width ``` After this, ```julia julia> T .+ T 0×0 Tridiagonal{Int64, Vector{Int64}} ``` The changes are minor, but the largish diff is because of adding a loop to the tests, and additional indentation as a consequence.
1 parent 41db513 commit dccd6f8

File tree

2 files changed

+152
-148
lines changed

2 files changed

+152
-148
lines changed

src/structuredbroadcast.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ function structured_broadcast_alloc(bc, ::Type{Bidiagonal}, ::Type{ElType}, n) w
8484
return Bidiagonal(Array{ElType}(undef, n),Array{ElType}(undef, n1), uplo)
8585
end
8686
structured_broadcast_alloc(bc, ::Type{SymTridiagonal}, ::Type{ElType}, n) where {ElType} =
87-
SymTridiagonal(Array{ElType}(undef, n),Array{ElType}(undef, n-1))
87+
SymTridiagonal(Array{ElType}(undef, n),Array{ElType}(undef, max(0,n-1)))
8888
structured_broadcast_alloc(bc, ::Type{Tridiagonal}, ::Type{ElType}, n) where {ElType} =
89-
Tridiagonal(Array{ElType}(undef, n-1),Array{ElType}(undef, n),Array{ElType}(undef, n-1))
89+
Tridiagonal(Array{ElType}(undef, max(0,n-1)),Array{ElType}(undef, n),Array{ElType}(undef, max(0,n-1)))
9090
structured_broadcast_alloc(bc, ::Type{LowerTriangular}, ::Type{ElType}, n) where {ElType} =
9191
LowerTriangular(Array{ElType}(undef, n, n))
9292
structured_broadcast_alloc(bc, ::Type{UpperTriangular}, ::Type{ElType}, n) where {ElType} =

test/structuredbroadcast.jl

Lines changed: 150 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -11,160 +11,164 @@ isdefined(Main, :SizedArrays) || @eval Main include(joinpath($(BASE_TEST_PATH),
1111
using .Main.SizedArrays
1212

1313
@testset "broadcast[!] over combinations of scalars, structured matrices, and dense vectors/matrices" begin
14-
N = 10
15-
s = rand()
16-
fV = rand(N)
17-
fA = rand(N, N)
18-
Z = copy(fA)
19-
D = Diagonal(rand(N))
20-
B = Bidiagonal(rand(N), rand(N - 1), :U)
21-
T = Tridiagonal(rand(N - 1), rand(N), rand(N - 1))
22-
S = SymTridiagonal(rand(N), rand(N - 1))
23-
U = UpperTriangular(rand(N,N))
24-
L = LowerTriangular(rand(N,N))
25-
M = Matrix(rand(N,N))
26-
structuredarrays = (D, B, T, U, L, M, S)
27-
fstructuredarrays = map(Array, structuredarrays)
28-
for (X, fX) in zip(structuredarrays, fstructuredarrays)
29-
@test (Q = broadcast(sin, X); typeof(Q) == typeof(X) && Q == broadcast(sin, fX))
30-
@test broadcast!(sin, Z, X) == broadcast(sin, fX)
31-
@test (Q = broadcast(cos, X); Q isa Matrix && Q == broadcast(cos, fX))
32-
@test broadcast!(cos, Z, X) == broadcast(cos, fX)
33-
@test (Q = broadcast(*, s, X); typeof(Q) == typeof(X) && Q == broadcast(*, s, fX))
34-
@test broadcast!(*, Z, s, X) == broadcast(*, s, fX)
35-
@test (Q = broadcast(+, fV, fA, X); Q isa Matrix && Q == broadcast(+, fV, fA, fX))
36-
@test broadcast!(+, Z, fV, fA, X) == broadcast(+, fV, fA, fX)
37-
@test (Q = broadcast(*, s, fV, fA, X); Q isa Matrix && Q == broadcast(*, s, fV, fA, fX))
38-
@test broadcast!(*, Z, s, fV, fA, X) == broadcast(*, s, fV, fA, fX)
39-
40-
@test X .* 2.0 == X .* (2.0,) == fX .* 2.0
41-
@test X .* 2.0 isa typeof(X)
42-
@test X .* (2.0,) isa typeof(X)
43-
@test isequal(X .* Inf, fX .* Inf)
44-
45-
two = 2
46-
@test X .^ 2 == X .^ (2,) == fX .^ 2 == X .^ two
47-
@test X .^ 2 isa typeof(X)
48-
@test X .^ (2,) isa typeof(X)
49-
@test X .^ two isa typeof(X)
50-
@test X .^ 0 == fX .^ 0
51-
@test X .^ -1 == fX .^ -1
52-
53-
for (Y, fY) in zip(structuredarrays, fstructuredarrays)
54-
@test broadcast(+, X, Y) == broadcast(+, fX, fY)
55-
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
56-
@test broadcast(*, X, Y) == broadcast(*, fX, fY)
57-
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
14+
@testset for N in (0,1,2,10) # some edge cases, and a structured case
15+
s = rand()
16+
fV = rand(N)
17+
fA = rand(N, N)
18+
Z = copy(fA)
19+
D = Diagonal(rand(N))
20+
B = Bidiagonal(rand(N), rand(max(0,N-1)), :U)
21+
T = Tridiagonal(rand(max(0,N-1)), rand(N), rand(max(0,N-1)))
22+
S = SymTridiagonal(rand(N), rand(max(0,N-1)))
23+
U = UpperTriangular(rand(N,N))
24+
L = LowerTriangular(rand(N,N))
25+
M = Matrix(rand(N,N))
26+
structuredarrays = (D, B, T, U, L, M, S)
27+
fstructuredarrays = map(Array, structuredarrays)
28+
@testset "$(nameof(typeof(X)))" for (X, fX) in zip(structuredarrays, fstructuredarrays)
29+
@test (Q = broadcast(sin, X); typeof(Q) == typeof(X) && Q == broadcast(sin, fX))
30+
@test broadcast!(sin, Z, X) == broadcast(sin, fX)
31+
@test (Q = broadcast(cos, X); Q isa Matrix && Q == broadcast(cos, fX))
32+
@test broadcast!(cos, Z, X) == broadcast(cos, fX)
33+
@test (Q = broadcast(*, s, X); typeof(Q) == typeof(X) && Q == broadcast(*, s, fX))
34+
@test broadcast!(*, Z, s, X) == broadcast(*, s, fX)
35+
@test (Q = broadcast(+, fV, fA, X); Q isa Matrix && Q == broadcast(+, fV, fA, fX))
36+
@test broadcast!(+, Z, fV, fA, X) == broadcast(+, fV, fA, fX)
37+
@test (Q = broadcast(*, s, fV, fA, X); Q isa Matrix && Q == broadcast(*, s, fV, fA, fX))
38+
@test broadcast!(*, Z, s, fV, fA, X) == broadcast(*, s, fV, fA, fX)
39+
40+
@test X .* 2.0 == X .* (2.0,) == fX .* 2.0
41+
@test X .* 2.0 isa typeof(X)
42+
@test X .* (2.0,) isa typeof(X)
43+
@test isequal(X .* Inf, fX .* Inf)
44+
45+
two = 2
46+
@test X .^ 2 == X .^ (2,) == fX .^ 2 == X .^ two
47+
@test X .^ 2 isa typeof(X)
48+
@test X .^ (2,) isa typeof(X)
49+
@test X .^ two isa typeof(X)
50+
@test X .^ 0 == fX .^ 0
51+
@test X .^ -1 == fX .^ -1
52+
53+
for (Y, fY) in zip(structuredarrays, fstructuredarrays)
54+
@test broadcast(+, X, Y) == broadcast(+, fX, fY)
55+
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
56+
@test broadcast(*, X, Y) == broadcast(*, fX, fY)
57+
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
58+
end
5859
end
59-
end
60-
diagonals = (D, B, T)
61-
fdiagonals = map(Array, diagonals)
62-
for (X, fX) in zip(diagonals, fdiagonals)
63-
for (Y, fY) in zip(diagonals, fdiagonals)
64-
@test broadcast(+, X, Y)::Union{Diagonal,Bidiagonal,Tridiagonal} == broadcast(+, fX, fY)
65-
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
66-
@test broadcast(*, X, Y)::Union{Diagonal,Bidiagonal,Tridiagonal} == broadcast(*, fX, fY)
67-
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
60+
diagonals = (D, B, T)
61+
fdiagonals = map(Array, diagonals)
62+
for (X, fX) in zip(diagonals, fdiagonals)
63+
for (Y, fY) in zip(diagonals, fdiagonals)
64+
@test broadcast(+, X, Y)::Union{Diagonal,Bidiagonal,Tridiagonal} == broadcast(+, fX, fY)
65+
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
66+
@test broadcast(*, X, Y)::Union{Diagonal,Bidiagonal,Tridiagonal} == broadcast(*, fX, fY)
67+
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
68+
end
6869
end
69-
end
70-
UU = UnitUpperTriangular(rand(N,N))
71-
UL = UnitLowerTriangular(rand(N,N))
72-
unittriangulars = (UU, UL)
73-
Ttris = typeof.((UpperTriangular(parent(UU)), LowerTriangular(parent(UU))))
74-
funittriangulars = map(Array, unittriangulars)
75-
for (X, fX, Ttri) in zip(unittriangulars, funittriangulars, Ttris)
76-
@test (Q = broadcast(sin, X); typeof(Q) == Ttri && Q == broadcast(sin, fX))
77-
@test broadcast!(sin, Z, X) == broadcast(sin, fX)
78-
@test (Q = broadcast(cos, X); Q isa Matrix && Q == broadcast(cos, fX))
79-
@test broadcast!(cos, Z, X) == broadcast(cos, fX)
80-
@test (Q = broadcast(*, s, X); typeof(Q) == Ttri && Q == broadcast(*, s, fX))
81-
@test broadcast!(*, Z, s, X) == broadcast(*, s, fX)
82-
@test (Q = broadcast(+, fV, fA, X); Q isa Matrix && Q == broadcast(+, fV, fA, fX))
83-
@test broadcast!(+, Z, fV, fA, X) == broadcast(+, fV, fA, fX)
84-
@test (Q = broadcast(*, s, fV, fA, X); Q isa Matrix && Q == broadcast(*, s, fV, fA, fX))
85-
@test broadcast!(*, Z, s, fV, fA, X) == broadcast(*, s, fV, fA, fX)
86-
87-
@test X .* 2.0 == X .* (2.0,) == fX .* 2.0
88-
@test X .* 2.0 isa Ttri
89-
@test X .* (2.0,) isa Ttri
90-
@test isequal(X .* Inf, fX .* Inf)
91-
92-
two = 2
93-
@test X .^ 2 == X .^ (2,) == fX .^ 2 == X .^ two
94-
@test X .^ 2 isa typeof(X) # special cased, as isstructurepreserving
95-
@test X .^ (2,) isa Ttri
96-
@test X .^ two isa Ttri
97-
@test X .^ 0 == fX .^ 0
98-
@test X .^ -1 == fX .^ -1
99-
100-
for (Y, fY) in zip(unittriangulars, funittriangulars)
101-
@test broadcast(+, X, Y) == broadcast(+, fX, fY)
102-
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
103-
@test broadcast(*, X, Y) == broadcast(*, fX, fY)
104-
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
70+
UU = UnitUpperTriangular(rand(N,N))
71+
UL = UnitLowerTriangular(rand(N,N))
72+
unittriangulars = (UU, UL)
73+
Ttris = typeof.((UpperTriangular(parent(UU)), LowerTriangular(parent(UU))))
74+
funittriangulars = map(Array, unittriangulars)
75+
for (X, fX, Ttri) in zip(unittriangulars, funittriangulars, Ttris)
76+
@test (Q = broadcast(sin, X); typeof(Q) == Ttri && Q == broadcast(sin, fX))
77+
@test broadcast!(sin, Z, X) == broadcast(sin, fX)
78+
@test (Q = broadcast(cos, X); Q isa Matrix && Q == broadcast(cos, fX))
79+
@test broadcast!(cos, Z, X) == broadcast(cos, fX)
80+
@test (Q = broadcast(*, s, X); typeof(Q) == Ttri && Q == broadcast(*, s, fX))
81+
@test broadcast!(*, Z, s, X) == broadcast(*, s, fX)
82+
@test (Q = broadcast(+, fV, fA, X); Q isa Matrix && Q == broadcast(+, fV, fA, fX))
83+
@test broadcast!(+, Z, fV, fA, X) == broadcast(+, fV, fA, fX)
84+
@test (Q = broadcast(*, s, fV, fA, X); Q isa Matrix && Q == broadcast(*, s, fV, fA, fX))
85+
@test broadcast!(*, Z, s, fV, fA, X) == broadcast(*, s, fV, fA, fX)
86+
87+
@test X .* 2.0 == X .* (2.0,) == fX .* 2.0
88+
@test X .* 2.0 isa Ttri
89+
@test X .* (2.0,) isa Ttri
90+
@test isequal(X .* Inf, fX .* Inf)
91+
92+
two = 2
93+
@test X .^ 2 == X .^ (2,) == fX .^ 2 == X .^ two
94+
@test X .^ 2 isa typeof(X) # special cased, as isstructurepreserving
95+
@test X .^ (2,) isa Ttri
96+
@test X .^ two isa Ttri
97+
@test X .^ 0 == fX .^ 0
98+
@test X .^ -1 == fX .^ -1
99+
100+
for (Y, fY) in zip(unittriangulars, funittriangulars)
101+
@test broadcast(+, X, Y) == broadcast(+, fX, fY)
102+
@test broadcast!(+, Z, X, Y) == broadcast(+, fX, fY)
103+
@test broadcast(*, X, Y) == broadcast(*, fX, fY)
104+
@test broadcast!(*, Z, X, Y) == broadcast(*, fX, fY)
105+
end
105106
end
106-
end
107107

108-
@testset "type-stability in Bidiagonal" begin
109-
B2 = @inferred (B -> .- B)(B)
110-
@test B2 isa Bidiagonal
111-
@test B2 == -1 * B
112-
B2 = @inferred (B -> B .* 2)(B)
113-
@test B2 isa Bidiagonal
114-
@test B2 == B + B
115-
B2 = @inferred (B -> 2 .* B)(B)
116-
@test B2 isa Bidiagonal
117-
@test B2 == B + B
118-
B2 = @inferred (B -> B ./ 1)(B)
119-
@test B2 isa Bidiagonal
120-
@test B2 == B
121-
B2 = @inferred (B -> 1 .\ B)(B)
122-
@test B2 isa Bidiagonal
123-
@test B2 == B
108+
@testset "type-stability in Bidiagonal" begin
109+
B2 = @inferred (B -> .- B)(B)
110+
@test B2 isa Bidiagonal
111+
@test B2 == -1 * B
112+
B2 = @inferred (B -> B .* 2)(B)
113+
@test B2 isa Bidiagonal
114+
@test B2 == B + B
115+
B2 = @inferred (B -> 2 .* B)(B)
116+
@test B2 isa Bidiagonal
117+
@test B2 == B + B
118+
B2 = @inferred (B -> B ./ 1)(B)
119+
@test B2 isa Bidiagonal
120+
@test B2 == B
121+
B2 = @inferred (B -> 1 .\ B)(B)
122+
@test B2 isa Bidiagonal
123+
@test B2 == B
124+
end
124125
end
125126
end
126127

127128
@testset "broadcast! where the destination is a structured matrix" begin
128-
N = 5
129-
A = rand(N, N)
130-
sA = A + copy(A')
131-
D = Diagonal(rand(N))
132-
Bu = Bidiagonal(rand(N), rand(N - 1), :U)
133-
Bl = Bidiagonal(rand(N), rand(N - 1), :L)
134-
T = Tridiagonal(rand(N - 1), rand(N), rand(N - 1))
135-
= LowerTriangular(rand(N,N))
136-
= UpperTriangular(rand(N,N))
137-
M = Matrix(rand(N,N))
138-
139-
@test broadcast!(sin, copy(D), D) == Diagonal(sin.(D))
140-
@test broadcast!(sin, copy(Bu), Bu) == Bidiagonal(sin.(Bu), :U)
141-
@test broadcast!(sin, copy(Bl), Bl) == Bidiagonal(sin.(Bl), :L)
142-
@test broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T))
143-
@test broadcast!(sin, copy(◣), ◣) == LowerTriangular(sin.(◣))
144-
@test broadcast!(sin, copy(◥), ◥) == UpperTriangular(sin.(◥))
145-
@test broadcast!(sin, copy(M), M) == Matrix(sin.(M))
146-
@test broadcast!(*, copy(D), D, A) == Diagonal(broadcast(*, D, A))
147-
@test broadcast!(*, copy(Bu), Bu, A) == Bidiagonal(broadcast(*, Bu, A), :U)
148-
@test broadcast!(*, copy(Bl), Bl, A) == Bidiagonal(broadcast(*, Bl, A), :L)
149-
@test broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A))
150-
@test broadcast!(*, copy(◣), ◣, A) == LowerTriangular(broadcast(*, ◣, A))
151-
@test broadcast!(*, copy(◥), ◥, A) == UpperTriangular(broadcast(*, ◥, A))
152-
@test broadcast!(*, copy(M), M, A) == Matrix(broadcast(*, M, A))
153-
154-
@test_throws ArgumentError broadcast!(cos, copy(D), D) == Diagonal(sin.(D))
155-
@test_throws ArgumentError broadcast!(cos, copy(Bu), Bu) == Bidiagonal(sin.(Bu), :U)
156-
@test_throws ArgumentError broadcast!(cos, copy(Bl), Bl) == Bidiagonal(sin.(Bl), :L)
157-
@test_throws ArgumentError broadcast!(cos, copy(T), T) == Tridiagonal(sin.(T))
158-
@test_throws ArgumentError broadcast!(cos, copy(◣), ◣) == LowerTriangular(sin.(◣))
159-
@test_throws ArgumentError broadcast!(cos, copy(◥), ◥) == UpperTriangular(sin.(◥))
160-
@test_throws ArgumentError broadcast!(+, copy(D), D, A) == Diagonal(broadcast(*, D, A))
161-
@test_throws ArgumentError broadcast!(+, copy(Bu), Bu, A) == Bidiagonal(broadcast(*, Bu, A), :U)
162-
@test_throws ArgumentError broadcast!(+, copy(Bl), Bl, A) == Bidiagonal(broadcast(*, Bl, A), :L)
163-
@test_throws ArgumentError broadcast!(+, copy(T), T, A) == Tridiagonal(broadcast(*, T, A))
164-
@test_throws ArgumentError broadcast!(+, copy(◣), ◣, A) == LowerTriangular(broadcast(*, ◣, A))
165-
@test_throws ArgumentError broadcast!(+, copy(◥), ◥, A) == UpperTriangular(broadcast(*, ◥, A))
166-
@test_throws ArgumentError broadcast!(*, copy(◥), ◣, 2)
167-
@test_throws ArgumentError broadcast!(*, copy(Bu), Bl, 2)
129+
@testset for N in (0,1,2,5)
130+
A = rand(N, N)
131+
sA = A + copy(A')
132+
D = Diagonal(rand(N))
133+
Bu = Bidiagonal(rand(N), rand(max(0,N-1)), :U)
134+
Bl = Bidiagonal(rand(N), rand(max(0,N-1)), :L)
135+
T = Tridiagonal(rand(max(0,N-1)), rand(N), rand(max(0,N-1)))
136+
= LowerTriangular(rand(N,N))
137+
= UpperTriangular(rand(N,N))
138+
M = Matrix(rand(N,N))
139+
140+
@test broadcast!(sin, copy(D), D) == Diagonal(sin.(D))
141+
@test broadcast!(sin, copy(Bu), Bu) == Bidiagonal(sin.(Bu), :U)
142+
@test broadcast!(sin, copy(Bl), Bl) == Bidiagonal(sin.(Bl), :L)
143+
@test broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T))
144+
@test broadcast!(sin, copy(◣), ◣) == LowerTriangular(sin.(◣))
145+
@test broadcast!(sin, copy(◥), ◥) == UpperTriangular(sin.(◥))
146+
@test broadcast!(sin, copy(M), M) == Matrix(sin.(M))
147+
@test broadcast!(*, copy(D), D, A) == Diagonal(broadcast(*, D, A))
148+
@test broadcast!(*, copy(Bu), Bu, A) == Bidiagonal(broadcast(*, Bu, A), :U)
149+
@test broadcast!(*, copy(Bl), Bl, A) == Bidiagonal(broadcast(*, Bl, A), :L)
150+
@test broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A))
151+
@test broadcast!(*, copy(◣), ◣, A) == LowerTriangular(broadcast(*, ◣, A))
152+
@test broadcast!(*, copy(◥), ◥, A) == UpperTriangular(broadcast(*, ◥, A))
153+
@test broadcast!(*, copy(M), M, A) == Matrix(broadcast(*, M, A))
154+
155+
if N > 2
156+
@test_throws ArgumentError broadcast!(cos, copy(D), D)
157+
@test_throws ArgumentError broadcast!(cos, copy(Bu), Bu)
158+
@test_throws ArgumentError broadcast!(cos, copy(Bl), Bl)
159+
@test_throws ArgumentError broadcast!(cos, copy(T), T)
160+
@test_throws ArgumentError broadcast!(cos, copy(◣), ◣)
161+
@test_throws ArgumentError broadcast!(cos, copy(◥), ◥)
162+
@test_throws ArgumentError broadcast!(+, copy(D), D, A)
163+
@test_throws ArgumentError broadcast!(+, copy(Bu), Bu, A)
164+
@test_throws ArgumentError broadcast!(+, copy(Bl), Bl, A)
165+
@test_throws ArgumentError broadcast!(+, copy(T), T, A)
166+
@test_throws ArgumentError broadcast!(+, copy(◣), ◣, A)
167+
@test_throws ArgumentError broadcast!(+, copy(◥), ◥, A)
168+
@test_throws ArgumentError broadcast!(*, copy(◥), ◣, 2)
169+
@test_throws ArgumentError broadcast!(*, copy(Bu), Bl, 2)
170+
end
171+
end
168172
end
169173

170174
@testset "map[!] over combinations of structured matrices" begin

0 commit comments

Comments
 (0)