@@ -35,7 +35,7 @@ consider defining `similar_type` as in the `FieldVector` example.
35
35
yyyy::Float64
36
36
end
37
37
"""
38
- abstract type FieldArray{N, T, D} <: StaticArray{N, T, D} end
38
+ abstract type FieldArray{N,T, D} <: StaticArray{N,T, D} end
39
39
40
40
"""
41
41
abstract FieldMatrix{N1, N2, T} <: FieldArray{Tuple{N1, N2}, 2}
@@ -84,7 +84,7 @@ you may consider using the alternative
84
84
4.0 5.0 6.0;
85
85
7.0 8.0 9.0])
86
86
"""
87
- abstract type FieldMatrix{N1, N2, T} <: FieldArray{Tuple{N1, N2}, T, 2} end
87
+ abstract type FieldMatrix{N1,N2,T} <: FieldArray{Tuple{N1,N2},T, 2} end
88
88
89
89
"""
90
90
abstract FieldVector{N, T} <: FieldArray{Tuple{N}, 1}
@@ -108,11 +108,11 @@ array operations as in the example below.
108
108
109
109
StaticArrays.similar_type(::Type{<:Vec3D}, ::Type{T}, s::Size{(3,)}) where {T} = Vec3D{T}
110
110
"""
111
- abstract type FieldVector{N, T} <: FieldArray{Tuple{N}, T, 1} end
111
+ abstract type FieldVector{N,T} <: FieldArray{Tuple{N},T, 1} end
112
112
113
- @inline (:: Type{FA} )(x:: Tuple ) where {FA <: FieldArray } = construct_type (FA, x)(x... )
113
+ @inline (:: Type{FA} )(x:: Tuple ) where {FA<: FieldArray } = construct_type (FA, x)(x... )
114
114
115
- function construct_type (:: Type{FA} , x) where {FA <: FieldArray }
115
+ function construct_type (:: Type{FA} , x) where {FA<: FieldArray }
116
116
has_size (FA) || error (" $FA has no static size!" )
117
117
length_match_size (FA, x)
118
118
return adapt_eltype (FA, x)
@@ -125,14 +125,20 @@ Base.cconvert(::Type{<:Ptr}, a::FieldArray) = Base.RefValue(a)
125
125
Base. unsafe_convert (:: Type{Ptr{T}} , m:: Base.RefValue{FA} ) where {N,T,D,FA<: FieldArray{N,T,D} } =
126
126
Ptr {T} (Base. unsafe_convert (Ptr{FA}, m))
127
127
128
- # We can automatically preserve FieldArrays in array operations which do not
129
- # change their eltype or Size. This should cover all non-parametric FieldArray,
130
- # but for those which are parametric on the eltype the user will still need to
131
- # overload similar_type themselves.
132
- similar_type (:: Type{A} , :: Type{T} , S:: Size ) where {N, T, A<: FieldArray{N, T} } =
133
- _fieldarray_similar_type (A, T, S, Size (A))
134
-
135
- # Extra layer of dispatch to match NewSize and OldSize
136
- _fieldarray_similar_type (A, T, NewSize:: S , OldSize:: S ) where {S} = A
137
- _fieldarray_similar_type (A, T, NewSize, OldSize) =
138
- default_similar_type (T, NewSize, length_val (NewSize))
128
+ # We can preserve FieldArrays in array operations which do not change their `Size` and `eltype`.
129
+ # FieldArrays with parametric `eltype` would be adapted to the new `eltype` automatically.
130
+ # Otherwise, we fallback to `S/MArray` based on it's mutability.
131
+ function similar_type (:: Type{A} , :: Type{T} , S:: Size ) where {T,A<: FieldArray }
132
+ A′ = Base. typeintersect (base_type (A), StaticArray{Tuple{Tuple (S)... },T,length (S)})
133
+ isabstracttype (A′) || A′ === Union{} || return A′
134
+ if ismutabletype (A)
135
+ return mutable_similar_type (T, S, length_val (S))
136
+ else
137
+ return default_similar_type (T, S, length_val (S))
138
+ end
139
+ end
140
+
141
+ @pure base_type (@nospecialize (T:: Type )) = Base. unwrap_unionall (T). name. wrapper
142
+ if VERSION < v " 1.7"
143
+ @pure ismutabletype (@nospecialize (T:: Type )) = Base. unwrap_unionall (T). mutable
144
+ end
0 commit comments