Skip to content

Commit c816ae2

Browse files
committed
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. (cherry picked from commit dccd6f8)
1 parent a7eea43 commit c816ae2

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
@@ -8,160 +8,164 @@ isdefined(Main, :SizedArrays) || @eval Main include(joinpath($(BASE_TEST_PATH),
88
using .Main.SizedArrays
99

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

105-
@testset "type-stability in Bidiagonal" begin
106-
B2 = @inferred (B -> .- B)(B)
107-
@test B2 isa Bidiagonal
108-
@test B2 == -1 * B
109-
B2 = @inferred (B -> B .* 2)(B)
110-
@test B2 isa Bidiagonal
111-
@test B2 == B + B
112-
B2 = @inferred (B -> 2 .* B)(B)
113-
@test B2 isa Bidiagonal
114-
@test B2 == B + B
115-
B2 = @inferred (B -> B ./ 1)(B)
116-
@test B2 isa Bidiagonal
117-
@test B2 == B
118-
B2 = @inferred (B -> 1 .\ B)(B)
119-
@test B2 isa Bidiagonal
120-
@test B2 == B
105+
@testset "type-stability in Bidiagonal" begin
106+
B2 = @inferred (B -> .- B)(B)
107+
@test B2 isa Bidiagonal
108+
@test B2 == -1 * B
109+
B2 = @inferred (B -> B .* 2)(B)
110+
@test B2 isa Bidiagonal
111+
@test B2 == B + B
112+
B2 = @inferred (B -> 2 .* B)(B)
113+
@test B2 isa Bidiagonal
114+
@test B2 == B + B
115+
B2 = @inferred (B -> B ./ 1)(B)
116+
@test B2 isa Bidiagonal
117+
@test B2 == B
118+
B2 = @inferred (B -> 1 .\ B)(B)
119+
@test B2 isa Bidiagonal
120+
@test B2 == B
121+
end
121122
end
122123
end
123124

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

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

0 commit comments

Comments
 (0)