Skip to content

DArray: Add diag - #766

Merged
jpsamaroo merged 1 commit into
JuliaParallel:masterfrom
aalquwayfili:darray-diag
Oct 7, 2026
Merged

jpsamaroo merged 1 commit into
JuliaParallel:masterfrom
aalquwayfili:darray-diag

Conversation

@aalquwayfili

Copy link
Copy Markdown
Contributor

Fixes #765.

diag(::DMatrix) fell back to Base, which indexes with a stepped range of CartesianIndex that getindex(::DArray, ...) cannot split across partitions. tr and Diagonal failed the same way.

This adds LinearAlgebra.diag(A::DMatrix, k::Integer=0). It allocates a DVector and copies each partition's stretch of the diagonal into it under spawn_datadeps. Only the partitions that the diagonal crosses are read. The result uses Blocks(min(mb, nb)), so for the main diagonal of square blocks each partition fills exactly one partition of the result. k can be any Integer, and a k outside of the matrix gives an empty diagonal, as it does for a Matrix. tr and Diagonal need no method of their own once diag works.

Tests cover every k from -m-2 to n+2 for square, single partition, ragged, wide and tall layouts in Float64 and ComplexF64, k given as UInt, Int8, BigInt and Bool, and tr.

array/linalg/core passes on Julia 1.10, 1.11 and 1.12 (853 tests, 3 workers).

I also ran it on a DArray of CuArrays (Quadro RTX 8000, CUDA.jl 6.4.2): every k matches the CPU result and the partitions of the result are CuArrays. tr does not work there yet, because sum of a GPU backed DArray fails on master for an unrelated reason. I will report that separately.

`diag(::DMatrix)` and `tr(::DMatrix)` threw

    ArgumentError: Cannot convert StepRangeLen{CartesianIndex{2}, ...} to UnitRange

`Base`'s fallback indexes with `diagind`, a stepped range of
`CartesianIndex`, and `getindex(::DArray, ...)` can only split unit
ranges across partitions.

Copy each partition's stretch of the diagonal into a `DVector` instead.
Only the partitions that the diagonal crosses are read, and for the main
diagonal of square blocks each one fills exactly one partition of the
result. `tr` and `Diagonal` work through `Base` once `diag` does.

`k` may be any `Integer`, and a `k` outside of the matrix gives an
empty diagonal, as it does for a `Matrix`.
@jpsamaroo
jpsamaroo merged commit c8497c2 into JuliaParallel:master Oct 7, 2026
44 of 57 checks passed
@jpsamaroo

Copy link
Copy Markdown
Member

Thanks!

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.

diag and tr of a DMatrix throw an ArgumentError

2 participants