diff options
author | Kaspar Thommen <49198627+kasparthommen@users.noreply.github.com> | 2020-06-10 22:50:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-10 23:50:43 +0300 |
commit | 0ac02d3819157a9c64b78157428336200632cff8 (patch) | |
tree | 9a834e03fc3a1819166d499da044efc8dd69a58e | |
parent | d0928f871ccb42484c7e03c456ce489dea908313 (diff) | |
download | numpy-0ac02d3819157a9c64b78157428336200632cff8.tar.gz |
BUG: endpoints of array returned by geomspace() should match arguments (#16411)
* BUG: make sure the endpoints of the array returned by geomspace() matches the 'start' and 'stop' arguments exactly
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
-rw-r--r-- | numpy/core/function_base.py | 14 | ||||
-rw-r--r-- | numpy/core/tests/test_function_base.py | 36 |
2 files changed, 47 insertions, 3 deletions
diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py index 9e46f0ea5..946e255c1 100644 --- a/numpy/core/function_base.py +++ b/numpy/core/function_base.py @@ -408,8 +408,18 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0): log_start = _nx.log10(start) log_stop = _nx.log10(stop) - result = out_sign * logspace(log_start, log_stop, num=num, - endpoint=endpoint, base=10.0, dtype=dtype) + result = logspace(log_start, log_stop, num=num, + endpoint=endpoint, base=10.0, dtype=dtype) + + # Make sure the endpoints match the start and stop arguments. This is + # necessary because np.exp(np.log(x)) is not necessarily equal to x. + if num > 0: + result[0] = start + if num > 1 and endpoint: + result[-1] = stop + + result = out_sign * result + if axis != 0: result = _nx.moveaxis(result, 0, axis) diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py index 2197ef0cd..62a9772c8 100644 --- a/numpy/core/tests/test_function_base.py +++ b/numpy/core/tests/test_function_base.py @@ -1,6 +1,6 @@ from numpy import ( logspace, linspace, geomspace, dtype, array, sctypes, arange, isnan, - ndarray, sqrt, nextafter, stack + ndarray, sqrt, nextafter, stack, errstate ) from numpy.testing import ( assert_, assert_equal, assert_raises, assert_array_equal, assert_allclose, @@ -113,6 +113,40 @@ class TestGeomspace: assert_array_equal(y, [-100, -10, -1]) assert_array_equal(y.imag, 0) + def test_boundaries_match_start_and_stop_exactly(self): + # make sure that the boundaries of the returned array exactly + # equal 'start' and 'stop' - this isn't obvious because + # np.exp(np.log(x)) isn't necessarily exactly equal to x + start = 0.3 + stop = 20.3 + + y = geomspace(start, stop, num=1) + assert_equal(y[0], start) + + y = geomspace(start, stop, num=1, endpoint=False) + assert_equal(y[0], start) + + y = geomspace(start, stop, num=3) + assert_equal(y[0], start) + assert_equal(y[-1], stop) + + y = geomspace(start, stop, num=3, endpoint=False) + assert_equal(y[0], start) + + def test_nan_interior(self): + with errstate(invalid='ignore'): + y = geomspace(-3, 3, num=4) + + assert_equal(y[0], -3.0) + assert_(isnan(y[1:-1]).all()) + assert_equal(y[3], 3.0) + + with errstate(invalid='ignore'): + y = geomspace(-3, 3, num=4, endpoint=False) + + assert_equal(y[0], -3.0) + assert_(isnan(y[1:]).all()) + def test_complex(self): # Purely imaginary y = geomspace(1j, 16j, num=5) |