Repository navigation
fix: validate the sampling method and reject an empty mean in multinormal_cholesky - #189
Open
antonwolfy wants to merge 2 commits into
Open
antonwolfy wants to merge 2 commits into
antonwolfy wants to merge 2 commits into
Conversation
…rmal_cholesky choose_method returned any value that compared equal to a method id, so np.int64(0), np.int64(2), False and 1.0 passed through unchanged. The callers then compare the result with `is`, so those values were routed to the final else branch (BoxMuller) instead of the method they named. Unrecognized values, such as a misspelled name, were mapped to the default method without any notice. - choose_method now accepts strings from the alias table and integers (including NumPy integers) matching an id, and returns the module-level constant so the `is` comparisons keep working. - bool and float, which compare equal to the ids but are not valid specifications, and any other unrecognized value now emit a UserWarning and fall back to the function's default, like an unrecognized brng does. - multinormal_cholesky raises ValueError for an empty mean instead of ZeroDivisionError. - test_randomdist_lognormal asked lognormal for "Box-Muller2", which it does not support and silently treated as ICDF; it now asserts the warning.
antonwolfy
requested review from
jharlow-intel,
ndgrigorian,
vlad-perevezentsev and
xaleryb
as code owners
October 6, 2026 18:04
…tests Place them next to test_normal_family_array_methods so they do not touch the same lines as other pull requests adding multinormal_cholesky tests.
This branch has not been deployed
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.
Follow-up to the review of #187, which turned up three unrelated behaviours in the Python layer. This PR does not depend on #187 and does not touch the same code.
Problem
choose_methodreturned any value that compared equal to a method id, e.g.np.int64(0),np.int64(2),Falseor1.0. The callers then test the result withis, so those values fell through to the finalelsebranch, which is BoxMuller. For examplemultinormal_cholesky(..., method=np.int64(2))silently ran BoxMuller instead of BoxMuller2, andmethod=Falseran BoxMuller instead of the default.None, or an unsupported method for that function (e.g."Box-Muller2"forlognormal, which only supports ICDF and BoxMuller) got the default method without any notice.multinormal_choleskywith an emptymeanraisedZeroDivisionError(PyArray_SIZE(...) // dimwithdim == 0). NumPy'smultivariate_normalraisesValueErrorfor the same input.Changes
choose_method(mkl_random/mklrand.pyx) now accepts strings from the function's alias table and integers (including NumPy integers) matching one of its ids, and returns the module-level constant, so the existingiscomparisons keep working.bool,floatand any other unrecognized value emit aUserWarningand fall back to the function's default method, in the same style as an unrecognizedbrng. Results for those inputs are unchanged apart from the new warning, except where the old code misrouted them (item 1).multinormal_choleskyraisesValueError("mean must have at least one element")for an emptymean. oneMKL'svdRngGaussianMValso requiresdimen >= 1.test_randomdist_lognormalaskedlognormalfor"Box-Muller2", which it does not support and silently treated as ICDF. It now asserts the warning explicitly; the expected values are unchanged.CHANGELOG.md: oneChangedand twoFixedentries.Behaviour change to be aware of
Code that passes an unsupported or misspelled
methodstill gets the same numbers as before, but now sees aUserWarning. I chose a warning over an exception to stay backward compatible, consistent with how an unrecognizedbrngis handled (gh-177). RaisingValueErrorinstead would be a small change inchoose_methodif that is preferred.Testing
New tests in
mkl_random/tests/test_random.py:test_multinormal_cholesky_empty_mean: both the 2-D and the packed 1-D empty Cholesky factor raiseValueError.test_multinormal_cholesky_integer_method: for each ofICDF,BoxMuller,BoxMuller2, the ids passed asint,np.int64andnp.uint8give exactly the same draws as the name, and emit no warning.test_unrecognized_method_warns_and_uses_default:"bogus",7,-1,1.0,None,False,Trueand[1]warn and give the default (ICDF) result.test_unrecognized_method_uses_each_functions_default: the fallback is the called function's own default (poissonfalls back toPOISNORM, not ICDF).Unlike the tests in #187, these fail on master: running them against a master build, 15 of the 20 cases fail (the other 5 are cases master already handled, such as
np.int64(1), which happened to land on BoxMuller). On this branch all 20 pass.The full suite passes (358 passed, 24 skipped), also with
-W error::UserWarning, which confirms that no other call in the test suite triggers the new warning.