@@ -24,34 +24,47 @@ _size1(::Type{<:StaticMatrix{M}}) where {M} = M
2424 return :($ N)
2525end
2626
27- const FirstClass = Union{SArray, MArray, SHermitianCompact, SizedArray}
28-
2927"""
30- construct_type(::Type{<:StaticArray }, x)
28+ construct_type(::Type{SA }, x) where {SA<:StaticArray}
3129
3230Returns a constructor for a statically-sized array based on `x`'s size and eltype.
33- The first argument is returned by default.
31+ If no derivation rules are provided, the default return value is `SA` itself.
32+
33+ Offical `StaticArray`s have specific `construct_type` defined to support size/eltype
34+ adaptation during construction.
35+
36+ # `SA <: FieldArray`
37+
38+ `FieldArray`s should always be fully static-sized. We only derive the output's eltype using type promotion if needed.
39+
40+ # `SA <: Union{SArray, MArray, SHermitianCompact, SizedArray}`
41+
42+ These `StaticArray`s support size/eltype derivation during construction.
43+ The adaption rule could be summarized as:
44+ - SA(x::Tuple)
45+ If `SA` is fully static-sized, then we first try to fill `SA` with `x`'s elements.
46+ If failed and `length(SA) == 1`, then we try to fill `SA` with `x` itself.
47+
48+ If `SA` is not fully static-sized, then we always try to fill `SA` with `x`'s elements,
49+ and the constructor's `Size` is derived based on:
50+ 1. If `SA <: StaticVector`, then we use `length(x)` as the output `Length`
51+ 2. If `SA <: StaticMatrix{M}`, then we use `(M, N)` (`N = length(x) ÷ M`) as the output `Size`
52+ 3. If `SA <: StaticMatrix{M,M} where M`, then we use `(N, N)` (`N = sqrt(length(x)`) as the output `Size`.
53+ - SA(x...)
54+ Similar to `Tuple`, but we never fill `SA` with `x` itself.
55+ - SA(x::StaticArray)
56+ We treat `x` as `Tuple` whenever possible. If failed, then try to inherit `x`'s `Size`.
57+ - SA(x::AbstractArray)
58+ `x` is used to provide eltype. Thus `SA` must be static sized.
3459"""
3560function construct_type (:: Type{SA} , x) where {SA<: StaticArray }
3661 x isa BadArgs || return SA
3762 _no_precise_size (SA, x. args[1 ][1 ])
3863end
3964
40- # Here we define `construct_type(SA, x)` for `SArray`, `MArray`, `SHermitianCompact`, `SizedArray`
41- # Different `x` has different rules, to summarize:
42- # 1. Tuple
43- # We try to fill `SA` with elements in `x` if `SA` is static-sized.
44- # If `SA <: StaticVector`, the output `Length` is derived based on `length(x)`.
45- # If `SA <: StaticMatrix{M}`, the output `Size` is derived based on `length(x)÷M`.
46- # If `SA <: StaticMatrix{M,M} where M`, the output `Size` is derived based on `sqrt(length(x))`.
47- # If `length(SA) == 1 && length(x) > 1`, then we tries to fill `SA` with `x` itself. (rewrapping)
48- # 2. Args (`SA(x...)`)
49- # Similar to `Tuple`, but rewrapping is not allowed.
50- # 3. StaticArray
51- # Treat `x` as `Tuple` whenever possible. If failed, then try to inherit `x`'s `Size`.
52- # 4. AbstractArray
53- # `x` is used to provide eltype. Thus `SA` must be static sized.
54- function construct_type (:: Type{SA} , x) where {SA<: FirstClass }
65+ # These StaticArrays support `size`/`eltype` adaption during construction.
66+ const SizeEltypeAdaptable = Union{SArray, MArray, SHermitianCompact, SizedArray}
67+ function construct_type (:: Type{SA} , x) where {SA<: SizeEltypeAdaptable }
5568 SA′ = adapt_eltype_size (SA, x)
5669 check_parameters (SA′)
5770 x isa Tuple && SA === SA′ && error (" Constructor for $SA is missing. Please file a bug." )
@@ -113,10 +126,10 @@ end
113126
114127need_rewrap (:: Type{<:StaticArray} , x) = false
115128function need_rewrap (:: Type{SA} , x:: Union{Tuple,StaticArray} ) where {SA <: StaticArray }
116- has_size (SA) && length (SA) == 1 && length (x) > 1
129+ has_size (SA) && length (SA) == 1 && length (x) != 1
117130end
118131
119- check_parameters (:: Type{<:FirstClass } ) = nothing
132+ check_parameters (:: Type{<:SizeEltypeAdaptable } ) = nothing
120133check_parameters (:: Type{SArray{S,T,N,L}} ) where {S<: Tuple ,T,N,L} = check_array_parameters (S,T,Val{N},Val{L})
121134check_parameters (:: Type{MArray{S,T,N,L}} ) where {S<: Tuple ,T,N,L} = check_array_parameters (S,T,Val{N},Val{L})
122135check_parameters (:: Type{SHermitianCompact{N,T,L}} ) where {N,T,L} = _check_hermitian_parameters (Val (N), Val (L))
@@ -127,7 +140,7 @@ _no_precise_size(SA, x::StaticArray) = throw(DimensionMismatch("No precise const
127140_no_precise_size (SA, x) = throw (DimensionMismatch (" No precise constructor for $SA found. Input is not static sized." ))
128141
129142@inline (:: Type{SA} )(x... ) where {SA <: StaticArray } = construct_type (SA, Args (x))(x)
130- @inline function (:: Type{SA} )(x:: Tuple ) where {SA <: FirstClass }
143+ @inline function (:: Type{SA} )(x:: Tuple ) where {SA <: SizeEltypeAdaptable }
131144 SA′ = construct_type (SA, x)
132145 need_rewrap (SA′, x) ? SA′ ((x,)) : SA′ (x)
133146end
0 commit comments