summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/records.py3
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c10
-rw-r--r--numpy/core/src/umath/loops.c.src7
-rw-r--r--numpy/distutils/misc_util.py7
-rw-r--r--numpy/ma/mrecords.py3
-rw-r--r--numpy/random/common.pxd2
-rw-r--r--numpy/random/setup.py7
-rw-r--r--numpy/random/src/bitgen.h (renamed from numpy/core/include/numpy/random/bitgen.h)0
-rw-r--r--numpy/random/src/distributions/distributions.h2
-rw-r--r--numpy/testing/_private/utils.py89
-rw-r--r--numpy/testing/tests/test_utils.py52
11 files changed, 125 insertions, 57 deletions
diff --git a/numpy/core/records.py b/numpy/core/records.py
index 2b31625c3..8a5fee541 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -496,8 +496,7 @@ class recarray(ndarray):
except Exception:
fielddict = ndarray.__getattribute__(self, 'dtype').fields or {}
if attr not in fielddict:
- exctype, value = sys.exc_info()[:2]
- raise exctype(value)
+ raise
else:
fielddict = ndarray.__getattribute__(self, 'dtype').fields or {}
if attr not in fielddict:
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 413decd9d..084a5dd46 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -1581,8 +1581,7 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
PyArrayObject *oparr = NULL, *ret = NULL;
npy_bool subok = NPY_FALSE;
npy_bool copy = NPY_TRUE;
- int nd;
- npy_intp ndmin = 0;
+ int ndmin = 0, nd;
PyArray_Descr *type = NULL;
PyArray_Descr *oldtype = NULL;
NPY_ORDER order = NPY_KEEPORDER;
@@ -1644,13 +1643,14 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
ndmin_obj = PyDict_GetItem(kws, npy_ma_str_ndmin);
if (ndmin_obj) {
- ndmin = PyLong_AsLong(ndmin_obj);
- if (error_converting(ndmin)) {
+ long t = PyLong_AsLong(ndmin_obj);
+ if (error_converting(t)) {
goto clean_type;
}
- else if (ndmin > NPY_MAXDIMS) {
+ else if (t > NPY_MAXDIMS) {
goto full_path;
}
+ ndmin = t;
}
/* copy=False with default dtype, order (any is OK) and ndim */
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index f84d74efe..1931cd100 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -384,7 +384,11 @@ PyUFunc_O_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
PyObject **out = (PyObject **)op1;
PyObject *ret, *func;
func = PyObject_GetAttrString(in1 ? in1 : Py_None, meth);
- if (func == NULL || !PyCallable_Check(func)) {
+ if (func != NULL && !PyCallable_Check(func)) {
+ Py_DECREF(func);
+ func = NULL;
+ }
+ if (func == NULL) {
PyObject *exc, *val, *tb;
PyTypeObject *type = in1 ? Py_TYPE(in1) : Py_TYPE(Py_None);
PyErr_Fetch(&exc, &val, &tb);
@@ -397,6 +401,7 @@ PyUFunc_O_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
return;
}
ret = PyObject_Call(func, tup, NULL);
+ Py_DECREF(func);
if (ret == NULL) {
Py_DECREF(tup);
return;
diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py
index 89171eede..2a6472b95 100644
--- a/numpy/distutils/misc_util.py
+++ b/numpy/distutils/misc_util.py
@@ -2281,8 +2281,11 @@ def generate_config_py(target):
extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs')
if sys.platform == 'win32' and os.path.isdir(extra_dll_dir):
- os.environ.setdefault('PATH', '')
- os.environ['PATH'] += os.pathsep + extra_dll_dir
+ if sys.version_info >= (3, 8):
+ os.add_dll_directory(extra_dll_dir)
+ else:
+ os.environ.setdefault('PATH', '')
+ os.environ['PATH'] += os.pathsep + extra_dll_dir
"""))
diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py
index 826fb0f64..ae1a12c2c 100644
--- a/numpy/ma/mrecords.py
+++ b/numpy/ma/mrecords.py
@@ -260,8 +260,7 @@ class MaskedRecords(MaskedArray, object):
fielddict = ndarray.__getattribute__(self, 'dtype').fields or {}
optinfo = ndarray.__getattribute__(self, '_optinfo') or {}
if not (attr in fielddict or attr in optinfo):
- exctype, value = sys.exc_info()[:2]
- raise exctype(value)
+ raise
else:
# Get the list of names
fielddict = ndarray.__getattribute__(self, 'dtype').fields or {}
diff --git a/numpy/random/common.pxd b/numpy/random/common.pxd
index 2f7baa06e..ac0a94bb0 100644
--- a/numpy/random/common.pxd
+++ b/numpy/random/common.pxd
@@ -5,7 +5,7 @@ from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
uintptr_t)
from libc.math cimport sqrt
-cdef extern from "numpy/random/bitgen.h":
+cdef extern from "src/bitgen.h":
struct bitgen:
void *state
uint64_t (*next_uint64)(void *st) nogil
diff --git a/numpy/random/setup.py b/numpy/random/setup.py
index f0ebe331f..52e020e58 100644
--- a/numpy/random/setup.py
+++ b/numpy/random/setup.py
@@ -34,8 +34,6 @@ def configuration(parent_package='', top_path=None):
defs.append(('NPY_NO_DEPRECATED_API', 0))
config.add_data_dir('tests')
- config.add_data_files('common.pxd')
- config.add_data_files('bit_generator.pxd')
EXTRA_LINK_ARGS = []
# Math lib
@@ -49,11 +47,6 @@ def configuration(parent_package='', top_path=None):
elif not is_msvc:
# Some bit generators require c99
EXTRA_COMPILE_ARGS += ['-std=c99']
- INTEL_LIKE = any(arch in platform.machine()
- for arch in ('x86', 'i686', 'i386', 'amd64'))
- if INTEL_LIKE:
- # Assumes GCC or GCC-like compiler
- EXTRA_COMPILE_ARGS += ['-msse2']
# Use legacy integer variable sizes
LEGACY_DEFS = [('NP_RANDOM_LEGACY', '1')]
diff --git a/numpy/core/include/numpy/random/bitgen.h b/numpy/random/src/bitgen.h
index 0adaaf2ee..0adaaf2ee 100644
--- a/numpy/core/include/numpy/random/bitgen.h
+++ b/numpy/random/src/bitgen.h
diff --git a/numpy/random/src/distributions/distributions.h b/numpy/random/src/distributions/distributions.h
index f2c370c07..b778968d7 100644
--- a/numpy/random/src/distributions/distributions.h
+++ b/numpy/random/src/distributions/distributions.h
@@ -9,7 +9,7 @@
#include "Python.h"
#include "numpy/npy_common.h"
#include "numpy/npy_math.h"
-#include "numpy/random/bitgen.h"
+#include "src/bitgen.h"
/*
* RAND_INT_TYPE is used to share integer generators with RandomState which
diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py
index 09fe85e5f..306967216 100644
--- a/numpy/testing/_private/utils.py
+++ b/numpy/testing/_private/utils.py
@@ -301,6 +301,10 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
check that all elements of these objects are equal. An exception is raised
at the first conflicting values.
+ When one of `actual` and `desired` is a scalar and the other is array_like,
+ the function checks that each element of the array_like object is equal to
+ the scalar.
+
This function handles NaN comparisons as if NaN was a "normal" number.
That is, no assertion is raised if both objects have NaNs in the same
positions. This is in contrast to the IEEE standard on NaNs, which says
@@ -391,21 +395,6 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
if isscalar(desired) != isscalar(actual):
raise AssertionError(msg)
- # Inf/nan/negative zero handling
- try:
- isdesnan = gisnan(desired)
- isactnan = gisnan(actual)
- if isdesnan and isactnan:
- return # both nan, so equal
-
- # handle signed zero specially for floats
- if desired == 0 and actual == 0:
- if not signbit(desired) == signbit(actual):
- raise AssertionError(msg)
-
- except (TypeError, ValueError, NotImplementedError):
- pass
-
try:
isdesnat = isnat(desired)
isactnat = isnat(actual)
@@ -421,6 +410,33 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
except (TypeError, ValueError, NotImplementedError):
pass
+ # Inf/nan/negative zero handling
+ try:
+ isdesnan = gisnan(desired)
+ isactnan = gisnan(actual)
+ if isdesnan and isactnan:
+ return # both nan, so equal
+
+ # handle signed zero specially for floats
+ array_actual = array(actual)
+ array_desired = array(desired)
+ if (array_actual.dtype.char in 'Mm' or
+ array_desired.dtype.char in 'Mm'):
+ # version 1.18
+ # until this version, gisnan failed for datetime64 and timedelta64.
+ # Now it succeeds but comparison to scalar with a different type
+ # emits a DeprecationWarning.
+ # Avoid that by skipping the next check
+ raise NotImplementedError('cannot compare to a scalar '
+ 'with a different type')
+
+ if desired == 0 and actual == 0:
+ if not signbit(desired) == signbit(actual):
+ raise AssertionError(msg)
+
+ except (TypeError, ValueError, NotImplementedError):
+ pass
+
try:
# Explicitly use __eq__ for comparison, gh-2552
if not (desired == actual):
@@ -703,7 +719,7 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
header='', precision=6, equal_nan=True,
equal_inf=True):
__tracebackhide__ = True # Hide traceback for py.test
- from numpy.core import array, array2string, isnan, inf, bool_, errstate, all
+ from numpy.core import array, array2string, isnan, inf, bool_, errstate, all, max, object_
x = array(x, copy=False, subok=True)
y = array(y, copy=False, subok=True)
@@ -804,15 +820,19 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
# do not trigger a failure (np.ma.masked != True evaluates as
# np.ma.masked, which is falsy).
if cond != True:
- mismatch = 100. * (reduced.size - reduced.sum(dtype=intp)) / ox.size
- remarks = ['Mismatch: {:.3g}%'.format(mismatch)]
+ n_mismatch = reduced.size - reduced.sum(dtype=intp)
+ n_elements = flagged.size if flagged.ndim != 0 else reduced.size
+ percent_mismatch = 100 * n_mismatch / n_elements
+ remarks = [
+ 'Mismatched elements: {} / {} ({:.3g}%)'.format(
+ n_mismatch, n_elements, percent_mismatch)]
with errstate(invalid='ignore', divide='ignore'):
# ignore errors for non-numeric types
with contextlib.suppress(TypeError):
error = abs(x - y)
- max_abs_error = error.max()
- if error.dtype == 'object':
+ max_abs_error = max(error)
+ if getattr(error, 'dtype', object_) == object_:
remarks.append('Max absolute difference: '
+ str(max_abs_error))
else:
@@ -826,8 +846,8 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True,
if all(~nonzero):
max_rel_error = array(inf)
else:
- max_rel_error = (error[nonzero] / abs(y[nonzero])).max()
- if error.dtype == 'object':
+ max_rel_error = max(error[nonzero] / abs(y[nonzero]))
+ if getattr(error, 'dtype', object_) == object_:
remarks.append('Max relative difference: '
+ str(max_rel_error))
else:
@@ -854,10 +874,11 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
Raises an AssertionError if two array_like objects are not equal.
Given two array_like objects, check that the shape is equal and all
- elements of these objects are equal. An exception is raised at
- shape mismatch or conflicting values. In contrast to the standard usage
- in numpy, NaNs are compared like numbers, no assertion is raised if
- both objects have NaNs in the same positions.
+ elements of these objects are equal (but see the Notes for the special
+ handling of a scalar). An exception is raised at shape mismatch or
+ conflicting values. In contrast to the standard usage in numpy, NaNs
+ are compared like numbers, no assertion is raised if both objects have
+ NaNs in the same positions.
The usual caution for verifying equality with floating point numbers is
advised.
@@ -884,6 +905,12 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
relative and/or absolute precision.
assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal
+ Notes
+ -----
+ When one of `x` and `y` is a scalar and the other is array_like, the
+ function checks that each element of the array_like object is equal to
+ the scalar.
+
Examples
--------
The first assert does not raise an exception:
@@ -891,7 +918,7 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
>>> np.testing.assert_array_equal([1.0,2.33333,np.nan],
... [np.exp(0),2.33333, np.nan])
- Assert fails with numerical inprecision with floats:
+ Assert fails with numerical imprecision with floats:
>>> np.testing.assert_array_equal([1.0,np.pi,np.nan],
... [1, np.sqrt(np.pi)**2, np.nan])
@@ -912,6 +939,12 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
... [1, np.sqrt(np.pi)**2, np.nan],
... rtol=1e-10, atol=0)
+ As mentioned in the Notes section, `assert_array_equal` has special
+ handling for scalars. Here the test checks that each value in `x` is 3:
+
+ >>> x = np.full((2, 5), fill_value=3)
+ >>> np.testing.assert_array_equal(x, 3)
+
"""
__tracebackhide__ = True # Hide traceback for py.test
assert_array_compare(operator.__eq__, x, y, err_msg=err_msg,
@@ -1150,7 +1183,7 @@ def assert_string_equal(actual, desired):
if desired == actual:
return
- diff = list(difflib.Differ().compare(actual.splitlines(1), desired.splitlines(1)))
+ diff = list(difflib.Differ().compare(actual.splitlines(True), desired.splitlines(True)))
diff_list = []
while diff:
d1 = diff.pop(0)
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index 76c842f25..ad72b9199 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -90,6 +90,21 @@ class TestArrayEqual(_GenericTest):
for t in ['S1', 'U1']:
foo(t)
+ def test_0_ndim_array(self):
+ x = np.array(473963742225900817127911193656584771)
+ y = np.array(18535119325151578301457182298393896)
+ assert_raises(AssertionError, self._assert_func, x, y)
+
+ y = x
+ self._assert_func(x, y)
+
+ x = np.array(43)
+ y = np.array(10)
+ assert_raises(AssertionError, self._assert_func, x, y)
+
+ y = x
+ self._assert_func(x, y)
+
def test_generic_rank3(self):
"""Test rank 3 array for all dtypes."""
def foo(t):
@@ -520,7 +535,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y, decimal=12)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatch: 100%')
+ assert_equal(msgs[3], 'Mismatched elements: 3 / 3 (100%)')
assert_equal(msgs[4], 'Max absolute difference: 1.e-05')
assert_equal(msgs[5], 'Max relative difference: 3.33328889e-06')
assert_equal(
@@ -536,7 +551,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatch: 33.3%')
+ assert_equal(msgs[3], 'Mismatched elements: 1 / 3 (33.3%)')
assert_equal(msgs[4], 'Max absolute difference: 1.e-05')
assert_equal(msgs[5], 'Max relative difference: 3.33328889e-06')
assert_equal(msgs[6], ' x: array([1. , 2. , 3.00003])')
@@ -548,7 +563,7 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatch: 50%')
+ assert_equal(msgs[3], 'Mismatched elements: 1 / 2 (50%)')
assert_equal(msgs[4], 'Max absolute difference: 1.')
assert_equal(msgs[5], 'Max relative difference: 1.')
assert_equal(msgs[6], ' x: array([inf, 0.])')
@@ -560,10 +575,30 @@ class TestAlmostEqual(_GenericTest):
with pytest.raises(AssertionError) as exc_info:
self._assert_func(x, y)
msgs = str(exc_info.value).split('\n')
- assert_equal(msgs[3], 'Mismatch: 100%')
+ assert_equal(msgs[3], 'Mismatched elements: 2 / 2 (100%)')
assert_equal(msgs[4], 'Max absolute difference: 2')
assert_equal(msgs[5], 'Max relative difference: inf')
+ def test_error_message_2(self):
+ """Check the message is formatted correctly when either x or y is a scalar."""
+ x = 2
+ y = np.ones(20)
+ with pytest.raises(AssertionError) as exc_info:
+ self._assert_func(x, y)
+ msgs = str(exc_info.value).split('\n')
+ assert_equal(msgs[3], 'Mismatched elements: 20 / 20 (100%)')
+ assert_equal(msgs[4], 'Max absolute difference: 1.')
+ assert_equal(msgs[5], 'Max relative difference: 1.')
+
+ y = 2
+ x = np.ones(20)
+ with pytest.raises(AssertionError) as exc_info:
+ self._assert_func(x, y)
+ msgs = str(exc_info.value).split('\n')
+ assert_equal(msgs[3], 'Mismatched elements: 20 / 20 (100%)')
+ assert_equal(msgs[4], 'Max absolute difference: 1.')
+ assert_equal(msgs[5], 'Max relative difference: 0.5')
+
def test_subclass_that_cannot_be_bool(self):
# While we cannot guarantee testing functions will always work for
# subclasses, the tests should ideally rely only on subclasses having
@@ -588,9 +623,9 @@ class TestApproxEqual(object):
def setup(self):
self._assert_func = assert_approx_equal
- def test_simple_arrays(self):
- x = np.array([1234.22])
- y = np.array([1234.23])
+ def test_simple_0d_arrays(self):
+ x = np.array(1234.22)
+ y = np.array(1234.23)
self._assert_func(x, y, significant=5)
self._assert_func(x, y, significant=6)
@@ -855,7 +890,8 @@ class TestAssertAllclose(object):
with pytest.raises(AssertionError) as exc_info:
assert_allclose(a, b)
msg = str(exc_info.value)
- assert_('Mismatch: 25%\nMax absolute difference: 1\n'
+ assert_('Mismatched elements: 1 / 4 (25%)\n'
+ 'Max absolute difference: 1\n'
'Max relative difference: 0.5' in msg)
def test_equal_nan(self):