Hi,
I would like to ask for help generalizing the following construction that uses Base.Cartesian
for automatic creation of loops. First, the particular case n=8
:
@macroexpand begin
@inbounds for i_8 in eachindex(v[8])
@nloops 7 i i -> eachindex(v[i]) d -> d == 1 ? nothing : d == 7 ? cache[d-1] = v[i_{d}, d] * v[i_{d+1}, d+1] : cache[d-1] = cache[d] * v[i_{d}, d] begin (@nref 8 A i) = v[i_1, 1] * cache[1] end
end
end
quote # In[51], line 2:
begin
$(Expr(:inbounds, true))
for i_8 = eachindex(v[8]) # In[51], line 3:
begin # cartesian.jl, line 62:
for i_7 = eachindex(v[7]) # cartesian.jl, line 63:
cache[6] = v[i_7, 7] * v[i_8, 8] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_6 = eachindex(v[6]) # cartesian.jl, line 63:
cache[5] = cache[6] * v[i_6, 6] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_5 = eachindex(v[5]) # cartesian.jl, line 63:
cache[4] = cache[5] * v[i_5, 5] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_4 = eachindex(v[4]) # cartesian.jl, line 63:
cache[3] = cache[4] * v[i_4, 4] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_3 = eachindex(v[3]) # cartesian.jl, line 63:
cache[2] = cache[3] * v[i_3, 3] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_2 = eachindex(v[2]) # cartesian.jl, line 63:
cache[1] = cache[2] * v[i_2, 2] # cartesian.jl, line 64:
begin # cartesian.jl, line 62:
for i_1 = eachindex(v[1]) # cartesian.jl, line 63:
nothing # cartesian.jl, line 64:
begin # In[51], line 3:
A[i_1, i_2, i_3, i_4, i_5, i_6, i_7, i_8] = v[i_1, 1] * cache[1]
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end # cartesian.jl, line 65:
nothing
end
end
end
$(Expr(:inbounds, :pop))
end
end
My attempt for generalization to n
dimensions inside a function is to use @generated
(as suggested in the docs),
@generated function y(A, v::VectorOfArray)
quote
n = length(v)
cache = Vector{Float64}($n-2)
@inbounds for i_{$n} in eachindex(v[$n])
@nloops ($n-1) i i -> eachindex(v[i]) d -> d == 1 ? nothing : d == $n-1 ? cache[d-1] = v[i_{d}, d] * v[i_{d+1}, d+1] : cache[d-1] = cache[d] * v[i_{d}, d] begin (@nref $n A i) = v[i_1, 1] * cache[1] end
end
end
end
Test:
t = [1.0, 1.5, 2.22222, 3.25, 4.69048, 6.67857, 9.38095, 13.0, 17.7778, 24.0, 32.0]
v = VectorOfArray([t for i in 1:8])
A = Array{Float64}(11,11,11,11,11,11,11,11);
F = y(A, v);
MethodError: no method matching _nloops(::Expr, ::Symbol, ::Expr, ::Expr, ::Expr)
Closest candidates are:
_nloops(::Int64, ::Symbol, ::Expr, ::Expr...) at cartesian.jl:48
_nloops(::Int64, ::Symbol, ::Symbol, ::Expr...) at cartesian.jl:43