Skip to content

Document and test ultra-narrow float bins (no output change) - #87

Merged
guijacquemet merged 2 commits into
mainfrom
claude/narrow-float-bins
Nov 9, 2026
Merged

guijacquemet merged 2 commits into
mainfrom
claude/narrow-float-bins

Conversation

@guijacquemet

@guijacquemet guijacquemet commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #86

Takes the first option of the issue: document, test, and change no output. The bin count is not reduced; bins, counts and representatives are bit-identical to main.

What is documented

  • bin_centres.float_bin_centres docstring and docs/contract.md (histogram section), CHANGELOG.md, AGENTS.md map.
  • When [lo, hi] holds fewer representable floats than bins ([0, 5e-324], 4 bins: centres 0, 0, 5e-324, 5e-324), bins no float64 value can fall in may share a centre.
  • Precise invariant, found by enumerating every float64 of narrow ranges: the centre of every bin holding two or more representable values maps back to that bin. A bin holding exactly one value can have a centre that rounds to the neighbouring float, in the adjacent bin, because its midpoint is not representable ([0, 3*5e-324], 3 bins: bin 1 holds only 5e-324, its midpoint 1.5*5e-324 rounds to 2*5e-324, in bin 2). This is slightly weaker than "every reachable bin maps back", which is false in that case; it is documented and tested rather than changed.

New module bin_reachability.py (histogram.py is not touched)

  • float_bin_indices: the histograms' binning as a function.
  • reachable_float_bins: exact bisection over ordered float64 values (position is monotone), about 64 vectorised steps.
  • centres_map_back.

Tests (tests/test_bin_reachability.py)

  • The issue's example, plus the [0, 3*5e-324] one-value-bin case.
  • Enumeration of every float64 of ranges starting at 0, -0, subnormals, tiny, 1e-300, 0.1, 1, 3.7, 1e10, 1e300, 1e308, -max and so on, 1 to 100 ulps wide, with 1 to 256 bins: reachable bins are exactly those some value lands in, bins with two or more values map back, a one-value bin's centre is in an adjacent bin.
  • Histograms of every value of those ranges: empty bins are exactly the unreachable ones.
  • Wide and 3000 random ranges of every magnitude: all reachable centres map back; position monotonicity; constant range.

Comparison with main

tools/dump_outputs.py --corpus dumps histograms of every pixel type over extreme, subnormal, one-ulp, narrow, ordinary and wide ranges, 2 to 1024 bins (4 to 256 for integers), min-max and robust, whole and in blocks (4764 lines, bit-exact via float.hex). Run with PYTHONPATH=<base>/src on main (0811bca) and on this branch: both a4c37fdfc41d640db1f8849803b59ffbc47d91cdd3125ed96d91beeb4548be2d. The default dump is unchanged, dfd5e740e04e16057bc6a017e844ae62cb94025690531b443a9489f52900537e on both.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc

Bins no float64 value can fall in may share a centre; add reachable_float_bins and
centres_map_back to state and test the invariant. No output changes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
@guijacquemet
guijacquemet marked this pull request as ready for review November 9, 2026 05:55
@guijacquemet
guijacquemet merged commit 1c9ef7c into main Nov 9, 2026
8 checks passed
@guijacquemet
guijacquemet deleted the claude/narrow-float-bins branch November 9, 2026 05:56
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.

Ultra-narrow float ranges: more bins than representable values, so centres do not map back to their bins

2 participants