Skip to content

Commit 8ca11f8

Browse files
authored
Code clean and reuse for constructor. (#1016)
* Define `construct_type` Similar to `similar_type`, but not fallback to `SArray`. It is used to pick the most `concrete` constructor with `size`, `eltype` and `ndims` defined. * Define general `constructor` with `construct_type` * Define general `convert` with `construct_type`. And fix for input with non-1 based axes. * Make `FieldArray`'s general constructor based on `construct_type` This also enable auto type promotion. * `Constructor` and `convertor` clean. With `construct_type`, there's no need to keep all these dispatches. This also fix empty construction for `S/MVector`, and remove most of the ambiguities. * Add more test * Test fix and clean. * Drop `StaticSquareMatrix` & add more test. 1. remove `StaticSquareMatrix` (`StaticMatrix{N,N}` should be shorter and clear enough) 2. Add missing Test. * Add constructor test for `OffsetArray`. * Rename `FirstClass` as `SizeEltypeAdaptable` And convert comments to docstring. * Replace `_NTuple` with `_TupleOf` and typo fix.
1 parent c09bc9a commit 8ca11f8

26 files changed

+351
-248
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ julia = "1.6"
1313
[extras]
1414
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
1515
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
16+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
1617
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1718

1819
[targets]
19-
test = ["InteractiveUtils", "Test", "BenchmarkTools"]
20+
test = ["InteractiveUtils", "Test", "BenchmarkTools", "OffsetArrays"]

src/FieldArray.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ array operations as in the example below.
110110
"""
111111
abstract type FieldVector{N, T} <: FieldArray{Tuple{N}, T, 1} end
112112

113-
@inline function (::Type{FA})(x::Tuple{Vararg{Any, N}}) where {N, FA <: FieldArray}
114-
@boundscheck if length(FA) != length(x)
115-
throw(DimensionMismatch("No precise constructor for $FA found. Length of input was $(length(x))."))
116-
end
117-
return FA(x...)
113+
@inline (::Type{FA})(x::Tuple) where {FA <: FieldArray} = construct_type(FA, x)(x...)
114+
115+
function construct_type(::Type{FA}, x) where {FA <: FieldArray}
116+
has_size(FA) || error("$FA has no static size!")
117+
length_match_size(FA, x)
118+
return adapt_eltype(FA, x)
118119
end
119120

120121
@propagate_inbounds getindex(a::FieldArray, i::Int) = getfield(a, i)

src/MArray.jl

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,42 +20,23 @@ the compiler (the element type may optionally also be specified).
2020
mutable struct MArray{S <: Tuple, T, N, L} <: StaticArray{S, T, N}
2121
data::NTuple{L,T}
2222

23-
function MArray{S,T,N,L}(x::NTuple{L,T}) where {S,T,N,L}
23+
function MArray{S,T,N,L}(x::NTuple{L,T}) where {S<:Tuple,T,N,L}
2424
check_array_parameters(S, T, Val{N}, Val{L})
2525
new{S,T,N,L}(x)
2626
end
2727

28-
function MArray{S,T,N,L}(x::NTuple{L,Any}) where {S,T,N,L}
28+
function MArray{S,T,N,L}(x::NTuple{L,Any}) where {S<:Tuple,T,N,L}
2929
check_array_parameters(S, T, Val{N}, Val{L})
3030
new{S,T,N,L}(convert_ntuple(T, x))
3131
end
3232

33-
function MArray{S,T,N,L}(::UndefInitializer) where {S,T,N,L}
33+
function MArray{S,T,N,L}(::UndefInitializer) where {S<:Tuple,T,N,L}
3434
check_array_parameters(S, T, Val{N}, Val{L})
3535
new{S,T,N,L}()
3636
end
3737
end
3838

39-
@generated function (::Type{MArray{S,T,N}})(x::Tuple) where {S,T,N}
40-
return quote
41-
$(Expr(:meta, :inline))
42-
MArray{S,T,N,$(tuple_prod(S))}(x)
43-
end
44-
end
45-
46-
@generated function (::Type{MArray{S,T}})(x::Tuple) where {S,T}
47-
return quote
48-
$(Expr(:meta, :inline))
49-
MArray{S,T,$(tuple_length(S)),$(tuple_prod(S))}(x)
50-
end
51-
end
52-
53-
@generated function (::Type{MArray{S}})(x::T) where {S, T <: Tuple}
54-
return quote
55-
$(Expr(:meta, :inline))
56-
MArray{S,promote_tuple_eltype(T),$(tuple_length(S)),$(tuple_prod(S))}(x)
57-
end
58-
end
39+
@inline MArray{S,T,N}(x::Tuple) where {S<:Tuple,T,N} = MArray{S,T,N,tuple_prod(S)}(x)
5940

6041
@generated function (::Type{MArray{S,T,N}})(::UndefInitializer) where {S,T,N}
6142
return quote
@@ -71,8 +52,6 @@ end
7152
end
7253
end
7354

74-
@inline MArray(a::StaticArray{S,T}) where {S<:Tuple,T} = MArray{S,T}(Tuple(a))
75-
7655
####################
7756
## MArray methods ##
7857
####################

src/MMatrix.jl

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,13 @@ unknown to the compiler (the element type may optionally also be specified).
1717
"""
1818
const MMatrix{S1, S2, T, L} = MArray{Tuple{S1, S2}, T, 2, L}
1919

20-
@generated function (::Type{MMatrix{S1}})(x::NTuple{L}) where {S1,L}
21-
S2 = div(L, S1)
22-
if S1*S2 != L
23-
throw(DimensionMismatch("Incorrect matrix sizes. $S1 does not divide $L elements"))
24-
end
25-
return quote
26-
$(Expr(:meta, :inline))
27-
T = eltype(typeof(x))
28-
MMatrix{S1, $S2, T, L}(x)
29-
end
30-
end
31-
32-
@generated function (::Type{MMatrix{S1,S2}})(x::NTuple{L}) where {S1,S2,L}
33-
return quote
34-
$(Expr(:meta, :inline))
35-
T = eltype(typeof(x))
36-
MMatrix{S1, S2, T, L}(x)
37-
end
38-
end
39-
40-
@generated function (::Type{MMatrix{S1,S2,T}})(x::NTuple{L}) where {S1,S2,T,L}
41-
return quote
42-
$(Expr(:meta, :inline))
43-
MMatrix{S1, S2, T, L}(x)
44-
end
45-
end
46-
4720
@generated function (::Type{MMatrix{S1,S2,T}})(::UndefInitializer) where {S1,S2,T}
4821
return quote
4922
$(Expr(:meta, :inline))
5023
MMatrix{S1, S2, T, $(S1*S2)}(undef)
5124
end
5225
end
5326

54-
@inline convert(::Type{MMatrix{S1,S2}}, a::StaticArray{<:Tuple, T}) where {S1,S2,T} = MMatrix{S1,S2,T}(Tuple(a))
55-
@inline MMatrix(a::StaticMatrix{N,M,T}) where {N,M,T} = MMatrix{N,M,T}(Tuple(a))
56-
5727
# Some more advanced constructor-like functions
5828
@inline one(::Type{MMatrix{N}}) where {N} = one(MMatrix{N,N})
5929

src/MVector.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ compiler (the element type may optionally also be specified).
1616
"""
1717
const MVector{S, T} = MArray{Tuple{S}, T, 1, S}
1818

19-
@inline MVector(a::StaticVector{N,T}) where {N,T} = MVector{N,T}(a)
20-
@inline MVector(x::NTuple{S,Any}) where {S} = MVector{S}(x)
21-
@inline MVector{S}(x::NTuple{S,T}) where {S, T} = MVector{S, T}(x)
22-
@inline MVector{S}(x::NTuple{S,Any}) where {S} = MVector{S, promote_tuple_eltype(typeof(x))}(x)
23-
2419
# Some more advanced constructor-like functions
2520
@inline zeros(::Type{MVector{N}}) where {N} = zeros(MVector{N,Float64})
2621
@inline ones(::Type{MVector{N}}) where {N} = ones(MVector{N,Float64})

src/SArray.jl

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,18 @@ compiler (the element type may optionally also be specified).
1818
struct SArray{S <: Tuple, T, N, L} <: StaticArray{S, T, N}
1919
data::NTuple{L,T}
2020

21-
function SArray{S, T, N, L}(x::NTuple{L,T}) where {S, T, N, L}
21+
function SArray{S, T, N, L}(x::NTuple{L,T}) where {S<:Tuple, T, N, L}
2222
check_array_parameters(S, T, Val{N}, Val{L})
2323
new{S, T, N, L}(x)
2424
end
2525

26-
function SArray{S, T, N, L}(x::NTuple{L,Any}) where {S, T, N, L}
26+
function SArray{S, T, N, L}(x::NTuple{L,Any}) where {S<:Tuple, T, N, L}
2727
check_array_parameters(S, T, Val{N}, Val{L})
2828
new{S, T, N, L}(convert_ntuple(T, x))
2929
end
3030
end
3131

32-
@generated function (::Type{SArray{S, T, N}})(x::Tuple) where {S <: Tuple, T, N}
33-
return quote
34-
@_inline_meta
35-
SArray{S, T, N, $(tuple_prod(S))}(x)
36-
end
37-
end
38-
39-
@generated function (::Type{SArray{S, T}})(x::Tuple) where {S <: Tuple, T}
40-
return quote
41-
@_inline_meta
42-
SArray{S, T, $(tuple_length(S)), $(tuple_prod(S))}(x)
43-
end
44-
end
45-
46-
@generated function (::Type{SArray{S}})(x::T) where {S <: Tuple, T <: Tuple}
47-
return quote
48-
@_inline_meta
49-
SArray{S, promote_tuple_eltype(T), $(tuple_length(S)), $(tuple_prod(S))}(x)
50-
end
51-
end
52-
32+
@inline SArray{S,T,N}(x::Tuple) where {S<:Tuple,T,N} = SArray{S,T,N,tuple_prod(S)}(x)
5333

5434
@noinline function generator_too_short_error(inds::CartesianIndices, i::CartesianIndex)
5535
error("Generator produced too few elements: Expected exactly $(shape_string(inds)) elements, but generator stopped at $(shape_string(i))")
@@ -106,8 +86,6 @@ sacollect
10686
@inline (::Type{SA})(gen::Base.Generator) where {SA <: StaticArray} =
10787
sacollect(SA, gen)
10888

109-
@inline SArray(a::StaticArray{S,T}) where {S<:Tuple,T} = SArray{S,T}(Tuple(a))
110-
11189
####################
11290
## SArray methods ##
11391
####################

src/SHermitianCompact.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ lowertriangletype(::Type{SHermitianCompact{N}}) where {N} = SVector{triangularnu
6060
end
6161

6262
@generated function SHermitianCompact{N, T, L}(a::Tuple) where {N, T, L}
63+
_check_hermitian_parameters(Val(N), Val(L))
6364
expr = Vector{Expr}(undef, L)
6465
i = 0
6566
for col = 1 : N, row = col : N
@@ -77,15 +78,13 @@ end
7778
SHermitianCompact{N, T, L}(a)
7879
end
7980

80-
@inline SHermitianCompact{N}(a::Tuple) where {N} = SHermitianCompact{N, promote_tuple_eltype(a)}(a)
81-
@inline SHermitianCompact{N}(a::NTuple{M, T}) where {N, T, M} = SHermitianCompact{N, T}(a)
82-
@inline SHermitianCompact(a::StaticMatrix{N, N, T}) where {N, T} = SHermitianCompact{N, T}(a)
83-
8481
@inline (::Type{SSC})(a::SHermitianCompact) where {SSC <: SHermitianCompact} = SSC(a.lowertriangle)
85-
@inline (::Type{SSC})(a::SSC) where {SSC <: SHermitianCompact} = a
8682

8783
@inline (::Type{SSC})(a::AbstractVector) where {SSC <: SHermitianCompact} = SSC(convert(lowertriangletype(SSC), a))
8884

85+
# disambiguation
86+
@inline (::Type{SSC})(a::StaticArray{<:Tuple,<:Any,1}) where {SSC <: SHermitianCompact} = SSC(convert(SVector, a))
87+
8988
@generated function _hermitian_compact_indices(::Val{N}) where N
9089
# Returns a Tuple{Pair{Int, Bool}} I such that for linear index i,
9190
# * I[i][1] is the index into the lowertriangle field of an SHermitianCompact{N};

src/SMatrix.jl

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,61 +16,13 @@ unknown to the compiler (the element type may optionally also be specified).
1616
"""
1717
const SMatrix{S1, S2, T, L} = SArray{Tuple{S1, S2}, T, 2, L}
1818

19-
@generated function SMatrix{S1}(x::NTuple{L,Any}) where {S1,L}
20-
S2 = div(L, S1)
21-
if S1*S2 != L
22-
throw(DimensionMismatch("Incorrect matrix sizes. $S1 does not divide $L elements"))
23-
end
24-
25-
return quote
26-
$(Expr(:meta, :inline))
27-
T = promote_tuple_eltype(typeof(x))
28-
SMatrix{S1, $S2, T, L}(x)
29-
end
30-
end
31-
32-
@generated function SMatrix{S1,S2}(x::NTuple{L,Any}) where {S1,S2,L}
33-
return quote
34-
$(Expr(:meta, :inline))
35-
T = promote_tuple_eltype(typeof(x))
36-
SMatrix{S1, S2, T, L}(x)
37-
end
38-
end
39-
SMatrixNoType{S1, S2, L, T} = SMatrix{S1, S2, T, L}
40-
@generated function SMatrixNoType{S1, S2, L}(x::NTuple{L,Any}) where {S1,S2,L}
41-
return quote
42-
$(Expr(:meta, :inline))
43-
T = promote_tuple_eltype(typeof(x))
44-
SMatrix{S1, S2, T, L}(x)
45-
end
46-
end
47-
48-
@generated function SMatrix{S1,S2,T}(x::NTuple{L,Any}) where {S1,S2,T,L}
49-
return quote
50-
$(Expr(:meta, :inline))
51-
SMatrix{S1, S2, T, L}(x)
52-
end
53-
end
54-
55-
@inline SMatrix{M, N, T}(gen::Base.Generator) where {M, N, T} =
56-
sacollect(SMatrix{M, N, T}, gen)
57-
@inline SMatrix{M, N}(gen::Base.Generator) where {M, N} =
58-
sacollect(SMatrix{M, N}, gen)
59-
60-
@inline convert(::Type{SMatrix{S1,S2}}, a::StaticArray{<:Tuple, T}) where {S1,S2,T} = SMatrix{S1,S2,T}(Tuple(a))
61-
@inline SMatrix(a::StaticMatrix{S1, S2, T}) where {S1, S2, T} = SMatrix{S1, S2, T}(Tuple(a))
62-
6319
# Some more advanced constructor-like functions
6420
@inline one(::Type{SMatrix{N}}) where {N} = one(SMatrix{N,N})
6521

6622
#####################
6723
## SMatrix methods ##
6824
#####################
6925

70-
@propagate_inbounds function getindex(v::SMatrix, i::Int)
71-
v.data[i]
72-
end
73-
7426
function check_matrix_size(x::Tuple, T = :S)
7527
if length(x) > 2
7628
all(isone, x[3:end]) || error("Bad input for @$(T)Matrix, must be matrix like.")

src/SVector.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,6 @@ compiler (the element type may optionally also be specified).
1515
"""
1616
const SVector{S, T} = SArray{Tuple{S}, T, 1, S}
1717

18-
@inline SVector(a::StaticVector{N,T}) where {N,T} = SVector{N,T}(a)
19-
@inline SVector(x::NTuple{S,Any}) where {S} = SVector{S}(x)
20-
@inline SVector{S}(x::NTuple{S,T}) where {S, T} = SVector{S,T}(x)
21-
@inline SVector{S}(x::T) where {S, T <: Tuple} = SVector{S,promote_tuple_eltype(T)}(x)
22-
23-
@inline SVector{N, T}(gen::Base.Generator) where {N, T} =
24-
sacollect(SVector{N, T}, gen)
25-
@inline SVector{N}(gen::Base.Generator) where {N} =
26-
sacollect(SVector{N}, gen)
27-
28-
# conversion from AbstractVector / AbstractArray (better inference than default)
29-
#@inline convert{S,T}(::Type{SVector{S}}, a::AbstractArray{T}) = SVector{S,T}((a...))
30-
3118
# Some more advanced constructor-like functions
3219
@inline zeros(::Type{SVector{N}}) where {N} = zeros(SVector{N,Float64})
3320
@inline ones(::Type{SVector{N}}) where {N} = ones(SVector{N,Float64})

src/Scalar.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ Construct a statically-sized 0-dimensional array that contains a single element,
66
"""
77
const Scalar{T} = SArray{Tuple{},T,0,1}
88

9-
@inline Scalar(x::Tuple{T}) where {T} = Scalar{T}(x[1])
109
@inline Scalar(a::AbstractArray) = Scalar{typeof(a)}((a,))
10+
@inline Scalar(a::StaticArray) = Scalar{typeof(a)}((a,)) # disambiguation
11+
1112
@inline Scalar(a::AbstractScalar) = Scalar{eltype(a)}((a[],)) # Do we want this to convert or wrap?
12-
@inline function convert(::Type{SA}, a::AbstractArray) where {SA <: Scalar}
13-
return SA((a[],))
14-
end
15-
@inline convert(::Type{SA}, sa::SA) where {SA <: Scalar} = sa
13+
@inline Scalar(a::StaticScalar) = Scalar{eltype(a)}((a[],)) # disambiguation
1614

1715
@propagate_inbounds function getindex(v::Scalar, i::Int)
1816
@boundscheck if i != 1

0 commit comments

Comments
 (0)