Skip to content

Instantly share code, notes, and snippets.

@davidagold
Created July 7, 2016 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidagold/d7088aae22f23d383e5bf1f26aa1a045 to your computer and use it in GitHub Desktop.
Save davidagold/d7088aae22f23d383e5bf1f26aa1a045 to your computer and use it in GitHub Desktop.
macro fcall(Xs, nargs)
res = Expr(:call, :f)
for i in 1:nargs
push!(res.args, :($(Xs)[$i][i]))
end
return res
end
mymap(f, Xs...) = _map(f, Xs...)
@generated function _map{N}(f, Xs::Vararg{Array, N})
return quote
shp = size(zip(Xs...))
len = prod(shp)
i = 1
i <= len || return similar(Xs[1], Base.return_types(f, tuple([ eltype(X) for X in Xs ])))
v = @fcall Xs $N
dest = similar(Xs[1], typeof(v))
dest[i] = v
map_to!(f, dest, Xs, i+1, len)
end
end
@generated function map_to!{T, N}(f, dest::Array{T}, Xs::Tuple{Vararg{Array, N}}, offs, len)
return quote
i = offs
while i <= len
@inbounds el = @fcall Xs $N
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
i += 1
else
R = typejoin(T, S)
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, Xs, i+1, len)
end
end
return dest
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment