Skip to content

Commit 924c632

Browse files
committed
Merge branch 'master' into sd/fixedsizearrays
2 parents bee237d + 8d3ec32 commit 924c632

23 files changed

+413
-362
lines changed

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ julia 0.5 with default optimizations.
5656
## Quick start
5757

5858
```julia
59-
Pkg.add("StaticArrays") # or Pkg.clone("https://github.com/andyferris/StaticArrays.jl")
59+
Pkg.add("StaticArrays") # or Pkg.clone("https://github.com/JuliaArrays/StaticArrays.jl")
6060
using StaticArrays
6161

6262
# Create an SVector using various forms, using constructors, functions or macros
@@ -90,9 +90,9 @@ v8 = sin.(v3)
9090
v3 == m3 * v3 # recall that m3 = eye(SMatrix{3,3})
9191
# map, reduce, broadcast, map!, broadcast!, etc...
9292

93-
# Indexing also supports tuples
93+
# Indexing can also be done using static arrays of integers
9494
v1[1] === 1
95-
v1[(3,2,1)] === @SVector [3, 2, 1]
95+
v1[SVector(3,2,1)] === @SVector [3, 2, 1]
9696
v1[:] === v1
9797
typeof(v1[[1,2,3]]) <: Vector # Can't determine size from the type of [1,2,3]
9898

@@ -101,7 +101,7 @@ rand(MMatrix{20,20}) * rand(MMatrix{20,20}) # large matrices can use BLAS
101101
eig(m3) # eig(), etc uses specialized algorithms up to 3×3, or else LAPACK
102102

103103
# Static arrays stay statically sized, even when used by Base functions, etc:
104-
typeof(eig(m3)) == Tuple{MVector{3,Float64}, MMatrix{3,3,Float64,9}}
104+
typeof(eig(m3)) == Tuple{SVector{3,Float64}, SMatrix{3,3,Float64,9}}
105105

106106
# similar() returns a mutable container, while similar_type() returns a constructor:
107107
typeof(similar(m3)) == MMatrix{3,3,Float64,9} # (final parameter is length = 9)
@@ -110,15 +110,15 @@ similar_type(m3) == SMatrix{3,3,Float64,9}
110110
# The Size trait is a compile-time constant representing the size
111111
Size(m3) === Size(3,3)
112112

113-
# reshape() uses Size() or types to specify size:
114-
reshape([1,2,3,4], Size(2,2)) === @SMatrix [ 1 3 ;
115-
2 4 ]
116-
reshape([1,2,3,4], SMatrix{2,2}) === @SMatrix [ 1 3 ;
117-
2 4 ]
118-
119113
# A standard Array can be wrapped into a SizedArray
120114
m4 = Size(3,3)(rand(3,3))
121115
inv(m4) # Take advantage of specialized fast methods
116+
117+
# reshape() uses Size() or types to specify size:
118+
reshape([1,2,3,4], Size(2,2)) == @SMatrix [ 1 3 ;
119+
2 4 ]
120+
typeof(reshape([1,2,3,4], Size(2,2))) === SizedArray{(2, 2),Int64,2,1}
121+
122122
```
123123

124124
## Approach
@@ -348,9 +348,9 @@ you may want to define a default constructor (no inputs) that can be called by
348348

349349
### Implementing your own types
350350

351-
You can easily create your own `StaticArray` type, by defining both `Size` (on the
352-
*type*, e.g. `StaticArrays.Size(::Type{Point3D}) = Size(3)`), and linear
353-
`getindex` (and optionally `setindex!` for mutable types - see
351+
You can easily create your own `StaticArray` type, by defining both `Size` (on the
352+
*type*, e.g. `StaticArrays.Size(::Type{Point3D}) = Size(3)`), and linear
353+
`getindex` (and optionally `setindex!` for mutable types - see
354354
`setindex(::SVector, val, i)` in *MVector.jl* for an example of how to
355355
achieve this through pointer manipulation). Your type should define a constructor
356356
that takes a tuple of the data (and mutable containers may want to define a

src/MArray.jl

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,75 +20,63 @@ type MArray{Size, T, N, L} <: StaticArray{T, N}
2020
data::NTuple{L,T}
2121

2222
function (::Type{MArray{Size,T,N,L}}){Size,T,N,L}(x::NTuple{L,T})
23-
check_marray_parameters(Val{Size}, T, Val{N}, Val{L})
23+
check_array_parameters(Size, T, Val{N}, Val{L})
2424
new{Size,T,N,L}(x)
2525
end
2626

2727
function (::Type{MArray{Size,T,N,L}}){Size,T,N,L}(x::NTuple{L,Any})
28-
check_marray_parameters(Val{Size}, T, Val{N}, Val{L})
28+
check_array_parameters(Size, T, Val{N}, Val{L})
2929
new{Size,T,N,L}(convert_ntuple(T, x))
3030
end
3131

3232
function (::Type{MArray{Size,T,N,L}}){Size,T,N,L}()
33-
check_marray_parameters(Val{Size}, T, Val{N}, Val{L})
33+
check_array_parameters(Size, T, Val{N}, Val{L})
3434
new{Size,T,N,L}()
3535
end
3636
end
3737

38-
@generated function check_marray_parameters{Size,T,N,L}(::Type{Val{Size}}, ::Type{T}, ::Type{Val{N}}, ::Type{Val{L}})
39-
if !(isa(Size, Tuple{Vararg{Int}}))
40-
error("MArray parameter Size must be a tuple of Ints (e.g. `MArray{(3,3)}`)")
41-
end
42-
43-
if L != prod(Size) || L < 0 || minimum(Size) < 0 || length(Size) != N
44-
error("Size mismatch in MArray parameters. Got size $Size, dimension $N and length $L.")
45-
end
46-
47-
return nothing
48-
end
49-
5038
@generated function (::Type{MArray{Size,T,N}}){Size,T,N}(x::Tuple)
5139
return quote
5240
$(Expr(:meta, :inline))
53-
MArray{Size,T,N,$(prod(Size))}(x)
41+
MArray{Size,T,N,$(tuple_prod(Size))}(x)
5442
end
5543
end
5644

5745
@generated function (::Type{MArray{Size,T}}){Size,T}(x::Tuple)
5846
return quote
5947
$(Expr(:meta, :inline))
60-
MArray{Size,T,$(length(Size)),$(prod(Size))}(x)
48+
MArray{Size,T,$(tuple_length(Size)),$(tuple_prod(Size))}(x)
6149
end
6250
end
6351

6452
@generated function (::Type{MArray{Size}}){Size, T <: Tuple}(x::T)
6553
return quote
6654
$(Expr(:meta, :inline))
67-
MArray{Size,$(promote_tuple_eltype(T)),$(length(Size)),$(prod(Size))}(x)
55+
MArray{Size,$(promote_tuple_eltype(T)),$(tuple_length(Size)),$(tuple_prod(Size))}(x)
6856
end
6957
end
7058

7159
@generated function (::Type{MArray{Size,T,N}}){Size,T,N}()
7260
return quote
7361
$(Expr(:meta, :inline))
74-
MArray{Size, T, N, $(prod(Size))}()
62+
MArray{Size, T, N, $(tuple_prod(Size))}()
7563
end
7664
end
7765

7866
@generated function (::Type{MArray{Size,T}}){Size,T}()
7967
return quote
8068
$(Expr(:meta, :inline))
81-
MArray{Size, T, $(length(Size)), $(prod(Size))}()
69+
MArray{Size, T, $(tuple_length(Size)), $(tuple_prod(Size))}()
8270
end
8371
end
8472

85-
@inline MArray(a::StaticArray) = MArray{size(typeof(a))}(Tuple(a))
73+
@inline MArray(a::StaticArray) = MArray{size_tuple(typeof(a))}(Tuple(a))
8674

8775
# Some more advanced constructor-like functions
88-
@inline one(::Type{MArray{S}}) where {S} = one(MArray{S,Float64,length(S)})
89-
@inline eye(::Type{MArray{S}}) where {S} = eye(MArray{S,Float64,length(S)})
90-
@inline one(::Type{MArray{S,T}}) where {S,T} = one(MArray{S,T,length(S)})
91-
@inline eye(::Type{MArray{S,T}}) where {S,T} = eye(MArray{S,T,length(S)})
76+
@inline one(::Type{MArray{S}}) where {S} = one(MArray{S,Float64,tuple_length(S)})
77+
@inline eye(::Type{MArray{S}}) where {S} = eye(MArray{S,Float64,tuple_length(S)})
78+
@inline one(::Type{MArray{S,T}}) where {S,T} = one(MArray{S,T,tuple_length(S)})
79+
@inline eye(::Type{MArray{S,T}}) where {S,T} = eye(MArray{S,T,tuple_length(S)})
9280

9381
####################
9482
## MArray methods ##
@@ -133,17 +121,17 @@ macro MArray(ex)
133121
end
134122

135123
if ex.head == :vect # vector
136-
return esc(Expr(:call, MArray{(length(ex.args),)}, Expr(:tuple, ex.args...)))
124+
return esc(Expr(:call, MArray{Tuple{length(ex.args)}}, Expr(:tuple, ex.args...)))
137125
elseif ex.head == :ref # typed, vector
138-
return esc(Expr(:call, Expr(:curly, :MArray, ((length(ex.args)-1),), ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
126+
return esc(Expr(:call, Expr(:curly, :MArray, Tuple{length(ex.args)-1}, ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
139127
elseif ex.head == :hcat # 1 x n
140128
s1 = 1
141129
s2 = length(ex.args)
142-
return esc(Expr(:call, MArray{(s1, s2)}, Expr(:tuple, ex.args...)))
130+
return esc(Expr(:call, MArray{Tuple{s1, s2}}, Expr(:tuple, ex.args...)))
143131
elseif ex.head == :typed_hcat # typed, 1 x n
144132
s1 = 1
145133
s2 = length(ex.args) - 1
146-
return esc(Expr(:call, Expr(:curly, :MArray, (s1, s2), ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
134+
return esc(Expr(:call, Expr(:curly, :MArray, Tuple{s1, s2}, ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
147135
elseif ex.head == :vcat
148136
if isa(ex.args[1], Expr) && ex.args[1].head == :row # n x m
149137
# Validate
@@ -155,9 +143,9 @@ macro MArray(ex)
155143
end
156144

157145
exprs = [ex.args[i].args[j] for i = 1:s1, j = 1:s2]
158-
return esc(Expr(:call, MArray{(s1, s2)}, Expr(:tuple, exprs...)))
146+
return esc(Expr(:call, MArray{Tuple{s1, s2}}, Expr(:tuple, exprs...)))
159147
else # n x 1
160-
return esc(Expr(:call, MArray{(length(ex.args), 1)}, Expr(:tuple, ex.args...)))
148+
return esc(Expr(:call, MArray{Tuple{length(ex.args), 1}}, Expr(:tuple, ex.args...)))
161149
end
162150
elseif ex.head == :typed_vcat
163151
if isa(ex.args[2], Expr) && ex.args[2].head == :row # typed, n x m
@@ -170,9 +158,9 @@ macro MArray(ex)
170158
end
171159

172160
exprs = [ex.args[i+1].args[j] for i = 1:s1, j = 1:s2]
173-
return esc(Expr(:call, Expr(:curly, :MArray, (s1, s2), ex.args[1]), Expr(:tuple, exprs...)))
161+
return esc(Expr(:call, Expr(:curly, :MArray, Tuple{s1, s2}, ex.args[1]), Expr(:tuple, exprs...)))
174162
else # typed, n x 1
175-
return esc(Expr(:call, Expr(:curly, :MArray, (length(ex.args)-1, 1), ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
163+
return esc(Expr(:call, Expr(:curly, :MArray, Tuple{length(ex.args)-1, 1}, ex.args[1]), Expr(:tuple, ex.args[2:end]...)))
176164
end
177165
elseif isa(ex, Expr) && ex.head == :comprehension
178166
if length(ex.args) != 1 || !isa(ex.args[1], Expr) || ex.args[1].head != :generator
@@ -210,7 +198,7 @@ macro MArray(ex)
210198

211199
return quote
212200
$(esc(f_expr))
213-
$(esc(Expr(:call, Expr(:curly, :MArray, (rng_lengths...)), Expr(:tuple, exprs...))))
201+
$(esc(Expr(:call, Expr(:curly, :MArray, Tuple{rng_lengths...}), Expr(:tuple, exprs...))))
214202
end
215203
elseif isa(ex, Expr) && ex.head == :typed_comprehension
216204
if length(ex.args) != 2 || !isa(ex.args[2], Expr) || ex.args[2].head != :generator
@@ -249,7 +237,7 @@ macro MArray(ex)
249237

250238
return quote
251239
$(esc(f_expr))
252-
$(esc(Expr(:call, Expr(:curly, :MArray, (rng_lengths...), T), Expr(:tuple, exprs...))))
240+
$(esc(Expr(:call, Expr(:curly, :MArray, Tuple{rng_lengths...}, T), Expr(:tuple, exprs...))))
253241
end
254242
elseif isa(ex, Expr) && ex.head == :call
255243
if ex.args[1] == :zeros || ex.args[1] == :ones || ex.args[1] == :rand || ex.args[1] == :randn
@@ -258,9 +246,9 @@ macro MArray(ex)
258246
else
259247
return quote
260248
if isa($(esc(ex.args[2])), DataType)
261-
$(ex.args[1])($(esc(Expr(:curly, MArray, Expr(:tuple, ex.args[3:end]...), ex.args[2]))))
249+
$(ex.args[1])($(esc(Expr(:curly, MArray, Expr(:curly, Tuple, ex.args[3:end]...), ex.args[2]))))
262250
else
263-
$(ex.args[1])($(esc(Expr(:curly, MArray, Expr(:tuple, ex.args[2:end]...)))))
251+
$(ex.args[1])($(esc(Expr(:curly, MArray, Expr(:curly, Tuple, ex.args[2:end]...)))))
264252
end
265253
end
266254
end
@@ -271,26 +259,26 @@ macro MArray(ex)
271259
error("@MArray got bad expression: $(ex.args[1])($(ex.args[2]))")
272260
else
273261
return quote
274-
$(esc(ex.args[1]))($(esc(ex.args[2])), MArray{$(esc(Expr(:tuple, ex.args[3:end]...)))})
262+
$(esc(ex.args[1]))($(esc(ex.args[2])), MArray{$(esc(Expr(:curly, Tuple, ex.args[3:end]...)))})
275263
end
276264
end
277265
elseif ex.args[1] == :eye
278266
if length(ex.args) == 2
279267
return quote
280-
eye(MArray{($(esc(ex.args[2])), $(esc(ex.args[2])))})
268+
eye(MArray{Tuple{$(esc(ex.args[2])), $(esc(ex.args[2]))}})
281269
end
282270
elseif length(ex.args) == 3
283271
# We need a branch, depending if the first argument is a type or a size.
284272
return quote
285273
if isa($(esc(ex.args[2])), DataType)
286-
eye(MArray{($(esc(ex.args[3])), $(esc(ex.args[3]))), $(esc(ex.args[2]))})
274+
eye(MArray{Tuple{$(esc(ex.args[3])), $(esc(ex.args[3]))}, $(esc(ex.args[2]))})
287275
else
288-
eye(MArray{($(esc(ex.args[2])), $(esc(ex.args[3])))})
276+
eye(MArray{Tuple{$(esc(ex.args[2])), $(esc(ex.args[3]))}})
289277
end
290278
end
291279
elseif length(ex.args) == 4
292280
return quote
293-
eye(MArray{($(esc(ex.args[3])), $(esc(ex.args[4]))), $(esc(ex.args[2]))})
281+
eye(MArray{Tuple{$(esc(ex.args[3])), $(esc(ex.args[4]))}, $(esc(ex.args[2]))})
294282
end
295283
else
296284
error("Bad eye() expression for @MArray")

src/MMatrix.jl

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,7 @@ Construct a statically-sized, mutable matrix of dimensions `S1 × S2` using the
1515
`mat`. The parameters `S1` and `S2` are mandatory since the size of `mat` is
1616
unknown to the compiler (the element type may optionally also be specified).
1717
"""
18-
type MMatrix{S1, S2, T, L} <: StaticMatrix{T}
19-
data::NTuple{L, T}
20-
21-
function (::Type{MMatrix{S1,S2,T,L}}){S1,S2,T,L}(d::NTuple{L,T})
22-
check_MMatrix_params(Val{S1}, Val{S2}, T, Val{L})
23-
new{S1,S2,T,L}(d)
24-
end
25-
26-
function (::Type{MMatrix{S1,S2,T,L}}){S1,S2,T,L}(d::NTuple{L,Any})
27-
check_MMatrix_params(Val{S1}, Val{S2}, T, Val{L})
28-
new{S1,S2,T,L}(convert_ntuple(T, d))
29-
end
30-
31-
function (::Type{MMatrix{S1,S2,T,L}}){S1,S2,T,L}()
32-
check_MMatrix_params(Val{S1}, Val{S2}, T, Val{L})
33-
new{S1,S2,T,L}()
34-
end
35-
end
36-
37-
function check_MMatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, T, ::Type{Val{L}}) where {S1,S2,L}
38-
throw(ArgumentError("MMatrix: Parameter T must be a Type. Got $T"))
39-
end
40-
41-
@generated function check_MMatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, ::Type{T}, ::Type{Val{L}}) where {S1,S2,L,T}
42-
if !isa(S1, Int) || !isa(S2, Int) || !isa(L, Int) || S1 < 0 || S2 < 0 || L < 0
43-
throw(ArgumentError("MMatrix: Sizes must be positive integers. Got $S1 × $S2 ($L elements)"))
44-
end
45-
46-
if S1*S2 == L
47-
return nothing
48-
else
49-
throw(ArgumentError("Size mismatch in MMatrix. S1 = $S1, S2 = $S2, but recieved $L elements"))
50-
end
51-
end
18+
const MMatrix{S1, S2, T, L} = MArray{Tuple{S1, S2}, T, 2, L}
5219

5320
@generated function (::Type{MMatrix{S1}}){S1,L}(x::NTuple{L})
5421
S2 = div(L, S1)

src/MVector.jl

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,7 @@ Construct a statically-sized, mutable vector of length `S` using the data from
1414
`vec`. The parameter `S` is mandatory since the length of `vec` is unknown to the
1515
compiler (the element type may optionally also be specified).
1616
"""
17-
type MVector{S, T} <: StaticVector{T}
18-
data::NTuple{S, T}
19-
20-
function (::Type{MVector{S,T}}){S,T}(in::NTuple{S, T})
21-
new{S,T}(in)
22-
end
23-
24-
function (::Type{MVector{S,T}}){S,T}(in::NTuple{S, Any})
25-
new{S,T}(convert_ntuple(T,in))
26-
end
27-
28-
function (::Type{MVector{S,T}}){S,T}(in::T)
29-
new{S,T}((in,))
30-
end
31-
32-
function (::Type{MVector{S,T}}){S,T}()
33-
new{S,T}()
34-
end
35-
end
17+
const MVector{S, T} = MArray{Tuple{S}, T, 1, S}
3618

3719
@inline (::Type{MVector}){S}(x::NTuple{S,Any}) = MVector{S}(x)
3820
@inline (::Type{MVector{S}}){S, T}(x::NTuple{S,T}) = MVector{S,T}(x)

0 commit comments

Comments
 (0)