Skip to content

Commit 9a0a588

Browse files
authored
Initial version
1 parent e888389 commit 9a0a588

File tree

4 files changed

+185
-0
lines changed

4 files changed

+185
-0
lines changed

Project.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name = "StaticArraysCore"
2+
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
3+
version = "1.0.0"
4+
5+
[compat]
6+
julia = "1.6"
7+
8+
[extras]
9+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
10+
11+
[targets]
12+
test = ["Test"]

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# StaticArraysCore
2+
3+
Interface package for [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl).
4+
5+

src/StaticArraysCore.jl

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
module StaticArraysCore
2+
3+
4+
"""
5+
abstract type StaticArray{S, T, N} <: AbstractArray{T, N} end
6+
StaticScalar{T} = StaticArray{Tuple{}, T, 0}
7+
StaticVector{N,T} = StaticArray{Tuple{N}, T, 1}
8+
StaticMatrix{N,M,T} = StaticArray{Tuple{N,M}, T, 2}
9+
10+
`StaticArray`s are Julia arrays with fixed, known size.
11+
12+
## Dev docs
13+
14+
They must define the following methods:
15+
- Constructors that accept a flat tuple of data.
16+
- `getindex()` with an integer (linear indexing) (preferably `@inline` with `@boundscheck`).
17+
- `Tuple()`, returning the data in a flat Tuple.
18+
19+
It may be useful to implement:
20+
21+
- `similar_type(::Type{MyStaticArray}, ::Type{NewElType}, ::Size{NewSize})`, returning a
22+
type (or type constructor) that accepts a flat tuple of data.
23+
24+
For mutable containers you may also need to define the following:
25+
26+
- `setindex!` for a single element (linear indexing).
27+
- `similar(::Type{MyStaticArray}, ::Type{NewElType}, ::Size{NewSize})`.
28+
- In some cases, a zero-parameter constructor, `MyStaticArray{...}()` for unintialized data
29+
is assumed to exist.
30+
31+
(see also `SVector`, `SMatrix`, `SArray`, `MVector`, `MMatrix`, `MArray`, `SizedArray`, `FieldVector`, `FieldMatrix` and `FieldArray`)
32+
"""
33+
abstract type StaticArray{S <: Tuple, T, N} <: AbstractArray{T, N} end
34+
const StaticScalar{T} = StaticArray{Tuple{}, T, 0}
35+
const StaticVector{N, T} = StaticArray{Tuple{N}, T, 1}
36+
const StaticMatrix{N, M, T} = StaticArray{Tuple{N, M}, T, 2}
37+
const StaticVecOrMat{T} = Union{StaticVector{<:Any, T}, StaticMatrix{<:Any, <:Any, T}}
38+
39+
# The ::Tuple variants exist to make sure that anything that calls with a tuple
40+
# instead of a Tuple gets through to the constructor, so the user gets a nice
41+
# error message
42+
Base.@pure tuple_length(T::Type{<:Tuple}) = length(T.parameters)
43+
Base.@pure tuple_length(T::Tuple) = length(T)
44+
Base.@pure tuple_prod(T::Type{<:Tuple}) = length(T.parameters) == 0 ? 1 : *(T.parameters...)
45+
Base.@pure tuple_prod(T::Tuple) = prod(T)
46+
Base.@pure tuple_minimum(T::Type{<:Tuple}) = length(T.parameters) == 0 ? 0 : minimum(tuple(T.parameters...))
47+
Base.@pure tuple_minimum(T::Tuple) = minimum(T)
48+
49+
50+
# Something doesn't match up type wise
51+
function check_array_parameters(Size, T, N, L)
52+
(!isa(Size, DataType) || (Size.name !== Tuple.name)) && throw(ArgumentError("Static Array parameter Size must be a Tuple type, got $Size"))
53+
!isa(T, Type) && throw(ArgumentError("Static Array parameter T must be a type, got $T"))
54+
!isa(N.parameters[1], Int) && throw(ArgumentError("Static Array parameter N must be an integer, got $(N.parameters[1])"))
55+
!isa(L.parameters[1], Int) && throw(ArgumentError("Static Array parameter L must be an integer, got $(L.parameters[1])"))
56+
# shouldn't reach here. Anything else should have made it to the function below
57+
error("Internal error. Please file a bug")
58+
end
59+
@generated function check_array_parameters(::Type{Size}, ::Type{T}, ::Type{Val{N}}, ::Type{Val{L}}) where {Size,T,N,L}
60+
if !all(x->isa(x, Int), Size.parameters)
61+
return :(throw(ArgumentError("Static Array parameter Size must be a tuple of Ints (e.g. `SArray{Tuple{3,3}}` or `SMatrix{3,3}`).")))
62+
end
63+
64+
if L != tuple_prod(Size) || L < 0 || tuple_minimum(Size) < 0 || tuple_length(Size) != N
65+
return :(throw(ArgumentError("Size mismatch in Static Array parameters. Got size $Size, dimension $N and length $L.")))
66+
end
67+
68+
return nothing
69+
end
70+
71+
72+
"""
73+
SArray{S, T, N, L}(x::NTuple{L})
74+
SArray{S, T, N, L}(x1, x2, x3, ...)
75+
76+
Construct a statically-sized array `SArray`. Since this type is immutable, the data must be
77+
provided upon construction and cannot be mutated later. The `S` parameter is a Tuple-type
78+
specifying the dimensions, or size, of the array - such as `Tuple{3,4,5}` for a 3×4×5-sized
79+
array. The `N` parameter is the dimension of the array; the `L` parameter is the `length`
80+
of the array and is always equal to `prod(S)`. Constructors may drop the `L`, `N` and `T`
81+
parameters if they are inferrable from the input (e.g. `L` is always inferrable from `S`).
82+
83+
SArray{S}(a::Array)
84+
85+
Construct a statically-sized array of dimensions `S` (expressed as a `Tuple{...}`) using
86+
the data from `a`. The `S` parameter is mandatory since the size of `a` is unknown to the
87+
compiler (the element type may optionally also be specified).
88+
"""
89+
struct SArray{S <: Tuple, T, N, L} <: StaticArray{S, T, N}
90+
data::NTuple{L,T}
91+
92+
function SArray{S, T, N, L}(x::NTuple{L,T}) where {S<:Tuple, T, N, L}
93+
check_array_parameters(S, T, Val{N}, Val{L})
94+
new{S, T, N, L}(x)
95+
end
96+
97+
function SArray{S, T, N, L}(x::NTuple{L,Any}) where {S<:Tuple, T, N, L}
98+
check_array_parameters(S, T, Val{N}, Val{L})
99+
new{S, T, N, L}(convert_ntuple(T, x))
100+
end
101+
end
102+
103+
@inline SArray{S,T,N}(x::Tuple) where {S<:Tuple,T,N} = SArray{S,T,N,tuple_prod(S)}(x)
104+
105+
106+
"""
107+
MArray{S, T, N, L}(undef)
108+
MArray{S, T, N, L}(x::NTuple{L})
109+
MArray{S, T, N, L}(x1, x2, x3, ...)
110+
111+
112+
Construct a statically-sized, mutable array `MArray`. The data may optionally be
113+
provided upon construction and can be mutated later. The `S` parameter is a Tuple-type
114+
specifying the dimensions, or size, of the array - such as `Tuple{3,4,5}` for a 3×4×5-sized
115+
array. The `N` parameter is the dimension of the array; the `L` parameter is the `length`
116+
of the array and is always equal to `prod(S)`. Constructors may drop the `L`, `N` and `T`
117+
parameters if they are inferrable from the input (e.g. `L` is always inferrable from `S`).
118+
119+
MArray{S}(a::Array)
120+
121+
Construct a statically-sized, mutable array of dimensions `S` (expressed as a `Tuple{...}`)
122+
using the data from `a`. The `S` parameter is mandatory since the size of `a` is unknown to
123+
the compiler (the element type may optionally also be specified).
124+
"""
125+
mutable struct MArray{S <: Tuple, T, N, L} <: StaticArray{S, T, N}
126+
data::NTuple{L,T}
127+
128+
function MArray{S,T,N,L}(x::NTuple{L,T}) where {S<:Tuple,T,N,L}
129+
check_array_parameters(S, T, Val{N}, Val{L})
130+
new{S,T,N,L}(x)
131+
end
132+
133+
function MArray{S,T,N,L}(x::NTuple{L,Any}) where {S<:Tuple,T,N,L}
134+
check_array_parameters(S, T, Val{N}, Val{L})
135+
new{S,T,N,L}(convert_ntuple(T, x))
136+
end
137+
138+
function MArray{S,T,N,L}(::UndefInitializer) where {S<:Tuple,T,N,L}
139+
check_array_parameters(S, T, Val{N}, Val{L})
140+
new{S,T,N,L}()
141+
end
142+
end
143+
144+
@inline MArray{S,T,N}(x::Tuple) where {S<:Tuple,T,N} = MArray{S,T,N,tuple_prod(S)}(x)
145+
146+
@generated function (::Type{MArray{S,T,N}})(::UndefInitializer) where {S,T,N}
147+
return quote
148+
$(Expr(:meta, :inline))
149+
MArray{S, T, N, $(tuple_prod(S))}(undef)
150+
end
151+
end
152+
153+
@generated function (::Type{MArray{S,T}})(::UndefInitializer) where {S,T}
154+
return quote
155+
$(Expr(:meta, :inline))
156+
MArray{S, T, $(tuple_length(S)), $(tuple_prod(S))}(undef)
157+
end
158+
end
159+
160+
161+
162+
end # module

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using StaticArraysCore, Test
2+
3+
@testset "types" begin
4+
@test StaticArraysCore.SArray{Tuple{2},Int,1}((1, 2)) isa StaticArraysCore.SArray
5+
end
6+

0 commit comments

Comments
 (0)