Skip to content

Commit dbd5111

Browse files
authored
Merge pull request JuliaArrays#196 from bshall/broadcast-fix
Fix broadcast issue
2 parents 4ab61ef + 8eb2868 commit dbd5111

File tree

3 files changed

+146
-36
lines changed

3 files changed

+146
-36
lines changed

src/broadcast.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ end
1212
_broadcast(f, (Size(), Size(x)), T, x)
1313
end
1414

15-
@inline broadcast_sizes(a...) = _broadcast_sizes((), a...)
16-
@inline _broadcast_sizes(t::Tuple) = t
17-
@inline _broadcast_sizes(t::Tuple, a::StaticArray, as...) = _broadcast_sizes((t..., Size(a)), as...)
18-
@inline _broadcast_sizes(t::Tuple, a::Number, as...) = _broadcast_sizes((t..., Size()), as...)
15+
@inline broadcast_sizes(a::StaticArray, as...) = (Size(a), broadcast_sizes(as...)...)
16+
@inline broadcast_sizes(a::Number, as...) = (Size(), broadcast_sizes(as...)...)
17+
@inline broadcast_sizes() = ()
1918

2019
function broadcasted_index(oldsize, newindex)
2120
index = ones(Int, length(oldsize))
@@ -147,5 +146,6 @@ end
147146
return quote
148147
@_inline_meta
149148
@inbounds $(Expr(:block, exprs...))
149+
return dest
150150
end
151151
end

test/arraymath.jl

-32
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,4 @@
11
@testset "Array math" begin
2-
@testset "AbstractArray-of-StaticArray with scalar math" begin
3-
v = SVector{2,Float64}[SVector{2,Float64}(1,1)]
4-
@test @inferred(v .* 1.0)::typeof(v) == v
5-
@test @inferred(1 .- v)::typeof(v) == v .- v
6-
v2 = SVector{2,Int}[SVector{2,Int}(1,1)]
7-
@test @inferred(v2 .* 1.0)::typeof(v) == v
8-
end
9-
10-
@testset "Array-scalar math" begin
11-
m = @SMatrix [1 2; 3 4]
12-
13-
@test @inferred(m .+ 1) === @SMatrix [2 3; 4 5]
14-
@test @inferred(1 .+ m) === @SMatrix [2 3; 4 5]
15-
@test @inferred(m .* 2) === @SMatrix [2 4; 6 8]
16-
@test @inferred(2 .* m) === @SMatrix [2 4; 6 8]
17-
@test @inferred(m .- 1) === @SMatrix [0 1; 2 3]
18-
@test @inferred(1 .- m) === @SMatrix [0 -1; -2 -3]
19-
@test @inferred(m ./ 2) === @SMatrix [0.5 1.0; 1.5 2.0]
20-
@test @inferred(12 ./ m) === @SMatrix [12.0 6.0; 4.0 3.0]
21-
22-
end
23-
24-
@testset "Elementwise array math" begin
25-
m1 = @SMatrix [1 2; 3 4]
26-
m2 = @SMatrix [4 3; 2 1]
27-
28-
@test @inferred(m1 .+ m2) === @SMatrix [5 5; 5 5]
29-
@test @inferred(m1 .* m2) === @SMatrix [4 6; 6 4]
30-
@test @inferred(m1 .- m2) === @SMatrix [-3 -1; 1 3]
31-
@test @inferred(m1 ./ m2) === @SMatrix [0.25 2/3; 1.5 4.0]
32-
end
33-
342
@testset "zeros() and ones()" begin
353
@test @inferred(zeros(SVector{3,Float64})) === @SVector [0.0, 0.0, 0.0]
364
@test @inferred(zeros(SVector{3,Int})) === @SVector [0, 0, 0]

test/broadcast.jl

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
@testset "Broadcast sizes" begin
2+
@test @inferred(broadcast_sizes(1, 1, 1)) === (Size(), Size(), Size())
3+
for t in (SVector{2}, MVector{2}, SMatrix{2, 2}, MMatrix{2, 2})
4+
@test @inferred(broadcast_sizes(ones(t), ones(t), ones(t))) === (Size(t), Size(t), Size(t))
5+
@test @inferred(broadcast_sizes(ones(t), 1, ones(t))) === (Size(t), Size(), Size(t))
6+
@test @inferred(broadcast_sizes(1, ones(t), ones(t))) === (Size(), Size(t), Size(t))
7+
@test @inferred(broadcast_sizes(ones(t), ones(t), 1)) === (Size(t), Size(t), Size())
8+
@test @inferred(broadcast_sizes(1, ones(t), 1)) === (Size(), Size(t), Size())
9+
@test @inferred(broadcast_sizes(ones(t), 1, 1)) === (Size(t), Size(), Size())
10+
@test @inferred(broadcast_sizes(1, 1, ones(t))) === (Size(), Size(), Size(t))
11+
end
12+
# test case issue #191
13+
@test @inferred(broadcast((a, b, c) -> 0, SVector(1, 1), 0, 0)) == SVector(0, 0)
14+
end
15+
16+
@testset "Broadcast" begin
17+
@testset "AbstractArray-of-StaticArray with scalar math" begin
18+
v = SVector{2,Float64}[SVector{2,Float64}(1,1)]
19+
@test @inferred(v .* 1.0)::typeof(v) == v
20+
@test @inferred(1 .- v)::typeof(v) == v .- v
21+
v2 = SVector{2,Int}[SVector{2,Int}(1,1)]
22+
@test @inferred(v2 .* 1.0)::typeof(v) == v
23+
end
24+
25+
@testset "2x2 StaticMatrix with StaticVector" begin
26+
m = @SMatrix [1 2; 3 4]
27+
v = SVector(1, 4)
28+
@test @inferred(broadcast(+, m, v)) === @SMatrix [2 3; 7 8]
29+
@test @inferred(m .+ v) === @SMatrix [2 3; 7 8]
30+
@test @inferred(v .+ m) === @SMatrix [2 3; 7 8]
31+
@test @inferred(m .* v) === @SMatrix [1 2; 12 16]
32+
@test @inferred(v .* m) === @SMatrix [1 2; 12 16]
33+
@test @inferred(m ./ v) === @SMatrix [1 2; 3/4 1]
34+
@test @inferred(v ./ m) === @SMatrix [1 1/2; 4/3 1]
35+
@test @inferred(m .- v) === @SMatrix [0 1; -1 0]
36+
@test @inferred(v .- m) === @SMatrix [0 -1; 1 0]
37+
@test @inferred(m .^ v) === @SMatrix [1 2; 81 256]
38+
@test @inferred(v .^ m) === @SMatrix [1 1; 64 256]
39+
end
40+
41+
@testset "2x2 StaticMatrix with 1x2 StaticMatrix" begin
42+
m1 = @SMatrix [1 2; 3 4]
43+
m2 = @SMatrix [1 4]
44+
@test_broken @inferred(broadcast(+, m1, m2)) === @SMatrix [2 6; 4 8] #197
45+
@test_broken @inferred(m1 .+ m2) === @SMatrix [2 6; 4 8] #197
46+
@test @inferred(m2 .+ m1) === @SMatrix [2 6; 4 8]
47+
@test_broken @inferred(m1 .* m2) === @SMatrix [1 8; 3 16] #197
48+
@test @inferred(m2 .* m1) === @SMatrix [1 8; 3 16]
49+
@test_broken @inferred(m1 ./ m2) === @SMatrix [1 1/2; 3 1] #197
50+
@test @inferred(m2 ./ m1) === @SMatrix [1 2; 1/3 1]
51+
@test_broken @inferred(m1 .- m2) === @SMatrix [0 -2; 2 0] #197
52+
@test @inferred(m2 .- m1) === @SMatrix [0 2; -2 0]
53+
@test_broken @inferred(m1 .^ m2) === @SMatrix [1 16; 1 256] #197
54+
end
55+
56+
@testset "1x2 StaticMatrix with StaticVector" begin
57+
m = @SMatrix [1 2]
58+
v = SVector(1, 4)
59+
@test @inferred(broadcast(+, m, v)) === @SMatrix [2 3; 5 6]
60+
@test @inferred(m .+ v) === @SMatrix [2 3; 5 6]
61+
@test_broken @inferred(v .+ m) === @SMatrix [2 3; 5 6] #197
62+
@test @inferred(m .* v) === @SMatrix [1 2; 4 8]
63+
@test_broken @inferred(v .* m) === @SMatrix [1 2; 4 8] #197
64+
@test @inferred(m ./ v) === @SMatrix [1 2; 1/4 1/2]
65+
@test_broken @inferred(v ./ m) === @SMatrix [1 1/2; 4 2] #197
66+
@test @inferred(m .- v) === @SMatrix [0 1; -3 -2]
67+
@test_broken @inferred(v .- m) === @SMatrix [0 -1; 3 2] #197
68+
@test @inferred(m .^ v) === @SMatrix [1 2; 1 16]
69+
@test_broken @inferred(v .^ m) === @SMatrix [1 1; 4 16] #197
70+
end
71+
72+
@testset "StaticVector with StaticVector" begin
73+
v1 = SVector(1, 2)
74+
v2 = SVector(1, 4)
75+
@test @inferred(broadcast(+, v1, v2)) === SVector(2, 6)
76+
@test @inferred(v1 .+ v2) === SVector(2, 6)
77+
@test @inferred(v2 .+ v1) === SVector(2, 6)
78+
@test @inferred(v1 .* v2) === SVector(1, 8)
79+
@test @inferred(v2 .* v1) === SVector(1, 8)
80+
@test @inferred(v1 ./ v2) === SVector(1, 1/2)
81+
@test @inferred(v2 ./ v1) === SVector(1, 2/1)
82+
@test @inferred(v1 .- v2) === SVector(0, -2)
83+
@test @inferred(v2 .- v1) === SVector(0, 2)
84+
@test @inferred(v1 .^ v2) === SVector(1, 16)
85+
@test @inferred(v2 .^ v1) === SVector(1, 16)
86+
# test case issue #199
87+
@test @inferred(SVector(1) .+ SVector()) === SVector()
88+
@test_broken @inferred(SVector() .+ SVector(1)) === SVector()
89+
# test case issue #200
90+
@test_broken @inferred(v1 .+ v2') === @SMatrix [2 5; 3 5]
91+
end
92+
93+
@testset "StaticVector with Scalar" begin
94+
v = SVector(1, 2)
95+
@test @inferred(broadcast(+, v, 2)) === SVector(3, 4)
96+
@test @inferred(v .+ 2) === SVector(3, 4)
97+
@test @inferred(2 .+ v) === SVector(3, 4)
98+
@test @inferred(v .* 2) === SVector(2, 4)
99+
@test @inferred(2 .* v) === SVector(2, 4)
100+
@test @inferred(v ./ 2) === SVector(1/2, 1)
101+
@test @inferred(2 ./ v) === SVector(2, 1/1)
102+
@test @inferred(v .- 2) === SVector(-1, 0)
103+
@test @inferred(2 .- v) === SVector(1, 0)
104+
@test @inferred(v .^ 2) === SVector(1, 4)
105+
@test @inferred(2 .^ v) === SVector(2, 4)
106+
end
107+
108+
@testset "Mutating broadcast!" begin
109+
# No setindex! error
110+
A = eye(SMatrix{2, 2}); @test_throws ErrorException broadcast!(+, A, A, SVector(1, 4))
111+
A = eye(MMatrix{2, 2}); @test @inferred(broadcast!(+, A, A, SVector(1, 4))) == @MMatrix [2 1; 4 5]
112+
A = eye(MMatrix{2, 2}); @test @inferred(broadcast!(+, A, A, @SMatrix([1 4]))) == @MMatrix [2 4; 1 5]
113+
A = @MMatrix([1 0]); @test_throws DimensionMismatch broadcast!(+, A, A, SVector(1, 4))
114+
A = @MMatrix([1 0]); @test @inferred(broadcast!(+, A, A, @SMatrix([1 4]))) == @MMatrix [2 4]
115+
A = @MMatrix([1 0]); @test @inferred(broadcast!(+, A, A, 2)) == @MMatrix [3 2]
116+
end
117+
118+
@testset "eltype after broadcast" begin
119+
# test cases issue #198
120+
let a = SVector{4, Number}(2, 2.0, 4//2, 2+0im)
121+
@test_broken eltype(a + 2) == Number
122+
@test_broken eltype(a - 2) == Number
123+
@test_broken eltype(a * 2) == Number
124+
@test_broken eltype(a / 2) == Number
125+
end
126+
let a = SVector{3, Real}(2, 2.0, 4//2)
127+
@test_broken eltype(a + 2) == Real
128+
@test_broken eltype(a - 2) == Real
129+
@test_broken eltype(a * 2) == Real
130+
@test_broken eltype(a / 2) == Real
131+
end
132+
let a = SVector{3, Real}(2, 2.0, 4//2)
133+
@test_broken eltype(a + 2.0) == Float64
134+
@test_broken eltype(a - 2.0) == Float64
135+
@test_broken eltype(a * 2.0) == Float64
136+
@test_broken eltype(a / 2.0) == Float64
137+
end
138+
let a = broadcast(Float32, SVector(3, 4, 5))
139+
@test eltype(a) == Float32
140+
end
141+
end
142+
end

0 commit comments

Comments
 (0)