Skip to content

Fix dpnp.median/dpnp.nanmedian result shape for empty and size-1 kept dimensions - #3081

Merged
antonwolfy merged 5 commits into
masterfrom
fix-median-empty-kept-axis
Oct 4, 2026
Merged

antonwolfy merged 5 commits into
masterfrom
fix-median-empty-kept-axis

Conversation

@antonwolfy

@antonwolfy antonwolfy commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes two kept-dimension shape bugs in dpnp.median/dpnp.nanmedian.

Empty kept dimension. dpnp.median and dpnp.nanmedian raised ValueError when called with a tuple (or list) axis and one of the kept, non-reduced dimensions has size 0, e.g.

dpnp.median(dpnp.empty((0, 3, 4)), axis=(1, 2))

The sequence-axis path flattens the reduced axes in _flatten_array_along_axes with a.reshape(kept_shape + (-1,)). The -1 cannot be inferred once the array has size 0 and a kept axis is also 0 (every merged length yields a size-0 array, so the dimension is ambiguous), which makes reshape raise. The merged length is now computed explicitly with math.prod(...), so the tuple-axis path returns the same empty result as the single-axis path.

Size-1 kept dimension. dpnp.nanmedian dropped kept dimensions of size 1 and returned the wrong shape, e.g. a (1, 5) array reduced over axis=1 returned shape () instead of (1,). _calc_nanmedian ended with an unconditional dpnp.squeeze(res), which also removed non-reduced size-1 axes; it now squeezes only the reduced trailing axis with dpnp.squeeze(res, axis=-1).

  • Have you provided a meaningful PR description?
  • Have you added a test, reproducer or referred to an issue with a reproducer?
  • Have you tested your changes locally for CPU and GPU devices?
  • Have you made sure that new changes do not introduce compiler warnings?
  • Have you checked performance impact of proposed changes?
  • Have you added documentation for your changes, if necessary?
  • Have you added your changes to the changelog?

`_flatten_array_along_axes` merged the reduced axes with a trailing `-1`,
which `reshape` cannot infer once the array has size 0 and a kept axis is
also 0. Reducing e.g. an array of shape `(0, 3, 4)` over `axis=(1, 2)`
raised `ValueError: cannot reshape array of size 0 into shape (0,newaxis)`.
Compute the merged length explicitly so the empty case returns the expected
empty result.
@antonwolfy antonwolfy added this to the 0.21.0 release milestone Oct 1, 2026
@antonwolfy antonwolfy self-assigned this Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

View rendered docs @ https://intelpython.github.io/dpnp/index.html

@coveralls

coveralls commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 78.624% (+0.002%) from 78.622% — fix-median-empty-kept-axis into master

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Array API standard conformance tests for dpnp=0.21.0dev11=np2py314h8d9cdd5_19 ran successfully.
Passed: 1376
Failed: 0
Skipped: 6

antonwolfy and others added 3 commits October 2, 2026 12:55
`_calc_nanmedian` squeezed every size-1 axis, which also dropped kept
(non-reduced) dimensions of size 1 and produced a wrong result shape
(e.g. a (1, 5) array reduced over axis=1 returned shape () instead of
(1,)). Squeeze only the reduced trailing axis.
@antonwolfy antonwolfy changed the title Fix dpnp.median/dpnp.nanmedian for a tuple axis with an empty kept dimension Fix dpnp.median/dpnp.nanmedian result shape for empty and size-1 kept dimensions Oct 2, 2026

@ndgrigorian ndgrigorian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@antonwolfy
antonwolfy merged commit eec0aeb into master Oct 4, 2026
110 of 113 checks passed
@antonwolfy
antonwolfy deleted the fix-median-empty-kept-axis branch October 4, 2026 14:56
github-actions Bot added a commit that referenced this pull request Oct 4, 2026
…kept dimensions (#3081)

This PR fixes two kept-dimension shape bugs in
`dpnp.median`/`dpnp.nanmedian`.

**Empty kept dimension.** `dpnp.median` and `dpnp.nanmedian` raised
`ValueError` when called with a tuple (or list) `axis` and one of the
kept, non-reduced dimensions has size 0, e.g.
```
dpnp.median(dpnp.empty((0, 3, 4)), axis=(1, 2))
```
The sequence-axis path flattens the reduced axes in
`_flatten_array_along_axes` with `a.reshape(kept_shape + (-1,))`. The
`-1` cannot be inferred once the array has size 0 and a kept axis is
also 0 (every merged length yields a size-0 array, so the dimension is
ambiguous), which makes `reshape` raise. The merged length is now
computed explicitly with `math.prod(...)`, so the tuple-axis path
returns the same empty result as the single-axis path.

**Size-1 kept dimension.** `dpnp.nanmedian` dropped kept dimensions of
size 1 and returned the wrong shape, e.g. a `(1, 5)` array reduced over
`axis=1` returned shape `()` instead of `(1,)`. `_calc_nanmedian` ended
with an unconditional `dpnp.squeeze(res)`, which also removed
non-reduced size-1 axes; it now squeezes only the reduced trailing axis
with `dpnp.squeeze(res, axis=-1)`. eec0aeb
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.

3 participants