summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/include/numpy/npy_common.h8
-rw-r--r--numpy/core/setup.py10
-rw-r--r--numpy/core/setup_common.py5
-rw-r--r--numpy/core/src/multiarray/buffer.c115
-rw-r--r--numpy/core/src/multiarray/einsum.c.src6
-rw-r--r--numpy/core/src/npysort/selection.c.src8
-rw-r--r--numpy/core/src/private/ufunc_override.h172
-rw-r--r--numpy/core/src/umath/loops.c.src3
-rw-r--r--numpy/core/src/umath/simd.inc.src26
-rw-r--r--numpy/core/tests/test_multiarray.py78
-rw-r--r--numpy/core/tests/test_scalarmath.py47
-rw-r--r--numpy/core/tests/test_umath.py8
-rw-r--r--numpy/lib/npyio.py27
13 files changed, 388 insertions, 125 deletions
diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h
index 62ffa4006..08582bf79 100644
--- a/numpy/core/include/numpy/npy_common.h
+++ b/numpy/core/include/numpy/npy_common.h
@@ -18,6 +18,14 @@
#define NPY_GCC_UNROLL_LOOPS
#endif
+#if defined HAVE_XMMINTRIN_H && defined HAVE__MM_LOAD_PS
+#define NPY_HAVE_SSE_INTRINSICS
+#endif
+
+#if defined HAVE_EMMINTRIN_H && defined HAVE__MM_LOAD_PD
+#define NPY_HAVE_SSE2_INTRINSICS
+#endif
+
/*
* give a hint to the compiler which branch is more likely or unlikely
* to occur, e.g. rare error cases:
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 1c8cea4f7..576b7d5ff 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -165,8 +165,14 @@ def check_math_capabilities(config, moredefs, mathlibs):
if config.check_func("", decl=False, call=False, headers=[h]):
moredefs.append((fname2def(h).replace(".", "_"), 1))
- for f, args in OPTIONAL_INTRINSICS:
- if config.check_func(f, decl=False, call=True, call_args=args):
+ for tup in OPTIONAL_INTRINSICS:
+ headers = None
+ if len(tup) == 2:
+ f, args = tup
+ else:
+ f, args, headers = tup[0], tup[1], [tup[2]]
+ if config.check_func(f, decl=False, call=True, call_args=args,
+ headers=headers):
moredefs.append((fname2def(f), 1))
for dec, fn in OPTIONAL_GCC_ATTRIBUTES:
diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py
index 1f3e6b44e..bad3607fa 100644
--- a/numpy/core/setup_common.py
+++ b/numpy/core/setup_common.py
@@ -107,7 +107,8 @@ OPTIONAL_HEADERS = [
"emmintrin.h", # SSE2
]
-# optional gcc compiler builtins and their call arguments
+# optional gcc compiler builtins and their call arguments and optional a
+# required header
# call arguments are required as the compiler will do strict signature checking
OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
("__builtin_isinf", '5.'),
@@ -115,6 +116,8 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
("__builtin_bswap32", '5u'),
("__builtin_bswap64", '5u'),
("__builtin_expect", '5, 0'),
+ ("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE
+ ("_mm_load_pd", '(double*)0', "emmintrin.h"), # SSE2
]
# gcc function attributes
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index 3ae3c7d0d..975891b3a 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -767,11 +767,18 @@ NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
* Convert PEP 3118 format string to PyArray_Descr
*/
+static int
+_descriptor_from_pep3118_format_fast(char *s, PyObject **result);
+
+static int
+_pep3118_letter_to_type(char letter, int native, int complex);
+
NPY_NO_EXPORT PyArray_Descr*
_descriptor_from_pep3118_format(char *s)
{
char *buf, *p;
int in_name = 0;
+ int obtained;
PyObject *descr;
PyObject *str;
PyObject *_numpy_internal;
@@ -780,6 +787,12 @@ _descriptor_from_pep3118_format(char *s)
return PyArray_DescrNewFromType(NPY_BYTE);
}
+ /* Fast path */
+ obtained = _descriptor_from_pep3118_format_fast(s, &descr);
+ if (obtained) {
+ return (PyArray_Descr*)descr;
+ }
+
/* Strip whitespace, except from field names */
buf = malloc(strlen(s) + 1);
if (buf == NULL) {
@@ -828,3 +841,105 @@ _descriptor_from_pep3118_format(char *s)
}
return (PyArray_Descr*)descr;
}
+
+/*
+ * Fast path for parsing buffer strings corresponding to simple types.
+ *
+ * Currently, this deals only with single-element data types.
+ */
+
+static int
+_descriptor_from_pep3118_format_fast(char *s, PyObject **result)
+{
+ PyArray_Descr *descr;
+
+ int is_standard_size = 0;
+ char byte_order = '=';
+ int is_complex = 0;
+
+ int type_num = NPY_BYTE;
+ int item_seen = 0;
+
+ for (; *s != '\0'; ++s) {
+ is_complex = 0;
+ switch (*s) {
+ case '@':
+ case '^':
+ /* ^ means no alignment; doesn't matter for a single element */
+ byte_order = '=';
+ is_standard_size = 0;
+ break;
+ case '<':
+ byte_order = '<';
+ is_standard_size = 1;
+ break;
+ case '>':
+ case '!':
+ byte_order = '>';
+ is_standard_size = 1;
+ break;
+ case '=':
+ byte_order = '=';
+ is_standard_size = 1;
+ break;
+ case 'Z':
+ is_complex = 1;
+ ++s;
+ default:
+ if (item_seen) {
+ /* Not a single-element data type */
+ return 0;
+ }
+ type_num = _pep3118_letter_to_type(*s, !is_standard_size,
+ is_complex);
+ if (type_num < 0) {
+ /* Something unknown */
+ return 0;
+ }
+ item_seen = 1;
+ break;
+ }
+ }
+
+ if (!item_seen) {
+ return 0;
+ }
+
+ descr = PyArray_DescrFromType(type_num);
+ if (byte_order == '=') {
+ *result = (PyObject*)descr;
+ }
+ else {
+ *result = (PyObject*)PyArray_DescrNewByteorder(descr, byte_order);
+ Py_DECREF(descr);
+ }
+
+ return 1;
+}
+
+static int
+_pep3118_letter_to_type(char letter, int native, int complex)
+{
+ switch (letter)
+ {
+ case '?': return NPY_BOOL;
+ case 'b': return NPY_BYTE;
+ case 'B': return NPY_UBYTE;
+ case 'h': return native ? NPY_SHORT : NPY_INT16;
+ case 'H': return native ? NPY_USHORT : NPY_UINT16;
+ case 'i': return native ? NPY_INT : NPY_INT32;
+ case 'I': return native ? NPY_UINT : NPY_UINT32;
+ case 'l': return native ? NPY_LONG : NPY_INT32;
+ case 'L': return native ? NPY_ULONG : NPY_UINT32;
+ case 'q': return native ? NPY_LONGLONG : NPY_INT64;
+ case 'Q': return native ? NPY_ULONGLONG : NPY_UINT64;
+ case 'e': return NPY_HALF;
+ case 'f': return complex ? NPY_CFLOAT : NPY_FLOAT;
+ case 'd': return complex ? NPY_CDOUBLE : NPY_DOUBLE;
+ case 'g': return native ? (complex ? NPY_CLONGDOUBLE : NPY_LONGDOUBLE) : -1;
+ default:
+ /* Other unhandled cases */
+ return -1;
+ }
+ return -1;
+}
diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src
index 56b1ce746..7a94c9305 100644
--- a/numpy/core/src/multiarray/einsum.c.src
+++ b/numpy/core/src/multiarray/einsum.c.src
@@ -14,16 +14,16 @@
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
+#include <numpy/npy_common.h>
#include <numpy/arrayobject.h>
#include <numpy/halffloat.h>
#include <npy_pycompat.h>
-#include <npy_config.h>
#include <ctype.h>
#include "convert.h"
-#ifdef HAVE_XMMINTRIN_H
+#ifdef NPY_HAVE_SSE_INTRINSICS
#define EINSUM_USE_SSE1 1
#else
#define EINSUM_USE_SSE1 0
@@ -32,7 +32,7 @@
/*
* TODO: Only some SSE2 for float64 is implemented.
*/
-#ifdef HAVE_EMMINTRIN_H
+#ifdef NPY_HAVE_SSE2_INTRINSICS
#define EINSUM_USE_SSE2 1
#else
#define EINSUM_USE_SSE2 0
diff --git a/numpy/core/src/npysort/selection.c.src b/numpy/core/src/npysort/selection.c.src
index b11753367..073b5847f 100644
--- a/numpy/core/src/npysort/selection.c.src
+++ b/numpy/core/src/npysort/selection.c.src
@@ -176,12 +176,8 @@ static npy_intp @name@median5_@suff@(
}
}
else {
- if (@TYPE@_LT(v[IDX(2)], v[IDX(1)])) {
- return 1;
- }
- else {
- return 2;
- }
+ /* v[1] and v[2] swapped into order above */
+ return 2;
}
}
diff --git a/numpy/core/src/private/ufunc_override.h b/numpy/core/src/private/ufunc_override.h
index 5c3cbdb12..af7f6e46e 100644
--- a/numpy/core/src/private/ufunc_override.h
+++ b/numpy/core/src/private/ufunc_override.h
@@ -11,6 +11,9 @@
* routine returning something other than `NotImplemented` determines the
* result. If all of the `__numpy_ufunc__` operations returns `NotImplemented`,
* a `TypeError` is raised.
+ *
+ * Returns 0 on success and 1 on exception. On success, *result contains the
+ * result of the operation, if any. If *result is NULL, there is no override.
*/
static int
PyUFunc_CheckOverride(PyObject *ufunc, char *method,
@@ -21,31 +24,36 @@ PyUFunc_CheckOverride(PyObject *ufunc, char *method,
int i;
int override_pos; /* Position of override in args.*/
int j;
- int pos_in_with_override; /* Position of override in with_override.*/
int nargs = PyTuple_GET_SIZE(args);
int noa = 0; /* Number of overriding args.*/
- int normalized = 0; /* Is normalized flag.*/
PyObject *obj;
PyObject *other_obj;
- PyObject *override_args;
- PyObject *method_name = PyUString_FromString(method);
+ PyObject *method_name = NULL;
PyObject *normal_args = NULL; /* normal_* holds normalized arguments. */
PyObject *normal_kwds = NULL;
- PyObject *override_obj = NULL; /* overriding object */
- PyObject *numpy_ufunc = NULL; /* the __numpy_ufunc__ method */
PyObject *with_override[NPY_MAXARGS];
+
/* Pos of each override in args */
int with_override_pos[NPY_MAXARGS];
- /* Checks */
+ /*
+ * Check inputs
+ */
if (!PyTuple_Check(args)) {
+ PyErr_SetString(PyExc_ValueError,
+ "Internal Numpy error: call to PyUFunc_CheckOverride "
+ "with non-tuple");
goto fail;
}
+
if (PyTuple_GET_SIZE(args) > NPY_MAXARGS) {
+ PyErr_SetString(PyExc_ValueError,
+ "Internal Numpy error: too many arguments in call "
+ "to PyUFunc_CheckOverride");
goto fail;
}
@@ -63,12 +71,48 @@ PyUFunc_CheckOverride(PyObject *ufunc, char *method,
/* No overrides, bail out.*/
if (noa == 0) {
- Py_DECREF(method_name);
+ *result = NULL;
return 0;
}
+ /*
+ * Normalize ufunc arguments.
+ */
+ normal_args = PyTuple_GetSlice(args, 0, nin);
+ if (normal_args == NULL) {
+ goto fail;
+ }
+
+ /* Build new kwds */
+ if (kwds && PyDict_CheckExact(kwds)) {
+ normal_kwds = PyDict_Copy(kwds);
+ }
+ else {
+ normal_kwds = PyDict_New();
+ }
+ if (normal_kwds == NULL) {
+ goto fail;
+ }
+
+ /* If we have more args than nin, the last one must be `out`.*/
+ if (nargs > nin) {
+ obj = PyTuple_GET_ITEM(args, nargs - 1);
+ PyDict_SetItemString(normal_kwds, "out", obj);
+ }
+
+ method_name = PyUString_FromString(method);
+ if (method_name == NULL) {
+ goto fail;
+ }
+
+ /*
+ * Call __numpy_ufunc__ functions in correct order
+ */
while (1) {
- obj = NULL;
+ PyObject *numpy_ufunc;
+ PyObject *override_args;
+ PyObject *override_obj;
+
override_obj = NULL;
*result = NULL;
@@ -78,10 +122,10 @@ PyUFunc_CheckOverride(PyObject *ufunc, char *method,
if (obj == NULL) {
continue;
}
+
/* Get the first instance of an overriding arg.*/
override_pos = with_override_pos[i];
override_obj = obj;
- pos_in_with_override = i;
/* Check for sub-types to the right of obj. */
for (j = i + 1; j < noa; j++) {
@@ -93,103 +137,67 @@ PyUFunc_CheckOverride(PyObject *ufunc, char *method,
break;
}
}
+
/* override_obj had no subtypes to the right. */
if (override_obj) {
+ with_override[i] = NULL; /* We won't call this one again */
break;
}
}
- /* No good override_obj */
+
+ /* Check if there is a method left to call */
if (!override_obj) {
- break;
+ /* No acceptable override found. */
+ PyErr_SetString(PyExc_TypeError,
+ "__numpy_ufunc__ not implemented for this type.");
+ goto fail;
}
- /*
- * Normalize the ufuncs arguments. Returns a tuple of
- * (args, kwds).
- *
- * Test with and without kwds.
- */
- if (!normalized) {
- PyObject *out_arg;
-
- /* If we have more args than nin, the last one must be `out`.*/
- if (nargs > nin) {
- out_arg = PyTuple_GET_ITEM(args, nargs - 1);
-
- /* Build new args.*/
- normal_args = PyTuple_GetSlice(args, 0, nin);
-
- /* Build new kwds with out arg.*/
- if (kwds && PyDict_CheckExact(kwds)) {
- normal_kwds = PyDict_Copy(kwds);
- PyDict_SetItemString(normal_kwds, "out", out_arg);
- }
- else {
- normal_kwds = PyDict_New();
- PyDict_SetItemString(normal_kwds, "out", out_arg);
- }
- normalized = 1;
- }
- else {
- /* Copy args */
- normal_args = PyTuple_GetSlice(args, 0, nin);
- if (kwds && PyDict_CheckExact(kwds)) {
- normal_kwds = PyDict_Copy(kwds);
- }
- else {
- normal_kwds = PyDict_New();
- }
+ /* Call the override */
+ numpy_ufunc = PyObject_GetAttrString(override_obj,
+ "__numpy_ufunc__");
+ if (numpy_ufunc == NULL) {
+ goto fail;
+ }
- normalized = 1;
- }
+ override_args = Py_BuildValue("OOiO", ufunc, method_name,
+ override_pos, normal_args);
+ if (override_args == NULL) {
+ Py_DECREF(numpy_ufunc);
+ goto fail;
}
- /* Calculate a result if we have a override. */
- if (override_obj) {
- numpy_ufunc = PyObject_GetAttrString(override_obj,
- "__numpy_ufunc__");
- override_args = Py_BuildValue("OOiO", ufunc, method_name,
- override_pos, normal_args);
- *result = PyObject_Call(numpy_ufunc, override_args, normal_kwds);
+ *result = PyObject_Call(numpy_ufunc, override_args, normal_kwds);
- Py_DECREF(numpy_ufunc);
- Py_DECREF(override_args);
+ Py_DECREF(numpy_ufunc);
+ Py_DECREF(override_args);
- /* Remove this arg if it gives not implemented */
- if (*result == Py_NotImplemented) {
- with_override[pos_in_with_override] = NULL;
- Py_DECREF(*result);
- continue;
- }
- /* Good result. */
- else {
- break;
- }
+ if (*result == NULL) {
+ /* Exception occurred */
+ goto fail;
+ }
+ else if (*result == Py_NotImplemented) {
+ /* Try the next one */
+ Py_DECREF(*result);
+ continue;
}
-
- /* All overrides checked. */
else {
+ /* Good result. */
break;
}
}
- /* No acceptable override found. */
- if (!*result) {
- PyErr_SetString(PyExc_TypeError,
- "__numpy_ufunc__ not implemented for this type.");
- Py_XDECREF(normal_args);
- Py_XDECREF(normal_kwds);
- goto fail;
- }
+
/* Override found, return it. */
- Py_DECREF(method_name);
+ Py_XDECREF(method_name);
Py_XDECREF(normal_args);
Py_XDECREF(normal_kwds);
return 0;
fail:
- Py_DECREF(method_name);
+ Py_XDECREF(method_name);
+ Py_XDECREF(normal_args);
+ Py_XDECREF(normal_kwds);
return 1;
-
}
#endif
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index d1fc58ffa..a444d37c3 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -10,6 +10,7 @@
#define NO_IMPORT_ARRAY
#endif
+#include "numpy/npy_common.h"
#include "numpy/arrayobject.h"
#include "numpy/ufuncobject.h"
#include "numpy/npy_math.h"
@@ -564,7 +565,7 @@ NPY_NO_EXPORT void
BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
{
if(IS_BINARY_REDUCE) {
-#ifdef HAVE_EMMINTRIN_H
+#ifdef NPY_HAVE_SSE2_INTRINSICS
/*
* stick with our variant for more reliable performance, only known
* platform which outperforms it by ~20% is an i7 with glibc 2.17
diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src
index e1fe6c5b5..e274e0596 100644
--- a/numpy/core/src/umath/simd.inc.src
+++ b/numpy/core/src/umath/simd.inc.src
@@ -16,10 +16,10 @@
#define __NPY_SIMD_INC
#include "lowlevel_strided_loops.h"
-#include "npy_config.h"
+#include "numpy/npy_common.h"
/* for NO_FLOATING_POINT_SUPPORT */
#include "numpy/ufuncobject.h"
-#ifdef HAVE_EMMINTRIN_H
+#ifdef NPY_HAVE_SSE2_INTRINSICS
#include <emmintrin.h>
#endif
#include <assert.h>
@@ -140,7 +140,7 @@ static const npy_int32 fanout_4[] = {
* #name = unary, unary, unary_reduce, unary_reduce#
*/
-#if @vector@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
/* prototypes */
static void
@@ -151,7 +151,7 @@ sse2_@func@_@TYPE@(@type@ *, @type@ *, const npy_intp n);
static NPY_INLINE int
run_@name@_simd_@func@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if @vector@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
if (@check@(sizeof(@type@), 16)) {
sse2_@func@_@TYPE@((@type@*)args[1], (@type@*)args[0], dimensions[0]);
return 1;
@@ -167,7 +167,7 @@ run_@name@_simd_@func@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps
* # kind = add, subtract, multiply, divide#
*/
-#if @vector@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
/* prototypes */
static void
@@ -185,7 +185,7 @@ sse2_binary_scalar2_@kind@_@TYPE@(@type@ * op, @type@ * ip1, @type@ * ip2,
static NPY_INLINE int
run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if @vector@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
@type@ * ip1 = (@type@ *)args[0];
@type@ * ip2 = (@type@ *)args[1];
@type@ * op = (@type@ *)args[2];
@@ -216,7 +216,7 @@ run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps
* #simd = 1, 1, 1, 1, 1, 1, 0, 0#
*/
-#if @vector@ && @simd@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && @simd@ && defined NPY_HAVE_SSE2_INTRINSICS
/* prototypes */
static void
@@ -234,7 +234,7 @@ sse2_binary_scalar2_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2,
static NPY_INLINE int
run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if @vector@ && @simd@ && defined HAVE_EMMINTRIN_H
+#if @vector@ && @simd@ && defined NPY_HAVE_SSE2_INTRINSICS
@type@ * ip1 = (@type@ *)args[0];
@type@ * ip2 = (@type@ *)args[1];
npy_bool * op = (npy_bool *)args[2];
@@ -278,7 +278,7 @@ sse2_binary_@kind@_BOOL(npy_bool * op, npy_bool * ip1, npy_bool * ip2,
static NPY_INLINE int
run_binary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if defined HAVE_EMMINTRIN_H
+#if defined NPY_HAVE_SSE2_INTRINSICS
if (sizeof(npy_bool) == 1 && IS_BLOCKABLE_BINARY(sizeof(npy_bool), 16)) {
sse2_binary_@kind@_BOOL((npy_bool*)args[2], (npy_bool*)args[0],
(npy_bool*)args[1], dimensions[0]);
@@ -295,7 +295,7 @@ sse2_reduce_@kind@_BOOL(npy_bool * op, npy_bool * ip, npy_intp n);
static NPY_INLINE int
run_reduce_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if defined HAVE_EMMINTRIN_H
+#if defined NPY_HAVE_SSE2_INTRINSICS
if (sizeof(npy_bool) == 1 && IS_BLOCKABLE_REDUCE(sizeof(npy_bool), 16)) {
sse2_reduce_@kind@_BOOL((npy_bool*)args[0], (npy_bool*)args[1],
dimensions[0]);
@@ -317,7 +317,7 @@ sse2_@kind@_BOOL(npy_bool *, npy_bool *, const npy_intp n);
static NPY_INLINE int
run_unary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
{
-#if defined HAVE_EMMINTRIN_H
+#if defined NPY_HAVE_SSE2_INTRINSICS
if (sizeof(npy_bool) == 1 && IS_BLOCKABLE_UNARY(sizeof(npy_bool), 16)) {
sse2_@kind@_BOOL((npy_bool*)args[1], (npy_bool*)args[0], dimensions[0]);
return 1;
@@ -328,7 +328,7 @@ run_unary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
/**end repeat**/
-#ifdef HAVE_EMMINTRIN_H
+#ifdef NPY_HAVE_SSE2_INTRINSICS
/*
* Vectorized operations
@@ -843,6 +843,6 @@ sse2_@kind@_BOOL(@type@ * op, @type@ * ip, const npy_intp n)
/**end repeat**/
-#endif /* HAVE_EMMINTRIN_H */
+#endif /* NPY_HAVE_SSE2_INTRINSICS */
#endif
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 33e3bdcab..012fa0cab 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1141,6 +1141,17 @@ class TestMethods(TestCase):
assert_array_equal(d[np.argpartition(d, -6, kind=k)],
np.partition(d, 41, kind=k))
+ # median of 3 killer, O(n^2) on pure median 3 pivot quickselect
+ # exercises the median of median of 5 code used to keep O(n)
+ d = np.arange(1000000)
+ x = np.roll(d, d.size // 2)
+ mid = x.size // 2 + 1
+ assert_equal(np.partition(x, mid)[mid], mid)
+ d = np.arange(1000001)
+ x = np.roll(d, d.size // 2 + 1)
+ mid = x.size // 2 + 1
+ assert_equal(np.partition(x, mid)[mid], mid)
+
# equal elements
d = np.arange((47)) % 7
tgt = np.sort(np.arange((47)) % 7)
@@ -3239,6 +3250,29 @@ class TestNewBufferProtocol(object):
x = np.array(half_list, dtype='<e')
self._check_roundtrip(x)
+ def test_roundtrip_single_types(self):
+ for typ in np.typeDict.values():
+ dtype = np.dtype(typ)
+
+ if dtype.char in 'Mm':
+ # datetimes cannot be used in buffers
+ continue
+ if dtype.char == 'V':
+ # skip void
+ continue
+
+ x = np.zeros(4, dtype=dtype)
+ self._check_roundtrip(x)
+
+ if dtype.char not in 'qQgG':
+ dt = dtype.newbyteorder('<')
+ x = np.zeros(4, dtype=dt)
+ self._check_roundtrip(x)
+
+ dt = dtype.newbyteorder('>')
+ x = np.zeros(4, dtype=dt)
+ self._check_roundtrip(x)
+
def test_export_simple_1d(self):
x = np.array([1, 2, 3, 4, 5], dtype='i')
y = memoryview(x)
@@ -3407,6 +3441,7 @@ class TestArrayAttributeDeletion(object):
for s in attr:
assert_raises(AttributeError, delattr, a, s)
+
def test_array_interface():
# Test scalar coercion within the array interface
class Foo(object):
@@ -3629,5 +3664,48 @@ class TestArrayPriority(TestCase):
assert_(isinstance(res4, PriorityNdarray))
+class TestConversion(TestCase):
+ def test_array_scalar_relational_operation(self):
+ #All integer
+ for dt1 in np.typecodes['AllInteger']:
+ assert_(1 > np.array(0, dtype=dt1), "type %s failed" % (dt1,))
+ assert_(not 1 < np.array(0, dtype=dt1), "type %s failed" % (dt1,))
+
+ for dt2 in np.typecodes['AllInteger']:
+ assert_(np.array(1, dtype=dt1) > np.array(0, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1) < np.array(0, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+
+ #Unsigned integers
+ for dt1 in 'BHILQP':
+ assert_(-1 < np.array(1, dtype=dt1), "type %s failed" % (dt1,))
+ assert_(not -1 > np.array(1, dtype=dt1), "type %s failed" % (dt1,))
+ assert_(-1 != np.array(1, dtype=dt1), "type %s failed" % (dt1,))
+
+ #unsigned vs signed
+ for dt2 in 'bhilqp':
+ assert_(np.array(1, dtype=dt1) > np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1) < np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(np.array(1, dtype=dt1) != np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+
+ #Signed integers and floats
+ for dt1 in 'bhlqp' + np.typecodes['Float']:
+ assert_(1 > np.array(-1, dtype=dt1), "type %s failed" % (dt1,))
+ assert_(not 1 < np.array(-1, dtype=dt1), "type %s failed" % (dt1,))
+ assert_(-1 == np.array(-1, dtype=dt1), "type %s failed" % (dt1,))
+
+ for dt2 in 'bhlqp' + np.typecodes['Float']:
+ assert_(np.array(1, dtype=dt1) > np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1) < np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(np.array(-1, dtype=dt1) == np.array(-1, dtype=dt2),
+ "type %s and %s failed" % (dt1, dt2))
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py
index a4cc5e711..a3d1200ca 100644
--- a/numpy/core/tests/test_scalarmath.py
+++ b/numpy/core/tests/test_scalarmath.py
@@ -139,7 +139,6 @@ class TestConversion(TestCase):
a = np.array(l[:3], dtype=np.uint64)
assert_equal([int(_m) for _m in a], li[:3])
-
def test_iinfo_long_values(self):
for code in 'bBhH':
res = np.array(np.iinfo(code).max + 1, dtype=code)
@@ -156,16 +155,56 @@ class TestConversion(TestCase):
tgt = np.iinfo(code).max
assert_(res == tgt)
-
def test_int_raise_behaviour(self):
-
- def Overflow_error_func(dtype):
+ def Overflow_error_func(dtype):
res = np.typeDict[dtype](np.iinfo(dtype).max + 1)
for code in 'lLqQ':
assert_raises(OverflowError, Overflow_error_func, code)
+ def test_numpy_scalar_relational_operators(self):
+ #All integer
+ for dt1 in np.typecodes['AllInteger']:
+ assert_(1 > np.array(0, dtype=dt1)[()], "type %s failed" % (dt1,))
+ assert_(not 1 < np.array(0, dtype=dt1)[()], "type %s failed" % (dt1,))
+
+ for dt2 in np.typecodes['AllInteger']:
+ assert_(np.array(1, dtype=dt1)[()] > np.array(0, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1)[()] < np.array(0, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+
+ #Unsigned integers
+ for dt1 in 'BHILQP':
+ assert_(-1 < np.array(1, dtype=dt1)[()], "type %s failed" % (dt1,))
+ assert_(not -1 > np.array(1, dtype=dt1)[()], "type %s failed" % (dt1,))
+ assert_(-1 != np.array(1, dtype=dt1)[()], "type %s failed" % (dt1,))
+
+ #unsigned vs signed
+ for dt2 in 'bhilqp':
+ assert_(np.array(1, dtype=dt1)[()] > np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1)[()] < np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(np.array(1, dtype=dt1)[()] != np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+
+ #Signed integers and floats
+ for dt1 in 'bhlqp' + np.typecodes['Float']:
+ assert_(1 > np.array(-1, dtype=dt1)[()], "type %s failed" % (dt1,))
+ assert_(not 1 < np.array(-1, dtype=dt1)[()], "type %s failed" % (dt1,))
+ assert_(-1 == np.array(-1, dtype=dt1)[()], "type %s failed" % (dt1,))
+
+ for dt2 in 'bhlqp' + np.typecodes['Float']:
+ assert_(np.array(1, dtype=dt1)[()] > np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(not np.array(1, dtype=dt1)[()] < np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+ assert_(np.array(-1, dtype=dt1)[()] == np.array(-1, dtype=dt2)[()],
+ "type %s and %s failed" % (dt1, dt2))
+
+
#class TestRepr(TestCase):
# def test_repr(self):
# for t in types:
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 61f084a01..1fc59f5fd 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -1051,6 +1051,14 @@ class TestSpecialMethods(TestCase):
assert_equal(res4['out'], 'out_arg')
assert_equal(res5['out'], 'out_arg')
+ def test_ufunc_override_exception(self):
+ class A(object):
+ def __numpy_ufunc__(self, *a, **kwargs):
+ raise ValueError("oops")
+ a = A()
+ for func in [np.divide, np.dot]:
+ assert_raises(ValueError, func, a, a)
+
class TestChoose(TestCase):
def test_mixed(self):
c = np.array([True, True])
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py
index 6873a4785..888bf4370 100644
--- a/numpy/lib/npyio.py
+++ b/numpy/lib/npyio.py
@@ -138,19 +138,19 @@ class NpzFile(object):
archive provided on construction.
`NpzFile` is used to load files in the NumPy ``.npz`` data archive
- format. It assumes that files in the archive have a ".npy" extension,
+ format. It assumes that files in the archive have a ``.npy`` extension,
other files are ignored.
The arrays and file strings are lazily loaded on either
getitem access using ``obj['key']`` or attribute lookup using
- ``obj.f.key``. A list of all files (without ".npy" extensions) can
+ ``obj.f.key``. A list of all files (without ``.npy`` extensions) can
be obtained with ``obj.files`` and the ZipFile object itself using
``obj.zip``.
Attributes
----------
files : list of str
- List of all files in the archive with a ".npy" extension.
+ List of all files in the archive with a ``.npy`` extension.
zip : ZipFile instance
The ZipFile object initialized with the zipped archive.
f : BagObj instance
@@ -270,7 +270,7 @@ class NpzFile(object):
yield (f, self[f])
def keys(self):
- """Return files in the archive with a ".npy" extension."""
+ """Return files in the archive with a ``.npy`` extension."""
return self.files
def iterkeys(self):
@@ -283,7 +283,7 @@ class NpzFile(object):
def load(file, mmap_mode=None):
"""
- Load an array(s) or pickled objects from .npy, .npz, or pickled files.
+ Load arrays or pickled objects from ``.npy``, ``.npz`` or pickled files.
Parameters
----------
@@ -301,7 +301,7 @@ def load(file, mmap_mode=None):
Returns
-------
result : array, tuple, dict, etc.
- Data stored in the file. For '.npz' files, the returned instance of
+ Data stored in the file. For ``.npz`` files, the returned instance of
NpzFile class must be closed to avoid leaking file descriptors.
Raises
@@ -457,9 +457,9 @@ def savez(file, *args, **kwds):
Save several arrays into a single file in uncompressed ``.npz`` format.
If arguments are passed in with no keywords, the corresponding variable
- names, in the .npz file, are 'arr_0', 'arr_1', etc. If keyword arguments
- are given, the corresponding variable names, in the ``.npz`` file will
- match the keyword names.
+ names, in the ``.npz`` file, are 'arr_0', 'arr_1', etc. If keyword
+ arguments are given, the corresponding variable names, in the ``.npz``
+ file will match the keyword names.
Parameters
----------
@@ -484,7 +484,7 @@ def savez(file, *args, **kwds):
--------
save : Save a single array to a binary file in NumPy format.
savetxt : Save an array to a file as plain text.
- savez_compressed : Save several arrays into a compressed .npz file format
+ savez_compressed : Save several arrays into a compressed ``.npz`` archive
Notes
-----
@@ -540,7 +540,7 @@ def savez_compressed(file, *args, **kwds):
Parameters
----------
file : str
- File name of .npz file.
+ File name of ``.npz`` file.
args : Arguments
Function arguments.
kwds : Keyword arguments
@@ -548,7 +548,7 @@ def savez_compressed(file, *args, **kwds):
See Also
--------
- numpy.savez : Save several arrays into an uncompressed .npz file format
+ numpy.savez : Save several arrays into an uncompressed ``.npz`` file format
"""
_savez(file, args, kwds, True)
@@ -923,7 +923,8 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
See Also
--------
save : Save an array to a binary file in NumPy ``.npy`` format
- savez : Save several arrays into a ``.npz`` compressed archive
+ savez : Save several arrays into an uncompressed ``.npz`` archive
+ savez_compressed : Save several arrays into a compressed ``.npz`` archive
Notes
-----