Skip to content

fix(random): correct six distribution bugs found in audit#211

Merged
chaoming0625 merged 1 commit into
mainfrom
worktree-random-audit
Jun 11, 2026
Merged

fix(random): correct six distribution bugs found in audit#211
chaoming0625 merged 1 commit into
mainfrom
worktree-random-audit

Conversation

@chaoming0625

Copy link
Copy Markdown
Collaborator

Summary

Audited brainstate.random for errors, bugs, and edge cases. Found six reachable correctness bugs, each contradicting the function's own NumPy-style docstring. All are fixed and covered by test-first regression tests (TestAuditRegressions in _fun_test.py), with statistical checks gated behind --run-slow.

# Function Bug Fix
A standard_t Array df + size=None raised ValueError (dead u.math.shape(size) branch always yielded ()) Infer shape from df (matches sibling t + docstring)
B weibull_min Divided by scale instead of multiplying r * scale (matches scipy.stats.weibull_min + weibull docstring)
C triangular Was 2*bernoulli-1 (Rademacher ±1) with a size-only signature; the documented triangular(-3, 0, 8, N) raised TypeError Real triangular(left, mode, right, size) via inverse-CDF, with shared-unit support like uniform
D geometric Off-by-one (support {0,1,…} not {1,2,…}) and returned float floor(…) + 1, cast to integer dtype, so P(k==1)==p
E randint_like Default high = max(input) (Python builtin) raised on >1-D templates Use u.math.max
F chisquare Summed df squared normals — rejected non-integer scalar df (TypeError) and array df with size=None (NotImplementedError) 2 * Gamma(df/2), valid for any positive real / array df (mirrors t, noncentral_chisquare)

Tests that encoded the old buggy behavior (triangular ±1; chisquare NotImplementedError) are updated to assert the corrected contracts.

Out of scope (documented in audit, not changed here)

  • ir_compilation=True breaks every named_scope-decorated method (even normal) because static_argnums indices reference size/dtype/key positions passed as kwargs. This is a transform-layer concern (brainstate/transform/_named_scope.py + jit), off by default, with no random test coverage — a fix belongs there with its own tests.
  • Minor docstring inaccuracies (seed_context claims it touches NumPy state; __init__.py shuffle example implies in-place mutation).

Testing

  • pytest brainstate/random/ --run-slow539 passed.
  • No code outside brainstate/random/ references the changed functions.

🤖 Generated with Claude Code

Audit of brainstate.random surfaced six reachable correctness bugs, each
contradicting the function's own NumPy-style docstring. All are fixed with
test-first regression coverage (TestAuditRegressions in _fun_test.py).

- standard_t: with array `df` and `size=None`, output shape was always ()
  (dead `u.math.shape(size)` branch) and raised ValueError. Now infers the
  shape from `df`, matching the sibling `t` and the docstring.
- weibull_min: divided by `scale` instead of multiplying. Now `r * scale`,
  matching scipy.stats.weibull_min and the `weibull` docstring (lambda scale).
- triangular: was `2*bernoulli-1` (Rademacher ±1) with a size-only signature,
  so the documented `triangular(-3, 0, 8, N)` raised TypeError. Reimplemented
  as the real triangular(left, mode, right, size) via inverse-CDF, with
  shared-unit support like `uniform`.
- geometric: off-by-one (support {0,1,...} instead of {1,2,...}) and returned
  float. Now `floor(...) + 1` cast to an integer dtype, so P(k==1)==p.
- randint_like: default `high = max(input)` used the Python builtin and raised
  on >1-D templates. Now uses `u.math.max`.
- chisquare: summed `df` squared normals, rejecting non-integer scalar `df`
  (TypeError) and array `df` with `size=None` (NotImplementedError). Now uses
  the `2 * Gamma(df/2)` relation, valid for any positive real / array `df`.

Tests encoding the old buggy behavior (triangular ±1, chisquare
NotImplementedError) are updated to assert the corrected contracts.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry @chaoming0625, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@chaoming0625 chaoming0625 merged commit c771f4e into main Jun 11, 2026
6 checks passed
@chaoming0625 chaoming0625 deleted the worktree-random-audit branch June 11, 2026 14:08
@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
brainstate/random/_state.py 90.62% 2 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

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.

1 participant