Skip to content

Add a general directsum built on a concatenation interface#210

Merged
mtfishman merged 9 commits into
mainfrom
mf/concatenate-directsum
Jul 14, 2026
Merged

Add a general directsum built on a concatenation interface#210
mtfishman merged 9 commits into
mainfrom
mf/concatenate-directsum

Conversation

@mtfishman

@mtfishman mtfishman commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

Adds directsum for summing arrays over a chosen set of axes, together with the concatenation interface it builds on. Moving that interface here from SparseArraysBase gives the sparse and graded array packages a single owner to extend for their own storage, and lets directsum build on it generically. directsum is currently plain concatenation, a valid direct sum for dense and graded backings alike. A fusing variant can be added later when a backend needs it.

The SparseArraysBase and GradedArrays changes that route through this interface, and the name-aware directsum for ITensorBase, land in follow-up PRs.

Move the generic concatenate machinery into TensorAlgebra as the single source of
truth, included flat (no Concatenate submodule): the lazy Concatenated{Style,Dims,Args},
concatenate/cat/cat!, the cat_axes/cat_axis/cat_style helpers, and the generic
copyto!(::Concatenated{Nothing}) block-placement fallback. Reuse TensorAlgebra's own
unval and zero!, and rename the internal dims/style accessors to concatenated_dims and
concatenated_style to avoid occupying those generic names at the top level.

Add directsum along given dims. Its FusionStyle is resolved by directsum_style, which
defaults to ReshapeFusion for every backend (a straight cat: a valid direct sum for a
dense or AbelianGradedArray backing, no basis rotation). A backend overloads
directsum_style to opt its arrays into a fusing or rotating variant such as SectorFusion,
or the style can be passed explicitly, like matricize(style, ...). directsum_style is
deliberately distinct from FusionStyle(a) (which matricize uses) and from cat_style
(the Concatenated broadcast style).

Downstream packages (SparseArraysBase, GradedArrays) will consolidate onto this copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.52459% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.33%. Comparing base (eaae289) to head (2ccc83f).

Files with missing lines Patch % Lines
src/concatenate.jl 88.33% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #210      +/-   ##
==========================================
+ Coverage   80.85%   81.33%   +0.47%     
==========================================
  Files          24       26       +2     
  Lines         914      975      +61     
==========================================
+ Hits          739      793      +54     
- Misses        175      182       +7     
Flag Coverage Δ
docs 22.50% <0.00%> (-1.56%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mtfishman
mtfishman marked this pull request as draft July 13, 2026 23:48
@mtfishman mtfishman changed the title Add a general directsum built on the Concatenate interface [WIP] Add a general directsum built on the Concatenate interface Jul 13, 2026
mtfishman and others added 2 commits July 13, 2026 21:00
`directsum_style` now resolves the direct-sum style over several arguments by folding a per-argument `directsum_style(a)` with a binary `directsum_style(s1, s2)` combine, mirroring how `Base.Broadcast` folds `BroadcastStyle`. Two of the same style combine to that style and any mismatch falls back to `ReshapeFusion`, so heterogeneous inputs resolve to a well-defined combined style. This replaces the `directsum_style(as...) = ReshapeFusion()` vararg stub, which ignored its arguments and so was no better than plain vararg dispatch. The default is still `ReshapeFusion` for every backend, so behavior is unchanged. Its binary combine is kept independent of `FusionStyle`'s so the two traits can diverge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The concatenation interface no longer builds a lazy `Concatenated{Style,Dims,Args}` object. Concatenation does not fuse, so there was nothing for the wrapper to defer, and its only real jobs (choosing the destination and the placement per style, and computing the result axes) are expressed directly as functions. `cat`/`cat!`/`concatenate` now resolve the combined `cat_style`, allocate with `cat_similar(style, T, ax, args...)`, and place with `cat_copyto!(dest, style, dims, args...)`. Backends customize concatenation by overloading `cat_similar`/`cat_copyto!` on their style, replacing the previous overloads of `Base.similar`/`Base.copyto!` on `Concatenated{<:TheirStyle}`. The default `cat_copyto!` strips the style to `nothing`, which keeps the "specialize on the destination type without ambiguity against the style dispatch" property the `Concatenated{Nothing}` conversion used to provide. `Concatenated` and `concatenated` are dropped from the public interface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mtfishman added a commit to ITensor/GradedArrays.jl that referenced this pull request Jul 14, 2026
Follows the TensorAlgebra change that replaces the lazy `Concatenated` wrapper with a function interface (ITensor/TensorAlgebra.jl#210). The abelian graded concatenation now overloads `TensorAlgebra.cat_similar(::AbelianGradedStyle, ...)` for the destination and `TensorAlgebra.cat_copyto!(dest, ::AbelianGradedStyle, ...)` for the block placement, in place of the previous `Base.similar`/`Base.copyto!` methods on `Concatenated{<:AbelianGradedStyle}`. Behavior is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mtfishman and others added 3 commits July 13, 2026 21:43
For now `directsum(as...; dims)` is just `cat(as...; dims)`. The `directsum_style` trait (per-argument style plus pairwise combine) had no user yet, since every backend resolved to `ReshapeFusion` and there is no fusing/rotating direct sum implemented, so it was speculative infrastructure. The style selector will come back the same way `matricize` takes a `FusionStyle` once a backend needs the canonicalizing (merge-and-sort) direct sum. `directsum_style` is dropped from the public interface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ments

`cat_ndims`, `cat_axes`, and `dims2cat` now implement on their `Val` method and have the plain-value method forward with `Val(dims)`, matching the direction `concatenate` already normalizes. The forward can call `Val` directly rather than through a `to_val` helper, since dispatch guarantees the plain method never receives a `Val`. Also cut the comments down to the non-obvious rationale (the difference from `Base.cat`, the `Broadcasted` reuse, the style-to-`nothing` fallback, the Base attribution).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The keyword-dims entry point is Base.cat, routed to the concatenation
interface through the Base._cat overloads that backends define. Keeping a
separate TensorAlgebra.cat only shadowed Base.cat, so it is removed. The
positional-dims TensorAlgebra names are now concatenate and concatenate!.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mtfishman mtfishman changed the title [WIP] Add a general directsum built on the Concatenate interface [WIP] Add a general directsum built on a concatenation interface Jul 14, 2026
mtfishman and others added 3 commits July 14, 2026 12:00
Fold the separate placement hook into `concatenate!` by leading with the
style: `concatenate!(::BroadcastStyle, dest, dims, args...)` is the generic
placement, and `concatenate!(dest, args...; dims)` forwards to it after
computing `cat_style`. A backend customizes placement by overloading
`concatenate!` on its own style, alongside `cat_similar` for allocation.
This drops the `cat_copyto!` name and its style-stripping fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
By placement time `cat_similar` has already used the combined `cat_style` to
build the destination, so `concatenate!` can dispatch on the destination type
and does not need the style. This drops the leading style argument and the
keyword forwarding method, leaving `concatenate!(dest, dims, args...)` with
`dims` positional, matching `concatenate(dims, args...)`. Allocation still
dispatches on the style through `cat_similar`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`directsum(dims, as...)` matches `concatenate(dims, as...)` and the rest of
the interface, and a positional signature composes better for later
customization, whether a leading style argument or dispatch on the summed
arrays. Also drops the empty `function directsum end` stub, since the
fallback method already defines the function.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mtfishman added a commit to ITensor/ITensorBase.jl that referenced this pull request Jul 14, 2026
Match the `directsum(dims, as...)` signature introduced in
ITensor/TensorAlgebra.jl#210.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mtfishman mtfishman changed the title [WIP] Add a general directsum built on a concatenation interface Add a general directsum built on a concatenation interface Jul 14, 2026
@mtfishman
mtfishman marked this pull request as ready for review July 14, 2026 17:36
@mtfishman
mtfishman enabled auto-merge (squash) July 14, 2026 17:36
@mtfishman
mtfishman merged commit 2fe9d5c into main Jul 14, 2026
31 checks passed
@mtfishman
mtfishman deleted the mf/concatenate-directsum branch July 14, 2026 18:02
mtfishman added a commit to ITensor/SparseArraysBase.jl that referenced this pull request Jul 14, 2026
## Summary

Drops the vendored `Concatenate` interface now that it lives in
TensorAlgebra (ITensor/TensorAlgebra.jl#210),
and extends that interface for sparse storage there instead. `zero!` is
routed through TensorAlgebra the same way: the sparse array types extend
`TensorAlgebra.zero!` to empty their storage in place rather than
filling it with zeros.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mtfishman added a commit to ITensor/GradedArrays.jl that referenced this pull request Jul 14, 2026
## Summary

Adds `Base.cat` and `directsum` for abelian graded arrays by hooking
into the concatenation interface in TensorAlgebra
(ITensor/TensorAlgebra.jl#210). `cat_axis` on
graded ranges block-appends in concat-order, keeping the argument
sectors in order rather than merging or sorting them, and
materialization places each argument's blocks into the destination's
diagonal hyper-block. `AbelianBlocks` becomes an `AbstractSparseArray`
exposing the stored (symmetry-allowed) blocks, so the placement visits
only those blocks and never touches a forbidden position. The default
`directsum` is plain concatenation, so it shares this path.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mtfishman added a commit to ITensor/ITensorBase.jl that referenced this pull request Jul 14, 2026
## Summary

Adds a name-aware `directsum` for tensors, building on the general
`directsum` in TensorAlgebra
(ITensor/TensorAlgebra.jl#210). It aligns the
arguments by index name, sums them over a chosen set of indices, and
returns a single tensor with the summed indices trailing. Two forms are
provided, one taking the output indices explicitly and one minting fresh
indices for the summed dimensions.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant