@@ -592,7 +592,7 @@ function schurpow(A::AbstractMatrix, p)
592592 end
593593
594594 # if A has nonpositive real eigenvalues, retmat is a nonprincipal matrix power.
595- if isreal (retmat)
595+ if eltype (A) <: Real && isreal (retmat)
596596 return real (retmat)
597597 else
598598 return retmat
@@ -602,26 +602,35 @@ function (^)(A::AbstractMatrix{T}, p::Real) where T
602602 checksquare (A)
603603 # Quicker return if A is diagonal
604604 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)
609609 end
610- return retmat
611610 end
612611
613612 # For integer powers, use power_by_squaring
614613 isinteger (p) && return integerpow (A, p)
615614
616615 # If possible, use diagonalization
617616 if ishermitian (A)
618- return (Hermitian (A)^ p)
617+ return _safe_parent (Hermitian (A)^ p)
619618 end
620619
621620 # Otherwise, use Schur decomposition
622621 return schurpow (A, p)
623622end
624623
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
625634"""
626635 ^(A::AbstractMatrix, p::Number)
627636
@@ -918,15 +927,13 @@ julia> log(A)
918927function log (A:: AbstractMatrix )
919928 # If possible, use diagonalization
920929 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)
923932 else
924- return applydiagonal (log∘ complex , A)
933+ return applydiagonal (log, A)
925934 end
926935 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)))
930937 elseif istriu (A)
931938 return triu! (parent (log (UpperTriangular (A))))
932939 elseif isreal (A)
@@ -1004,13 +1011,14 @@ sqrt(::AbstractMatrix)
10041011function sqrt (A:: AbstractMatrix{T} ) where {T<: Union{Real,Complex} }
10051012 if checksquare (A) == 0
10061013 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
10101020 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)))
10141022 elseif istriu (A)
10151023 return triu! (parent (sqrt (UpperTriangular (A))))
10161024 elseif isreal (A)
@@ -1044,7 +1052,7 @@ sqrt(A::TransposeAbsMat) = transpose(sqrt(parent(A)))
10441052Computes the real-valued cube root of a real-valued matrix `A`. If `T = cbrt(A)`, then
10451053we have `T*T*T ≈ A`, see example given below.
10461054
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
10481056find the cube root. Otherwise, a specialized version of the p-th root algorithm [^S03] is
10491057utilized, which exploits the real-valued Schur decomposition ([`schur`](@ref))
10501058to compute the cube root.
@@ -1077,7 +1085,7 @@ function cbrt(A::AbstractMatrix{<:Real})
10771085 elseif isdiag (A)
10781086 return applydiagonal (cbrt, A)
10791087 elseif issymmetric (A)
1080- return cbrt (Symmetric (A, :U ) )
1088+ return copytri_maybe_inplace ( parent ( cbrt (Symmetric (A))), ' U ' )
10811089 else
10821090 S = schur (A)
10831091 return S. Z * _cbrt_quasi_triu! (S. T) * S. Z'
@@ -1118,7 +1126,7 @@ end
11181126
11191127Compute the matrix cosine of a square matrix `A`.
11201128
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
11221130compute the cosine. Otherwise, the cosine is determined by calling [`exp`](@ref).
11231131
11241132# Examples
@@ -1160,7 +1168,7 @@ end
11601168
11611169Compute the matrix sine of a square matrix `A`.
11621170
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
11641172compute the sine. Otherwise, the sine is determined by calling [`exp`](@ref).
11651173
11661174# Examples
@@ -1265,7 +1273,7 @@ end
12651273
12661274Compute the matrix tangent of a square matrix `A`.
12671275
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
12691277compute the tangent. Otherwise, the tangent is determined by calling [`exp`](@ref).
12701278
12711279# Examples
@@ -1357,7 +1365,7 @@ _subadd!!(X, Y) = X - Y, X + Y
13571365
13581366Compute the inverse matrix cosine of a square matrix `A`.
13591367
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
13611369compute the inverse cosine. Otherwise, the inverse cosine is determined by using
13621370[`log`](@ref) and [`sqrt`](@ref). For the theory and logarithmic formulas used to compute
13631371this function, see [^AH16_1].
@@ -1376,9 +1384,7 @@ function acos(A::AbstractMatrix)
13761384 if isdiag (A)
13771385 return applydiagonal (acos, A)
13781386 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)))
13821388 end
13831389 SchurF = Schur {Complex} (schur (A))
13841390 U = UpperTriangular (SchurF. T)
@@ -1391,7 +1397,7 @@ end
13911397
13921398Compute the inverse matrix sine of a square matrix `A`.
13931399
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
13951401compute the inverse sine. Otherwise, the inverse sine is determined by using [`log`](@ref)
13961402and [`sqrt`](@ref). For the theory and logarithmic formulas used to compute this function,
13971403see [^AH16_2].
@@ -1425,7 +1431,7 @@ end
14251431
14261432Compute the inverse matrix tangent of a square matrix `A`.
14271433
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
14291435compute the inverse tangent. Otherwise, the inverse tangent is determined by using
14301436[`log`](@ref). For the theory and logarithmic formulas used to compute this function, see
14311437[^AH16_3].
@@ -1436,8 +1442,8 @@ compute the inverse tangent. Otherwise, the inverse tangent is determined by usi
14361442```julia-repl
14371443julia> atan(tan([0.5 0.1; -0.2 0.3]))
143814442×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
14411447```
14421448"""
14431449function atan (A:: AbstractMatrix )
@@ -1450,7 +1456,12 @@ function atan(A::AbstractMatrix)
14501456 SchurF = Schur {Complex} (schur (A))
14511457 U = im * UpperTriangular (SchurF. T)
14521458 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
14541465end
14551466
14561467"""
@@ -1465,9 +1476,7 @@ function acosh(A::AbstractMatrix)
14651476 if isdiag (A)
14661477 return applydiagonal (acosh, A)
14671478 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)))
14711480 end
14721481 SchurF = Schur {Complex} (schur (A))
14731482 U = UpperTriangular (SchurF. T)
@@ -1493,7 +1502,12 @@ function asinh(A::AbstractMatrix)
14931502 SchurF = Schur {Complex} (schur (A))
14941503 U = UpperTriangular (SchurF. T)
14951504 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
14971511end
14981512
14991513"""
@@ -1508,8 +1522,7 @@ function atanh(A::AbstractMatrix)
15081522 if isdiag (A)
15091523 return applydiagonal (atanh, A)
15101524 elseif ishermitian (A)
1511- P = parent (atanh (Hermitian (A)))
1512- return copytri_maybe_inplace (P, ' U' , true )
1525+ return _safe_parent (atanh (Hermitian (A)))
15131526 end
15141527 SchurF = Schur {Complex} (schur (A))
15151528 U = UpperTriangular (SchurF. T)
0 commit comments