Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/pyrecest/_backend/_shared_numpy/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def _normalize_size(size):


def _validate_uniform_bound(bound, name):
if _contains_masked_value(bound):
raise TypeError(f"{name} must be real numeric")
if _contains_boolean_value(bound):
raise TypeError(f"{name} must be real numeric, not boolean")
try:
Expand Down Expand Up @@ -118,6 +120,8 @@ def _uniform(low=0.0, high=1.0, size=None):


def _validate_normal_parameter(value, name):
if _contains_masked_value(value):
raise TypeError(f"{name} must be real numeric")
if _contains_boolean_value(value):
raise TypeError(f"{name} must be real numeric, not boolean")
try:
Expand Down Expand Up @@ -150,6 +154,8 @@ def _normal(loc=0.0, scale=1.0, size=None):


def _validate_multivariate_normal_parameter(value, name):
if _contains_masked_value(value):
raise TypeError(f"{name} must be real numeric")
if _contains_boolean_value(value):
raise TypeError(f"{name} must be real numeric, not boolean")
try:
Expand Down Expand Up @@ -246,6 +252,8 @@ def _integer_choice_population_size(a_array):
def _validate_choice_probabilities(p, population_size):
if p is None:
return None
if _contains_masked_value(p):
raise TypeError("p must be real numeric")
if _contains_boolean_value(p):
raise TypeError("p must be real numeric, not boolean")
try:
Expand Down
89 changes: 89 additions & 0 deletions tests/backend/test_numpy_random_masked_distribution_parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import numpy as np
import pytest
from pyrecest._backend.numpy import random


@pytest.mark.parametrize(
("sampler", "message"),
(
(
lambda: random.uniform(low=np.ma.array(0.0, mask=True)),
"low must be real numeric",
),
(
lambda: random.uniform(high=np.ma.array(1.0, mask=True)),
"high must be real numeric",
),
(
lambda: random.normal(loc=np.ma.array(0.0, mask=True)),
"loc must be real numeric",
),
(
lambda: random.normal(scale=np.ma.array(1.0, mask=True)),
"scale must be real numeric",
),
(
lambda: random.multivariate_normal(
mean=np.ma.array([0.0, 1.0], mask=[False, True]),
cov=np.eye(2),
),
"mean must be real numeric",
),
(
lambda: random.multivariate_normal(
mean=np.zeros(2),
cov=np.ma.array(
np.eye(2),
mask=[[False, False], [False, True]],
),
),
"cov must be real numeric",
),
(
lambda: random.choice(
2,
p=np.ma.array([0.25, 0.75], mask=[False, True]),
),
"p must be real numeric",
),
(
lambda: random.choice(2, p=[0.25, np.ma.masked]),
"p must be real numeric",
),
),
)
def test_numpy_random_rejects_masked_distribution_parameters(sampler, message):
with pytest.raises(TypeError, match=message):
sampler()


def test_numpy_random_accepts_fully_unmasked_distribution_parameters():
uniform_samples = random.uniform(
low=np.ma.array(0.0, mask=False),
high=np.ma.array(1.0, mask=False),
size=4,
)
normal_samples = random.normal(
loc=np.ma.array(0.0, mask=False),
scale=np.ma.array(1.0, mask=False),
size=4,
)
multivariate_samples = random.multivariate_normal(
mean=np.ma.array([0.0, 1.0], mask=False),
cov=np.ma.array(np.eye(2), mask=False),
size=3,
)
choice_samples = random.choice(
2,
size=4,
p=np.ma.array([0.25, 0.75], mask=False),
)

assert uniform_samples.shape == (4,)
assert normal_samples.shape == (4,)
assert multivariate_samples.shape == (3, 2)
assert choice_samples.shape == (4,)
assert np.isfinite(uniform_samples).all()
assert np.isfinite(normal_samples).all()
assert np.isfinite(multivariate_samples).all()
assert np.isin(choice_samples, [0, 1]).all()
Loading