Hi, I’m looking to calculate nested functions of form f(g(h(...k(x)...)) and have written a function that takes in two arguments. One is called chain which is the vector of Function defined in the order of their calculation and the input array x.
function chain_cal(chain:: Vector{Function}, x:: CuArray)
n = size(chain)[1]
for i in 1:n
x = chain[i](x)
end
return x
end
I defined a variable chain with two functions named square
chain = Vector([square, square])
2-element Array{typeof(square),1}:
square (generic function with 1 method)
square (generic function with 1 method)
and when I run chain_cal, I get an error as follows
chain_cal(chain, x)
MethodError: no method matching chain_cal(::Array{typeof(square),1}, ::CuArray{Int64,1})
Closest candidates are:
chain_cal(!Matched::Array{Array{Function,1},1}, ::CuArray) at In[16]:1
chain_cal(!Matched::Array{Function,1}, ::CuArray) at In[31]:1
Stacktrace:
[1] top-level scope at In[35]:1
[2] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091
Is there a way where I can modify chain_cal such that it accepts all functions or do I have to modify my earlier defined square function such that it’s type is Function?
#=
Square each element in the input CUDA Array
=#
function square(x:: CuArray)
return x.^2
end
Creating a unique type for every function allows the compiler to specialize higher-order functions (e.g. map) based on the types of their function arguments. You pass an anonymous function to map and it may be inlined inside map.
For a different implementation you could also use ∘ (though I haven’t worked with CuArrays, maybe there’s something special about them that interferes?)
We can also chain scalar functions and make a broadcast call on the result:
chain = [x->x^2, sqrt, inv]; # These functions don't work on vectors...
julia> ∘(chain...).(x) # but we can use a broadcast call
3-element Array{Float64,1}:
1.0
0.5000000000000001
0.3333333333333333