@@ -311,54 +311,58 @@ end
311311# ------------------------------------------------------------------------------------------
312312const RealOrComplexFloat = Union{AbstractFloat,Complex{<: AbstractFloat }}
313313
314+ function _reverse! (t:: AbstractTensorMap ; dims= :)
315+ for (c, b) in blocks (t)
316+ reverse! (b; dims)
317+ end
318+ return t
319+ end
320+
314321function leftorth! (t:: TensorMap{<:RealOrComplexFloat} ;
315322 alg:: Union{QR,QRpos,QL,QLpos,SVD,SDD,Polar} = QRpos (),
316323 atol:: Real = zero (float (real (scalartype (t)))),
317324 rtol:: Real = (alg ∉ (SVD (), SDD ())) ? zero (float (real (scalartype (t)))) :
318325 eps (real (float (one (scalartype (t))))) * iszero (atol))
319326 InnerProductStyle (t) === EuclideanInnerProduct () ||
320327 throw_invalid_innerproduct (:leftorth! )
321- if ! iszero (rtol)
322- atol = max (atol, rtol * norm (t))
323- end
324- I = sectortype (t)
325- dims = SectorDict {I,Int} ()
326328
327- # compute QR factorization for each block
328- if ! isempty (blocks (t))
329- generator = Base. Iterators. map (blocks (t)) do (c, b)
330- Qc, Rc = MatrixAlgebra. leftorth! (b, alg, atol)
331- dims[c] = size (Qc, 2 )
332- return c => (Qc, Rc)
329+ if alg isa QR
330+ return left_orth! (t; kind= :qr , atol, rtol)
331+ elseif alg isa QRpos
332+ return left_orth! (t; kind= :qrpos , atol, rtol)
333+ elseif alg isa SDD
334+ return left_orth! (t; kind= :svd , atol, rtol)
335+ elseif alg isa Polar
336+ return left_orth! (t; kind= :polar , atol, rtol)
337+ elseif alg isa SVD
338+ kind = :svd
339+ if iszero (atol) && iszero (rtol)
340+ alg′ = LAPACK_QRIteration ()
341+ return left_orth! (t; kind, alg= BlockAlgorithm (alg′, default_blockscheduler (t)),
342+ atol, rtol)
343+ else
344+ trunc = MatrixAlgebraKit. TruncationKeepAbove (atol, rtol)
345+ svd_alg = LAPACK_QRIteration ()
346+ scheduler = default_blockscheduler (t)
347+ alg′ = MatrixAlgebraKit. TruncatedAlgorithm (BlockAlgorithm (svd_alg, scheduler),
348+ trunc)
349+ return left_orth! (t; kind, alg= alg′, atol, rtol)
333350 end
334- QRdata = SectorDict (generator)
351+ elseif alg isa QL
352+ _reverse! (t; dims= 2 )
353+ Q, R = left_orth! (t; kind= :qr , atol, rtol)
354+ _reverse! (Q; dims= 2 )
355+ _reverse! (R)
356+ return Q, R
357+ elseif alg isa QLpos
358+ _reverse! (t; dims= 2 )
359+ Q, R = left_orth! (t; kind= :qrpos , atol, rtol)
360+ _reverse! (Q; dims= 2 )
361+ _reverse! (R)
362+ return Q, R
335363 end
336364
337- # construct new space
338- S = spacetype (t)
339- V = S (dims)
340- if alg isa Polar
341- @assert V ≅ domain (t)
342- W = domain (t)
343- elseif length (domain (t)) == 1 && domain (t) ≅ V
344- W = domain (t)
345- elseif length (codomain (t)) == 1 && codomain (t) ≅ V
346- W = codomain (t)
347- else
348- W = ProductSpace (V)
349- end
350-
351- # construct output tensors
352- T = float (scalartype (t))
353- Q = similar (t, T, codomain (t) ← W)
354- R = similar (t, T, W ← domain (t))
355- if ! isempty (blocks (t))
356- for (c, (Qc, Rc)) in QRdata
357- copy! (block (Q, c), Qc)
358- copy! (block (R, c), Rc)
359- end
360- end
361- return Q, R
365+ throw (ArgumentError (" Algorithm $alg not implemented for leftorth!" ))
362366end
363367
364368function leftnull! (t:: TensorMap{<:RealOrComplexFloat} ;
@@ -685,8 +689,8 @@ function LinearAlgebra.ishermitian(t::TensorMap)
685689end
686690
687691function LinearAlgebra. isposdef! (t:: TensorMap )
688- domain (t) == codomain (t) ||
689- throw (SpaceMismatch (" `isposdef` requires domain and codomain to be the same " ))
692+ domain (t) ≅ codomain (t) ||
693+ throw (SpaceMismatch (" `isposdef` requires domain and codomain to be isomorphic " ))
690694 InnerProductStyle (spacetype (t)) === EuclideanInnerProduct () || return false
691695 for (c, b) in blocks (t)
692696 isposdef! (b) || return false
0 commit comments