@@ -2537,3 +2537,94 @@ for (tritype, comptritype) in ((:LowerTriangular, :UpperTriangular),
25372537 @eval / (u:: TransposeAbsVec , A:: $tritype{<:Any,<:Adjoint} ) = transpose ($ comptritype (conj (parent (parent (A)))) \ u. parent)
25382538 @eval / (u:: TransposeAbsVec , A:: $tritype{<:Any,<:Transpose} ) = transpose (transpose (A) \ u. parent)
25392539end
2540+
2541+ # Cube root of a 2x2 real-valued matrix with complex conjugate eigenvalues and equal diagonal values.
2542+ # Reference [1]: Smith, M. I. (2003). A Schur Algorithm for Computing Matrix pth Roots.
2543+ # SIAM Journal on Matrix Analysis and Applications (Vol. 24, Issue 4, pp. 971–989).
2544+ # https://doi.org/10.1137/s0895479801392697
2545+ function _cbrt_2x2! (A:: AbstractMatrix{T} ) where {T<: Real }
2546+ @assert checksquare (A) == 2
2547+ @inbounds begin
2548+ (A[1 ,1 ] == A[2 ,2 ]) || throw (ArgumentError (" _cbrt_2x2!: Matrix A must have equal diagonal values." ))
2549+ (A[1 ,2 ]* A[2 ,1 ] < 0 ) || throw (ArgumentError (" _cbrt_2x2!: Matrix A must have complex conjugate eigenvalues." ))
2550+ μ = sqrt (- A[1 ,2 ]* A[2 ,1 ])
2551+ r = cbrt (hypot (A[1 ,1 ], μ))
2552+ θ = atan (μ, A[1 ,1 ])
2553+ s, c = sincos (θ/ 3 )
2554+ α, β′ = r* c, r* s/ µ
2555+ A[1 ,1 ] = α
2556+ A[2 ,2 ] = α
2557+ A[1 ,2 ] = β′* A[1 ,2 ]
2558+ A[2 ,1 ] = β′* A[2 ,1 ]
2559+ end
2560+ return A
2561+ end
2562+
2563+ # Cube root of a quasi upper triangular matrix (output of Schur decomposition)
2564+ # Reference [1]: Smith, M. I. (2003). A Schur Algorithm for Computing Matrix pth Roots.
2565+ # SIAM Journal on Matrix Analysis and Applications (Vol. 24, Issue 4, pp. 971–989).
2566+ # https://doi.org/10.1137/s0895479801392697
2567+ @views function _cbrt_quasi_triu! (A:: AbstractMatrix{T} ) where {T<: Real }
2568+ m, n = size (A)
2569+ (m == n) || throw (ArgumentError (" _cbrt_quasi_triu!: Matrix A must be square." ))
2570+ # Cube roots of 1x1 and 2x2 diagonal blocks
2571+ i = 1
2572+ sizes = ones (Int,n)
2573+ S = zeros (T,2 ,n)
2574+ while i < n
2575+ if ! iszero (A[i+ 1 ,i])
2576+ _cbrt_2x2! (A[i: i+ 1 ,i: i+ 1 ])
2577+ mul! (S[1 : 2 ,i: i+ 1 ], A[i: i+ 1 ,i: i+ 1 ], A[i: i+ 1 ,i: i+ 1 ])
2578+ sizes[i] = 2
2579+ sizes[i+ 1 ] = 0
2580+ i += 2
2581+ else
2582+ A[i,i] = cbrt (A[i,i])
2583+ S[1 ,i] = A[i,i]* A[i,i]
2584+ i += 1
2585+ end
2586+ end
2587+ if i == n
2588+ A[n,n] = cbrt (A[n,n])
2589+ S[1 ,n] = A[n,n]* A[n,n]
2590+ end
2591+ # Algorithm 4.3 in Reference [1]
2592+ Δ = I (4 )
2593+ M_L₀ = zeros (T,4 ,4 )
2594+ M_L₁ = zeros (T,4 ,4 )
2595+ M_Bᵢⱼ⁽⁰⁾ = zeros (T,2 ,2 )
2596+ M_Bᵢⱼ⁽¹⁾ = zeros (T,2 ,2 )
2597+ for k = 1 : n- 1
2598+ for i = 1 : n- k
2599+ if sizes[i] == 0 || sizes[i+ k] == 0 continue end
2600+ k₁, k₂ = i+ 1 + (sizes[i+ 1 ]== 0 ), i+ k- 1
2601+ i₁, i₂, j₁, j₂, s₁, s₂ = i, i+ sizes[i]- 1 , i+ k, i+ k+ sizes[i+ k]- 1 , sizes[i], sizes[i+ k]
2602+ L₀ = M_L₀[1 : s₁* s₂,1 : s₁* s₂]
2603+ L₁ = M_L₁[1 : s₁* s₂,1 : s₁* s₂]
2604+ Bᵢⱼ⁽⁰⁾ = M_Bᵢⱼ⁽⁰⁾[1 : s₁, 1 : s₂]
2605+ Bᵢⱼ⁽¹⁾ = M_Bᵢⱼ⁽¹⁾[1 : s₁, 1 : s₂]
2606+ # Compute Bᵢⱼ⁽⁰⁾ and Bᵢⱼ⁽¹⁾
2607+ mul! (Bᵢⱼ⁽⁰⁾, A[i₁: i₂,k₁: k₂], A[k₁: k₂,j₁: j₂])
2608+ # Retreive Rᵢ,ᵢ₊ₖ as A[i+k,i]'
2609+ mul! (Bᵢⱼ⁽¹⁾, A[i₁: i₂,k₁: k₂], A[j₁: j₂,k₁: k₂]' )
2610+ # Solve Uᵢ,ᵢ₊ₖ using Reference [1, (4.10)]
2611+ kron! (L₀, Δ[1 : s₂,1 : s₂], S[1 : s₁,i₁: i₂])
2612+ L₀ .+ = kron! (L₁, A[j₁: j₂,j₁: j₂]' , A[i₁: i₂,i₁: i₂])
2613+ L₀ .+ = kron! (L₁, S[1 : s₂,j₁: j₂]' , Δ[1 : s₁,1 : s₁])
2614+ mul! (A[i₁: i₂,j₁: j₂], A[i₁: i₂,i₁: i₂], Bᵢⱼ⁽⁰⁾, - 1.0 , 1.0 )
2615+ A[i₁: i₂,j₁: j₂] .- = Bᵢⱼ⁽¹⁾
2616+ ldiv! (lu! (L₀), A[i₁: i₂,j₁: j₂][:])
2617+ # Compute and store Rᵢ,ᵢ₊ₖ' in A[i+k,i]
2618+ mul! (Bᵢⱼ⁽⁰⁾, A[i₁: i₂,i₁: i₂], A[i₁: i₂,j₁: j₂], 1.0 , 1.0 )
2619+ mul! (Bᵢⱼ⁽⁰⁾, A[i₁: i₂,j₁: j₂], A[j₁: j₂,j₁: j₂], 1.0 , 1.0 )
2620+ A[j₁: j₂,i₁: i₂] .= Bᵢⱼ⁽⁰⁾'
2621+ end
2622+ end
2623+ # Make quasi triangular
2624+ for j= 1 : n for i= j+ 1 + (sizes[j]== 2 ): n A[i,j] = 0 end end
2625+ return A
2626+ end
2627+
2628+ # Cube roots of real-valued triangular matrices
2629+ cbrt (A:: UpperTriangular{T} ) where {T<: Real } = UpperTriangular (_cbrt_quasi_triu! (Matrix {T} (A)))
2630+ cbrt (A:: LowerTriangular{T} ) where {T<: Real } = LowerTriangular (_cbrt_quasi_triu! (Matrix {T} (A' ))' )
0 commit comments