Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "BlockTensorKit"
uuid = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd"
version = "0.3.13"
version = "0.3.14"
authors = ["Lukas Devos <ldevos98@gmail.com> and contributors"]

[deps]
Expand Down Expand Up @@ -36,12 +36,12 @@ MatrixAlgebraKit = "0.6"
Random = "1"
SafeTestsets = "0.1"
Strided = "2.3.3"
TensorKit = "0.16.4"
TensorKit = "0.17"
TensorOperations = "5"
Test = "1"
TestExtras = "0.2, 0.3"
TupleTools = "1"
VectorInterface = "0.4.8, 0.5"
VectorInterface = "0.4.8, 0.5, 0.6"
Comment thread
lkdvos marked this conversation as resolved.
julia = "1.10"

[extras]
Expand Down
272 changes: 111 additions & 161 deletions src/tensors/indexmanipulations.jl
Original file line number Diff line number Diff line change
@@ -1,233 +1,183 @@
function TK.add_transform!(
tdst::BlockTensorMap, tsrc::BlockTensorMap, (p₁, p₂)::Index2Tuple{N₁, N₂},
fusiontreetransform,
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
@propagate_inbounds function TK.add_transform!(
tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple, transformer,
α::Number, β::Number, backend, allocator
)
@boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p)

dstdata = parent(tdst)
srcdata = permutedims(StridedView(parent(tsrc)), (p..., p...))
srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...))

@inbounds for I in eachindex(dstdata, srcdata)
dstdata[I] = TK.add_transform!(
dstdata[I], srcdata[I], (p₁, p₂), fusiontreetransform, α, β, backend...
dstdata[I], srcdata[I], p, transformer, α, β, backend, allocator
)
end
return tdst
end
function TK.add_transform!(
@propagate_inbounds function TK.add_transform!(
tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap,
(p₁, p₂)::Index2Tuple{N₁, N₂},
fusiontreetransform,
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
p::Index2Tuple, transformer, α::Number, β::Number, backend, allocator
)
@boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p)
scale!(tdst, β)
p = (p..., p...)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
I′ = CartesianIndex(TT.getindices(I.I, p_lin))
tdst[I′] = TK.add_transform!(
tdst[I′], v, (p₁, p₂), fusiontreetransform, α, One(), backend...
tdst[I′], v, p_lin, transformer, α, One(), backend, allocator
)
end
return tdst
end
function TK.add_transform!(
tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT},
(p₁, p₂)::Index2Tuple,
fusiontreetransform,
α::Number, β::Number,
backend::AbstractBackend...,
p::Index2Tuple, transformer, α::Number, β::Number, backend, allocator
) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
@boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p)
scale!(tdst, β)
p = (p..., p...)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
I′ = CartesianIndex(TT.getindices(I.I, p_lin))
tdst[I′] = TK.add_transform!(
tdst[I′], v, (p₁, p₂), fusiontreetransform, α, One(), backend...
tdst[I′], v, p, transformer, α, One(), backend, allocator
)
end
return tdst
end
function TK.add_transform!(
tdst::TensorMap, tsrc::BlockTensorMap, (p₁, p₂)::Index2Tuple,
fusiontreetransform,
α::Number, β::Number,
backend::AbstractBackend...,
tdst::TensorMap, tsrc::BlockTensorMap, p::Index2Tuple, transformer,
α::Number, β::Number, backend, allocator
)
@assert length(tsrc) == 1 "source tensor must be a single tensor"
return TK.add_transform!(
tdst, only(tsrc), (p₁, p₂), fusiontreetransform, α, β, backend...
tdst, only(tsrc), p, transformer, α, β, backend, allocator
)
end
function TK.add_transform!(
tdst::BlockTensorMap, tsrc::TensorMap,
(p₁, p₂)::Index2Tuple,
fusiontreetransform,
α::Number, β::Number,
backend::AbstractBackend...,
tdst::BlockTensorMap, tsrc::TensorMap, p::Index2Tuple, transformer,
α::Number, β::Number, backend, allocator
)
# @assert length(tsrc) == 1 "source tensor must be a single tensor"
return TK.add_transform!(
only(tdst), tsrc, (p₁, p₂), fusiontreetransform, α, β, backend...
only(tdst), tsrc, p, transformer, α, β, backend, allocator
)
end

# we need to capture the other functions earlier to enjoy the fast transformers...
for f! in (:add_permute!, :add_transpose!)
@eval function TK.$f!(
tdst::BlockTensorMap, tsrc::BlockTensorMap,
(p₁, p₂)::Index2Tuple{N₁, N₂},
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
dstdata = parent(tdst)
srcdata = permutedims(StridedView(parent(tsrc)), (p₁..., p₂...))
for f in (:permute, :transpose)
f! = Symbol(f, :!)
@eval begin
function TK.$f!(
tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
@boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p)

@inbounds for I in eachindex(dstdata, srcdata)
dstdata[I] = TK.$f!(dstdata[I], srcdata[I], (p₁, p₂), α, β, backend...)
dstdata = parent(tdst)
srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...))

@inbounds for I in eachindex(dstdata, srcdata)
dstdata[I] = TK.$f!(dstdata[I], srcdata[I], p, α, β, backend, allocator)
end
return tdst
end
return tdst
end
@eval function TK.$f!(
tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap,
(p₁, p₂)::Index2Tuple{N₁, N₂},
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
function TK.$f!(
tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap,
p::Index2Tuple, α::Number, β::Number, backend::AbstractBackend, allocator
)
@boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p)
scale!(tdst, β)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p_lin))
tdst[I′] = TK.$f!(tdst[I′], v, p, α, One(), backend, allocator)
end
return tdst
end
scale!(tdst, β)
p = (p₁..., p₂...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend...)
function TK.$f!(
tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT},
p::Index2Tuple, α::Number, β::Number, backend::AbstractBackend, allocator
) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap}
@boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p)
scale!(tdst, β)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend, allocator)
end
return tdst
end
return tdst
end
@eval function TK.$f!(
tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT},
(p₁, p₂)::Index2Tuple,
α::Number, β::Number,
backend::AbstractBackend...,
) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
function TK.$f!(
tdst::TensorMap, tsrc::BlockTensorMap, p::Index2Tuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
return TK.$f!(tdst, only(tsrc), p, α, β, backend, allocator)
end
scale!(tdst, β)
p = (p₁..., p₂...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend...)
function TK.$f!(
tdst::BlockTensorMap, tsrc::TensorMap, p::Index2Tuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
TK.$f!(only(tdst), tsrc, p, α, β, backend, allocator)
return tdst
end
return tdst
end
@eval function TK.$f!(
tdst::TensorMap, tsrc::BlockTensorMap,
(p₁, p₂)::Index2Tuple,
α::Number, β::Number,
backend::AbstractBackend...,
)
@assert length(tsrc) == 1 "source tensor must be a single tensor"
return TK.$f!(tdst, only(tsrc), (p₁, p₂), α, β, backend...)
end
end

function TK.add_braid!(
tdst::BlockTensorMap, tsrc::BlockTensorMap,
(p₁, p₂)::Index2Tuple{N₁, N₂},
levels::IndexTuple,
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
@propagate_inbounds function TK.braid!(
tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple, levels::IndexTuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
@boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels)

dstdata = parent(tdst)
srcdata = permutedims(StridedView(parent(tsrc)), (p..., p...))
srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...))

@inbounds for I in eachindex(dstdata, srcdata)
dstdata[I] = TK.add_braid!(
dstdata[I], srcdata[I], (p₁, p₂), levels, α, β, backend...
dstdata[I] = TK.braid!(
dstdata[I], srcdata[I], p, levels, α, β, backend, allocator
)
end
return tdst
end
function TK.add_braid!(
@propagate_inbounds function TK.braid!(
tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap,
(p₁, p₂)::Index2Tuple{N₁, N₂},
levels::IndexTuple,
α::Number, β::Number,
backend::AbstractBackend...,
) where {N₁, N₂}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
p::Index2Tuple, levels::IndexTuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
@boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels)
scale!(tdst, β)
p = (p..., p...)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
tdst[I′] = TK.add_braid!(tdst[I′], v, (p₁, p₂), levels, α, One(), backend...)
I′ = CartesianIndex(TT.getindices(I.I, p_lin))
tdst[I′] = TK.braid!(tdst[I′], v, p, levels, α, One(), backend, allocator)
end
return tdst
end
function TK.add_braid!(
function TK.braid!(
tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT},
(p₁, p₂)::Index2Tuple,
levels::IndexTuple,
α::Number, β::Number,
backend::AbstractBackend...,
p::Index2Tuple, levels::IndexTuple, α::Number, β::Number, backend::AbstractBackend, allocator
) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap}
@boundscheck begin
permute(space(tsrc), (p₁, p₂)) == space(tdst) ||
throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)),
dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)"))
end
@boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels)
scale!(tdst, β)
p = (p..., p...)
p_lin = (p[1]..., p[2]...)
@inbounds for (I, v) in nonzero_pairs(tsrc)
I′ = CartesianIndex(TT.getindices(I.I, p))
tdst[I′] = TK.add_braid!(tdst[I′], v, (p₁, p₂), levels, α, One(), backend...)
I′ = CartesianIndex(TT.getindices(I.I, p_lin))
tdst[I′] = TK.braid!(tdst[I′], v, p, levels, α, One(), backend, allocator)
end
return tdst
end
function TK.add_braid!(
function TK.braid!(
tdst::TensorMap, tsrc::BlockTensorMap,
(p₁, p₂)::Index2Tuple,
levels::IndexTuple,
α::Number, β::Number,
backend::AbstractBackend...,
p::Index2Tuple, levels::IndexTuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
return TK.add_braid!(tdst, only(tsrc), p, levels, α, β, backend, allocator)
end
function TK.braid!(
tdst::BlockTensorMap, tsrc::TensorMap,
p::Index2Tuple, levels::IndexTuple,
α::Number, β::Number, backend::AbstractBackend, allocator
)
@assert length(tsrc) == 1 "source tensor must be a single tensor"
return TK.add_braid!(tdst, only(tsrc), (p₁, p₂), levels, α, β, backend...)
TK.braid!(only(tdst), tsrc, p, levels, α, β, backend, allocator)
return tdst
end

Base.@constprop :aggressive function TK.insertleftunit(
Expand Down
Loading