Boolean short circuit "fusion"

I’ve wondered for a while whether it is possible to abuse the broadcast machinery to do something like this (basically to avoid materialize being called on the lazy broadcasted object). I’ve not found a nice way of doing it (i.e., a way that doesn’t obscure/muddy the semantics of dot broadcasting) but here is a not-so-nice way of doing it.

myany(x) = any(x)  # avoid piracy!
Broadcast.broadcasted(::typeof(myany), x) = myany(x)  # exploit the fact that the broadcasted object is iterable

On a simple test case this gives

julia> a = rand(10000) ; b = rand(10000) ; c = rand(10000) ;

julia> @btime any(($a .> 0.5) .& ($b .> 0.5) .& ($c .> 0.5))
  19.828 μs (3 allocations: 5.55 KiB)
true

julia> @btime myany.(($a .> 0.5) .& ($b .> 0.5) .& ($c .> 0.5))
  59.478 ns (10 allocations: 240 bytes)
true

So much faster than the original case but not as fast as the anonymous function or generator expression versions as mentioned above (and it allocates more).

julia> @btime any(((aa, bb, cc),) -> (aa > 0.5) && (bb > 0.5) && (cc > 0.5), zip($a, $b, $c))
  13.820 ns (2 allocations: 64 bytes)
true

julia> @btime any((aa > 0.5) && (bb > 0.5) && (cc > 0.5) for (aa, bb, cc) in zip($a, $b, $c))
  16.822 ns (3 allocations: 80 bytes)
true
3 Likes