diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 68 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 36 |
2 files changed, 97 insertions, 7 deletions
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 5d3cee647..da017eb0d 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2999,11 +2999,26 @@ PyArray_Arange(double start, double stop, double step, int type_num) PyArray_ArrFuncs *funcs; PyObject *obj; int ret; + double delta, tmp_len; NPY_BEGIN_THREADS_DEF; - length = _arange_safe_ceil_to_intp((stop - start)/step); - if (error_converting(length)) { - return NULL; + delta = stop - start; + tmp_len = delta/step; + + /* Underflow and divide-by-inf check */ + if (tmp_len == 0.0 && delta != 0.0) { + if (npy_signbit(tmp_len)) { + length = 0; + } + else { + length = 1; + } + } + else { + length = _arange_safe_ceil_to_intp(tmp_len); + if (error_converting(length)) { + return NULL; + } } if (length <= 0) { @@ -3067,7 +3082,8 @@ static npy_intp _calc_length(PyObject *start, PyObject *stop, PyObject *step, PyObject **next, int cmplx) { npy_intp len, tmp; - PyObject *val; + PyObject *zero, *val; + int next_is_nonzero, val_is_zero; double value; *next = PyNumber_Subtract(stop, start); @@ -3080,12 +3096,37 @@ _calc_length(PyObject *start, PyObject *stop, PyObject *step, PyObject **next, i } return -1; } + + zero = PyInt_FromLong(0); + if (!zero) { + Py_DECREF(*next); + *next = NULL; + return -1; + } + + next_is_nonzero = PyObject_RichCompareBool(*next, zero, Py_NE); + if (next_is_nonzero == -1) { + Py_DECREF(zero); + Py_DECREF(*next); + *next = NULL; + return -1; + } val = PyNumber_TrueDivide(*next, step); Py_DECREF(*next); *next = NULL; + if (!val) { + Py_DECREF(zero); return -1; } + + val_is_zero = PyObject_RichCompareBool(val, zero, Py_EQ); + Py_DECREF(zero); + if (val_is_zero == -1) { + Py_DECREF(val); + return -1; + } + if (cmplx && PyComplex_Check(val)) { value = PyComplex_RealAsDouble(val); if (error_converting(value)) { @@ -3114,11 +3155,24 @@ _calc_length(PyObject *start, PyObject *stop, PyObject *step, PyObject **next, i if (error_converting(value)) { return -1; } - len = _arange_safe_ceil_to_intp(value); - if (error_converting(len)) { - return -1; + + /* Underflow and divide-by-inf check */ + if (val_is_zero && next_is_nonzero) { + if (npy_signbit(value)) { + len = 0; + } + else { + len = 1; + } + } + else { + len = _arange_safe_ceil_to_intp(value); + if (error_converting(len)) { + return -1; + } } } + if (len > 0) { *next = PyNumber_Add(start, step); if (!*next) { diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index d6dcaa982..f8f75d9ea 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -224,6 +224,42 @@ class TestRegression(object): x = np.arange(10, dtype='>f8') assert_array_equal(ref, x) + def test_arange_inf_step(self): + ref = np.arange(0, 1, 10) + x = np.arange(0, 1, np.inf) + assert_array_equal(ref, x) + + ref = np.arange(0, 1, -10) + x = np.arange(0, 1, -np.inf) + assert_array_equal(ref, x) + + ref = np.arange(0, -1, -10) + x = np.arange(0, -1, -np.inf) + assert_array_equal(ref, x) + + ref = np.arange(0, -1, 10) + x = np.arange(0, -1, np.inf) + assert_array_equal(ref, x) + + def test_arange_underflow_stop_and_step(self): + finfo = np.finfo(np.float64) + + ref = np.arange(0, finfo.eps, 2 * finfo.eps) + x = np.arange(0, finfo.eps, finfo.max) + assert_array_equal(ref, x) + + ref = np.arange(0, finfo.eps, -2 * finfo.eps) + x = np.arange(0, finfo.eps, -finfo.max) + assert_array_equal(ref, x) + + ref = np.arange(0, -finfo.eps, -2 * finfo.eps) + x = np.arange(0, -finfo.eps, -finfo.max) + assert_array_equal(ref, x) + + ref = np.arange(0, -finfo.eps, 2 * finfo.eps) + x = np.arange(0, -finfo.eps, finfo.max) + assert_array_equal(ref, x) + def test_argmax(self): # Ticket #119 a = np.random.normal(0, 1, (4, 5, 6, 7, 8)) |