Vector in 3 space

I’m trying to define a vector in 3 dimensional space for a geometry application.

I can define

const Vec3 = Array{Number, 3}

Vec3(x::Number, y::Number, z::Number) = Array{Number, 3}(x, y, z)

in the REPL and call Vec3 to construct a Vec3, but if I put these definitions in a file and include it, when I try to construct a Vec3 I get a stack overflow

julia
include("src/vector_utils.jl")
distance (generic function with 1 method)
Vec3(1,2,3)
ERROR: StackOverflowError:
Stacktrace:
 [1] Array{Number, 3}(x::Int64, y::Int64, z::Int64) (repeats 79984 times)
   @ Main ~\.julia\dev\Tangle\src\vector_utils.jl:6

What’s up with that?

Oops. Looks likeI accidentally lost some text. To be clear, if the type alias and constructor are defined in the REPL the constructor works as expected, but if the definitions are loaded from a file then I get a strack overflow when calling the constructor.

I’m pretty sure that if you say const Vec3 = Array{Number, 3}, then that is a type alias and so your second line then expands to Array{Number, 3}(x, y, z) = Array{Number, 3}(x, y, z), which will definitely cause a stack overflow.

As an aside, by the way, if you want specific three-vectors, you might look at StaticArrays.jl. Your current type annotation of 3 refers to the dimension of the array, not the length of it like I would guess you expect it to be doing.

3 Likes

This definition means that your alias is an array with 3 dimensions, meaning it’s a cuboid, not a vector. It has N*M*K elements (N, M and K being the size in each dimension), not 3. The second type parameter of Array is the number of dimensions, not the number of elements or the size in each dimension.

2 Likes

I’m seeing a stack overflow error when starting from a fresh REPL session. Let’s put that aside for a minute, though - I don’t think your type definition is doing what you think it’s doing. The first parameter in to the Array constructor is the eltype, and if you set that to Number, the array will be able to hold any combination of Number elements, which makes life difficult for the compiler (and leads to slow code):

julia> Number[1, 2.0, π]
3-element Vector{Number}:
 1
 2.0
 π = 3.1415926535897...

julia> eltype.(ans)
3-element Vector{DataType}:
 Int64
 Float64
 Irrational{:π}

The second parameter is the dimension of the array, not the length, as mentioned above. Besides StaticArrays, you may also want to check out Meshes.jl, which provides several useful types (and associated methods) for geometry applications: Vectors · Meshes.jl

1 Like

Independently of that particular syntax problem, use static arrays:

julia> using StaticArrays

julia> x = SVector{3,Float64}(1,2,3)
3-element SVector{3, Float64} with indices SOneTo(3):
 1.0
 2.0
 3.0

#or
julia> struct Vec3{T} <: FieldVector{3,T}
         x::T
         y::T
         z::T
       end

julia> x = Vec3{Float64}(1,2,3)
3-element Vec3{Float64} with indices SOneTo(3):
 1.0
 2.0
 3.0

julia> x[1]
1.0

julia> x.x
1.0



5 Likes

Thanks everyone.

Now that I try it again, I also get a stack overflow when Vec3 is defined in a REPL. I’m not going to bother to investigate the context in which this occurred several times:

Vec3(2, 2, 2)
3-element Vec3 with indices SOneTo(3):
 2
 2
 2

Regarding my 3 dimesnional array versus 3 element vector confusion, I thought I saw parameterized type syntax of the form Array{elementtype, dims…} but I can’t find that now.

Thank you for referring me to StaticArrays.FieldVector. That is doing what I want.