summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/__init__.py25
-rw-r--r--numpy/core/src/multiarray/datetime.c5
-rw-r--r--numpy/core/tests/test_datetime.py20
-rw-r--r--numpy/linalg/tests/test_linalg.py36
-rw-r--r--numpy/ma/core.py15
5 files changed, 88 insertions, 13 deletions
diff --git a/numpy/__init__.py b/numpy/__init__.py
index d10a1ecd3..d250ed5ac 100644
--- a/numpy/__init__.py
+++ b/numpy/__init__.py
@@ -194,3 +194,28 @@ else:
from numpy.testing._private.pytesttester import PytestTester
test = PytestTester(__name__)
del PytestTester
+
+
+ def _sanity_check():
+ """
+ Quick sanity checks for common bugs caused by environment.
+ There are some cases e.g. with wrong BLAS ABI that cause wrong
+ results under specific runtime conditions that are not necessarily
+ achieved during test suite runs, and it is useful to catch those early.
+
+ See https://github.com/numpy/numpy/issues/8577 and other
+ similar bug reports.
+
+ """
+ try:
+ x = ones(2, dtype=float32)
+ if not abs(x.dot(x) - 2.0) < 1e-5:
+ raise AssertionError()
+ except AssertionError:
+ msg = ("The current Numpy installation ({!r}) fails to "
+ "pass simple sanity checks. This can be caused for example "
+ "by incorrect BLAS library being linked in.")
+ raise RuntimeError(msg.format(__file__))
+
+ _sanity_check()
+ del _sanity_check
diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c
index b026e5fae..af542aecc 100644
--- a/numpy/core/src/multiarray/datetime.c
+++ b/numpy/core/src/multiarray/datetime.c
@@ -2808,9 +2808,12 @@ convert_pyobject_to_timedelta(PyArray_DatetimeMetaData *meta, PyObject *obj,
us_meta.base = NPY_FR_m;
}
else if (td % (24*60*60*1000000LL) != 0) {
- us_meta.base = NPY_FR_D;
+ us_meta.base = NPY_FR_h;
}
else if (td % (7*24*60*60*1000000LL) != 0) {
+ us_meta.base = NPY_FR_D;
+ }
+ else {
us_meta.base = NPY_FR_W;
}
us_meta.num = 1;
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index 43e8a3325..e433877e8 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -124,7 +124,7 @@ class TestDateTime(object):
assert_(not np.can_cast('M8[h]', 'M8', casting='safe'))
def test_compare_generic_nat(self):
- # regression tests for GH6452
+ # regression tests for gh-6452
assert_equal(np.datetime64('NaT'),
np.datetime64('2000') + np.timedelta64('NaT'))
# nb. we may want to make NaT != NaT true in the future
@@ -331,6 +331,24 @@ class TestDateTime(object):
a = np.timedelta64(1, 'Y')
assert_raises(TypeError, np.timedelta64, a, 'D')
assert_raises(TypeError, np.timedelta64, a, 'm')
+ a = datetime.timedelta(seconds=3)
+ assert_raises(TypeError, np.timedelta64, a, 'M')
+ assert_raises(TypeError, np.timedelta64, a, 'Y')
+ a = datetime.timedelta(weeks=3)
+ assert_raises(TypeError, np.timedelta64, a, 'M')
+ assert_raises(TypeError, np.timedelta64, a, 'Y')
+ a = datetime.timedelta()
+ assert_raises(TypeError, np.timedelta64, a, 'M')
+ assert_raises(TypeError, np.timedelta64, a, 'Y')
+
+ def test_timedelta_object_array_conversion(self):
+ # Regression test for gh-11096
+ inputs = [datetime.timedelta(28),
+ datetime.timedelta(30),
+ datetime.timedelta(31)]
+ expected = np.array([28, 30, 31], dtype='timedelta64[D]')
+ actual = np.array(inputs, dtype='timedelta64[D]')
+ assert_equal(expected, actual)
def test_timedelta_scalar_construction_units(self):
# String construction detecting units
diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py
index 5ed1ff1c0..87dfe988a 100644
--- a/numpy/linalg/tests/test_linalg.py
+++ b/numpy/linalg/tests/test_linalg.py
@@ -7,6 +7,8 @@ import os
import sys
import itertools
import traceback
+import textwrap
+import subprocess
import pytest
import numpy as np
@@ -1761,6 +1763,40 @@ def test_xerbla_override():
raise SkipTest('Numpy xerbla not linked in.')
+def test_sdot_bug_8577():
+ # Regression test that loading certain other libraries does not
+ # result to wrong results in float32 linear algebra.
+ #
+ # There's a bug gh-8577 on OSX that can trigger this, and perhaps
+ # there are also other situations in which it occurs.
+ #
+ # Do the check in a separate process.
+
+ bad_libs = ['PyQt5.QtWidgets', 'IPython']
+
+ template = textwrap.dedent("""
+ import sys
+ {before}
+ try:
+ import {bad_lib}
+ except ImportError:
+ sys.exit(0)
+ {after}
+ x = np.ones(2, dtype=np.float32)
+ sys.exit(0 if np.allclose(x.dot(x), 2.0) else 1)
+ """)
+
+ for bad_lib in bad_libs:
+ code = template.format(before="import numpy as np", after="",
+ bad_lib=bad_lib)
+ subprocess.check_call([sys.executable, "-c", code])
+
+ # Swapped import order
+ code = template.format(after="import numpy as np", before="",
+ bad_lib=bad_lib)
+ subprocess.check_call([sys.executable, "-c", code])
+
+
class TestMultiDot(object):
def test_basic_function_with_three_arguments(self):
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index c0dda6f31..17682d13f 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -2799,13 +2799,8 @@ class MaskedArray(ndarray):
# FIXME _sharedmask is never used.
_sharedmask = True
# Process mask.
- # Number of named fields (or zero if none)
- names_ = _data.dtype.names or ()
# Type of the mask
- if names_:
- mdtype = make_mask_descr(_data.dtype)
- else:
- mdtype = MaskType
+ mdtype = make_mask_descr(_data.dtype)
if mask is nomask:
# Case 1. : no mask in input.
@@ -2831,14 +2826,12 @@ class MaskedArray(ndarray):
_data._mask = mask
_data._sharedmask = False
else:
+ _data._sharedmask = not copy
if copy:
_data._mask = _data._mask.copy()
- _data._sharedmask = False
# Reset the shape of the original mask
if getmask(data) is not nomask:
data._mask.shape = data.shape
- else:
- _data._sharedmask = True
else:
# Case 2. : With a mask in input.
# If mask is boolean, create an array of True or False
@@ -2875,7 +2868,7 @@ class MaskedArray(ndarray):
_data._mask = mask
_data._sharedmask = not copy
else:
- if names_:
+ if _data.dtype.names:
def _recursive_or(a, b):
"do a|=b on each field of a, recursively"
for name in a.dtype.names:
@@ -2884,7 +2877,7 @@ class MaskedArray(ndarray):
_recursive_or(af, bf)
else:
af |= bf
- return
+
_recursive_or(_data._mask, mask)
else:
_data._mask = np.logical_or(mask, _data._mask)