Skip to content

Fix nonzero bool nonstandard bytes - #3055

Open
abagusetty wants to merge 4 commits into
IntelPython:masterfrom
abagusetty:fix-nonzero-bool-nonstandard-bytes
Open

Fix nonzero bool nonstandard bytes#3055
abagusetty wants to merge 4 commits into
IntelPython:masterfrom
abagusetty:fix-nonzero-bool-nonstandard-bytes

Conversation

@abagusetty

Copy link
Copy Markdown
Contributor

Boolean arrays may contain non-zero bytes like 0x02 or 0xFF that NumPy treats as True but dpnp does not.

Fixes #3054

  • 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?

`NonZeroIndicator` compared against `inputT(0)` and the `Cumsum1D` factories
used `NoOpTransformer`; for `bool` both fold into a raw byte load, so the
scan summed byte values instead of 0/1. A mask stored as [0, 1, 2, 255, 0, 1]
reported 259 non-zeros instead of 4, affecting `nonzero`, `where`, `extract`,
`place` and `repeat`.

Cast bool via `sycl::bit_cast<std::uint8_t>` / `CastTransformer`, as
`convert_impl` already does (IntelPythongh-2121).
C++ may fold a bool comparison into a raw byte load, so a byte other than
0x00/0x01 compared unequal to a normalized True, ordered by its byte value,
and leaked into computed bool results. Such a byte arises when a buffer is
written through a raw pointer or viewed from integer data.

Add `normalize_bool` and apply it where a bool is read from memory:
elementwise operand loads (bool is excluded from the vector paths, which
cannot normalize per element), the `convert_impl` same-type branch, the
search-reduction loads, the `isin` equality test and the argsort projection.
Add bool comparators for the merge-sort path.

`sort` now orders False before True rather than reproducing NumPy's raw byte
order, which would carry garbage bytes through a sort.
@intel-python-devops

Copy link
Copy Markdown

Can one of the admins verify this patch?

@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.

I've looked over the changes, seems like a welcome fix for a previously unnoticed bug, LGTM

@ndgrigorian

Copy link
Copy Markdown
Collaborator

@abagusetty seems that the tests fail with the open-source compiler, interestingly enough. Possible bug in the nightly DPC++?

@coveralls

coveralls commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 78.465% (-0.02%) from 78.489% — abagusetty:fix-nonzero-bool-nonstandard-bytes into IntelPython:master

`bool` takes a single radix pass, so the bucket index is `byte & 0xF`. An
unnormalized byte whose low nibble is zero (0x10, 0x80, 0xF0) bucketed as
False and sorted before True elements.

Normalize in `order_preserving_cast`, where every radix path converges, and
take the argument by reference so a copy cannot let the compiler assume a
0/1 byte.
@abagusetty

Copy link
Copy Markdown
Contributor Author

@abagusetty seems that the tests fail with the open-source compiler, interestingly enough. Possible bug in the nightly DPC++?

No bug in nightly. Interestingly, it is doing great. The issue was UB in the PR that the two compilers are treating it differently. A bool whose byte isnt 0x00/0x01 has an intermediate value that the compiler is free to assume 0 or 1. 2026.1 seems to just hide it. I did apply the same normalization of the bytes that was missed to the site it was failing to comply.

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.

Boolean arrays with elements are stored as bytes other than 0 or 1 give wrong results

4 participants