Git Product home page Git Product logo

staticarrays.jl's Introduction

StaticArrays

Statically sized arrays for Julia

Stable Dev Build Status codecov.io Aqua QA deps version

StaticArrays provides a framework for implementing statically sized arrays in Julia, using the abstract type StaticArray{Size,T,N} <: AbstractArray{T,N}. Subtypes of StaticArray will provide fast implementations of common array and linear algebra operations. Note that here "statically sized" means that the size can be determined from the type, and "static" does not necessarily imply immutable.

The package also provides some concrete static array types: SVector, SMatrix and SArray, which may be used as-is (or else embedded in your own type). Mutable versions MVector, MMatrix and MArray are also exported, as well as SizedArray for annotating standard Arrays with static size information. Further, the abstract FieldVector can be used to make fast StaticVectors out of any uniform Julia "struct". Full documentation can be found here.

Most of the primary array types exported by StaticArrays.jl are defined in the small interface package StaticArraysCore.jl. This includes e.g., the definitions of the abstract type StaticArray and the concrete types SArray, MArray, and SizedArray (as well as their dimension-specific aliases). This enables downstream packages to implement new methods for these types without depending on (and hence loading) the entirety of StaticArrays.jl, and thereby to avoid incurring the full load-time of StaticArrays.jl (which is on the order of 0.6 s for StaticArrays.jl v1.4 on Julia v1.7).

Speed

The speed of small SVectors, SMatrixs and SArrays is often > 10 × faster than Base.Array. For example, here's a microbenchmark showing some common operations.

============================================
    Benchmarks for 3×3 Float64 matrices
============================================
Matrix multiplication               -> 5.9x speedup
Matrix multiplication (mutating)    -> 1.8x speedup
Matrix addition                     -> 33.1x speedup
Matrix addition (mutating)          -> 2.5x speedup
Matrix determinant                  -> 112.9x speedup
Matrix inverse                      -> 67.8x speedup
Matrix symmetric eigendecomposition -> 25.0x speedup
Matrix Cholesky decomposition       -> 8.8x speedup
Matrix LU decomposition             -> 6.1x speedup
Matrix QR decomposition             -> 65.0x speedup

These numbers were generated on an Intel i7-7700HQ using Julia-1.2. As with all synthetic benchmarks, the speedups you see here should only be taken as very roughly indicative of the speedup you may see in real code. When in doubt, benchmark your real application!

Note that in the current implementation, working with large StaticArrays puts a lot of stress on the compiler, and becomes slower than Base.Array as the size increases. A very rough rule of thumb is that you should consider using a normal Array for arrays larger than 100 elements.

Quick start

Add StaticArrays from the Pkg REPL, i.e., pkg> add StaticArrays. Then:

using LinearAlgebra
using StaticArrays

# Use the convenience constructor type `SA` to create vectors and matrices
SA[1, 2, 3]      isa SVector{3,Int}
SA_F64[1, 2, 3]  isa SVector{3,Float64}
SA_F32[1, 2, 3]  isa SVector{3,Float32}
SA[1 2; 3 4]     isa SMatrix{2,2,Int}
SA_F64[1 2; 3 4] isa SMatrix{2,2,Float64}

# Create an SVector using various forms, using constructors, functions or macros
v1 = SVector(1, 2, 3)
v1.data === (1, 2, 3) # SVector uses a tuple for internal storage
v2 = SVector{3,Float64}(1, 2, 3) # length 3, eltype Float64
v3 = @SVector [1, 2, 3]
v4 = @SVector [i^2 for i = 1:10] # arbitrary comprehensions (range is evaluated at global scope)
v5 = zeros(SVector{3}) # defaults to Float64
v6 = @SVector zeros(3)
v7 = SVector{3}([1, 2, 3]) # Array conversions must specify size

# Can get size() from instance or type
size(v1) == (3,)
size(typeof(v1)) == (3,)

# Similar constructor syntax for matrices
m1 = SMatrix{2,2}(1, 2, 3, 4) # flat, column-major storage, equal to m2:
m2 = @SMatrix [ 1  3 ;
                2  4 ]
m3 = SMatrix{3,3}(1I)
m4 = @SMatrix randn(4,4)
m5 = SMatrix{2,2}([1 3 ; 2 4]) # Array conversions must specify size

# Higher-dimensional support
a = @SArray randn(2, 2, 2, 2, 2, 2)

# Supports all the common operations of AbstractArray
v7 = v1 + v2
v8 = sin.(v3)
v3 == m3 * v3 # recall that m3 = SMatrix{3,3}(1I)
# map, reduce, broadcast, map!, broadcast!, etc...

# Indexing can also be done using static arrays of integers
v1[1] === 1
v1[SVector(3,2,1)] === @SVector [3, 2, 1]
v1[:] === v1
typeof(v1[[1,2,3]]) <: Vector # Can't determine size from the type of [1,2,3]

# Is (partially) hooked into BLAS, LAPACK, etc:
rand(MMatrix{20,20}) * rand(MMatrix{20,20}) # large matrices can use BLAS
eigen(m3) # eigen(), etc uses specialized algorithms up to 3×3, or else LAPACK

# Static arrays stay statically sized, even when used by Base functions, etc:
typeof(eigen(m3).vectors) == SMatrix{3,3,Float64,9}
typeof(eigen(m3).values) == SVector{3,Float64}

# similar() returns a mutable container, while similar_type() returns a constructor:
typeof(similar(m3)) == MArray{Tuple{3,3},Int64,2,9} # (final parameter is length = 9)
similar_type(m3) == SArray{Tuple{3,3},Int64,2,9}

# The Size trait is a compile-time constant representing the size
Size(m3) === Size(3,3)

# A standard Array can be wrapped into a SizedArray
m4 = SizedMatrix{3,3}(rand(3,3))
inv(m4) # Take advantage of specialized fast methods

# reshape() uses Size() or types to specify size:
reshape([1,2,3,4], Size(2,2)) == @SMatrix [ 1  3 ;
                                            2  4 ]
typeof(reshape([1,2,3,4], Size(2,2))) === SizedArray{Tuple{2, 2},Int64,2,1}

Approach

The package provides a range of different useful built-in StaticArray types, which include mutable and immutable arrays based upon tuples, arrays based upon structs, and wrappers of Array. There is a relatively simple interface for creating your own, custom StaticArray types, too.

This package also provides methods for a wide range of AbstractArray functions, specialized for (potentially immutable) StaticArrays. Many of Julia's built-in method definitions inherently assume mutability, and further performance optimizations may be made when the size of the array is known to the compiler. One example of this is by loop unrolling, which has a substantial effect on small arrays and tends to automatically trigger LLVM's SIMD optimizations. Another way performance is boosted is by providing specialized methods for det, inv, eigen and cholesky where the algorithm depends on the precise dimensions of the input. In combination with intelligent fallbacks to the methods in Base, we seek to provide a comprehensive support for statically sized arrays, large or small, that hopefully "just works".

staticarrays.jl's People

Contributors

andreasnoack avatar andyferris avatar avik-pal avatar bshall avatar c42f avatar cfbaptista avatar chriselrod avatar denius avatar fredrikekre avatar hyrodium avatar jishnub avatar jw3126 avatar kshyatt avatar marius311 avatar martinholters avatar mateuszbaran avatar mschauer avatar n5n3 avatar pablosanjose avatar rdeits avatar schmrlng avatar simonbyrne avatar simondanisch avatar thchr avatar timholy avatar tkf avatar tkoolen avatar tpapp avatar tsurherman avatar wsshin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

staticarrays.jl's Issues

zeros function: inconsistent output type

I'll be reporting a bunch of issues I found while switching over some of my code from FixedSizeArrays to StaticArrays. Here's the first.

Consider the following use of zeros:

x = zeros(SMatrix{3, 1, Float64})
zeros(x)

Currently, the output is:

3×1 StaticArrays.MMatrix{3,1,Float64,3}:
 0.0
 0.0
 0.0

I would expect the output to be of type SMatrix, not MMatrix.

Promotion with SArray * Number

This behavior is different between SVectors and base arrays (different resulting element type):

julia> 3.0 * rand(SVector{3, Float32})
3-element StaticArrays.SVector{3,Float64}:
 1.7314  
 0.394485
 0.566248

julia> 3.0 * rand(Float32, 3)
3-element Array{Float32,1}:
 1.5532  
 0.506801
 1.7563  

It is a bit annoying because it will promote the array when you multiply with a literal. In base they use promote_array_type it seems.

Many ambiguities

While it's not necessary to fix these unless they cause errors, this is a bit concerning:

julia> using StaticArrays

julia> Base.Test.detect_ambiguities(StaticArrays, Base, Core)
Skipping StaticArrays.MutableFieldVector
Skipping Base.<|
Skipping Base.>:
Skipping Base.cluster_manager
17-element Array{Tuple{Method,Method},1}:
 (+(a::Number, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:19,+(x::Bool, A::AbstractArray{Bool,N<:Any}) at arraymath.jl:91)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 (-(a::StaticArrays.StaticArray, b::AbstractArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:16,-(x::Union{Base.ReshapedArray{T<:Any,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{T<:Any,1},SubArray{T<:Any,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::AbstractSparseArray{Tv<:Any,Ti<:Any,1}) at sparse/sparsevector.jl:1184)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 (.*(a1::Number, a2::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/arraymath.jl:19,.*{P<:Base.Dates.Period}(y::Real, X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at dates/periods.jl:91)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
 (+(a::StaticArrays.StaticArray, b::AbstractArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:12,+{P<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period},Q<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period}}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, Y::Union{Base.ReshapedArray{Q,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Q,N<:Any},SubArray{Q,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at dates/periods.jl:338)
 (.*(a1::StaticArrays.StaticArray, a2::Number) at /home/tim/.julia/v0.6/StaticArrays/src/arraymath.jl:14,.*{P<:Base.Dates.Period}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::Real) at dates/periods.jl:101)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
 (+(a::StaticArrays.StaticArray, b::Number) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:20,+(A::AbstractArray{Bool,N<:Any}, x::Bool) at arraymath.jl:90)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 (-(a::AbstractArray, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:15,-{P<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period},Q<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period}}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, Y::Union{Base.ReshapedArray{Q,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Q,N<:Any},SubArray{Q,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at dates/periods.jl:338)
 (-(a::AbstractArray, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:15,-(x::AbstractSparseArray{Tv<:Any,Ti<:Any,1}, y::Union{Base.ReshapedArray{T<:Any,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{T<:Any,1},SubArray{T<:Any,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at sparse/sparsevector.jl:1185)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 (+(a::AbstractArray, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:11,+(x::AbstractSparseArray{Tv<:Any,Ti<:Any,1}, y::Union{Base.ReshapedArray{T<:Any,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{T<:Any,1},SubArray{T<:Any,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at sparse/sparsevector.jl:1185)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 (-(a::StaticArrays.StaticArray, b::Number) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:23,-(A::AbstractArray{Bool,N<:Any}, x::Bool) at arraymath.jl:92)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 (-(a::Number, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:22,-(x::Bool, A::AbstractArray{Bool,N<:Any}) at arraymath.jl:93)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 (./(a1::StaticArrays.StaticArray, a2::Number) at /home/tim/.julia/v0.6/StaticArrays/src/arraymath.jl:15,./{P<:Base.Dates.Period}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::Real) at dates/periods.jl:101)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
 (mapreduce(f, op, a1::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/mapreduce.jl:99,mapreduce(f, op::Union{Base.#&,Base.#|}, itr::AbstractArray) at reduce.jl:220)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
 (+(a::AbstractArray, b::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:11,+{P<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period},Q<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period}}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, Y::Union{Base.ReshapedArray{Q,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Q,N<:Any},SubArray{Q,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at dates/periods.jl:338)
 (mapreduce(f, op, a1::StaticArrays.StaticArray) at /home/tim/.julia/v0.6/StaticArrays/src/mapreduce.jl:99,mapreduce(f, op::Union{Base.#&,Base.#|}, itr) at reduce.jl:221)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
 (+(a::StaticArrays.StaticArray, b::AbstractArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:12,+(x::Union{Base.ReshapedArray{T<:Any,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{T<:Any,1},SubArray{T<:Any,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, y::AbstractSparseArray{Tv<:Any,Ti<:Any,1}) at sparse/sparsevector.jl:1184)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 (-(a::StaticArrays.StaticArray, b::AbstractArray) at /home/tim/.julia/v0.6/StaticArrays/src/linalg.jl:16,-{P<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period},Q<:Union{Base.Dates.CompoundPeriod,Base.Dates.Period}}(X::Union{Base.ReshapedArray{P,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{P,N<:Any},SubArray{P,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, Y::Union{Base.ReshapedArray{Q,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{Q,N<:Any},SubArray{Q,N<:Any,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at dates/periods.jl:338)

(In my packages' tests I'm starting to test that this returns an empty array. I can use setdiff to get rid of StaticArrays' ambiguities, but I thought I should let you know.)

`inv`, `det`, etc. with SMatrix{2,2,T<:Unsigned}

I noticed the behavior is inconsistent between Base and StaticArrays when working with unsigned integers. I think it's probably an unchecked overflow issue that Base avoids with promotion or something.

julia> inv(@SMatrix [0x01 0x02; 0x02 0x01])
2×2 StaticArrays.SMatrix{2,2,Float64,4}:
 0.00395257  1.00395   
 1.00395     0.00395257

julia> inv([0x01 0x02; 0x02 0x01])
2×2 Array{Float64,2}:
 -0.333333   0.666667
  0.666667  -0.333333

julia> det([0x01 0x02; 0x02 0x01])
-3.0

julia> det(@SMatrix [0x01 0x02; 0x02 0x01])
0xfd

julia> versioninfo()
Julia Version 0.5.0-rc4+0
Commit 9c76c3e (2016-09-09 01:43 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, haswell)

unsafe_getindex, etc

I'm having difficulties getting the same codegen out of @boundscheck and @inbounds pairs compared to not having a bounds check at-all (especially in the mutable case), so I'm suggesting we instead use unsafe_getindex and unsafe_setindex, at least for the linear case. It means a little more effort for people creating their own mutable array types, though...

slow construction and a big memory allocation overhead

show code

a = rand(8,8)
@time sa = SArray{(64,64), Float64}(a)
  8.675595 seconds (18.16 M allocations: 884.980 MB, 6.73% gc time)

julia> @time sa = SArray{(64,64), Float64}(a);
  1.273857 seconds (8.41 M allocations: 383.637 MB, 53.12% gc time)
julia> versioninfo()
Julia Version 0.5.0-rc3+0
Commit e6f843b (2016-08-22 23:43 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i7-5650U CPU @ 2.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)

Drop subtyping of `DenseArray`

I had originally defined

abstract StaticArray{T,N} <: DenseArray{T,N}

with the thought that a lot of functionality could be shared with Base.LinAlg functions, such as automatically calling out to BLAS functions and so-on.

In the end, I don't feel this has been as successful as I hoped. Most of the functions lack type-stability because Base makes a habit of calling similar (with the same size). So not only do users not get, e.g., an SMatrix back (they get an MMatrix), the code inside the functions (and sometimes the output) is frequently not type-stable and is probably much slower than just using Base.Array.

Further, most of the decompositions actually fail. Only eig seems to work well, and it is also not type stable internally.

And finally, we already have StaticArrays which are not dense, like Rotation and probably in the future things like static unit ranges and so-on.

So the proposal is to change to

abstract StaticArray{T,N} <: AbstractArray{T,N}

and to therefore drop some free functionality (and implement things ourselves).

maximum(A, d), sum(A, d), ... should give an SMatrix for A::SMatrix

Currently, this is using the generic reduction code:

julia> A = SMatrix{3,3}(rand(3,3))
3×3 StaticArrays.SMatrix{3,3,Float64,9}:
 0.0121247  0.371658  0.950669 
 0.450277   0.363499  0.0998775
 0.322925   0.158552  0.548777 

julia> maximum(A,2)
3×1 StaticArrays.MMatrix{3,1,Float64,3}:
 0.950669
 0.450277
 0.548777

julia> @which maximum(A,2)
maximum(A::AbstractArray, region) at reducedim.jl:305

`similar(staticarray, newsize)` produces a statically sized array

This is inefficient since the new size won't be known to the compiler, and Array would be faster. While speculative, future compiler enhancements might lead to proper constant propagation in this case, I think we should make this return an Array for now.

Should we introduce similar(array, Val{newsize})? It clashes with a method in base, but I think this usage makes more sense. @timholy?

Incorrect output type for zero function

Similar to #6, the zero function returns an MVector when the input is an SVector. For example:

julia> zero(SVector(1, 2))
2-element StaticArrays.MVector{2,Int64}:
 0
 0

Make proper documentaion

The README is becoming rather encyclopedic. It would be better to have a short README with an intro to the speed improvements over Array and the "Quick Start" section with the remaining documentation organized into a documentation webpage.

There are many approaches to take - we could try Documenter.jl combined with a github.io webpage.

.^ produces an MVector

julia> SVector(1,2,3) .^ 2
3-element StaticArrays.MVector{3,Int64}:
 1
 4
 9

julia> @which SVector(1,2,3) .^ 2
.^{T}(A::AbstractArray{T,N<:Any}, B::Number) at arraymath.jl:77

Probably there should be a specialized .^ method?

Implement `zero`

zero does not seem to be implemented for SArray and MArray?

I expected it and got tripped up 2-3 times by it. I can obviously just use @SVector zeros(3) (e.g.) but I think it would be useful to have (a) because some people may expect it and (b) for type-agnostic algorithms.

Consider having conversions from AbstractArray infer size

A little bit of convenience I initially expected from my use of FixedSizeArrays:

mat = [1 2; 3 4]
SMatrix(mat)

currently results in

ERROR: MethodError: no method matching size(::Type{StaticArrays.SMatrix})
Closest candidates are:
  size{T<:StaticArrays.StaticArray{T,N}}(::Union{T<:StaticArrays.StaticArray{T,N},Type{T<:StaticArrays.StaticArray}}, ::Integer) at <dir>/packages/v0.5/StaticArrays/src/abstractarray.jl:4
  size{N}(::Any, ::Integer, ::Integer, ::Integer...) at abstractarray.jl:30
  size(::BitArray{1}) at bitarray.jl:39
  ...
 in convert at <dir>/packages/v0.5/StaticArrays/src/core.jl:61 [inlined]
 in StaticArrays.SMatrix{S1,S2,T,L}(::Array{Int64,2}) at ./sysimg.jl:53

This works:

mat = [1 2; 3 4]
SMatrix{2, 2}(mat)

but it's a little annoying to have to specify the size parameters manually.

Implement LU matrix factorization

The lu() function should work on statically sized arrays. A first attempt would simply convert to Array and wrap the output in a SizedArray.

A fuller version of this would generate size-specialized code and be interfaced with inv.

Conversion to Static arrays

Currently there is no conversion from Base Arrays to static arrays:

julia> using StaticArrays

julia> SVector([1,2,3])
ERROR: MethodError: no method matching size(::Type{StaticArrays.SVector})
Closest candidates are:
  size{T<:StaticArrays.StaticArray{T,N}}(::Union{T<:StaticArrays.StaticArray{T,N},Type{T<:StaticArrays.StaticArray}}, ::Integer) at /home/admin/.julia/v0.5/StaticArrays/src/abstractarray.jl:4
  size{N}(::Any, ::Integer, ::Integer, ::Integer...) at abstractarray.jl:48
  size(::BitArray{1}) at bitarray.jl:39
  ...
 in StaticArrays.SVector{S,T}(::Array{Int64,1}) at ./sysimg.jl:53

Is there a good reason not to have such conversion?

Improve benchmarking

Current benchmarking is rather ad-hoc. I would like to use BenchmarkTools.jl but the results from perf/benchmark3.jl is rather different from my own (to the point where those results appear incorrect).

Can also steal code from FixedSizeArrays.

violation of GC safety

the MVector violates gc safety when it contains non-bitstypes (it lacks a write barrier), resulting in the possibility that the gc will lose the object and delete the objects in the array while still in-use:

else # TODO check that this isn't crazy. Also, check it doesn't cause problems with GC...
unsafe_store!(Base.unsafe_convert(Ptr{Ptr{Void}}, Base.data_pointer_from_objref(v.data)), Base.data_pointer_from_objref(val), i)

Minimum value over a dimension

Is there a better way to get the minimum value over a dimension for a Vector{SVector{3,Float64}} (e.g. minimum(points, 2))?
I have been doing this:

julia> points = [SVector{3, Float64}(rand(3)) for i = 1:5] 
5-element Array{StaticArrays.SVector{3,Float64},1}:
 [0.936339,0.268263,0.583008] 
 [0.564575,0.412917,0.469693] 
 [0.802534,0.699801,0.0992835]
 [0.379413,0.952707,0.229424] 
 [0.309086,0.335721,0.168284] 

julia> min_val = SVector{3, Float64}(minimum(map(x->x[1], points)), minimum(map(x->x[2], points)), 0)
3-element StaticArrays.SVector{3,Float64}:
 0.309086
 0.268263
 0.0

inlined sum, sumabs2, mean, and similar?

It seems like it would be worthwhile to inline common reduction operations for small vectors rather than calling the generic Base reduce code?

julia> @which sum(SVector(3,4,5))
sum(a) at reduce.jl:229

Relation to FixedSizeArrays.jl

Hi Andy,

Could you help me understand the differences in approach (pros/cons) between the implementations of SVector and SMatrix in this package and Vec and Mat in FixedSizeArrays.jl? The type definitions are identical (e.g., SVector and Vec both wrap NTuple) and the benchmarks are close, although it looks like StaticArrays might scale a bit better (do you have an idea of why)? At a very cursory level I understand that both implementations pack tightly in memory and are amenable to specialized/unrolled linear algebra code, and I'm a fan of how StaticArray is a subtype of AbstractArray, but are there any hidden design subtleties that potential users should be aware of?

Thanks,
Ed

Support for (n x 0) * (0 x m) products

This is not a critical feature, but a very-nice-to-have, as it gets rid of the need for lots of special cases in user code.
Plain arrays support the following:

m1 = zeros(3, 0)
m2 = zeros(0, 3)
v = zeros(0)
m1 * m2
m2 * m1
m1 * v

Currently, StaticArrays doesn't:

m1 = zeros(SMatrix{3, 0})
m2 = zeros(SMatrix{0, 3})
v = zeros(SVector{0}) # fine up to this point
m1 * m2 # ArgumentError: reducing over an empty collection is not allowed
m2 * m1 # fine
m1 * v # ArgumentError: reducing over an empty collection is not allowed

Type-stability of constructors for static matrices with splat arguments

This

f() = SMatrix{4,4}(1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.)
@code_warntype f()

returns Any.

However this (notice the tuple)

f() = SMatrix{4,4}((1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.))
@code_warntype f()

nicely returns SMatrix{4,4,Float64,16}.
Such issue also happens for SVectors and for both it only happens for more than 14 elements.

Is this something that is easily fixable, or is it something we must have to learn to live with?

Run the full benchmarks

A full set of benchmarks need to be done. Run perf/run_benchmarks.jl and create a file like bench11.txt and update the README accordingly.

create a new SArray using a normal Array?

julia> a = rand(3,3)
3×3 Array{Float64,2}:
 0.0843983  0.464536  0.48859 
 0.544042   0.591513  0.21486 
 0.162197   0.119602  0.781207

julia> @SArray a
ERROR: Bad input for @SArray

julia> SArray(a)
ERROR: MethodError: no method matching size(::Type{StaticArrays.SArray})
Closest candidates are:
  size{T<:StaticArrays.StaticArray{T,N}}(::Union{T<:StaticArrays.StaticArray{T,N},Type{T<:StaticArrays.StaticArray}}, ::Integer) at /Users/jpwu/.julia/v0.5/StaticArrays/src/abstractarray.jl:4
  size{N}(::Any, ::Integer, ::Integer, ::Integer...) at abstractarray.jl:48
  size(::BitArray{1}) at bitarray.jl:39
  ...
 in convert at /Users/jpwu/.julia/v0.5/StaticArrays/src/core.jl:61 [inlined]
 in StaticArrays.SArray{Size,T,N,L}(::Array{Float64,2}) at ./sysimg.jl:53


Generic conversion of AbstractArrays?

Would it make sense to define:

convert(::Type{SVector}, x::AbstractVector) = convert(SVector{length(x), eltype(x)}, x)

and perhaps similar for SMatrix or other arrays?

Implement QR matrix factorization

The qr() function should work on statically sized arrays. A first attempt would simply convert to Array and wrap the output in a SizedArray.

Unified, efficient code for mutable and immutable AbstractArrays

As mentioned in #31, nobody wants to write two versions of code, one for mutable arrays, vs one for immutable arrays like StaticArray. I'd like a central place where we identify the main issues, and discuss minimal changes to the AbstractArray interface or julia compiler which would allow packages like StaticArrays to exist without rewriting a lot of algorithms from Base. Here's a very incomplete list, I hope people will jump in with more detail:

API

  1. similar() assumes a mutable container can be created efficiently filled in an iterative way. JuliaLang/julia#17115 goes some way to solving this, though we'd be working with a statically sized buffer, something like Ref{T<:StaticArray} and would need to unwrap this to return the value.
  2. The hvcat() API doesn't reflect the structure of the input expression AST in a way which can give a type inferred output. (Potentially solvable with constant prop, without API changes?)

Optimization

  1. similar() with a size argument is not type inferrable for StaticArray. Constant prop in inference could potentially fix this in many cases, Ref. JuliaLang/julia#5560.
  2. getindex() with fancy indexing is not type inferrable for StaticArray. Constant prop in inference could fix a bunch of important instances of this, eg literal ranges v[3:5] could be known to be a SVector{3}. But what about non-inferrable cases, even after constant prop? We'd like to return an Array in those cases, can we achieve this in principle?
  3. Loop unrolling - small static arrays can benefit a lot from this, but in StaticArrays we're forced to do it at the AST level via @generated functions which no doubt pushes the compiler pretty hard and generates a heap of garbage. More interesting would be an @unroll meta to instruct codegen to unroll a given loop if the range is statically known.

Obviously one thing we can't fix is differences in the most appropriate algorithm for small vs large objects. For example, eigen decomposition of 2x2 matrices should probably just be done using a specialized analytical expression for that size.

FixedSizeArrays --> StaticArrays

The transition so far has been more painful then expected :(
I thought I should start a list with problems:

  • normalize is slow
  • constructors not inherited [decision needed]
  • missing op(::Array{SVector}, ::SVector), e.g. a.+b or (+).(a,b)

I repeat my concern from #11 :
Types inheriting from StaticVector don't inherit all constructors. Having a consistent set of constructors for different fixed arrays was an important goal for usability and because its not that trivial to implement them all correctly. Are there any plans to offer this? I must admit I got myself into quite a mess with that (the constructor code in FixedSizeArrays is probably the ugliest code I've written so far)... But maybe we could offer a macro that one could execute for a custom type?

I feel a bit like writing a new package targeting 0.6 (after it got a few more features we need) with all the goodies from FixedSizeArrays and StaticArrays :D

Devectorization of static array expressions?

I'm interested in knowing if there are any plans to support devectorization for expressions involving statically sized arrays. As a test, I tried using this in combination with the Devectorize.jl package, for example:

using StaticArrays
using Devectorize
x = SVector(1.0, 2.0, 3.0)
@devec y = x .+ x .+ x

Unfortunately, y comes out as an Array{Float64, 1}, not a static vector. Are there any plans to support such functionality in this package, or does that belong elsewhere?

Product of SMatrix and Vector results in ambiguity

Continuing from #25 (comment). I really appreciate the quick response, but unfortunately the new functionality doesn't seem to work as intended:

m = rand(SMatrix{3, 3})
v = rand(3)
m * v

now results in

ERROR: MethodError: *(::StaticArrays.SMatrix{3,3,Float64,9}, ::Array{Float64,1}) is ambiguous. Candidates:
  *(A::StaticArrays.StaticArray{T<:Any,2}, b::AbstractArray{T<:Any,1}) at /Users/twan/code/julia/RigidBodyDynamics/v0.5/StaticArrays/src/matrix_multiply.jl:136
  *{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},S}(A::Union{Base.ReshapedArray{T,2,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{T,2},SubArray{T,2,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}, x::Union{Base.ReshapedArray{S,1,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray{S,1},SubArray{S,1,A<:Union{Base.ReshapedArray{T<:Any,N<:Any,A<:DenseArray,MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N<:Any}}},DenseArray},I<:Tuple{Vararg{Union{Base.AbstractCartesianIndex,Colon,Int64,Range{Int64}},N<:Any}},L<:Any}}) at linalg/matmul.jl:79

Strange Error when calling Vec(1)

   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.5.1-pre+2 (2016-09-20 03:34 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit f0d40ec* (6 days old release-0.5)
|__/                   |  x86_64-linux-gnu

julia> using StaticArrays.FixedSizeArrays

julia> Vec(1,2)
2-element StaticArrays.SVector{2,Int64}:
 1
 2

julia> Vec(1)
ERROR: MethodError: no method matching size(::Type{StaticArrays.SVector})
Closest candidates are:
  size{T<:StaticArrays.StaticArray{T,N}}(::Union{T<:StaticArrays.StaticArray{T,N},Type{T<:StaticArrays.StaticArray}}, ::Integer) at /home/admin/.julia/v0.5/StaticArrays/src/abstractarray.jl:4
  size{N}(::Any, ::Integer, ::Integer, ::Integer...) at abstractarray.jl:48
  size(::BitArray{1}) at bitarray.jl:39
  ...
 in StaticArrays.SVector{S,T}(::Int64) at ./sysimg.jl:53


Naming for small vectors

As discussed at SimonDanisch/FixedSizeArrays.jl#159, I rather liked writing Vec and Mat for small sized arrays in FixedSizeArrays. Perhaps we should try to recover these names for StaticArrays, perhaps not?

Note that SIMD.jl has also started using Vec so there is unfortunately already a naming clash with FixedSizeArrays there @eschnett

Efficient SMatrix SubArrays

Maybe this is an issue for Base, but I thought I'd get your input first.

I have an application where I know the maximum size of a matrix at compile time, but the number of columns is only known at runtime. I was hoping that combining SMatrix and view would solve this problem. Making a view of an SMatrix works fine (awesome!), but there's a performance issue.

Consider the following code:

using StaticArrays
function view_colon()
    data = rand(SMatrix{3, 3, Float64})
    view(data, :, 1:2)
end

function view_range()
    data = rand(SMatrix{3, 3, Float64})
    view(data, 1:3, 1:2)
end

Base.linearindexing(view_colon()) # Base.LinearFast()
Base.linearindexing(view_range()) # Base.LinearSlow()

isbits(view_colon()) # false
isbits(view_range()) # true

So currently, I have to choose between a LinearFast view that is not isbits (resulting in lots of allocations down the line), or a LinearSlow view that is.

The only reason the colon version is not isbits seems to be that Colon is a type, instead of being immutable. So would it be possible to change that in Base without breaking things? Or should this be handled in StaticArrays instead?

Traits for static arrays and friends

One thing that was realized in the AbstractArray interface is that traits are a convenient and powerful way of expressing ways of interacting with different types of arrays, the prototypical exampling being LinearFast vs LinearSlow. I wanted to discuss some possible traits that would be useful for StaticArrays.jl while keeping in mind that with future language enhancements (e.g. the trait system experiments of Traitor.jl) might make them easier to use and interface into Base in the future.

  • Dispatch on size. We could have some kind of Dimensions trait (@timholy suggested SDims to complement Base.Dims). Unlike FixedSizeArrays, the size isn't specified in the abstract StaticVector{T}, while the package is meant to use the size() on types interface, it doesn't make it easy to allow, e.g., any 3-vector. Introducing a trait would at least allow an "official" way of doing that. Speculatively, this could be extended so that SDims <: AbstractDimensions and Base.Array etc have a dimensions trait with run-time size information (but compile-time rank). The dimensions trait could be combined with the "indices" trait being proposed/used in Base for non-1-based indexing.
  • Mutable vs. immutable. Or, more specifically, does setindex! work? Most algorithms in Base are defined using similar but that doesn't work for immutables, and it is a pain to define alternatives here that things other than StaticArray can't use at all.
  • Perhaps stack-allocated vs heap-allocated? We would put extra effort in for stack-allocated things so that we never make new heap allocations. This is obviously related to Mutable vs Immutable and similar vs similar_type.

Any thoughts appreciated. Is it a good idea to be defining types here, in this package?

Derivatives using SVector{Dual}

@andyferris Thanks for the offer to help. To avoid sabotaging #25, I'm putting my "Jacobian" code in this ticket.

Let's begin with a small, differentiable vector-valued function:

function cart_to_sphere(cart)
    x, y, z = cart
    r = sqrt(x^2 + y^2 + z^2)
    θ = acos(z / r)
    ϕ = atan2(y, x)
    SVector(r, θ, ϕ)
end

Suppose I want to evaluate this function and its derivative simultaneously, using AD forward mode with dual numbers. Because this is a low-dimensional space, I'd like to use SVector / SMatrix wherever possible.

@inbounds function eval_jacobian{N,T}(f::Function, x::SVector{N,T})
    dualtype = ForwardDiff.Dual{N,T}
    partials = make_partials(GetPartials{N,T}())
    xp = SVector{N,dualtype}(dualtype(x[i], partials[i]) for i=1:N)
    yp = f(xp)
    y = map(ForwardDiff.value, yp)
    P = length(yp)
    J = SMatrix{P,N}((ForwardDiff.partials(yp[i])[j] for i=1:P, j=1:N) ...) # slow line?
    (y, J)
end

Because the "diagonal" partials can be precomputed and re-used for any low-dimension space, I have moved these to a generated function. The function returns an MVector to avoid copying the result on each invocation.

# just a type to invoke make_partials with
immutable GetPartials{N,T} end

@generated function make_partials{N,T}(::GetPartials{N,T})
    partialtype = ForwardDiff.Partials{N,T}
    partials = MVector{N,partialtype}(
        partialtype(ntuple(N) do x x == i ? one(T) : zero(T) end)
        for i=1:N
    )
    return :($partials)
end

Evaluating make_partials is essentially free:

julia> @code_native make_partials(GetPartials{9,Float64}())
    .section    __TEXT,__text,regular,pure_instructions
Filename: REPL[28]
    pushq   %rbp
    movq    %rsp, %rbp
Source line: 2
    movabsq $4569288656, %rax       ## imm = 0x11059CFD0
    popq    %rbp
    retq

Based on timing tests, calling eval_jacobian(cart_to_sphere, SVector(1.,2.,3.)) is far more expensive than it could be:

julia> @time for i=1:10^5 eval_jacobian(cart_to_sphere, SVector(1.,2.,3.)) end
  0.684567 seconds (4.21 M allocations: 227.805 MB, 5.21% gc time)

If I change eval_jacobian to return yp (skipping the formation of y and J), then the timing is substantially better:

julia> @time for i=1:10^5 eval_jacobian(cart_to_sphere, SVector(1.,2.,3.)) end
  0.074104 seconds (1.40 M allocations: 57.983 MB, 9.93% gc time)

I think the cost of constructing the Jacobian matrix is the single biggest problem with my code right now.

Ideally, I'd like to see a version with no dynamic allocations (once compiled). Perhaps this will require crafting my own dual-number implementation using SVector to hold the partials.

Thoughts?

Mistake in ctranspose?

Hi, just trying out your package. So far so good, except for this. I'm getting:

ERROR: UndefVarError: v not defined
 in ctranspose(...) at <dir>/packages/v0.5/StaticArrays/src/linalg.jl:77
 in macro expansion at <dir>/packages/v0.5/StaticArrays/src/matrix_multiply.jl:20 [inlined]
 in Ac_mul_B(::StaticArrays.SMatrix{3,5,Float64,15}, ::StaticArrays.SVector{3,Float64}) at <dir>/packages/v0.5/StaticArrays/src/matrix_multiply.jl:18

See here:
https://github.com/andyferris/StaticArrays.jl/blob/master/src/linalg.jl#L77

You probably just meant to use m instead of v?

setindex! with StaticArrays of a non-isbits type

Nice.

My ArbFloats, while an immutable type, are not strictly isbits types because one of their static fields may be either an immediate value or an offset into preallocated memory that holds a fixed length BigNum.
They share some isibits type's behavior: changing a value does not alter the bit patterns of a value's fields, instead a new realization of the type is constructed and used in place of the original value.

I would like them to play well with StaticArrays. Please let me know the fuctional signatures to provide (and what they are doing, if there is any subtilty -- I have not learned that part of Julia yet). Feel free to abbreviate the types ArbFloat{ bits_of_precision } as AFloat.

If some of the linear algebra that you support gets passed along to C routines, at the algorithmic point where that transition occur, there would need to be me dispatching over the handoff. And this is a larger issue for ArbFloats (it is a corner of v0.5 where BigFloats sink).

Indexing a SArray with a range produces a MArray

julia> a = @SArray rand(2,2)
2×2 StaticArrays.SArray{(2,2),Float64,2,4}:
 0.84171   0.807997
 0.427424  0.743513

julia> a[1:1,:]
1×2 StaticArrays.MMatrix{1,2,Float64,2}:
 0.84171  0.807997

julia> a[1,:]
2-element StaticArrays.SVector{2,Float64}:
 0.84171 
 0.807997

broken Base.unsafe_convert method returns garbage pointers

data_pointer_from_objref returns an invalid pointer when called on SMatrix. This function should thrown an error in this case (the case where the object can be stack allocated), but that error checking hasn't been implemented yet. That means this function is invalid:

@inline function Base.unsafe_convert{N,M,T}(::Type{Ptr{T}}, m::SMatrix{N,M,T})
    Base.unsafe_convert(Ptr{T}, Base.data_pointer_from_objref(m))
end

The correct way to implement this is to use Ref:

Base.cconvert{T}(::Type{Ptr{T}}, m::SMatrix) = Ref(m)
Base.unsafe_convert{N,M,T}(::Type{Ptr{T}}, m::Ref{SMatrix{N,M,T}}) =
    Ptr{T}(Base.unsafe_convert(Ptr{SMatrix{N,M,T}}, m))

Appveyor isn't working

Does anyone know how I can restart Appveyor since the move to JuliaArrays?

I can log into Appveyor through github credentials as myself (but can't see this new repository) and JuliaGeo (can't see this repository, obviously) but not as JuliaArrays. So I can't see where/how to activate things. @timholy was it you that enabled Appveyor for JuliaArrays? Do you understand how this works?

rand with an SArray as eltype

Sorry for spamming issues.

It would be nice if this could work rand(SVector{5, Float64}, 5)

I guess it should be enough to implement rand(::RNG, ::SArray).

Inconsistent output type of vector outer product

Input:

x = SVector(0., 1., 0.)
y = x * x'

Current output:

3×3 StaticArrays.MMatrix{3,3,Float64,9}:
0.0  0.0  0.0
0.0  1.0  0.0
0.0  0.0  0.0

I would expect the output to be an SMatrix.

If I start with a 3x1 SMatrix instead of an SVector,

x = @SMatrix [0.; 1.; 0.]
y = x * x'

then the output is

3×3 StaticArrays.SMatrix{3,3,Float64,9}:
0.0  0.0  0.0
0.0  1.0  0.0
0.0  0.0  0.0

which is what I would expect.

Allow @SVector comprehension to eval range with locals?

Because the @SVector macro does not evaluate the range using the local scope, I find myself transforming code like this:

function mytransform{N}(x::SVector{N})
    @SVector [x[i] * i for i=1:N]
end

into this:

function mytransform{N,T}(x::SVector{N,T})
    SVector{N,T}(ntuple(i -> x[i] * i, N) ...)
end

I'm not sure if the second form is as efficient, but in either case, the first version is far easier to read.

Is there any chance that @SVector comprehensions can be made to support local variables in the range? Or, is there some other way I should be writing this?

isnan and isinf on SVectors return Arrays

I'm trying to use isinf and isnan, and those functions are returning Arrays instead of SVectors.

julia> a = SVector(1.0, NaN)
2-element StaticArrays.SVector{2,Float64}:
   1.0
 NaN

julia> isnan(a)
2-element Array{Bool,1}:
 false
  true

julia> a = SVector(1.0, Inf)
2-element StaticArrays.SVector{2,Float64}:
   1.0
 Inf

julia> isinf(a)
2-element Array{Bool,1}:
 false
  true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.