@@ -169,17 +169,63 @@ kron(a::Vector, b::Vector)=vec(kron(reshape(a,length(a),1),reshape(b,length(b),1
169
169
kron (a:: Matrix , b:: Vector )= kron (a,reshape (b,length (b),1 ))
170
170
kron (a:: Vector , b:: Matrix )= kron (reshape (a,length (a),1 ),b)
171
171
172
- ^ (A:: Matrix , p:: Integer ) = p < 0 ? inv (A^- p) : Base. power_by_squaring (A,p)
173
-
174
- function ^ (A:: Matrix , p:: Number )
172
+ # Matrix power
173
+ ^ (A:: AbstractMatrix , p:: Integer ) = p < 0 ? Base. power_by_squaring (inv (A),- p) : Base. power_by_squaring (A,p)
174
+ function ^ (A:: AbstractMatrix , p:: Real )
175
+ # For integer powers, use repeated squaring
175
176
if isinteger (p)
176
177
return A^ Integer (real (p))
177
178
end
178
- chksquare (A)
179
- v, X = eig (A)
180
- any (v.< 0 ) && (v = complex (v))
181
- Xinv = ishermitian (A) ? X' : inv (X)
182
- scale (X, v.^ p)* Xinv
179
+
180
+ # If possible, use diagonalization
181
+ if issym (A)
182
+ return full (Symmetric (A)^ p)
183
+ end
184
+ if ishermitian (A)
185
+ return full (Hermitian (A)^ p)
186
+ end
187
+
188
+ # General matrices
189
+ p1 = p - floor (p)
190
+ if cond (A) >= exp (log (p1/ (1 - p1)) / p1)
191
+ return powm (A,p1) * A^ floor (p)
192
+ else
193
+ return powm (A,p - ceil (p)) * A^ ceil (A)
194
+ end
195
+ end
196
+ function powm (A:: StridedMatrix , p:: Real )
197
+ if abs (p) >= 1
198
+ ArgumentError (" p must be a real number in (-1,1), got $p " )
199
+ end
200
+
201
+ # Use Schur decomposition
202
+ n = chksquare (A)
203
+ if istriu (A)
204
+ retmat = full (powm (UpperTriangular (complex (A)),p))
205
+ d = diag (A)
206
+ else
207
+ S,Q,d = schur (complex (A))
208
+ R = powm (UpperTriangular (S),p)
209
+ retmat = Q * R * Q'
210
+ end
211
+
212
+ # Check whether the matrix has nonpositive real eigs
213
+ np_real_eigs = false
214
+ for i = 1 : n
215
+ if imag (d[i]) < eps () && real (d[i]) <= 0
216
+ np_real_eigs = true
217
+ break
218
+ end
219
+ end
220
+ if np_real_eigs
221
+ warn (" Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned." )
222
+ end
223
+
224
+ if isreal (A) && ~ np_real_eigs
225
+ return real (retmat)
226
+ else
227
+ return retmat
228
+ end
183
229
end
184
230
185
231
# Matrix exponential
@@ -286,6 +332,9 @@ expm(x::Number) = exp(x)
286
332
287
333
function logm (A:: StridedMatrix )
288
334
# If possible, use diagonalization
335
+ if issym (A)
336
+ return full (logm (Symmetric (A)))
337
+ end
289
338
if ishermitian (A)
290
339
return full (logm (Hermitian (A)))
291
340
end
0 commit comments