Fix scalar-broadcast fill after a non-inclusive axis (scikit-hep/boost-histogram#960)#431
Open
NJManganelli wants to merge 2 commits into
Open
Fix scalar-broadcast fill after a non-inclusive axis (scikit-hep/boost-histogram#960)#431NJManganelli wants to merge 2 commits into
NJManganelli wants to merge 2 commits into
Conversation
In the vectorized fill (fill_n), a scalar argument is broadcast across an axis by computing that axis' contribution to the linear index once and adding it to every entry. The contribution was derived from the change of the first index (*begin_). When a previous axis had already invalidated some entries, including the first one, the broadcast axis then invalidated *all* entries, silently discarding valid data. This is scikit-hep/boost-histogram#960: a non-growing axis combined with out-of-bounds entries and a broadcast scalar fill produced a sum of zero. Compute the axis contribution on a fresh index instead and add it to all entries, leaving already-invalid entries untouched. The growing and non-growing scalar paths share the same code via linearize/linearize_growth. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compare the vectorized fill against the one-at-a-time reference for scalar broadcast after a non-inclusive axis, covering the growing-axis, zero-point-shift, and underflow variants. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author
|
I asked Claude to match the comment style of the repo, I don't know that it really did (and it left a comment I asked it to remove regarding a now-gone commit that templated a true/false growable axis to no real gain). I'll be ready to have Claude update based on any adversarial review, human feedback, etc. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In the vectorized fill (
detail/fill_n.hpp), a scalar argument is broadcast across anaxis by computing that axis' contribution to the linear index once and adding it to
every entry. The contribution was derived from the change of the first index
(
*begin_). When a previous axis had already invalidated some entries — including thefirst one — the broadcast axis then invalidated all entries and silently dropped
valid data.
This surfaced downstream as scikit-hep/boost-histogram#960
("Histogram with IntCategory and StrCategory axes can be zeroed by out-of-bounds fill
values"): a non-growing category axis combined with out-of-bounds entries and a
broadcast scalar on a second axis produced a sum of zero. One-at-a-time filling was
always correct; only the array/
fill_npath was affected.Fix
Compute the axis contribution on a fresh index and add it to all entries, leaving
already-invalid entries untouched. The growing and non-growing scalar paths now share
one code path through
linearize/linearize_growth, so the "delta from*begin_"heuristic is gone entirely.
Regression tests compare the vectorized fill against the one-at-a-time reference for
scalar-broadcast-after-non-inclusive-axis, including the growing-axis, zero-point-shift,
and underflow variants (static and dynamic histograms).
Note
The reported bug is in the Python bindings, but the defect is here in core
fill_n;consuming it there is just a submodule bump. Happy to open the companion PR against
scikit-hep/boost-histogram once this lands.
🤖 Root-caused and drafted with Claude Code; reviewed by @NJManganelli.