1- @noinline function _check_spacetype (
2- :: Type{S₁} , :: Type{S₂}
3- ) where {S₁ <: ElementarySpace , S₂ <: ElementarySpace }
4- S₁ === S₂ ||
5- S₁ === SumSpace{S₂} ||
6- SumSpace{S₁} === S₂ ||
7- throw (SpaceMismatch (lazy " incompatible spacetypes: $S₁ and $S₂" ))
8- return nothing
9- end
10-
111# TensorOperations
122# ----------------
133function TO. tensoradd_type (
144 TC, A:: AbstractBlockTensorMap , :: Index2Tuple{N₁, N₂} , :: Bool
155 ) where {N₁, N₂}
16- TA = eltype (A)
17- I = sectortype (A)
18- Tnew = sectorscalartype (I) <: Real ? TC : complex (TC)
19- if TA isa Union
20- M = Union{TK. similarstoragetype (TA. a, Tnew), TK. similarstoragetype (TA. b, Tnew)}
21- else
22- M = TK. similarstoragetype (TA, Tnew)
23- end
6+ S = spacetype (A)
7+ M = TK. similarstoragetype (A, TK. promote_permute (TC, sectortype (S)))
248 return if issparse (A)
25- sparseblocktensormaptype (spacetype (A) , N₁, N₂, M)
9+ sparseblocktensormaptype (S , N₁, N₂, M)
2610 else
27- blocktensormaptype (spacetype (A) , N₁, N₂, M)
11+ blocktensormaptype (S , N₁, N₂, M)
2812 end
2913end
3014function TO. tensoradd_type (TC, A:: AdjointBlockTensorMap , pA:: Index2Tuple , conjA:: Bool )
3317
3418# tensoralloc_contract
3519# --------------------
36- function TO. tensorcontract_type (
37- TC,
38- A:: AbstractBlockTensorMap , :: Index2Tuple , :: Bool ,
39- B:: AbstractBlockTensorMap , :: Index2Tuple , :: Bool ,
40- :: Index2Tuple{N₁, N₂} ,
41- ) where {N₁, N₂}
42- _check_spacetype (spacetype (A), spacetype (B))
43-
44- I = sectortype (A)
45- Tnew = sectorscalartype (I) <: Real ? TC : complex (TC)
46- M = promote_storagetype (Tnew, eltype (A), eltype (B))
47-
48- return if issparse (A) && issparse (B)
49- sparseblocktensormaptype (spacetype (A), N₁, N₂, M)
50- else
51- blocktensormaptype (spacetype (A), N₁, N₂, M)
52- end
53- end
54- function TO. tensorcontract_type (
55- TC,
56- A:: AbstractTensorMap , pA:: Index2Tuple , conjA:: Bool ,
57- B:: AbstractBlockTensorMap , pB:: Index2Tuple , conjB:: Bool ,
58- pAB:: Index2Tuple{N₁, N₂} ,
59- ) where {N₁, N₂}
60- _check_spacetype (spacetype (A), spacetype (B))
61-
62- I = sectortype (A)
63- Tnew = sectorscalartype (I) <: Real ? TC : complex (TC)
64- M = promote_storagetype (Tnew, typeof (A), eltype (B))
65-
66- return if issparse (A) && issparse (B)
67- sparseblocktensormaptype (spacetype (A), N₁, N₂, M)
68- else
69- blocktensormaptype (spacetype (A), N₁, N₂, M)
70- end
71- end
72- function TO. tensorcontract_type (
73- TC,
74- A:: AbstractBlockTensorMap , :: Index2Tuple , :: Bool ,
75- B:: AbstractTensorMap , :: Index2Tuple , :: Bool ,
76- :: Index2Tuple{N₁, N₂} ,
77- ) where {N₁, N₂}
78- _check_spacetype (spacetype (A), spacetype (B))
79-
80- I = sectortype (A)
81- Tnew = sectorscalartype (I) <: Real ? TC : complex (TC)
82- M = promote_storagetype (Tnew, eltype (A), typeof (B))
83-
84- return if issparse (A) && issparse (B)
85- sparseblocktensormaptype (spacetype (A), N₁, N₂, M)
86- else
87- blocktensormaptype (spacetype (A), N₁, N₂, M)
20+ for TTA in (:AbstractTensorMap , :AbstractBlockTensorMap ), TTB in (:AbstractTensorMap , :AbstractBlockTensorMap )
21+ TTA == TTB == :AbstractTensorMap && continue
22+ @eval function TO. tensorcontract_type (
23+ TC,
24+ A:: $TTA , :: Index2Tuple , :: Bool ,
25+ B:: $TTB , :: Index2Tuple , :: Bool ,
26+ :: Index2Tuple{N₁, N₂} ,
27+ ) where {N₁, N₂}
28+ S = TK. check_spacetype (A, B)
29+ TC′ = TK. promote_permute (TC, sectortype (S))
30+ M = TK. promote_storagetype (TK. similarstoragetype (A, TC′), TK. similarstoragetype (B, TC′))
31+ return if issparse (A) && issparse (B)
32+ sparseblocktensormaptype (S, N₁, N₂, M)
33+ else
34+ blocktensormaptype (S, N₁, N₂, M)
35+ end
8836 end
8937end
9038
@@ -117,23 +65,6 @@ function TO.tensoralloc_contract(
11765 end
11866end
11967
120- function promote_storagetype (:: Type{T} , :: Type{T₁} , :: Type{T₂} ) where {T, T₁, T₂}
121- if T₁ isa Union
122- M₁ = Union{TK. similarstoragetype (T₁. a, T), TK. similarstoragetype (T₁. b, T)}
123- else
124- M₁ = TK. similarstoragetype (T₁, T)
125- end
126- if T₂ isa Union
127- M₂ = Union{TK. similarstoragetype (T₂. a, T), TK. similarstoragetype (T₂. b, T)}
128- else
129- M₂ = TK. similarstoragetype (T₂, T)
130- end
131- return Union{M₁, M₂}
132- end
133-
134- # EVIL HACK!!!
135- TK. storagetype (:: Type{AbstractTensorMap{TT, S, N₁, N₂}} ) where {TT, S, N₁, N₂} = Vector{TT}
136-
13768function promote_blocktype (:: Type{TT} , :: Type{A₁} , :: Type{A₂} ) where {TT, A₁, A₂}
13869 N = similarblocktype (A₁, TT)
13970 @assert N === similarblocktype (A₂, TT) " incompatible block types"
@@ -154,80 +85,6 @@ function TO.tensoralloc(
15485 return C
15586end
15687
157- # unfortunate overlaod until TK fix
158- function TK. blas_contract! (
159- C:: AbstractBlockTensorMap ,
160- A:: AbstractTensorMap , pA:: Index2Tuple ,
161- B:: AbstractTensorMap , pB:: Index2Tuple ,
162- pAB:: Index2Tuple , α, β,
163- backend, allocator
164- )
165- bstyle = BraidingStyle (sectortype (C))
166- bstyle isa SymmetricBraiding ||
167- throw (SectorMismatch (" only tensors with symmetric braiding rules can be contracted; try `@planar` instead" ))
168- TC = scalartype (C)
169-
170- # check which tensors have to be permuted/copied
171- copyA = ! (TO. isblascontractable (A, pA) && eltype (A) === TC)
172- copyB = ! (TO. isblascontractable (B, pB) && eltype (B) === TC)
173-
174- if bstyle isa Fermionic && any (isdual ∘ Base. Fix1 (space, B), pB[1 ])
175- # twist smallest object if neither or both already have to be permuted
176- # otherwise twist the one that already is copied
177- if ! (copyA ⊻ copyB)
178- twistA = dim (A) < dim (B)
179- else
180- twistA = copyA
181- end
182- twistB = ! twistA
183- copyA |= twistA
184- copyB |= twistB
185- else
186- twistA = false
187- twistB = false
188- end
189-
190- # Bring A in the correct form for BLAS contraction
191- if copyA
192- Anew = TO. tensoralloc_add (TC, A, pA, false , Val (true ), allocator)
193- Anew = TO. tensoradd! (Anew, A, pA, false , One (), Zero (), backend, allocator)
194- twistA && twist! (Anew, filter (! isdual ∘ Base. Fix1 (space, Anew), domainind (Anew)))
195- else
196- Anew = permute (A, pA)
197- end
198- pAnew = (codomainind (Anew), domainind (Anew))
199-
200- # Bring B in the correct form for BLAS contraction
201- if copyB
202- Bnew = TO. tensoralloc_add (TC, B, pB, false , Val (true ), allocator)
203- Bnew = TO. tensoradd! (Bnew, B, pB, false , One (), Zero (), backend, allocator)
204- twistB && twist! (Bnew, filter (isdual ∘ Base. Fix1 (space, Bnew), codomainind (Bnew)))
205- else
206- Bnew = permute (B, pB)
207- end
208- pBnew = (codomainind (Bnew), domainind (Bnew))
209-
210- # Bring C in the correct form for BLAS contraction
211- ipAB = TO. oindABinC (pAB, pAnew, pBnew)
212- copyC = ! TO. isblasdestination (C, ipAB)
213-
214- if copyC
215- Cnew = TO. tensoralloc_add (TC, C, ipAB, false , Val (true ), allocator)
216- mul! (Cnew, Anew, Bnew)
217- TO. tensoradd! (C, Cnew, pAB, false , α, β, backend, allocator)
218- TO. tensorfree! (Cnew, allocator)
219- else
220- Cnew = permute (C, ipAB)
221- mul! (Cnew, Anew, Bnew, α, β)
222- end
223-
224- copyA && TO. tensorfree! (Anew, allocator)
225- copyB && TO. tensorfree! (Bnew, allocator)
226-
227- return C
228- end
229-
230-
23188# tensorfree!
23289# -----------
23390function TO. tensorfree! (t:: BlockTensorMap , allocator = TO. DefaultAllocator ())
@@ -248,7 +105,7 @@ function TK.trace_permute!(
248105 backend:: AbstractBackend = TO. DefaultBackend (),
249106 )
250107 # some input checks
251- _check_spacetype ( spacetype ( tdst), spacetype ( tsrc) )
108+ TK . check_spacetype ( tdst, tsrc)
252109 if ! (BraidingStyle (sectortype (tdst)) isa SymmetricBraiding)
253110 throw (
254111 SectorMismatch (
0 commit comments