Skip to content

fix(basehist): normalize negative integer indices#699

Draft
henryiii wants to merge 1 commit into
mainfrom
fix-negative-index
Draft

fix(basehist): normalize negative integer indices#699
henryiii wants to merge 1 commit into
mainfrom
fix-negative-index

Conversation

@henryiii

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Closes #559.

Negative slice bounds raised ValueError: begin < end required (e.g. h[1:-2]) because plain negative ints were passed straight to boost-histogram, which does not apply NumPy-style negative indexing. _loc_shortcut now threads the per-axis id through to slice bounds and normalizes plain negative int/np.integer against the axis length. bool, complex (by-value / loc), None, rebin step, etc. are untouched.

Test: tests/test_general.py::test_negative_index_accessh[-1]==h[9], h[1:-2]==h[1:8], h[-3:-1]==h[7:9], dict-form equivalents, and a two-axis per-axis-length case. Confirmed failing before, passing after.

Thread the per-axis id into _loc_shortcut so plain negative ints in
slice bounds and direct access (h[-2], h[1:-2]) are normalized against
the axis length, matching NumPy semantics. Complex/loc/rebin indices are
untouched. Closes #559.

Assisted-by: ClaudeCode:claude-opus-4.8
@henryiii henryiii force-pushed the fix-negative-index branch from 9030b81 to 3c0fdc1 Compare June 25, 2026 20:22
henryiii added a commit to scikit-hep/boost-histogram that referenced this pull request Jun 26, 2026
* fix: normalize negative integer slice bounds in indexing

Negative slice bounds raised `ValueError: begin < end required` (e.g.
`h[1:-2]`) because plain negative ints were passed straight to
Boost.Histogram, which does not apply NumPy-style negative indexing.

`Axis._process_callable` now normalizes plain negative ints relative to
the axis length, like Python/NumPy. Locators (`bh.loc`, `bh.tag.at`,
rebin/sum steps) are callables handled earlier and stay untouched. The
fix flows through `_process_loc`, so it applies to both `__getitem__`
and `__setitem__`. Scalar negative indexing already worked via
`_compute_uhi_index`.

Mirrors scikit-hep/hist#699, fixing the bug at the underlying layer.

Assisted-by: ClaudeCode:claude-opus-4.8

* feat: clamp out-of-range slice bounds to match NumPy

Out-of-range slice bounds now clamp to [0, len] like NumPy slicing
(e.g. h[5:100] -> h[5:], h[-15:5] -> h[:5]), instead of relying on
Boost's internal behavior or raising low-level errors.

NumPy returns an empty array for slices like h[1:-15] or h[5:2], but a
Boost.Histogram axis cannot have zero bins. These now raise a clear
IndexError explaining the limitation instead of the cryptic
"begin < end required" / "bins > 0 required". The check lives in
_handle_slice so that intentional flow access via integration
(e.g. h[3::sum] summing the overflow) is preserved.

Assisted-by: ClaudeCode:claude-opus-4.8

* ci: pin numpy<2.5 in hist nox session

numpy 2.5's stubs use a `type X = ...` statement that mypy rejects under
the downstream hist session ("Type statement is only supported in Python
3.12 and greater"), failing the Hist 3.14 job. Pin numpy below 2.5 until
the toolchain catches up.

Assisted-by: ClaudeCode:claude-opus-4.8

* style: pre-commit fixes

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
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.

[BUG] Indexing with negative numbers

1 participant