From 7ce784b3c65e0c6c7eef24ae1cec467316f5d9ee Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Wed, 1 Jul 2026 21:21:49 -0400 Subject: [PATCH 1/7] Write each graded block straight into its coupled-sector matrix slice Fold each stored block's permute, reshape, `op`, and fermion sign into a single in-place strided write, dropping the per-block permuted-and-reshaped intermediate. Roughly halves the matricize allocation. --- src/fusion.jl | 69 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/src/fusion.jl b/src/fusion.jl index a349f61..4ad155d 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -71,9 +71,47 @@ function TensorAlgebra.matricize( ) end +# Scatter one stored source block straight into its `(rows, cols)` slice of a coupled-sector +# matrix, folding the permute, reshape, `op`, and fermion sign into a single strided in-place +# write with no permuted-block intermediate. `biperm` reorders the source legs into the +# destination group order; `phase` is the block's ±1 fermion sign for that reordering. The +# 2D slice is `sreshape`d into the block's grouped N-D shape (a strided view of the slice) and +# the permuted source is broadcast into it. +function fused_block_scatter!(dest, op, srcdata, phase, biperm::NTuple{N, Int}) where {N} + dest_grouped = StridedViews.sreshape( + StridedViews.StridedView(dest), ntuple(i -> size(srcdata, biperm[i]), Val(N)) + ) + src = permutedims(StridedViews.StridedView(srcdata), biperm) + if op === identity + dest_grouped .= phase .* src + else + dest_grouped .= phase .* op.(src) + end + return dest +end + +# The coupled-sector matrix may have non-strided blocks (e.g. a `Diagonal` middle factor from a +# factorization), which `StridedView` cannot wrap; densify those slices, leaving the common +# dense-block contraction path a view. +stridedslice(x::StridedArray) = x +stridedslice(x) = Array(x) + +# Inverse of `fused_block_scatter!`: read one coupled-sector matrix slice straight into its +# destination N-D block, folding the reshape, permute back to destination order, and fermion +# sign into a single strided in-place write with no intermediate. `slice` is the `(rows, cols)` +# matrix view; `sreshape`d into the grouped codomain/domain shape `cd_dims`, then `biperm_dest` +# reorders those grouped legs back to destination order. +function fused_block_gather!( + destdata, slice, cd_dims::NTuple{N, Int}, phase, biperm_dest::NTuple{N, Int} + ) where {N} + cd_block = StridedViews.sreshape(StridedViews.StridedView(stridedslice(slice)), cd_dims) + StridedViews.StridedView(destdata) .= phase .* permutedims(cd_block, biperm_dest) + return destdata +end + # Build the sector-merged `FusedGradedMatrix` for the bipartition `(perm_codomain, perm_domain)`. -# `op` transforms the fused axes (`conj` dualizes them), and the per-block `matricizeopperm` permutes -# and reshapes each stored block to 2D, carrying `op` and the block's fermion permutation sign. +# `op` transforms the fused axes (`conj` dualizes them), and each stored block is scattered +# straight into its coupled-sector matrix slice, carrying `op` and the block's fermion sign. function TensorAlgebra.matricizeopperm( ::SectorFusion, op, a::AbelianGradedArray{T, <:Any, N}, perm_codomain::Tuple{Vararg{Int}}, perm_domain::Tuple{Vararg{Int}} @@ -99,6 +137,7 @@ function TensorAlgebra.matricizeopperm( cod_lin = LinearIndices(Tuple(blocklength.(codomain_axes))) dom_lin = LinearIndices(Tuple(blocklength.(domain_axes))) merged_row_sectors = eachsectoraxis(merged_row) + biperm = (perm_codomain..., perm_domain...) for bI_src in eachblockstoredindex(a) src = Tuple(bI_src) row_fine = cod_lin[ntuple(i -> Int(src[perm_codomain[i]]), Val(K))...] @@ -106,14 +145,11 @@ function TensorAlgebra.matricizeopperm( row_bir = row_dest[row_fine] col_bir = col_dest[col_fine] s = merged_row_sectors[Int(Block(row_bir))] - block_2d = TensorAlgebra.matricizeopperm( - SectorFusion(), - op, - a[bI_src], - perm_codomain, - perm_domain + blk = a[bI_src] + fused_block_scatter!( + view(m.blocks[s], only(row_bir.indices), only(col_bir.indices)), + op, data(blk), fermion_permutation_phase(op, sector(blk), biperm), biperm ) - m.blocks[s][only(row_bir.indices), only(col_bir.indices)] = data(block_2d) end return m end @@ -193,7 +229,6 @@ function TensorAlgebra.unmatricizeperm!( # Legs land in codomain/domain order; `biperm_dest` puts them back to destination order. biperm_dest = invperm((invperm_codomain..., invperm_domain...)) - noperm = biperm_dest == ntuple(identity, Val(N)) # Not every allocated block gets written below, so we zero first. zero!(a_dest) cod_lin = LinearIndices(Tuple(map(blocklength, codomain_axes))) @@ -206,18 +241,18 @@ function TensorAlgebra.unmatricizeperm!( col_bir = col_dest[col_fine] s = merged_row_sectors[Int(Block(row_bir))] haskey(m.blocks, s) || continue - sub = m.blocks[s][only(row_bir.indices), only(col_bir.indices)] + slice = view(m.blocks[s], only(row_bir.indices), only(col_bir.indices)) cd_leg = ntuple(d -> d <= K ? invperm_codomain[d] : invperm_domain[d - K], Val(N)) cd_dims = ntuple(d -> blocklengths(axes(a_dest)[cd_leg[d]])[dest_bk[cd_leg[d]]], Val(N)) cd_sects = ntuple(d -> eachsectoraxis(axes(a_dest)[cd_leg[d]])[dest_bk[cd_leg[d]]], Val(N)) - block = reshape(sub, cd_dims) - # Build the block's structural factor with `S` from the input: `cd_sects` is empty - # for a rank-0 destination (a full contraction to a scalar) and so carries no `S`. - block_cd = - AbelianSectorArray(AbelianSectorDelta{eltype(block), S, N}(cd_sects), block) - a_dest[bI] = noperm ? block_cd : permutedims(block_cd, biperm_dest) + # The block's fermion sign takes `S` from the input: `cd_sects` is empty for a rank-0 + # destination (a full contraction to a scalar) and so carries no `S`. + phase = fermion_permutation_phase( + identity, AbelianSectorDelta{eltype(slice), S, N}(cd_sects), biperm_dest + ) + fused_block_gather!(data(view(a_dest, bI)), slice, cd_dims, phase, biperm_dest) end return a_dest end From 8e93af7bb56cadf43164cdb584777be96e5852c1 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Wed, 1 Jul 2026 22:26:52 -0400 Subject: [PATCH 2/7] Read source blocks by view in the graded matricize gather The gather only reads each stored block, so take it with `view` instead of the block `getindex`, which materializes a copy. Removes the largest remaining per-block allocation in matricize. --- src/fusion.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fusion.jl b/src/fusion.jl index 4ad155d..abf335f 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -145,7 +145,7 @@ function TensorAlgebra.matricizeopperm( row_bir = row_dest[row_fine] col_bir = col_dest[col_fine] s = merged_row_sectors[Int(Block(row_bir))] - blk = a[bI_src] + blk = view(a, bI_src) fused_block_scatter!( view(m.blocks[s], only(row_bir.indices), only(col_bir.indices)), op, data(blk), fermion_permutation_phase(op, sector(blk), biperm), biperm From 5f18e3decb8bd8e16b85fd6bd8f2a1bbd18e0163 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Thu, 2 Jul 2026 12:19:01 -0400 Subject: [PATCH 3/7] Copy structure-preserving factorization blocks without densifying The unmatricize gather wrapped every matrix slice in a `StridedView`, forcing a dense `Array` copy for non-strided blocks like a `Diagonal` `S`. The no-reshape, no-permute case (a rank-2 factor whose axes already match) now writes through a plain type-preserving broadcast, keeping such blocks on their own array type. --- src/fusion.jl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/fusion.jl b/src/fusion.jl index abf335f..f20f401 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -90,21 +90,25 @@ function fused_block_scatter!(dest, op, srcdata, phase, biperm::NTuple{N, Int}) return dest end -# The coupled-sector matrix may have non-strided blocks (e.g. a `Diagonal` middle factor from a -# factorization), which `StridedView` cannot wrap; densify those slices, leaving the common -# dense-block contraction path a view. -stridedslice(x::StridedArray) = x -stridedslice(x) = Array(x) - # Inverse of `fused_block_scatter!`: read one coupled-sector matrix slice straight into its # destination N-D block, folding the reshape, permute back to destination order, and fermion # sign into a single strided in-place write with no intermediate. `slice` is the `(rows, cols)` # matrix view; `sreshape`d into the grouped codomain/domain shape `cd_dims`, then `biperm_dest` # reorders those grouped legs back to destination order. +# +# When the block needs neither a leg-fusion reshape nor a permute (`cd_dims` already matches the +# slice and `biperm_dest` is the identity, e.g. unmatricizing a rank-2 factor), the write is a +# plain type-preserving broadcast. That path avoids `StridedView`, which cannot wrap the +# non-strided blocks a factorization can produce (a `Diagonal` `S`), and keeps such blocks on +# their own array type rather than densifying them. function fused_block_gather!( destdata, slice, cd_dims::NTuple{N, Int}, phase, biperm_dest::NTuple{N, Int} ) where {N} - cd_block = StridedViews.sreshape(StridedViews.StridedView(stridedslice(slice)), cd_dims) + if biperm_dest == ntuple(identity, Val(N)) && size(slice) == cd_dims + destdata .= phase .* slice + return destdata + end + cd_block = StridedViews.sreshape(StridedViews.StridedView(slice), cd_dims) StridedViews.StridedView(destdata) .= phase .* permutedims(cd_block, biperm_dest) return destdata end From 2454c73e1b16c696a5220d94b216ef20d84892e5 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Thu, 2 Jul 2026 12:39:47 -0400 Subject: [PATCH 4/7] Name the block helpers after matricizeopperm/unmatricizeperm! and guard strided inputs Rename the per-block helpers to `matricizeopperm_block!` and `unmatricizeperm_block!` after the functions they factor out, rename their `biperm` argument to `perm`, and load `StridedView` into scope so it need not be qualified. Use `reshape` and `op` directly on the `StridedView` (both are lazy) rather than `sreshape` and a broadcast branch. The strided assumption is now an explicit `isstrided` check with a clear error instead of a cryptic `StridedView` failure. --- src/fusion.jl | 88 ++++++++++++++++++++++---------------------- src/tensoralgebra.jl | 2 +- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/fusion.jl b/src/fusion.jl index f20f401..c65ab2c 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -71,46 +71,48 @@ function TensorAlgebra.matricize( ) end -# Scatter one stored source block straight into its `(rows, cols)` slice of a coupled-sector -# matrix, folding the permute, reshape, `op`, and fermion sign into a single strided in-place -# write with no permuted-block intermediate. `biperm` reorders the source legs into the -# destination group order; `phase` is the block's ±1 fermion sign for that reordering. The -# 2D slice is `sreshape`d into the block's grouped N-D shape (a strided view of the slice) and -# the permuted source is broadcast into it. -function fused_block_scatter!(dest, op, srcdata, phase, biperm::NTuple{N, Int}) where {N} - dest_grouped = StridedViews.sreshape( - StridedViews.StridedView(dest), ntuple(i -> size(srcdata, biperm[i]), Val(N)) - ) - src = permutedims(StridedViews.StridedView(srcdata), biperm) - if op === identity - dest_grouped .= phase .* src - else - dest_grouped .= phase .* op.(src) - end - return dest +# The block-level piece of `matricizeopperm`: write one stored block into its region of the +# coupled-sector matrix, folding the permute, reshape to 2D, `op`, and fermion sign into a single +# strided in-place write with no intermediate. `perm` reorders the block's legs into the +# destination group order and `phase` is its ±1 fermion sign. The block must be strided (an +# `AbelianGradedArray` stores dense blocks); `op` and `permutedims` ride on the `StridedView` +# lazily. +function matricizeopperm_block!( + matrix_region, + op, + block, + phase, + perm::NTuple{N, Int} + ) where {N} + isstrided(block) || + throw(ArgumentError("non-strided blocks are not supported in matricize")) + grouped = reshape(StridedView(matrix_region), ntuple(i -> size(block, perm[i]), Val(N))) + grouped .= phase .* op(permutedims(StridedView(block), perm)) + return matrix_region end -# Inverse of `fused_block_scatter!`: read one coupled-sector matrix slice straight into its -# destination N-D block, folding the reshape, permute back to destination order, and fermion -# sign into a single strided in-place write with no intermediate. `slice` is the `(rows, cols)` -# matrix view; `sreshape`d into the grouped codomain/domain shape `cd_dims`, then `biperm_dest` -# reorders those grouped legs back to destination order. -# -# When the block needs neither a leg-fusion reshape nor a permute (`cd_dims` already matches the -# slice and `biperm_dest` is the identity, e.g. unmatricizing a rank-2 factor), the write is a -# plain type-preserving broadcast. That path avoids `StridedView`, which cannot wrap the -# non-strided blocks a factorization can produce (a `Diagonal` `S`), and keeps such blocks on -# their own array type rather than densifying them. -function fused_block_gather!( - destdata, slice, cd_dims::NTuple{N, Int}, phase, biperm_dest::NTuple{N, Int} +# The block-level piece of `unmatricizeperm!` and the inverse of `matricizeopperm_block!`: write +# one region of the coupled-sector matrix into its destination N-D block, folding the reshape, +# permute back to destination order, and fermion sign into a single in-place write. When the +# block needs neither a reshape nor a permute (a rank-2 factor whose axes already match), a plain +# type-preserving broadcast handles it, which keeps a non-strided factorization block (a +# `Diagonal` `S`) on its own array type. Any other non-strided region would need a permute or +# reshape, which is unsupported. +function unmatricizeperm_block!( + block, matrix_region, block_dims::NTuple{N, Int}, phase, perm::NTuple{N, Int} ) where {N} - if biperm_dest == ntuple(identity, Val(N)) && size(slice) == cd_dims - destdata .= phase .* slice - return destdata + if perm == ntuple(identity, Val(N)) && size(matrix_region) == block_dims + block .= phase .* matrix_region + return block end - cd_block = StridedViews.sreshape(StridedViews.StridedView(slice), cd_dims) - StridedViews.StridedView(destdata) .= phase .* permutedims(cd_block, biperm_dest) - return destdata + isstrided(matrix_region) || throw( + ArgumentError( + "non-strided blocks needing a permute or reshape are not supported in unmatricize" + ) + ) + grouped = reshape(StridedView(matrix_region), block_dims) + StridedView(block) .= phase .* permutedims(grouped, perm) + return block end # Build the sector-merged `FusedGradedMatrix` for the bipartition `(perm_codomain, perm_domain)`. @@ -141,7 +143,7 @@ function TensorAlgebra.matricizeopperm( cod_lin = LinearIndices(Tuple(blocklength.(codomain_axes))) dom_lin = LinearIndices(Tuple(blocklength.(domain_axes))) merged_row_sectors = eachsectoraxis(merged_row) - biperm = (perm_codomain..., perm_domain...) + perm = (perm_codomain..., perm_domain...) for bI_src in eachblockstoredindex(a) src = Tuple(bI_src) row_fine = cod_lin[ntuple(i -> Int(src[perm_codomain[i]]), Val(K))...] @@ -150,9 +152,9 @@ function TensorAlgebra.matricizeopperm( col_bir = col_dest[col_fine] s = merged_row_sectors[Int(Block(row_bir))] blk = view(a, bI_src) - fused_block_scatter!( + matricizeopperm_block!( view(m.blocks[s], only(row_bir.indices), only(col_bir.indices)), - op, data(blk), fermion_permutation_phase(op, sector(blk), biperm), biperm + op, data(blk), fermion_permutation_phase(op, sector(blk), perm), perm ) end return m @@ -231,8 +233,8 @@ function TensorAlgebra.unmatricizeperm!( col_dest = invblockmergeperm(unfused_col, sectorsortperm(unfused_col), merged_col) merged_row_sectors = eachsectoraxis(merged_row) - # Legs land in codomain/domain order; `biperm_dest` puts them back to destination order. - biperm_dest = invperm((invperm_codomain..., invperm_domain...)) + # Legs land in codomain/domain order; `perm_dest` puts them back to destination order. + perm_dest = invperm((invperm_codomain..., invperm_domain...)) # Not every allocated block gets written below, so we zero first. zero!(a_dest) cod_lin = LinearIndices(Tuple(map(blocklength, codomain_axes))) @@ -254,9 +256,9 @@ function TensorAlgebra.unmatricizeperm!( # The block's fermion sign takes `S` from the input: `cd_sects` is empty for a rank-0 # destination (a full contraction to a scalar) and so carries no `S`. phase = fermion_permutation_phase( - identity, AbelianSectorDelta{eltype(slice), S, N}(cd_sects), biperm_dest + identity, AbelianSectorDelta{eltype(slice), S, N}(cd_sects), perm_dest ) - fused_block_gather!(data(view(a_dest, bI)), slice, cd_dims, phase, biperm_dest) + unmatricizeperm_block!(data(view(a_dest, bI)), slice, cd_dims, phase, perm_dest) end return a_dest end diff --git a/src/tensoralgebra.jl b/src/tensoralgebra.jl index 9ab228c..ee5e042 100644 --- a/src/tensoralgebra.jl +++ b/src/tensoralgebra.jl @@ -1,5 +1,5 @@ using SplitApplyCombine: groupcount -using StridedViews: StridedViews +using StridedViews: StridedViews, StridedView, isstrided function tensor_product(r1, r2, r3, rs...) return tensor_product(tensor_product(r1, r2), r3, rs...) From 2af1f164dc846ef2f772d88da8f5b4212988bd27 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Thu, 2 Jul 2026 12:47:09 -0400 Subject: [PATCH 5/7] Name the block-helper arguments dst and src Use `dst`/`src` for the destination and source of `matricizeopperm_block!` and `unmatricizeperm_block!`, matching the `copyto!` convention, and rename the grouped-shape argument to `grouped_dims`. --- src/fusion.jl | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/fusion.jl b/src/fusion.jl index c65ab2c..d9b50c4 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -77,18 +77,12 @@ end # destination group order and `phase` is its ±1 fermion sign. The block must be strided (an # `AbelianGradedArray` stores dense blocks); `op` and `permutedims` ride on the `StridedView` # lazily. -function matricizeopperm_block!( - matrix_region, - op, - block, - phase, - perm::NTuple{N, Int} - ) where {N} - isstrided(block) || +function matricizeopperm_block!(dst, op, src, phase, perm::NTuple{N, Int}) where {N} + isstrided(src) || throw(ArgumentError("non-strided blocks are not supported in matricize")) - grouped = reshape(StridedView(matrix_region), ntuple(i -> size(block, perm[i]), Val(N))) - grouped .= phase .* op(permutedims(StridedView(block), perm)) - return matrix_region + grouped = reshape(StridedView(dst), ntuple(i -> size(src, perm[i]), Val(N))) + grouped .= phase .* op(permutedims(StridedView(src), perm)) + return dst end # The block-level piece of `unmatricizeperm!` and the inverse of `matricizeopperm_block!`: write @@ -99,20 +93,20 @@ end # `Diagonal` `S`) on its own array type. Any other non-strided region would need a permute or # reshape, which is unsupported. function unmatricizeperm_block!( - block, matrix_region, block_dims::NTuple{N, Int}, phase, perm::NTuple{N, Int} + dst, src, grouped_dims::NTuple{N, Int}, phase, perm::NTuple{N, Int} ) where {N} - if perm == ntuple(identity, Val(N)) && size(matrix_region) == block_dims - block .= phase .* matrix_region - return block + if perm == ntuple(identity, Val(N)) && size(src) == grouped_dims + dst .= phase .* src + return dst end - isstrided(matrix_region) || throw( + isstrided(src) || throw( ArgumentError( "non-strided blocks needing a permute or reshape are not supported in unmatricize" ) ) - grouped = reshape(StridedView(matrix_region), block_dims) - StridedView(block) .= phase .* permutedims(grouped, perm) - return block + grouped = reshape(StridedView(src), grouped_dims) + StridedView(dst) .= phase .* permutedims(grouped, perm) + return dst end # Build the sector-merged `FusedGradedMatrix` for the bipartition `(perm_codomain, perm_domain)`. From 7489cd5ee60c740ee938cc36ee7f8b37b4879b19 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Thu, 2 Jul 2026 12:52:11 -0400 Subject: [PATCH 6/7] Derive the unmatricize block dims from the destination The N-D grouping shape for reshaping the matrix slice is `size(dst)` under `invperm(perm)`, so `unmatricizeperm_block!` recovers it from `dst` and `perm` rather than taking it as an argument. --- src/fusion.jl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/fusion.jl b/src/fusion.jl index d9b50c4..1c35e32 100644 --- a/src/fusion.jl +++ b/src/fusion.jl @@ -92,10 +92,8 @@ end # type-preserving broadcast handles it, which keeps a non-strided factorization block (a # `Diagonal` `S`) on its own array type. Any other non-strided region would need a permute or # reshape, which is unsupported. -function unmatricizeperm_block!( - dst, src, grouped_dims::NTuple{N, Int}, phase, perm::NTuple{N, Int} - ) where {N} - if perm == ntuple(identity, Val(N)) && size(src) == grouped_dims +function unmatricizeperm_block!(dst, src, phase, perm::NTuple{N, Int}) where {N} + if perm == ntuple(identity, Val(N)) && size(src) == size(dst) dst .= phase .* src return dst end @@ -104,6 +102,7 @@ function unmatricizeperm_block!( "non-strided blocks needing a permute or reshape are not supported in unmatricize" ) ) + grouped_dims = ntuple(i -> size(dst, invperm(perm)[i]), Val(N)) grouped = reshape(StridedView(src), grouped_dims) StridedView(dst) .= phase .* permutedims(grouped, perm) return dst @@ -243,8 +242,6 @@ function TensorAlgebra.unmatricizeperm!( haskey(m.blocks, s) || continue slice = view(m.blocks[s], only(row_bir.indices), only(col_bir.indices)) cd_leg = ntuple(d -> d <= K ? invperm_codomain[d] : invperm_domain[d - K], Val(N)) - cd_dims = - ntuple(d -> blocklengths(axes(a_dest)[cd_leg[d]])[dest_bk[cd_leg[d]]], Val(N)) cd_sects = ntuple(d -> eachsectoraxis(axes(a_dest)[cd_leg[d]])[dest_bk[cd_leg[d]]], Val(N)) # The block's fermion sign takes `S` from the input: `cd_sects` is empty for a rank-0 @@ -252,7 +249,7 @@ function TensorAlgebra.unmatricizeperm!( phase = fermion_permutation_phase( identity, AbelianSectorDelta{eltype(slice), S, N}(cd_sects), perm_dest ) - unmatricizeperm_block!(data(view(a_dest, bI)), slice, cd_dims, phase, perm_dest) + unmatricizeperm_block!(data(view(a_dest, bI)), slice, phase, perm_dest) end return a_dest end From 208bf84ab7198de2b8f6bc1ef185003c5b54ce84 Mon Sep 17 00:00:00 2001 From: Matthew Fishman Date: Thu, 2 Jul 2026 13:03:10 -0400 Subject: [PATCH 7/7] Bump to 0.13.7 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index cbaf99c..1f524ee 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "GradedArrays" uuid = "bc96ca6e-b7c8-4bb6-888e-c93f838762c2" -version = "0.13.6" +version = "0.13.7" authors = ["ITensor developers and contributors"] [workspace]