Help with converting array to Static Array

I wish to speed up my datastructure by converting array type to Static Array but I encounter an error. What did I do wrong?

using StaticArrays

datetype = Array{Int64,1}
datestatictype = SVector{3,Int64}

function printdate(x::datetype)
    println("year ",x[1]," month ",x[2]," day ",x[3])
end

function printdatestatic(x::datestatictype)
    println("year ",x[1]," month ",x[2]," day ",x[3])
end

a = Int64[2019,5,6]
printdate(a)

b = SVector{3,Int64}[2019,5,6]
printdatestatic(b)

with output

   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-01-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

year 2019 month 5 day 6
ERROR: LoadError: MethodError: Cannot `convert` an object of type Int64 to an object of type SArray{Tuple{3},Int64,1,3}
Closest candidates are:
  convert(::Type{SA<:StaticArray}, ::SA<:StaticArray) where SA<:StaticArray at /Users/ssiew/.julia/packages/StaticArrays/VyRz3/src/convert.jl:11
  convert(::Type{SA<:StaticArray}, ::StaticArray) where SA<:StaticArray at /Users/ssiew/.julia/packages/StaticArrays/VyRz3/src/convert.jl:10
  convert(::Type{SA<:StaticArray}, ::AbstractArray) where SA<:StaticArray at /Users/ssiew/.julia/packages/StaticArrays/VyRz3/src/convert.jl:22
  ...
Stacktrace:
 [1] setindex!(::Array{SArray{Tuple{3},Int64,1,3},1}, ::Int64, ::Int64) at ./array.jl:767
 [2] getindex(::Type{SArray{Tuple{3},Int64,1,3}}, ::Int64, ::Int64, ::Int64) at ./array.jl:353
 [3] top-level scope at none:0
in expression starting at /Users/ssiew/juliascript/StaticArrayTest.jl:17

You missed the parenthesis b = SVector{3,Int64}([2019,5,6]). Without that, it tries to construct an array of Svectors so the error.

3 Likes

Note that you can also do

julia> b = @SVector [2019,5,6]
3-element SArray{Tuple{3},Int64,1,3} with indices SOneTo(3):
 2019
    5
    6

julia> @macroexpand @SVector [2019,5,6]
:((SArray{Tuple{3},T,1,3} where T)((2019, 5, 6)))

This macro avoids creating any temporaries and is type stable. Therefore it should be fast on top of convenient.

4 Likes

Don’t use [] here. Then you are making a vector and then converting it. Write

SVector{3}(2019, 5, 6)

or use the macro.

Edit: Actually, simply SVector(2019, 5, 6) will do.

4 Likes

You are of course right given the context, but all of the constructors

SVector{N,T}(vec)
SVector{T}(args...)
SVector(args...)
@SVector [args...]

are useful depending on the format of the input arguments, and whether the type is known or is meant to be figured out using promotion, and whether N is meant to be enforced/checked.

1 Like

Agreed, but since the poster was uncertain how to create SVectors in general, I considered it useful to mention the most obvious constructor.

2 Likes