Skip to content
This repository was archived by the owner on May 4, 2019. It is now read-only.

Commit ebca424

Browse files
committed
Fix performance without generated functions
1 parent 1190154 commit ebca424

File tree

1 file changed

+38
-44
lines changed

1 file changed

+38
-44
lines changed

src/broadcast.jl

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,29 @@ else
3131
using Base.Broadcast: ziptype
3232
end
3333

34-
@inline @generated function broadcast_lift{F, T}(f::F, x::NTuple{1, T})
35-
if null_safe_op(f.instance, eltype(T))
36-
return :( Nullable(f(unsafe_get(x[1])), !isnull(x[1])) )
34+
@inline function broadcast_lift(f, x)
35+
if null_safe_op(f, eltype(x))
36+
return @compat Nullable(f(unsafe_get(x)), !isnull(x))
3737
else
38-
U = Core.Inference.return_type(f.instance, Tuple{eltype(T)})
39-
return quote
40-
if isnull(x)
41-
return Nullable{$U}()
42-
else
43-
return Nullable(f(unsafe_get(x[1])))
44-
end
38+
U = Core.Inference.return_type(f, Tuple{eltype(x)})
39+
if isnull(x)
40+
return Nullable{U}()
41+
else
42+
return Nullable(f(unsafe_get(x)))
4543
end
4644
end
4745
end
4846

49-
@inline @generated function broadcast_lift{F, S, T}(f::F, x::Tuple{S, T})
50-
if null_safe_op(f.instance, eltype(S), eltype(T))
51-
return :( Nullable(f(unsafe_get(x[1]), unsafe_get(x[2])),
52-
!(isnull(x[1]) | isnull(x[2]))) )
47+
@inline function broadcast_lift(f, x1, x2)
48+
if null_safe_op(f, eltype(x1), eltype(x2))
49+
return @compat Nullable(f(unsafe_get(x1), unsafe_get(x2)),
50+
!(isnull(x1) | isnull(x2)))
5351
else
54-
U = Core.Inference.return_type(f.instance, Tuple{eltype(S), eltype(T)})
55-
return quote
56-
if isnull(x[1]) | isnull(x[2])
57-
return Nullable{$U}()
58-
else
59-
return Nullable(f(unsafe_get(x[1]), unsafe_get(x[2])))
60-
end
52+
U = Core.Inference.return_type(f, Tuple{eltype(x1), eltype(x2)})
53+
if isnull(x1) | isnull(x2)
54+
return Nullable{U}()
55+
else
56+
return Nullable(f(unsafe_get(x1), unsafe_get(x2)))
6157
end
6258
end
6359
end
@@ -67,27 +63,25 @@ eltypes(x) = Tuple{eltype(x)}
6763
eltypes(x, xs...) = Tuple{eltype(x), eltypes(xs...).parameters...}
6864

6965
"""
70-
broadcast_lift(f, x)
66+
broadcast_lift(f, xs...)
7167
72-
Lift function `f`, passing it arguments from the tuple `x`, using standard lifting semantics:
73-
for a function call `f(x...)`, return null if any `x` in `x` is null; otherwise,
74-
return `f` applied to values of `x`.
68+
Lift function `f`, passing it arguments `xs...`, using standard lifting semantics:
69+
for a function call `f(xs...)`, return null if any `x` in `xs` is null; otherwise,
70+
return `f` applied to values of `xs`.
7571
"""
76-
@inline @generated function broadcast_lift{F}(f::F, x::Tuple)
77-
if null_safe_op(f.instance, eltypes(x).parameters...)
72+
@inline function broadcast_lift(f, xs...)
73+
if null_safe_op(f, eltypes(xs).parameters...)
7874
# TODO: find a more efficient approach than mapreduce
7975
# (i.e. one which gets lowered to just isnull(x1) | isnull(x2) | ...)
80-
return :( Nullable(f(unsafe_get.(x)), !mapreduce(isnull, |, x)) )
76+
return @compat Nullable(f(unsafe_get.(xs)...), !mapreduce(isnull, |, xs))
8177
else
82-
U = Core.Inference.return_type(f.instance, eltypes(x))
83-
return quote
84-
# TODO: find a more efficient approach than mapreduce
85-
# (i.e. one which gets lowered to just isnull(x1) | isnull(x2) | ...)
86-
if mapreduce(isnull, |, x)
87-
return Nullable{$U}()
88-
else
89-
return Nullable(f(map(unsafe_get, x)...))
90-
end
78+
U = Core.Inference.return_type(f, eltypes(xs...))
79+
# TODO: find a more efficient approach than mapreduce
80+
# (i.e. one which gets lowered to just isnull(x1) | isnull(x2) | ...)
81+
if mapreduce(isnull, |, xs)
82+
return Nullable{U}()
83+
else
84+
return Nullable(f(map(unsafe_get, xs)...))
9185
end
9286
end
9387
end
@@ -109,9 +103,9 @@ of `broadcast` (i.e. without lifting).
109103
"""
110104
function Base.broadcast{F, N}(f::F, As::Vararg{NullableArray, N})
111105
# These definitions are needed to avoid allocation due to splatting
112-
f2(x1) = broadcast_lift(f, (x1,))
113-
f2(x1, x2) = broadcast_lift(f, (x1, x2))
114-
f2(x...) = broadcast_lift(f, x)
106+
f2(x1) = broadcast_lift(f, x1)
107+
f2(x1, x2) = broadcast_lift(f, x1, x2)
108+
f2(x...) = broadcast_lift(f, x...)
115109

116110
T = _default_eltype(Base.Generator{ziptype(As...), ftype(f2, As...)})
117111
if isleaftype(T) && !(T <: Nullable)
@@ -136,15 +130,15 @@ of `broadcast!` (i.e. without lifting).
136130
"""
137131
function Base.broadcast!{F, N}(f::F, dest::NullableArray, As::Vararg{NullableArray, N})
138132
# These definitions are needed to avoid allocation due to splatting
139-
f2(x1) = broadcast_lift(f, (x1,))
140-
f2(x1, x2) = broadcast_lift(f, (x1, x2))
141-
f2(x...) = broadcast_lift(f, x)
133+
f2(x1) = broadcast_lift(f, x1)
134+
f2(x1, x2) = broadcast_lift(f, x1, x2)
135+
f2(x...) = broadcast_lift(f, x...)
142136
call_broadcast(f2, dest, As...)
143137
end
144138

145139
# To fix ambiguity
146140
function Base.broadcast!{F}(f::F, dest::NullableArray)
147-
f2() = broadcast_lift(f, ())
141+
f2() = broadcast_lift(f)
148142
call_broadcast(f2, dest)
149143
end
150144

0 commit comments

Comments
 (0)