How to add class information to a "view" of array?

I’m dealing with some problems with points in both Cartesian and Polar coordinates, I need to:

  1. convert between them
  2. map function into Array{CartesianPoint, 1} and Array{PolarPoint, 1}.
  3. load raw Array{Float32, 2} with shape (N, 3) from disk.

for 1, it would be much easier to deal with them with explicit defined struct than directly using a array with size (3).

struct CartesianPoint <: AbstractPoint
    x::Float32
    y::Float32
    z::Float32
end

struct PolarPoint <: AbstractPoint
    r::Float32
    θ::Float32
    z::Float32
end

Also this is necessary for multidispatch for functions with same name for these two different kind of AbstractPoint.

But for 2. it would be easier to use pure array to get lots of built-in function support, like (+),(-),norm, etc.
Since points are actually really close to vectors. Currently I had to write some wrap code like

+(a::CartesianPoint, b::CartesianPoint) = CartesianPoint(a.x+b.x, a.y+b.y, a.z+b.z)

It seems a bad style.

For 3, there is really a problem, boxing and unboxing these classes is time consuming, especially when I’m dealing with a large number of them. Loading a pure array is fast, but construct them into CartesianPoints need much longer time.

I’m wondering what’s the proper pattern for this kind of problem?

Can we use pure array for store, and create only a light-weight layer “view” of them, thus parse raw data into different class, for multidispatch only?

Use macros for operations that just pass through, eg see the code in SaferIntegers.jl and many other libraries. But I guess you would need to do something more complex for the polar points.

Incidentally, it is more idiomatic to generalize with a parametric type, eg

struct CartesianPoint{T} <: AbstractPoint{T}
    x::T
    y::T
    z::T
end

Use Mmap.mmap and/or reinterpret.

I am not sure what you want here.

Thanks for your reply, thanks for your advice, macros used to be too heavy for me, since I’ve never used Lisp-like languages. I need to learn it now.

For map function into array, I’m just trying:

f.(ps)

where ps is an array of CartesianPoint or PolarPoint.
The problem is that I need f act differently for array of CartesianPoint and PolarPoint, and need to use type for multidispatch, thus can not directly use a pure array.

The seems already solved by your suggested method.

You can try using StaticArrays FieldVector. A lot of the simple arithmetic is built in and you won’t have to repeat code.

You should define a Base.convert method to convert between the two types you define.

1 Like