@@ -592,7 +592,7 @@ function schurpow(A::AbstractMatrix, p)
592
592
end
593
593
594
594
# if A has nonpositive real eigenvalues, retmat is a nonprincipal matrix power.
595
- if isreal (retmat)
595
+ if eltype (A) <: Real && isreal (retmat)
596
596
return real (retmat)
597
597
else
598
598
return retmat
@@ -602,26 +602,35 @@ function (^)(A::AbstractMatrix{T}, p::Real) where T
602
602
checksquare (A)
603
603
# Quicker return if A is diagonal
604
604
if isdiag (A)
605
- TT = promote_op ( ^ , T, typeof (p ))
606
- retmat = copymutable_oftype (A, TT )
607
- for i in diagind (retmat, IndexStyle (retmat))
608
- retmat[i] = retmat[i] ^ p
605
+ if T <: Real && any ( < ( 0 ), diagview (A ))
606
+ return applydiagonal (x -> complex (x) ^ p, A )
607
+ else
608
+ return applydiagonal (x -> x ^ p, A)
609
609
end
610
- return retmat
611
610
end
612
611
613
612
# For integer powers, use power_by_squaring
614
613
isinteger (p) && return integerpow (A, p)
615
614
616
615
# If possible, use diagonalization
617
616
if ishermitian (A)
618
- return (Hermitian (A)^ p)
617
+ return _safe_parent (Hermitian (A)^ p)
619
618
end
620
619
621
620
# Otherwise, use Schur decomposition
622
621
return schurpow (A, p)
623
622
end
624
623
624
+ function _safe_parent (fA)
625
+ parentfA = parent (fA)
626
+ if isa (fA, Hermitian) || isa (fA, Symmetric{<: Real })
627
+ return copytri_maybe_inplace (parentfA, ' U' , true )
628
+ elseif isa (fA, Symmetric)
629
+ return copytri_maybe_inplace (parentfA, ' U' )
630
+ else
631
+ return fA
632
+ end
633
+ end
625
634
"""
626
635
^(A::AbstractMatrix, p::Number)
627
636
@@ -918,15 +927,13 @@ julia> log(A)
918
927
function log (A:: AbstractMatrix )
919
928
# If possible, use diagonalization
920
929
if isdiag (A) && eltype (A) <: Union{Real,Complex}
921
- if eltype (A) <: Real && all ( >= (0 ), diagview (A))
922
- return applydiagonal (log, A)
930
+ if eltype (A) <: Real && any ( < (0 ), diagview (A))
931
+ return applydiagonal (log ∘ complex , A)
923
932
else
924
- return applydiagonal (log∘ complex , A)
933
+ return applydiagonal (log, A)
925
934
end
926
935
elseif ishermitian (A)
927
- logHermA = log (Hermitian (A))
928
- PH = parent (logHermA)
929
- return ishermitian (logHermA) ? copytri_maybe_inplace (PH, ' U' , true ) : PH
936
+ return _safe_parent (log (Hermitian (A)))
930
937
elseif istriu (A)
931
938
return triu! (parent (log (UpperTriangular (A))))
932
939
elseif isreal (A)
@@ -1004,13 +1011,14 @@ sqrt(::AbstractMatrix)
1004
1011
function sqrt (A:: AbstractMatrix{T} ) where {T<: Union{Real,Complex} }
1005
1012
if checksquare (A) == 0
1006
1013
return copy (float (A))
1007
- elseif isdiag (A) && (T <: Complex || all (x -> x ≥ zero (x), diagview (A)))
1008
- # Real Diagonal sqrt requires each diagonal element to be positive
1009
- return applydiagonal (sqrt, A)
1014
+ elseif isdiag (A)
1015
+ if T <: Real && any (< (0 ), diagview (A))
1016
+ return applydiagonal (sqrt ∘ complex, A)
1017
+ else
1018
+ return applydiagonal (sqrt, A)
1019
+ end
1010
1020
elseif ishermitian (A)
1011
- sqrtHermA = sqrt (Hermitian (A))
1012
- PS = parent (sqrtHermA)
1013
- return ishermitian (sqrtHermA) ? copytri_maybe_inplace (PS, ' U' , true ) : PS
1021
+ return _safe_parent (sqrt (Hermitian (A)))
1014
1022
elseif istriu (A)
1015
1023
return triu! (parent (sqrt (UpperTriangular (A))))
1016
1024
elseif isreal (A)
@@ -1044,7 +1052,7 @@ sqrt(A::TransposeAbsMat) = transpose(sqrt(parent(A)))
1044
1052
Computes the real-valued cube root of a real-valued matrix `A`. If `T = cbrt(A)`, then
1045
1053
we have `T*T*T ≈ A`, see example given below.
1046
1054
1047
- If `A` is symmetric, i.e., of type `HermOrSym{<:Real}`, then ([`eigen`](@ref)) is used to
1055
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1048
1056
find the cube root. Otherwise, a specialized version of the p-th root algorithm [^S03] is
1049
1057
utilized, which exploits the real-valued Schur decomposition ([`schur`](@ref))
1050
1058
to compute the cube root.
@@ -1077,7 +1085,7 @@ function cbrt(A::AbstractMatrix{<:Real})
1077
1085
elseif isdiag (A)
1078
1086
return applydiagonal (cbrt, A)
1079
1087
elseif issymmetric (A)
1080
- return cbrt (Symmetric (A, :U ) )
1088
+ return copytri_maybe_inplace ( parent ( cbrt (Symmetric (A))), ' U ' )
1081
1089
else
1082
1090
S = schur (A)
1083
1091
return S. Z * _cbrt_quasi_triu! (S. T) * S. Z'
@@ -1118,7 +1126,7 @@ end
1118
1126
1119
1127
Compute the matrix cosine of a square matrix `A`.
1120
1128
1121
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1129
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1122
1130
compute the cosine. Otherwise, the cosine is determined by calling [`exp`](@ref).
1123
1131
1124
1132
# Examples
@@ -1160,7 +1168,7 @@ end
1160
1168
1161
1169
Compute the matrix sine of a square matrix `A`.
1162
1170
1163
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1171
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1164
1172
compute the sine. Otherwise, the sine is determined by calling [`exp`](@ref).
1165
1173
1166
1174
# Examples
@@ -1265,7 +1273,7 @@ end
1265
1273
1266
1274
Compute the matrix tangent of a square matrix `A`.
1267
1275
1268
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1276
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1269
1277
compute the tangent. Otherwise, the tangent is determined by calling [`exp`](@ref).
1270
1278
1271
1279
# Examples
@@ -1357,7 +1365,7 @@ _subadd!!(X, Y) = X - Y, X + Y
1357
1365
1358
1366
Compute the inverse matrix cosine of a square matrix `A`.
1359
1367
1360
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1368
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1361
1369
compute the inverse cosine. Otherwise, the inverse cosine is determined by using
1362
1370
[`log`](@ref) and [`sqrt`](@ref). For the theory and logarithmic formulas used to compute
1363
1371
this function, see [^AH16_1].
@@ -1376,9 +1384,7 @@ function acos(A::AbstractMatrix)
1376
1384
if isdiag (A)
1377
1385
return applydiagonal (acos, A)
1378
1386
elseif ishermitian (A)
1379
- acosHermA = acos (Hermitian (A))
1380
- P = parent (acosHermA)
1381
- return isa (acosHermA, Hermitian) ? copytri_maybe_inplace (P, ' U' , true ) : P
1387
+ return _safe_parent (acos (Hermitian (A)))
1382
1388
end
1383
1389
SchurF = Schur {Complex} (schur (A))
1384
1390
U = UpperTriangular (SchurF. T)
@@ -1391,7 +1397,7 @@ end
1391
1397
1392
1398
Compute the inverse matrix sine of a square matrix `A`.
1393
1399
1394
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1400
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1395
1401
compute the inverse sine. Otherwise, the inverse sine is determined by using [`log`](@ref)
1396
1402
and [`sqrt`](@ref). For the theory and logarithmic formulas used to compute this function,
1397
1403
see [^AH16_2].
@@ -1425,7 +1431,7 @@ end
1425
1431
1426
1432
Compute the inverse matrix tangent of a square matrix `A`.
1427
1433
1428
- If `A` is symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1434
+ If `A` is real- symmetric or Hermitian, its eigendecomposition ([`eigen`](@ref)) is used to
1429
1435
compute the inverse tangent. Otherwise, the inverse tangent is determined by using
1430
1436
[`log`](@ref). For the theory and logarithmic formulas used to compute this function, see
1431
1437
[^AH16_3].
@@ -1436,8 +1442,8 @@ compute the inverse tangent. Otherwise, the inverse tangent is determined by usi
1436
1442
```julia-repl
1437
1443
julia> atan(tan([0.5 0.1; -0.2 0.3]))
1438
1444
2×2 Matrix{ComplexF64}:
1439
- 0.5+1.38778e-17im 0.1-2.77556e-17im
1440
- -0.2+6.93889e-17im 0.3-4.16334e-17im
1445
+ 0.5 0.1
1446
+ -0.2 0.3
1441
1447
```
1442
1448
"""
1443
1449
function atan (A:: AbstractMatrix )
@@ -1450,7 +1456,12 @@ function atan(A::AbstractMatrix)
1450
1456
SchurF = Schur {Complex} (schur (A))
1451
1457
U = im * UpperTriangular (SchurF. T)
1452
1458
R = triu! (parent (log ((I + U) / (I - U)) / 2im ))
1453
- return SchurF. Z * R * SchurF. Z'
1459
+ retmat = SchurF. Z * R * SchurF. Z'
1460
+ if eltype (A) <: Real
1461
+ return real (retmat)
1462
+ else
1463
+ return retmat
1464
+ end
1454
1465
end
1455
1466
1456
1467
"""
@@ -1465,9 +1476,7 @@ function acosh(A::AbstractMatrix)
1465
1476
if isdiag (A)
1466
1477
return applydiagonal (acosh, A)
1467
1478
elseif ishermitian (A)
1468
- acoshHermA = acosh (Hermitian (A))
1469
- P = parent (acoshHermA)
1470
- return isa (acoshHermA, Hermitian) ? copytri_maybe_inplace (P, ' U' , true ) : P
1479
+ return _safe_parent (acosh (Hermitian (A)))
1471
1480
end
1472
1481
SchurF = Schur {Complex} (schur (A))
1473
1482
U = UpperTriangular (SchurF. T)
@@ -1493,7 +1502,12 @@ function asinh(A::AbstractMatrix)
1493
1502
SchurF = Schur {Complex} (schur (A))
1494
1503
U = UpperTriangular (SchurF. T)
1495
1504
R = triu! (parent (log (U + sqrt (I + U^ 2 ))))
1496
- return SchurF. Z * R * SchurF. Z'
1505
+ retmat = SchurF. Z * R * SchurF. Z'
1506
+ if eltype (A) <: Real
1507
+ return real (retmat)
1508
+ else
1509
+ return retmat
1510
+ end
1497
1511
end
1498
1512
1499
1513
"""
@@ -1508,8 +1522,7 @@ function atanh(A::AbstractMatrix)
1508
1522
if isdiag (A)
1509
1523
return applydiagonal (atanh, A)
1510
1524
elseif ishermitian (A)
1511
- P = parent (atanh (Hermitian (A)))
1512
- return copytri_maybe_inplace (P, ' U' , true )
1525
+ return _safe_parent (atanh (Hermitian (A)))
1513
1526
end
1514
1527
SchurF = Schur {Complex} (schur (A))
1515
1528
U = UpperTriangular (SchurF. T)
0 commit comments