Loop Fusion usage between Arrays of custom structs

loops

#1

Hello,
Is possible to use the Loop Fusion between arrays of custom defined structures? For example:

struct point{T}
  x::T
  y::T
end

x = rand(100)
y = rand(100)

p = point{Array{Float64,1}}(x,y)

at this point I created a 100 elements array of points, and then i overload the + operator

Base.:+(a::Point{Float64}, b::Point{Float64}) = Point{Float64}(a.x+b.x , a.y+b.y)

then i defined another point and i tried to add it to every elements of array using .+ loop fusion operator

point_p = point{Float64}(1,1)
p_new .= p .+ point_p

and return the following error:

ERROR: LoadError: MethodError: no method matching length(::point{Array{Float64,1}})
Closest candidates are:
length(!Matched::Core.SimpleVector) at essentials.jl:582
length(!Matched::Base.MethodList) at reflection.jl:732
length(!Matched::Core.MethodTable) at reflection.jl:806

Is possible to overload the loop fusion . operator?


#2

First, what you create in p is a single point object, with 100 element x and y vectors. I don’t think this is what you want – you probably want a vector with 100 Point objects?

Second, unless I’m mistaken, to use the dot operators (broadcasting) with custom types, you need to wrap it in Ref in order to treat it as a scalar (or put it in a tuple or array). This was discussed at length in this topic.

This is how I would write your code:

struct Point{T}
  x::T
  y::T
end

points = [Point(rand(), rand()) for n = 1:5]

Base.:+(a::Point, b::Point) = Point(a.x+b.x , a.y+b.y)

point = Point(1, 1)

# these all give the same result, pick one:
points .+ Ref(point)
points .+ (point,)
points .+ [point] # note: extra allocation, slightly slower