Skip to content

Commit 75008f7

Browse files
committed
Add macros to generate matrix functions for symmetric and Hermitian matrices, fix type returned by logm and sqrtm
1 parent 568b3cf commit 75008f7

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

base/linalg.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ export
6666
eigvals!,
6767
eigvecs,
6868
expm,
69-
sqrtm,
7069
eye,
7170
factorize,
7271
givens,
@@ -106,6 +105,7 @@ export
106105
schur,
107106
schurfact!,
108107
schurfact,
108+
sqrtm,
109109
svd,
110110
svdfact!,
111111
svdfact,

base/linalg/dense.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ expm(x::Number) = exp(x)
189189
## "Functions of Matrices: Theory and Computation", SIAM
190190
function expm!{T<:BlasFloat}(A::StridedMatrix{T})
191191
n = chksquare(A)
192-
n<2 && return exp(A)
192+
if ishermitian(A)
193+
return full(expm(Hermitian(A)))
194+
end
193195
ilo, ihi, scale = LAPACK.gebal!('B', A) # modifies A
194196
nA = norm(A, 1)
195197
I = eye(T,n)
@@ -278,10 +280,12 @@ function rcswap!{T<:Number}(i::Integer, j::Integer, X::StridedMatrix{T})
278280
end
279281
end
280282

283+
expm(x::Number) = exp(x)
284+
281285
function logm(A::StridedMatrix)
282286
# If possible, use diagonalization
283287
if ishermitian(A)
284-
return logm(Hermitian(A))
288+
return full(logm(Hermitian(A)))
285289
end
286290

287291
# Use Schur decomposition
@@ -313,12 +317,13 @@ function logm(A::StridedMatrix)
313317
return retmat
314318
end
315319
end
320+
316321
logm(a::Number) = (b = log(complex(a)); imag(b) == 0 ? real(b) : b)
317322
logm(a::Complex) = log(a)
318323

319324
function sqrtm{T<:Real}(A::StridedMatrix{T})
320325
if issym(A)
321-
return sqrtm(Symmetric(A))
326+
return full(sqrtm(Symmetric(A)))
322327
end
323328
n = chksquare(A)
324329
SchurF = schurfact(complex(A))
@@ -328,13 +333,14 @@ function sqrtm{T<:Real}(A::StridedMatrix{T})
328333
end
329334
function sqrtm{T<:Complex}(A::StridedMatrix{T})
330335
if ishermitian(A)
331-
return sqrtm(Hermitian(A))
336+
return full(sqrtm(Hermitian(A)))
332337
end
333338
n = chksquare(A)
334339
SchurF = schurfact(A)
335340
R = full(sqrtm(UpperTriangular(SchurF[:T])))
336341
SchurF[:vectors]*R*SchurF[:vectors]'
337342
end
343+
338344
sqrtm(a::Number) = (b = sqrt(complex(a)); imag(b) == 0 ? real(b) : b)
339345
sqrtm(a::Complex) = sqrt(a)
340346

base/linalg/symmetric.jl

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,28 @@ function svdvals!{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{
126126
end
127127

128128
#Matrix-valued functions
129-
expm{T<:Real}(A::RealHermSymComplexHerm{T}) = (F = eigfact(A); F.vectors*Diagonal(exp(F.values))*F.vectors')
130-
function logm{T<:Real}(A::RealHermSymComplexHerm{T})
131-
F = eigfact(A)
132-
isposdef(F) && return F.vectors*Diagonal(log(F.values))*F.vectors'
133-
return F.vectors*Diagonal(log(complex(F.values)))*F.vectors'
134-
end
135-
function sqrtm{T<:Real}(A::RealHermSymComplexHerm{T})
136-
F = eigfact(A)
137-
isposdef(F) && return F.vectors*Diagonal(sqrt(F.values))*F.vectors'
138-
return F.vectors*Diagonal(sqrt(complex(F.values)))*F.vectors'
129+
for (funm, func) in ([:expm, :exp], [:logm,:log], [:sqrtm,:sqrt])
130+
131+
@eval begin
132+
function ($funm)(A::Symmetric)
133+
F = eigfact(A)
134+
if isposdef(F)
135+
retmat = F.vectors * Diagonal(($func)(F.values)) * F.vectors'
136+
else
137+
retmat = F.vectors * Diagonal(($func)(complex(F.values))) * F.vectors'
138+
end
139+
return Symmetric(retmat)
140+
end
141+
142+
function ($funm)(A::Hermitian)
143+
F = eigfact(A)
144+
if isposdef(F)
145+
retmat = Hermitian(F.vectors * Diagonal(($func)(F.values)) * F.vectors')
146+
else
147+
retmat = F.vectors * Diagonal(($func)(complex(F.values))) * F.vectors'
148+
end
149+
return retmat
150+
end
151+
end
152+
139153
end

0 commit comments

Comments
 (0)