8000 Allow many distributions to have a scale of 0. · numpy/numpy@c4ff5f6 · GitHub
[go: up one dir, main page]

Skip to content

Commit c4ff5f6

Browse files
committed
Allow many distributions to have a scale of 0.
(in which case a stream of 0's is usually returned (or 1's)). See #5818.
1 parent bd821f5 commit c4ff5f6

File tree

2 files changed

+80
-49
lines changed

2 files changed

+80
-49
lines changed

numpy/random/mtrand/mtrand.pyx

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,17 +1561,17 @@ cdef class RandomState:
15611561
floc = PyFloat_AsDouble(loc)
15621562
fscale = PyFloat_AsDouble(scale)
15631563
if not PyErr_Occurred():
1564-
if fscale <= 0:
1565-
raise ValueError("scale <= 0")
1564+
if fscale < 0:
1565+
raise ValueError("scale < 0")
15661566
return cont2_array_sc(self.internal_state, rk_normal, size, floc,
15671567
fscale, self.lock)
15681568

15691569
PyErr_Clear()
15701570

15711571
oloc = <ndarray>PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
15721572
oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
1573-
if np.any(np.less_equal(oscale, 0)):
1574-
raise ValueError("scale <= 0")
1573+
if np.any(np.less(oscale, 0)):
1574+
raise ValueError("scale < 0")
15751575
return cont2_array(self.internal_state, rk_normal, size, oloc, oscale,
15761576
self.lock)
15771577

@@ -1681,17 +1681,17 @@ cdef class RandomState:
16811681

16821682
fscale = PyFloat_AsDouble(scale)
16831683
if not PyErr_Occurred():
1684-
if fscale <= 0:
1685-
raise ValueError("scale <= 0")
1684+
if fscale < 0:
1685+
raise ValueError("scale < 0")
16861686
return cont1_array_sc(self.internal_state, rk_exponential, size,
16871687
fscale, self.lock)
16881688

16891689
PyErr_Clear()
16901690

16911691
oscale = <ndarray> PyArray_FROM_OTF(scale, NPY_DOUBLE,
16921692
NPY_ARRAY_ALIGNED)
1693-
if np.any(np.less_equal(oscale, 0.0)):
1694-
raise ValueError("scale <= 0")
1693+
if np.any(np.less(oscale, 0.0)):
1694+
raise ValueError("scale < 0")
16951695
return cont1_array(self.internal_state, rk_exponential, size, oscale,
16961696
self.lock)
16971697

@@ -1799,16 +1799,16 @@ cdef class RandomState:
17991799

18001800
fshape = PyFloat_AsDouble(shape)
18011801
if not PyErr_Occurred():
1802-
if fshape <= 0:
1803-
raise ValueError("shape <= 0")
1802+
if fshape < 0:
1803+
raise ValueError("shape < 0")
18041804
return cont1_array_sc(self.internal_state, rk_standard_gamma,
18051805
size, fshape, self.lock)
18061806

18071807
PyErr_Clear()
18081808
oshape = <ndarray> PyArray_FROM_OTF(shape, NPY_DOUBLE,
18091809
NPY_ARRAY_ALIGNED)
1810-
if np.any(np.less_equal(oshape, 0.0)):
1811-
raise ValueError("shape <= 0")
1810+
if np.any(np.less(oshape, 0.0)):
1811+
raise ValueError("shape < 0")
18121812
return cont1_array(self.internal_state, rk_standard_gamma, size,
18131813
oshape, self.lock)
18141814

@@ -1889,20 +1889,20 @@ cdef class RandomState:
18891889
fshape = PyFloat_AsDouble(shape)
18901890
fscale = PyFloat_AsDouble(scale)
18911891
if not PyErr_Occurred():
1892-
if fshape <= 0:
1893-
raise ValueError("shape <= 0")
1894-
if fscale <= 0:
1895-
raise ValueError("scale <= 0")
1892+
if fshape < 0:
1893+
raise ValueError("shape < 0")
1894+
if fscale < 0:
1895+
raise ValueError("scale < 0")
18961896
return cont2_array_sc(self.internal_state, rk_gamma, size, fshape,
18971897
fscale, self.lock)
18981898

18991899
PyErr_Clear()
19001900
oshape = <ndarray>PyArray_FROM_OTF(shape, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
19011901
oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
1902-
if np.any(np.less_equal(oshape, 0.0)):
1903-
raise ValueError("shape <= 0")
1904-
if np.any(np.less_equal(oscale, 0.0)):
1905-
raise ValueError("scale <= 0")
1902+
if np.any(np.less(oshape, 0.0)):
1903+
raise ValueError("shape < 0")
1904+
if np.any(np.less(oscale, 0.0)):
1905+
raise ValueError("scale < 0")
19061906
return cont2_array(self.internal_state, rk_gamma, size, oshape, oscale,
19071907
self.lock)
19081908

@@ -2753,16 +2753,16 @@ cdef class RandomState:
27532753

27542754
fa = PyFloat_AsDouble(a)
27552755
if not PyErr_Occurred():
2756-
if fa <= 0:
2757-
raise ValueError("a <= 0")
2756+
if fa < 0:
2757+
raise ValueError("a < 0")
27582758
return cont1_array_sc(self.internal_state, rk_weibull, size, fa,
27592759
self.lock)
27602760

27612761
PyErr_Clear()
27622762

27632763
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
2764-
if np.any(np.less_equal(oa, 0.0)):
2765-
raise ValueError("a <= 0")
2764+
if np.any(np.less(oa, 0.0)):
2765+
raise ValueError("a < 0")
27662766
return cont1_array(self.internal_state, rk_weibull, size, oa,
27672767
self.lock)
27682768

@@ -2865,16 +2865,16 @@ cdef class RandomState:
28652865

28662866
fa = PyFloat_AsDouble(a)
28672867
if not PyErr_Occurred():
2868-
if fa <= 0:
2869-
raise ValueError("a <= 0")
2868+
if fa < 0:
2869+
raise ValueError("a < 0")
28702870
return cont1_array_sc(self.internal_state, rk_power, size, fa,
28712871
self.lock)
28722872

28732873
PyErr_Clear()
28742874

28752875
oa = <ndarray>PyArray_FROM_OTF(a, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
2876-
if np.any(np.less_equal(oa, 0.0)):
2877-
raise ValueError("a <= 0")
2876+
if np.any(np.less(oa, 0.0)):
2877+
raise ValueError("a < 0")
28782878
return cont1_array(self.internal_state, rk_power, size, oa, self.lock)
28792879

28802880
def laplace(self, loc=0.0, scale=1.0, size=None):
@@ -2960,16 +2960,16 @@ cdef class RandomState:
29602960
floc = PyFloat_AsDouble(loc)
29612961
fscale = PyFloat_AsDouble(scale)
29622962
if not PyErr_Occurred():
2963-
if fscale <= 0:
2964-
raise ValueError("scale <= 0")
2963+
if fscale < 0:
2964+
raise ValueError("scale < 0")
29652965
return cont2_array_sc(self.internal_state, rk_laplace, size, floc,
29662966
fscale, self.lock)
29672967

29682968
PyErr_Clear()
29692969
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
29702970
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
2971-
if np.any(np.less_equal(oscale, 0.0)):
2972-
raise ValueError("scale <= 0")
2971+
if np.any(np.less(oscale, 0.0)):
2972+
raise ValueError("scale < 0")
29732973
return cont2_array(self.internal_state, rk_laplace, size, oloc, oscale,
29742974
self.lock)
29752975

@@ -3089,16 +3089,16 @@ cdef class RandomState:
30893089
floc = PyFloat_AsDouble(loc)
30903090
fscale = PyFloat_AsDouble(scale)
30913091
if not PyErr_Occurred():
3092-
if fscale <= 0:
3093-
raise ValueError("scale <= 0")
3092+
if fscale < 0:
3093+
raise ValueError("scale < 0")
30943094
return cont2_array_sc(self.internal_state, rk_gumbel, size, floc,
30953095
fscale, self.lock)
30963096

30973097
PyErr_Clear()
30983098
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
30993099
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
3100-
if np.any(np.less_equal(oscale, 0.0)):
3101-
raise ValueError("scale <= 0")
3100+
if np.any(np.less(oscale, 0.0)):
3101+
raise ValueError("scale < 0")
31023102
return cont2_array(self.internal_state, rk_gumbel, size, oloc, oscale,
31033103
self.lock)
31043104

@@ -3180,16 +3180,16 @@ cdef class RandomState:
31803180
floc = PyFloat_AsDouble(loc)
31813181
fscale = PyFloat_AsDouble(scale)
31823182
if not PyErr_Occurred():
3183-
if fscale <= 0:
3184-
raise ValueError("scale <= 0")
3183+
if fscale < 0:
3184+
raise ValueError("scale < 0")
31853185
return cont2_array_sc(self.internal_state, rk_logistic, size, floc,
31863186
fscale, self.lock)
31873187

31883188
PyErr_Clear()
31893189
oloc = PyArray_FROM_OTF(loc, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
31903190
oscale = PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
3191-
if np.any(np.less_equal(oscale, 0.0)):
3192-
raise ValueError("scale <= 0")
3191+
if np.any(np.less(oscale, 0.0)):
3192+
raise ValueError("scale < 0")
31933193
return cont2_array(self.internal_state, rk_logistic, size, oloc,
31943194
oscale, self.lock)
31953195

@@ -3304,17 +3304,17 @@ cdef class RandomState:
33043304
fsigma = PyFloat_AsDouble(sigma)
33053305

33063306
if not PyErr_Occurred():
3307-
if fsigma <= 0:
3308-
raise ValueError("sigma <= 0")
3307+
if fsigma < 0:
3308+
raise ValueError("sigma < 0")
33093309
return cont2_array_sc(self.internal_state, rk_lognormal, size,
33103310
fmean, fsigma, self.lock)
33113311

33123312
PyErr_Clear()
33133313

33143314
omean = PyArray_FROM_OTF(mean, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
33153315
osigma = PyArray_FROM_OTF(sigma, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
3316-
if np.any(np.less_equal(osigma, 0.0)):
3317-
raise ValueError("sigma <= 0.0")
3316+
if np.any(np.less(osigma, 0.0)):
3317+
raise ValueError("sigma < 0.0")
33183318
return cont2_array(self.internal_state, rk_lognormal, size, omean,
93C6 33193319
osigma, self.lock)
33203320

@@ -3380,16 +3380,16 @@ cdef class RandomState:
33803380
fscale = PyFloat_AsDouble(scale)
33813381

33823382
if not PyErr_Occurred():
3383-
if fscale <= 0:
3384-
raise ValueError("scale <= 0")
3383+
if fscale < 0:
3384+
raise ValueError("scale < 0")
33853385
return cont1_array_sc(self.internal_state, rk_rayleigh, size,
33863386
fscale, self.lock)
33873387

33883388
PyErr_Clear()
33893389

33903390
oscale = <ndarray>PyArray_FROM_OTF(scale, NPY_DOUBLE, NPY_ARRAY_ALIGNED)
3391-
if np.any(np.less_equal(oscale, 0.0)):
3392-
raise ValueError("scale <= 0.0")
3391+
if np.any(np.less(oscale, 0.0)):
3392+
raise ValueError("scale < 0.0")
33933393
return cont1_array(self.internal_state, rk_rayleigh, size, oscale,
33943394
self.lock)
33953395

numpy/random/tests/test_random.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ def test_negative_binomial(self):
128128
# arguments without truncation.
129129
self.prng.negative_binomial(0.5, 0.5)
130130

131+
131132
class TestRandomDist(TestCase):
132-
# Make sure the random distrobution return the correct value for a
133+
# Make sure the random distribution return the correct value for a
133134
# given seed
134135

135136
def setUp(self):
@@ -356,6 +357,9 @@ def test_exponential(self):
356357
[0.68717433461363442, 1.69175666993575979]])
357358
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
358359

360+
def test_exponential_0(self):
361+
assert_equal(np.random.exponential(scale=0), 0)
362+
359363
def test_f(self):
360364
np.random.seed(self.seed)
361365
actual = np.random.f(12, 77, size=(3, 2))
@@ -372,6 +376,9 @@ def test_gamma(self):
372376
[31.71863275789960568, 33.30143302795922011]])
373377
np.testing.assert_array_almost_equal(actual, desired, decimal=14)
374378

379+
def test_gamma_0(self):
380+
assert_equal(np.random.gamma(shape=0, scale=0), 0)
381+
375382
def test_geometric(self):
376383
np.random.seed(self.seed)
377384
actual = np.random.geometric(.123456789, size=(3, 2))
@@ -388,6 +395,9 @@ def test_gumbel(self):
388395
[1.10651090478803416, -0.69535848626236174]])
389396
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
390397

398+
def test_gumbel_0(self):
399+
assert_equal(np.random.gumbel(scale=0), 0)
400+
391401
def test_hypergeometric(self):
392402
np.random.seed(self.seed)
393403
actual = np.random.hypergeometric(10.1, 5.5, 14, size=(3, 2))
@@ -422,6 +432,9 @@ def test_laplace(self):
422432
[-0.05391065675859356, 1.74901336242837324]])
423433
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
424434

435+
def test_laplace_0(self):
436+
assert_equal(np.random.laplace(scale=0), 0)
437+
425438
def test_logistic(self):
426439
np.random.seed(self.seed)
427440
actual = np.random.logistic(loc=.123456789, scale=2.0, size=(3, 2))
@@ -430,6 +443,9 @@ def test_logistic(self):
430443
[-0.21682183359214885, 2.63373365386060332]])
431444
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
432445

446+
def test_laplace_0(self):
447+
assert_(np.random.laplace(scale=0) in [0, 1])
448+
433449
def test_lognormal(self):
434450
np.random.seed(self.seed)
435451
actual = np.random.lognormal(mean=.123456789, sigma=2.0, size=(3, 2))
@@ -438,6 +454,9 @@ def test_lognormal(self):
438454
[65.72798501792723869, 86.84341601437161273]])
439455
np.testing.assert_array_almost_equal(actual, desired, decimal=13)
440456

457+
def test_lognormal_0(self):
458+
assert_equal(np.random.lognormal(sigma=0), 1)
459+
441460
def test_logseries(self):
442461
np.random.seed(self.seed)
443462
actual = np.random.logseries(p=.923456789, size=(3, 2))
@@ -521,6 +540,9 @@ def test_normal(self):
521540
[4.18552478636557357, 4.46410668111310471]])
522541
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
523542

543+
def test_normal_0(self):
544+
assert_equal(np.random.normal(scale=0), 0)
545+
524546
def test_pareto(self):
525547
np.random.seed(self.seed)
526548
actual = np.random.pareto(a=.123456789, size=(3, 2))
@@ -568,6 +590,9 @@ def test_rayleigh(self):
568590
[11.06066537006854311, 17.35468505778271009]])
569591
np.testing.assert_array_almost_equal(actual, desired, decimal=14)
570592

593+
def test_rayleigh_0(self):
594+
assert_equal(np.random.rayleigh(scale=0), 0)
595+
571596
def test_standard_cauchy(self):
572597
np.random.seed(self.seed)
573598
actual = np.random.standard_cauchy(size=(3, 2))
@@ -592,6 +617,9 @@ def test_standard_gamma(self):
592617
[7.54838614231317084, 8.012756093271868]])
593618
np.testing.assert_array_almost_equal(actual, desired, decimal=14)
594619

620+
def test_standard_gamma_0(self):
621+
assert_equal(np.random.standard_gamma(shape=0), 0)
622+
595623
def test_standard_normal(self):
596624
np.random.seed(self.seed)
597625
actual = np.random.standard_normal(size=(3, 2))
@@ -667,6 +695,9 @@ def test_weibull(self):
667695
[0.67057783752390987, 1.39494046635066793]])
668696
np.testing.assert_array_almost_equal(actual, desired, decimal=15)
669697

698+
def test_weibull_0(self):
699+
assert_equal(np.random.weibull(a=0), 0)
700+
670701
def test_zipf(self):
671702
np.random.seed(self.seed)
672703
actual = np.random.zipf(a=1.23, size=(3, 2))

0 commit comments

Comments
 (0)
0