Skip to content

Commit b1714d9

Browse files
Kenoandyferris
authored andcommitted
RFC: Unify SArray,SMatrix,SVector (#127)
* RFC: Unify SArray,SMatrix,SVector After the recent refactor something that used to be an SMatrix became a two dimensional SArray (or vice versa - who can keep track). That situation seems unfortunate and unnecessary, so this is an attempt to unify them. This is decently breaking, because it requires the SArray dimension tuple to be e.g. `Tuple{1,2}` rather than `(1,2)`, but should allow us to avoid quite a bit of duplication. These are just the minimal changes to get this running. I would imagine, we could remove some further duplication in follow up patches. * Bring Scalar/MArray into the fold
1 parent 91ed94a commit b1714d9

17 files changed

+227
-310
lines changed

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)