@@ -123,25 +123,33 @@ end
123
123
return SVector {s[1], T} (vals)
124
124
end
125
125
126
+ # Utility to rewrap `Eigen` of normal `Array` into an Eigen containing `SArray`.
127
+ @inline function _make_static (s:: Size , E:: Eigen{T,V} ) where {T,V}
128
+ Eigen (similar_type (SVector, V, Size (s[1 ]))(E. values),
129
+ similar_type (SMatrix, T, s)(E. vectors))
130
+ end
126
131
127
- @inline function _eig (s:: Size , A:: StaticMatrix , permute, scale)
128
- # Only cover the hermitian branch, for now at least
129
- # This also solves some type-stability issues that arise in Base
132
+ @inline function _eig (s:: Size , A:: T , permute, scale) where {T <: StaticMatrix }
130
133
if ishermitian (A)
131
- return _eig (s, Hermitian (A), permute, scale)
134
+ return _eig (s, Hermitian (A), permute, scale)
132
135
else
133
- error (" Only hermitian matrices are diagonalizable by *StaticArrays*. Non-Hermitian matrices should be converted to `Array` first." )
136
+ # For the non-hermitian branch fall back to LinearAlgebra eigen().
137
+ # Eigenvalues could be real or complex so a Union of concrete types is
138
+ # inferred. Having _make_static a separate function allows inference to
139
+ # preserve the union of concrete types:
140
+ # Union{E{A,B},E{C,D}} -> Union{E{SA,SB},E{SC,SD}}
141
+ _make_static (s, eigen (Array (A); permute = permute, scale = scale))
134
142
end
135
143
end
136
144
137
145
@inline function _eig (s:: Size , A:: LinearAlgebra.RealHermSymComplexHerm{T} , permute, scale) where {T <: Real }
138
146
E = eigen (Hermitian (Array (parent (A))))
139
- return (SVector {s[1], T} (E. values), SMatrix {s[1], s[2], eltype(A)} (E. vectors))
147
+ return Eigen (SVector {s[1], T} (E. values), SMatrix {s[1], s[2], eltype(A)} (E. vectors))
140
148
end
141
149
142
150
143
151
@inline function _eig (:: Size{(1,1)} , A:: LinearAlgebra.RealHermSymComplexHerm{T} , permute, scale) where {T <: Real }
144
- @inbounds return (SVector {1,T} ((real (A[1 ]),)), SMatrix {1,1,eltype(A)} (I))
152
+ @inbounds return Eigen (SVector {1,T} ((real (A[1 ]),)), SMatrix {1,1,eltype(A)} (I))
145
153
end
146
154
147
155
@inline function _eig (:: Size{(2,2)} , A:: LinearAlgebra.RealHermSymComplexHerm{T} , permute, scale) where {T <: Real }
170
178
vecs = @SMatrix [ v11 v21 ;
171
179
v12 v22 ]
172
180
173
- return (vals, vecs)
181
+ return Eigen (vals, vecs)
174
182
end
175
183
else # A.uplo == 'L'
176
184
if ! iszero (a[2 ]) # A is not diagonal
194
202
vecs = @SMatrix [ v11 v21 ;
195
203
v12 v22 ]
196
204
197
- return (vals,vecs)
205
+ return Eigen (vals,vecs)
198
206
end
199
207
end
200
208
210
218
vecs = @SMatrix [convert (TA, 0 ) convert (TA, 1 );
211
219
convert (TA, 1 ) convert (TA, 0 )]
212
220
end
213
- return (vals,vecs)
221
+ return Eigen (vals,vecs)
214
222
end
215
223
216
224
# A small part of the code in the following method was inspired by works of David
@@ -243,19 +251,19 @@ end
243
251
244
252
if a11 < a22
245
253
if a22 < a33
246
- return (SVector (a11, a22, a33), hcat (v1,v2,v3))
254
+ return Eigen (SVector (( a11, a22, a33) ), hcat (v1,v2,v3))
247
255
elseif a33 < a11
248
- return (SVector (a33, a11, a22), hcat (v3,v1,v2))
256
+ return Eigen (SVector (( a33, a11, a22) ), hcat (v3,v1,v2))
249
257
else
250
- return (SVector (a11, a33, a22), hcat (v1,v3,v2))
258
+ return Eigen (SVector (( a11, a33, a22) ), hcat (v1,v3,v2))
251
259
end
252
260
else # a22 < a11
253
261
if a11 < a33
254
- return (SVector (a22, a11, a33), hcat (v2,v1,v3))
262
+ return Eigen (SVector (( a22, a11, a33) ), hcat (v2,v1,v3))
255
263
elseif a33 < a22
256
- return (SVector (a33, a22, a11), hcat (v3,v2,v1))
264
+ return Eigen (SVector (( a33, a22, a11) ), hcat (v3,v2,v1))
257
265
else
258
- return (SVector (a22, a33, a11), hcat (v2,v3,v1))
266
+ return Eigen (SVector (( a22, a33, a11) ), hcat (v2,v3,v1))
259
267
end
260
268
end
261
269
end
@@ -392,12 +400,11 @@ end
392
400
(eigvec1, eigvec3) = (eigvec3, eigvec1)
393
401
end
394
402
395
- return (SVector (eig1, eig2, eig3), hcat (eigvec1, eigvec2, eigvec3))
403
+ return Eigen (SVector (eig1, eig2, eig3), hcat (eigvec1, eigvec2, eigvec3))
396
404
end
397
405
398
406
@inline function eigen (A:: StaticMatrix ; permute:: Bool = true , scale:: Bool = true )
399
- vals, vecs = _eig (Size (A), A, permute, scale)
400
- return Eigen (vals, vecs)
407
+ _eig (Size (A), A, permute, scale)
401
408
end
402
409
403
410
# to avoid method ambiguity with LinearAlgebra
407
414
@inline eigen (A:: Symmetric{<:Complex,<:StaticMatrix} ; kwargs... ) = _eigen (A; kwargs... )
408
415
409
416
@inline function _eigen (A:: LinearAlgebra.HermOrSym ; permute:: Bool = true , scale:: Bool = true )
410
- vals, vecs = _eig (Size (A), A, permute, scale)
411
- return Eigen (vals, vecs)
417
+ _eig (Size (A), A, permute, scale)
412
418
end
413
419
414
420
# NOTE: The following Boost Software License applies to parts of the method:
0 commit comments