And here’s a simpler solution based on @Tortar’s idea:
struct Foo{T}
a :: T
b :: T
end
foos = (Foo(1,2), Foo(3.0,4.0))
I = zeros(Int, (100,200,300));
@. I[1:50,:,:] = 1;
@. I[51:100,:,:] = 2;
case_expr(idx, n) = idx == n ?
:(foos[$idx]) :
:(i == $idx ? foos[$idx] : $(case_expr(idx+1, n)))
@generated getfoo(foos, i) = case_expr(1, fieldcount(foos))
function bar(foos, I)
s = 0.0
@inbounds for i in eachindex(I)
s += getfoo(foos, I[i]).a
end
return s
end
julia> @btime bar($foos, $I)
5.696 ms (0 allocations: 0 bytes)
(I’m wary about generated functions due to the possible undefined behavior but it seems safe here.)