Skip to content

tensor: recurse conj() into nested tiles (tensor-of-tensors)#560

Merged
evaleev merged 2 commits into
zhihao/feature/strided-dgemmfrom
evaleev/feature/tensor-of-tensor-conj
Jun 6, 2026
Merged

tensor: recurse conj() into nested tiles (tensor-of-tensors)#560
evaleev merged 2 commits into
zhihao/feature/strided-dgemmfrom
evaleev/feature/tensor-of-tensor-conj

Conversation

@evaleev
Copy link
Copy Markdown
Member

@evaleev evaleev commented Jun 5, 2026

Summary

Tensor::conj() is scale(conj_op()), which multiplies each element by a ComplexConjugate operator and thus calls detail::conj() on each element. For a tensor-of-tensors the element is itself a TA::Tensor, and detail::conj() only had scalar (real / std::complex) overloads — so conj() of a Tensor<Tensor<...>> (and DistArray<Tensor<Tensor<...>>>::operator()(...).conj()) failed to compile.

Change

  • Add a detail::conj() overload for non-numeric types that forwards to the element's own conj(), recursing until the scalar overloads terminate it. SFINAE'd on a non-numeric type that provides a conj() member, so it never competes with the scalar overloads.
  • Add a Tensor<Tensor<complex>> conj unit test (tests/tensor.cpp).

Motivation

Downstream (SeQuant), evaluating the adjoint of a Nonsymm tensor backed by a complex tensor-of-tensors array needs arr(annot).conj() to work uniformly for regular and nested arrays. This removes a SeQuant-side local-tile-walk workaround in favor of the proper TA capability.

Notes

Based on zhihao/feature/strided-dgemm (the branch the consuming build currently tracks), not master. Can rebase onto master if preferred.

evaleev added 2 commits June 5, 2026 14:00
Tensor::conj() is scale(conj_op()), which multiplies each element by a
ComplexConjugate operator and thus calls detail::conj() on each element. For a
tensor-of-tensors the element is itself a TA::Tensor, and detail::conj() only
had scalar (real/std::complex) overloads, so conj() of a Tensor<Tensor<...>>
(and DistArray<Tensor<Tensor<...>>>::operator()(...).conj()) failed to compile.

Add a detail::conj() overload for non-numeric types that forwards to the
element's own conj(), recursing until the scalar overloads terminate it.
SFINAE'd on a non-numeric type with a conj() member so it never competes with
the scalar overloads. Add a Tensor<Tensor<complex>> conj test.
…renaTensor::conj_to)

The complex-ToT conj recursion (prior commit) handled the value-returning path,
but the out-of-place permuted path threw for arena/view inner: Tensor::scale(
factor, perm) had only a view-TA_EXCEPTION branch and a value-based unary branch.
The DistArray .conj() expression lowers to scale(factor, perm) (and scale_to),
so adjoint of a complex ArenaTensor-backed tensor-of-tensors hit that throw.

- scale(factor, perm): add an arena branch mirroring add(right, perm) — scale via
  the arena kernel (manages the slab), then permute the result if non-trivial
  (arena_perm_is_trivial). Precedes the view branch since ArenaTensor is a view.
- ArenaTensor::conj_to(): in-place conjugation via the free scale_to kernel with a
  ComplexConjugate factor (no-op for real T); mirrors neg_to(). Include complex.h.
- tests/tot_construction: conj_tot_{tensor,arena}_inner exercise conj(),
  conj(perm), and conj_to() on complex tensor-of-tensors for both inner kinds.

scale_to needed no arena branch: res *= conj_op routes through the free
operator*= -> scale_to kernel, conjugating arena scalars in place.
@evaleev evaleev force-pushed the evaleev/feature/tensor-of-tensor-conj branch from e8ed544 to 196f29a Compare June 6, 2026 01:49
@evaleev evaleev requested a review from Copilot June 6, 2026 02:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Tensor::conj() for tensor-of-tensors (e.g., Tensor<Tensor<std::complex<...>>>) by making the internal conjugation helper recurse into nested tensor elements, and extends test coverage to prevent regressions (including arena-backed inner tiles).

Changes:

  • Added a TiledArray::detail::conj(const T&) overload for non-numeric types that forwards to t.conj(), enabling recursive conjugation for nested tensor element types.
  • Updated Tensor::scale(..., perm) / Tensor::scale_to(...) handling for Tensor<ArenaTensor<...>> so conjugation/scaling paths work with arena-backed inner cells and permutations.
  • Added regression tests covering Tensor<Tensor<complex>>.conj() and ToT conjugation (including permuted and in-place variants, and arena inner tiles).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/TiledArray/tensor/complex.h Adds recursive detail::conj() overload to support conjugating nested tensor element types.
src/TiledArray/tensor/tensor.h Routes arena inner-cell scaling/conjugation through arena-aware paths and supports permuted scale for arena inners.
src/TiledArray/tensor/arena_tensor.h Adds ArenaTensor::conj_to() implemented via the arena scale_to kernel with conj_op().
tests/tensor.cpp Adds a regression test ensuring Tensor<Tensor<complex>>::conj() compiles and conjugates inner scalars.
tests/tot_construction.cpp Adds ToT conjugation tests covering out-of-place, permuted, and in-place conjugation for tensor and arena inner tiles.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@evaleev evaleev merged commit b8c1d75 into zhihao/feature/strided-dgemm Jun 6, 2026
10 checks passed
@evaleev evaleev deleted the evaleev/feature/tensor-of-tensor-conj branch June 6, 2026 02:39
evaleev added a commit to ValeevGroup/SeQuant that referenced this pull request Jun 6, 2026
…iledArray pin

TiledArray now recurses conj() into nested tiles and handles it for arena/view
inner cells (ValeevGroup/tiledarray#560), so the tensor-of-tensors adjoint() no
longer needs the complex-only local-tile-walk workaround — it uses the uniform
result(post_annot) = arr(pre_annot).conj(), identical to the regular-tensor
branch.

- external/versions.cmake: bump SEQUANT_TRACKED_TILEDARRAY_TAG to the merged TA
  commit (b8c1d7553) carrying the recursive + arena-aware conj.
- eval/backends/tiledarray: collapse ResultTensorOfTensorTA::adjoint() to the
  uniform .conj() (drops the local-tile walk and the now-unused <complex>).
- tests/test_eval_ta: ta_tot_conj_complex runtime-checks TA's ToT .conj() over a
  complex tensor-of-tensors; force-instantiate ResultTensorOfTensorTA<complex>
  to compile-check the collapsed adjoint().
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.

2 participants