Skip to content

Fix diag for zero-size input - #4165

Merged
zcbenz merged 1 commit into
ml-explore:mainfrom
devteamaegis:fix/diag-zero-size
Aug 12, 2026
Merged

Fix diag for zero-size input#4165
zcbenz merged 1 commit into
ml-explore:mainfrom
devteamaegis:fix/diag-zero-size

Conversation

@devteamaegis

Copy link
Copy Markdown
Contributor

Proposed changes

What's broken. mx.diag raises an internal scatter error on a zero-size 1-D input:

import mlx.core as mx
mx.diag(mx.zeros((0,)))
# ValueError: [scatter] Updates with shape (0,1,1) are too large for array with shape (0,0).

NumPy returns a (0, 0) array. The message comes from scatter, so this is an internal failure leaking out rather than a deliberate rejection — compare tril, which rejects a 1-D input with a clear [tril] array must be at least 2-D.

Only k = 0 is affected, which is the default. Every other offset already worked, because n is then at least |k|:

mx.diag(mx.zeros((0,)), k) np.diag(np.zeros((0,)), k)
k=-2 (2, 2) (2, 2)
k=-1 (1, 1) (1, 1)
k=0 ValueError (0, 0)
k=1 (1, 1) (1, 1)
k=2 (2, 2) (2, 2)

The neighbouring zero-size cases are all fine too, so this is an isolated hole: mx.diag on (0, 0), (0, 3) and (3, 0), plus mx.eye(0), mx.tri(0), mx.identity(0) and mx.tril/mx.triu on (0, 0) all match NumPy.

Why. diag builds an n x n zero matrix and scatters the input onto its diagonal. With an empty input and k = 0, n is 0, and scattering the empty updates into the 0x0 output is rejected.

The fix. Return the zero matrix directly when there is nothing to place on the diagonal.

The test. test_diag_zero_size in python/tests/test_ops.py, covering k in -2..2 across float32, int32 and complex64 (shape, dtype and values against NumPy), plus the zero-size 2-D inputs that already worked, so they stay covered.

Fails before, passes after:

# before
FAILED python/tests/test_ops.py::TestOps::test_diag_zero_size - ValueError: [scatter] Updates with shape (0,1,1) are too large for array with shape (0,0).
1 failed, 2 passed, 148 deselected

# after
3 passed, 148 deselected

python/tests/test_ops.py is green (151 passed, 309 subtests). The rest of the suite matches the baseline on this machine; the only failures are 18 pre-existing Metal DLPack import is not available errors from my CPU-only build, which are unrelated to this change.

No benchmark: the change is an early return on a zero-size input, so it cannot affect any non-empty path.

Checklist

  • I have read the CONTRIBUTING document
  • I have run pre-commit run --all-files to format my code / installed pre-commit prior to committing changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the necessary documentation (if needed) — no API change

diag builds an n x n zero matrix and scatters the input onto its
diagonal. When the input is empty and k is zero, n is zero too, and
scattering the empty updates into the 0x0 output raised

  [scatter] Updates with shape (0,1,1) are too large for array with shape (0,0)

Skip the scatter when there is nothing to place. Every non-zero k
already worked, since n is then at least |k|.
@zcbenz zcbenz changed the title fix(ops): return an empty matrix from diag for a zero-size input Fix diag for zero-size input Aug 12, 2026
@zcbenz
zcbenz merged commit 56c26e8 into ml-explore:main Aug 12, 2026
28 checks passed
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