diff options
-rw-r--r-- | doc/release/1.8.0-notes.rst | 130 | ||||
-rw-r--r-- | numpy/core/fromnumeric.py | 4 | ||||
-rw-r--r-- | numpy/core/include/numpy/ufuncobject.h | 5 | ||||
-rw-r--r-- | numpy/core/numeric.py | 2 | ||||
-rw-r--r-- | numpy/core/setup_common.py | 1 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.h | 46 | ||||
-rw-r--r-- | numpy/core/src/multiarray/convert_datatype.c | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 1 | ||||
-rw-r--r-- | numpy/core/src/multiarray/nditer_constr.c | 38 | ||||
-rw-r--r-- | numpy/core/src/multiarray/number.c | 20 | ||||
-rw-r--r-- | numpy/core/src/umath/test_rational.c.src | 3 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 15 | ||||
-rw-r--r-- | numpy/core/src/umath/umathmodule.c | 1 | ||||
-rw-r--r-- | numpy/core/tests/test_api.py | 24 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 2 | ||||
-rw-r--r-- | numpy/core/tests/test_numeric.py | 19 | ||||
-rw-r--r-- | numpy/core/tests/test_regression.py | 10 | ||||
-rwxr-xr-x | numpy/f2py/crackfortran.py | 2 | ||||
-rw-r--r-- | numpy/linalg/linalg.py | 11 | ||||
-rw-r--r-- | numpy/linalg/tests/test_linalg.py | 62 | ||||
-rwxr-xr-x | runtests.py | 85 |
21 files changed, 400 insertions, 83 deletions
diff --git a/doc/release/1.8.0-notes.rst b/doc/release/1.8.0-notes.rst index 05d797089..b1adbf87e 100644 --- a/doc/release/1.8.0-notes.rst +++ b/doc/release/1.8.0-notes.rst @@ -385,3 +385,133 @@ deprecated. Previously float indices and function arguments such as axes or shapes were truncated to integers without warning. For example `arr.reshape(3., -1)` or `arr[0.]` will trigger a deprecation warning in NumPy 1.8., and in some future version of NumPy they will raise an error. + + +Authors +======= + +This release contains work by the following people who contributed at least +one patch to this release. The names are in alphabetical order by first name: + +* 87 +* Adam Ginsburg + +* Adam Griffiths + +* Alexander Belopolsky + +* Alex Barth + +* Alex Ford + +* Andreas Hilboll + +* Andreas Kloeckner + +* Andreas Schwab + +* Andrew Horton + +* argriffing + +* Arink Verma + +* Bago Amirbekian + +* Bartosz Telenczuk + +* bebert218 + +* Benjamin Root + +* Bill Spotz + +* Bradley M. Froehle +* Carwyn Pelley + +* Charles Harris +* Chris +* Christian Brueffer + +* Christoph Dann + +* Christoph Gohlke +* Dan Hipschman + +* Daniel + +* Dan Miller + +* daveydave400 + +* David Cournapeau +* David Warde-Farley +* Denis Laxalde +* dmuellner + +* Edward Catmur + +* Egor Zindy + +* endolith +* Eric Firing +* Eric Fode +* Eric Moore + +* Eric Price + +* Fazlul Shahriar + +* Félix Hartmann + +* Fernando Perez +* Frank B + +* Frank Breitling + +* Frederic +* Gabriel +* GaelVaroquaux +* Guillaume Gay + +* Han Genuit +* HaroldMills + +* hklemm + +* jamestwebber + +* Jason Madden + +* Jay Bourque +* jeromekelleher + +* Jesús Gómez + +* jmozmoz + +* jnothman + +* Johannes Schönberger + +* John Benediktsson + +* John Salvatier + +* John Stechschulte + +* Jonathan Waltman + +* Joon Ro + +* Jos de Kloe + +* Joseph Martinot-Lagarde + +* Josh Warner (Mac) + +* Jostein Bø Fløystad + +* Juan Luis Cano Rodríguez + +* Julian Taylor + +* Julien Phalip + +* K.-Michael Aye + +* Kumar Appaiah + +* Lars Buitinck +* Leon Weber + +* Luis Pedro Coelho +* Marcin Juszkiewicz +* Mark Wiebe +* Marten van Kerkwijk + +* Martin Baeuml + +* Martin Spacek +* Martin Teichmann + +* Matt Davis + +* Matthew Brett +* Maximilian Albert + +* m-d-w + +* Michael Droettboom +* mwtoews + +* Nathaniel J. Smith +* Nicolas Scheffer + +* Nils Werner + +* ochoadavid + +* Ondřej Čertík +* ovillellas + +* Paul Ivanov +* Pauli Virtanen +* peterjc +* Ralf Gommers +* Raul Cota + +* Richard Hattersley + +* Robert Costa + +* Robert Kern +* Rob Ruana + +* Ronan Lamy +* Sandro Tosi +* Sascha Peilicke + +* Sebastian Berg +* Skipper Seabold +* Stefan van der Walt +* Steve + +* Takafumi Arakaki + +* Thomas Robitaille + +* Tomas Tomecek + +* Travis E. Oliphant +* Valentin Haenel +* Vladimir Rutsky + +* Warren Weckesser +* Yaroslav Halchenko +* Yury V. Zaytsev + + +A total of 119 people contributed to this release. +People with a "+" by their names contributed a patch for the first time. diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index abfa99e80..152cceb1b 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -615,7 +615,7 @@ def partition(a, kth, axis=-1, kind='introselect', order=None): a = asanyarray(a).flatten() axis = 0 else: - a = asanyarray(a).copy() + a = asanyarray(a).copy(order="K") a.partition(kth, axis=axis, kind=kind, order=order) return a @@ -784,7 +784,7 @@ def sort(a, axis=-1, kind='quicksort', order=None): a = asanyarray(a).flatten() axis = 0 else: - a = asanyarray(a).copy() + a = asanyarray(a).copy(order="K") a.sort(axis, kind, order) return a diff --git a/numpy/core/include/numpy/ufuncobject.h b/numpy/core/include/numpy/ufuncobject.h index 423fbc279..a6307df91 100644 --- a/numpy/core/include/numpy/ufuncobject.h +++ b/numpy/core/include/numpy/ufuncobject.h @@ -258,14 +258,11 @@ typedef struct _tagPyUFuncObject { #define UFUNC_FPE_UNDERFLOW 4 #define UFUNC_FPE_INVALID 8 -/* Error mode that avoids look-up (no checking) */ -#define UFUNC_ERR_DEFAULT 0 - #define UFUNC_OBJ_ISOBJECT 1 #define UFUNC_OBJ_NEEDS_API 2 /* Default user error mode */ -#define UFUNC_ERR_DEFAULT2 \ +#define UFUNC_ERR_DEFAULT \ (UFUNC_ERR_WARN << UFUNC_SHIFT_DIVIDEBYZERO) + \ (UFUNC_ERR_WARN << UFUNC_SHIFT_OVERFLOW) + \ (UFUNC_ERR_WARN << UFUNC_SHIFT_INVALID) diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index f43f93d64..1ed339401 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -2741,7 +2741,7 @@ class errstate(object): def _setdef(): - defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT2, None] + defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None] umath.seterrobj(defval) # set the default values diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 4633aef84..bad3607fa 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -116,7 +116,6 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'), ("__builtin_bswap32", '5u'), ("__builtin_bswap64", '5u'), ("__builtin_expect", '5, 0'), - ("__builtin_ctz", '5'), ("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE ("_mm_load_pd", '(double*)0', "emmintrin.h"), # SSE2 ] diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index 4b23b9442..5d77170ea 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -119,20 +119,10 @@ npy_is_aligned(const void * p, const npy_uintp alignment) */ static NPY_INLINE char * npy_memchr(char * haystack, char needle, - npy_intp stride, npy_intp size, npy_intp * subloopsize, int invert) + npy_intp stride, npy_intp size, npy_intp * psubloopsize, int invert) { char * p = haystack; - char * const end = haystack + size; - if (stride == 0) { - if (!invert) { - p = (*p != needle) ? end : haystack; - } - else { - p = (*p == needle) ? end : haystack; - } - *subloopsize = (p - haystack); - return haystack; - } + npy_intp subloopsize = 0; if (!invert) { /* @@ -140,38 +130,36 @@ npy_memchr(char * haystack, char needle, * performance less important here. * memchr has large setup cost if 0 byte is close to start. */ - while (p < end && *p != needle) { + while (subloopsize < size && *p != needle) { + subloopsize++; p += stride; } } else { /* usually find elements to skip path */ -#if (defined HAVE___BUILTIN_CTZ && defined NPY_CPU_HAVE_UNALIGNED_ACCESS) +#if defined NPY_CPU_HAVE_UNALIGNED_ACCESS if (needle == 0 && stride == 1) { - while (p < end - (size % sizeof(unsigned int))) { + /* iterate until last multiple of 4 */ + char * block_end = haystack + size - (size % sizeof(unsigned int)); + while (p < block_end) { unsigned int v = *(unsigned int*)p; - if (v == 0) { - p += sizeof(unsigned int); - continue; + if (v != 0) { + break; } - p += __builtin_ctz(v) / 8; - *subloopsize = (p - haystack) / stride; - return p; + p += sizeof(unsigned int); } + /* handle rest */ + subloopsize = (p - haystack); } #endif - while (p < end && *p == needle) { + while (subloopsize < size && *p == needle) { + subloopsize++; p += stride; } } - /* division is very expensive */ - if (NPY_LIKELY(stride == 1)) { - *subloopsize = (p - haystack); - } - else { - *subloopsize = (p - haystack) / stride; - } + *psubloopsize = subloopsize; + return p; } diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index a75a1c22e..4f0202ffb 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -1396,7 +1396,7 @@ static int min_scalar_type_num(char *valueptr, int type_num, break; } case NPY_CLONGDOUBLE: { - npy_cdouble value = *(npy_cdouble *)valueptr; + npy_clongdouble value = *(npy_clongdouble *)valueptr; /* if (value.imag == 0) { return min_scalar_type_num((char *)&value.real, diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index ea879c226..a89e27595 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -1548,6 +1548,7 @@ _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order) PyArray_FLAGS(arr), (PyObject *)arr); if (ret == NULL) { + Py_DECREF(arr); return NULL; } /* steals a reference to arr --- so don't increment here */ diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c index 053777f6a..a12457a1e 100644 --- a/numpy/core/src/multiarray/nditer_constr.c +++ b/numpy/core/src/multiarray/nditer_constr.c @@ -1161,11 +1161,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, /* Check the readonly/writeonly flags, and fill in op_itflags */ if (!npyiter_check_per_op_flags(op_flags[iop], &op_itflags[iop])) { - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } /* Extract the operand which is for masked iteration */ @@ -1174,11 +1170,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, PyErr_SetString(PyExc_ValueError, "Only one iterator operand may receive an " "ARRAYMASK flag"); - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } maskop = iop; @@ -1199,11 +1191,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, &op_dtype[iop], flags, op_flags[iop], &op_itflags[iop])) { - for (i = 0; i <= iop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } - return 0; + goto fail_iop; } } @@ -1217,13 +1205,9 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, } } if (all_null) { - for (i = 0; i < nop; ++i) { - Py_XDECREF(op[i]); - Py_XDECREF(op_dtype[i]); - } PyErr_SetString(PyExc_ValueError, "At least one iterator operand must be non-NULL"); - return 0; + goto fail_nop; } } @@ -1232,17 +1216,26 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in, "An iterator operand was flagged as WRITEMASKED, " "but no ARRAYMASK operand was given to supply " "the mask"); - return 0; + goto fail_nop; } else if (!any_writemasked_ops && maskop >= 0) { PyErr_SetString(PyExc_ValueError, "An iterator operand was flagged as the ARRAYMASK, " "but no WRITEMASKED operands were given to use " "the mask"); - return 0; + goto fail_nop; } return 1; + + fail_nop: + iop = nop; + fail_iop: + for (i = 0; i < iop; ++i) { + Py_XDECREF(op[i]); + Py_XDECREF(op_dtype[i]); + } + return 0; } static const char * @@ -1565,6 +1558,7 @@ npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itf NAD_SHAPE(axisdata) = 1; NAD_INDEX(axisdata) = 0; memcpy(NAD_PTRS(axisdata), op_dataptr, NPY_SIZEOF_INTP*nop); + memset(NAD_STRIDES(axisdata), 0, NPY_SIZEOF_INTP*nop); } /* Now process the operands, filling in the axisdata */ diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index 2ad65bbe8..bb281835b 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -771,6 +771,7 @@ array_int(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } @@ -812,6 +813,7 @@ array_float(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_float(pv); @@ -831,14 +833,19 @@ array_long(PyArrayObject *v) return NULL; } pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v); + if (pv == NULL) { + return NULL; + } if (Py_TYPE(pv)->tp_as_number == 0) { PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\ "scalar object is not a number"); + Py_DECREF(pv); return NULL; } if (Py_TYPE(pv)->tp_as_number->nb_long == 0) { PyErr_SetString(PyExc_TypeError, "don't know how to convert "\ "scalar number to long"); + Py_DECREF(pv); return NULL; } /* @@ -849,6 +856,7 @@ array_long(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_long(pv); @@ -866,14 +874,19 @@ array_oct(PyArrayObject *v) return NULL; } pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v); + if (pv == NULL) { + return NULL; + } if (Py_TYPE(pv)->tp_as_number == 0) { PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\ "scalar object is not a number"); + Py_DECREF(pv); return NULL; } if (Py_TYPE(pv)->tp_as_number->nb_oct == 0) { PyErr_SetString(PyExc_TypeError, "don't know how to convert "\ "scalar number to oct"); + Py_DECREF(pv); return NULL; } /* @@ -884,6 +897,7 @@ array_oct(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_oct(pv); @@ -901,14 +915,19 @@ array_hex(PyArrayObject *v) return NULL; } pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v); + if (pv == NULL) { + return NULL; + } if (Py_TYPE(pv)->tp_as_number == 0) { PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\ "scalar object is not a number"); + Py_DECREF(pv); return NULL; } if (Py_TYPE(pv)->tp_as_number->nb_hex == 0) { PyErr_SetString(PyExc_TypeError, "don't know how to convert "\ "scalar number to hex"); + Py_DECREF(pv); return NULL; } /* @@ -919,6 +938,7 @@ array_hex(PyArrayObject *v) PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) { PyErr_SetString(PyExc_TypeError, "object array may be self-referencing"); + Py_DECREF(pv); return NULL; } pv2 = Py_TYPE(pv)->tp_as_number->nb_hex(pv); diff --git a/numpy/core/src/umath/test_rational.c.src b/numpy/core/src/umath/test_rational.c.src index 1650dd1d3..d8f90f9e5 100644 --- a/numpy/core/src/umath/test_rational.c.src +++ b/numpy/core/src/umath/test_rational.c.src @@ -1242,12 +1242,15 @@ PyMODINIT_FUNC inittest_rational(void) { PyErr_Format(PyExc_AssertionError, \ "ufunc %s takes %d arguments, our loop takes %ld", \ #name, ufunc->nargs, sizeof(_types)/sizeof(int)); \ + Py_DECREF(ufunc); \ goto fail; \ } \ if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \ rational_ufunc_##name, _types, 0) < 0) { \ + Py_DECREF(ufunc); \ goto fail; \ } \ + Py_DECREF(ufunc); \ } #define REGISTER_UFUNC_BINARY_RATIONAL(name) \ REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational}) diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index e419a6611..a47d9a96c 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -432,10 +432,17 @@ _extract_pyvals(PyObject *ref, char *name, int *bufsize, { PyObject *retval; + /* default errobj case, skips dictionary lookup */ if (ref == NULL) { - *errmask = UFUNC_ERR_DEFAULT; - *errobj = Py_BuildValue("NO", PyBytes_FromString(name), Py_None); - *bufsize = NPY_BUFSIZE; + if (errmask) { + *errmask = UFUNC_ERR_DEFAULT; + } + if (errobj) { + *errobj = Py_BuildValue("NO", PyBytes_FromString(name), Py_None); + } + if (bufsize) { + *bufsize = NPY_BUFSIZE; + } return 0; } @@ -5076,7 +5083,7 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args) } else { Py_INCREF(PyArray_DESCR(op1_array)); - array_operands[2] = new_array_op(op1_array, iter->dataptr); + array_operands[1] = new_array_op(op1_array, iter->dataptr); array_operands[2] = NULL; } diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c index 0b789de26..8c95cebf5 100644 --- a/numpy/core/src/umath/umathmodule.c +++ b/numpy/core/src/umath/umathmodule.c @@ -403,7 +403,6 @@ PyMODINIT_FUNC initumath(void) ADDCONST(ERR_PRINT); ADDCONST(ERR_LOG); ADDCONST(ERR_DEFAULT); - ADDCONST(ERR_DEFAULT2); ADDCONST(SHIFT_DIVIDEBYZERO); ADDCONST(SHIFT_OVERFLOW); diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py index d642a2237..a1a3f896c 100644 --- a/numpy/core/tests/test_api.py +++ b/numpy/core/tests/test_api.py @@ -122,13 +122,13 @@ def test_array_array(): # Try with lists... assert_equal(np.array([None] * 10, dtype=np.float64), - np.empty((10,), dtype=np.float64) + np.nan) + np.full((10,), np.nan, dtype=np.float64)) assert_equal(np.array([[None]] * 10, dtype=np.float64), - np.empty((10, 1), dtype=np.float64) + np.nan) + np.full((10, 1), np.nan, dtype=np.float64)) assert_equal(np.array([[None] * 10], dtype=np.float64), - np.empty((1, 10), dtype=np.float64) + np.nan) + np.full((1, 10), np.nan, dtype=np.float64)) assert_equal(np.array([[None] * 10] * 10, dtype=np.float64), - np.empty((10, 10), dtype=np.float64) + np.nan) + np.full((10, 10), np.nan, dtype=np.float64)) assert_equal(np.array([1.0] * 10, dtype=np.float64), np.ones((10,), dtype=np.float64)) @@ -141,13 +141,13 @@ def test_array_array(): # Try with tuples assert_equal(np.array((None,) * 10, dtype=np.float64), - np.empty((10,), dtype=np.float64) + np.nan) + np.full((10,), np.nan, dtype=np.float64)) assert_equal(np.array([(None,)] * 10, dtype=np.float64), - np.empty((10, 1), dtype=np.float64) + np.nan) + np.full((10, 1), np.nan, dtype=np.float64)) assert_equal(np.array([(None,) * 10], dtype=np.float64), - np.empty((1, 10), dtype=np.float64) + np.nan) + np.full((1, 10), np.nan, dtype=np.float64)) assert_equal(np.array([(None,) * 10] * 10, dtype=np.float64), - np.empty((10, 10), dtype=np.float64) + np.nan) + np.full((10, 10), np.nan, dtype=np.float64)) assert_equal(np.array((1.0,) * 10, dtype=np.float64), np.ones((10,), dtype=np.float64)) @@ -332,6 +332,14 @@ def test_copyto(): assert_raises(TypeError, np.copyto, [1, 2, 3], [2, 3, 4]) def test_copyto_permut(): + # test explicit overflow case + pad = 500 + l = [True] * pad + [True, True, True, True] + r = np.zeros(len(l)-pad) + d = np.ones(len(l)-pad) + mask = np.array(l)[pad:] + np.copyto(r, d, where=mask[::-1]) + # test all permutation of possible masks, 9 should be sufficient for # current 4 byte unrolled code power = 9 diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 9f333a4a2..9d191da35 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -1624,7 +1624,7 @@ class TestBinop(object): # Check behavior against both bare ndarray objects and a # ndarray subclasses with and without their own override - obj = cls((1,)) + obj = cls((1,), buffer=np.ones(1,)) arr_objs = [np.array([1]), np.array([2]).view(OtherNdarraySubclass), diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index 5a3de8edd..ac341468c 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -8,6 +8,7 @@ import itertools import numpy as np from numpy.core import * +from numpy.core import umath from numpy.random import rand, randint, randn from numpy.testing import * from numpy.core.multiarray import dot as dot_ @@ -439,6 +440,24 @@ class TestSeterr(TestCase): np.seterrobj(olderrobj) del self.called + def test_errobj_noerrmask(self): + # errmask = 0 has a special code path for the default + olderrobj = np.geterrobj() + try: + # set errobj to something non default + np.seterrobj([umath.UFUNC_BUFSIZE_DEFAULT, + umath.ERR_DEFAULT + 1, None]) + #call a ufunc + np.isnan(np.array([6])) + # same with the default, lots of times to get rid of possible + # pre-existing stack in the code + for i in range(10000): + np.seterrobj([umath.UFUNC_BUFSIZE_DEFAULT, umath.ERR_DEFAULT, + None]) + np.isnan(np.array([6])) + finally: + np.seterrobj(olderrobj) + class TestFloatExceptions(TestCase): def assert_raises_fpe(self, fpeerr, flop, x, y): diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index 02cf1b8df..b98746e1b 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -1654,6 +1654,14 @@ class TestRegression(TestCase): assert_raises(TypeError, oct, a) assert_raises(TypeError, hex, a) + # Test the same for a circular reference. + b = np.array(a, dtype=object) + a[()] = b + assert_raises(TypeError, int, a) + # Numpy has no tp_traverse currently, so circular references + # cannot be detected. So resolve it: + a[()] = 0 + # This was causing a to become like the above a = np.array(0, dtype=object) a[...] += 1 @@ -1661,7 +1669,7 @@ class TestRegression(TestCase): def test_object_array_self_copy(self): # An object array being copied into itself DECREF'ed before INCREF'ing - # causing segmentation faults (gh-3787) + # causing segmentation faults (gh-3787) a = np.array(object(), dtype=object) np.copyto(a, a) assert_equal(sys.getrefcount(a[()]), 2) diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 34b6192e4..d0d8aa8fa 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -2402,7 +2402,7 @@ def expr2name(a, block, args=[]): na='e_' for c in a: c = c.lower() - if c not in string.lowercase+string.digits: c='_' + if c not in string.ascii_lowercase+string.digits: c='_' na=na+c if na[-1]=='_': na=na+'e' else: na=na+'_e' diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index aa3bdea34..1b82c7cc0 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -914,7 +914,7 @@ def eigvalsh(a, UPLO='L'): A complex- or real-valued matrix whose eigenvalues are to be computed. UPLO : {'L', 'U'}, optional - Same as `lower`, wth 'L' for lower and 'U' for upper triangular. + Same as `lower`, with 'L' for lower and 'U' for upper triangular. Deprecated. Returns @@ -950,6 +950,9 @@ def eigvalsh(a, UPLO='L'): array([ 0.17157288+0.j, 5.82842712+0.j]) """ + UPLO = UPLO.upper() + if UPLO not in ('L', 'U'): + raise ValueError("UPLO argument must be 'L' or 'U'") extobj = get_linalg_error_extobj( _raise_linalgerror_eigenvalues_nonconvergence) @@ -1194,7 +1197,9 @@ def eigh(a, UPLO='L'): [ 0.00000000+0.38268343j, 0.00000000-0.92387953j]]) """ - UPLO = asbytes(UPLO) + UPLO = UPLO.upper() + if UPLO not in ('L', 'U'): + raise ValueError("UPLO argument must be 'L' or 'U'") a, wrap = _makearray(a) _assertRankAtLeast2(a) @@ -1203,7 +1208,7 @@ def eigh(a, UPLO='L'): extobj = get_linalg_error_extobj( _raise_linalgerror_eigenvalues_nonconvergence) - if 'L' == UPLO: + if UPLO == 'L': gufunc = _umath_linalg.eigh_lo else: gufunc = _umath_linalg.eigh_up diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index d40157904..dd4cbcc4f 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -50,7 +50,7 @@ def get_complex_dtype(dtype): def get_rtol(dtype): # Choose a safe rtol - if dtype in (np.single, csingle): + if dtype in (single, csingle): return 1e-5 else: return 1e-11 @@ -616,7 +616,7 @@ class TestLstsq(LinalgTestCase, LinalgNonsquareTestCase): expect_resids.shape = (1,) assert_equal(residuals.shape, expect_resids.shape) else: - expect_resids = type(x)([]) + expect_resids = np.array([]).view(type(x)) assert_almost_equal(residuals, expect_resids) assert_(np.issubdtype(residuals.dtype, np.floating)) assert_(imply(isinstance(b, matrix), isinstance(x, matrix))) @@ -707,6 +707,34 @@ class TestEigvalsh(HermitianTestCase, HermitianGeneralizedTestCase): for dtype in [single, double, csingle, cdouble]: yield check, dtype + def test_invalid(self): + x = np.array([[1, 0.5], [0.5, 1]], dtype=np.float32) + assert_raises(ValueError, np.linalg.eigvalsh, x, UPLO="lrong") + assert_raises(ValueError, np.linalg.eigvalsh, x, "lower") + assert_raises(ValueError, np.linalg.eigvalsh, x, "upper") + + def test_UPLO(self): + Klo = np.array([[0, 0],[1, 0]], dtype=np.double) + Kup = np.array([[0, 1],[0, 0]], dtype=np.double) + tgt = np.array([-1, 1], dtype=np.double) + rtol = get_rtol(np.double) + + # Check default is 'L' + w = np.linalg.eigvalsh(Klo) + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'L' + w = np.linalg.eigvalsh(Klo, UPLO='L') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'l' + w = np.linalg.eigvalsh(Klo, UPLO='l') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'U' + w = np.linalg.eigvalsh(Kup, UPLO='U') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'u' + w = np.linalg.eigvalsh(Kup, UPLO='u') + assert_allclose(np.sort(w), tgt, rtol=rtol) + class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase): def do(self, a, b): @@ -728,7 +756,7 @@ class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase): assert_allclose(dot_generalized(a, evc2), np.asarray(ev2)[...,None,:] * np.asarray(evc2), - rtol=get_rtol(ev.dtype)) + rtol=get_rtol(ev.dtype), err_msg=repr(a)) def test_types(self): def check(dtype): @@ -739,6 +767,34 @@ class TestEigh(HermitianTestCase, HermitianGeneralizedTestCase): for dtype in [single, double, csingle, cdouble]: yield check, dtype + def test_invalid(self): + x = np.array([[1, 0.5], [0.5, 1]], dtype=np.float32) + assert_raises(ValueError, np.linalg.eigh, x, UPLO="lrong") + assert_raises(ValueError, np.linalg.eigh, x, "lower") + assert_raises(ValueError, np.linalg.eigh, x, "upper") + + def test_UPLO(self): + Klo = np.array([[0, 0],[1, 0]], dtype=np.double) + Kup = np.array([[0, 1],[0, 0]], dtype=np.double) + tgt = np.array([-1, 1], dtype=np.double) + rtol = get_rtol(np.double) + + # Check default is 'L' + w, v = np.linalg.eigh(Klo) + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'L' + w, v = np.linalg.eigh(Klo, UPLO='L') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'l' + w, v = np.linalg.eigh(Klo, UPLO='l') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'U' + w, v = np.linalg.eigh(Kup, UPLO='U') + assert_allclose(np.sort(w), tgt, rtol=rtol) + # Check 'u' + w, v = np.linalg.eigh(Kup, UPLO='u') + assert_allclose(np.sort(w), tgt, rtol=rtol) + class _TestNorm(object): diff --git a/runtests.py b/runtests.py index c50de3b37..738cd7769 100755 --- a/runtests.py +++ b/runtests.py @@ -12,6 +12,16 @@ Examples:: $ python runtests.py --ipython $ python runtests.py --python somescript.py +Run a debugger: + + $ gdb --args python runtests.py [...other args...] + +Generate C code coverage listing under build/lcov/: +(requires http://ltp.sourceforge.net/coverage/lcov.php) + + $ python runtests.py --gcov [...other args...] + $ python runtests.py --lcov-html + """ # @@ -64,6 +74,13 @@ def main(argv): parser.add_argument("--coverage", action="store_true", default=False, help=("report coverage of project code. HTML output goes " "under build/coverage")) + parser.add_argument("--gcov", action="store_true", default=False, + help=("enable C code coverage via gcov (requires GCC). " + "gcov output goes to build/**/*.gc*")) + parser.add_argument("--lcov-html", action="store_true", default=False, + help=("produce HTML for C code coverage information " + "from a previous run with --gcov. " + "HTML output goes to build/lcov/")) parser.add_argument("--mode", "-m", default="fast", help="'fast', 'full', or something that could be " "passed to nosetests -A [default: fast]") @@ -87,10 +104,18 @@ def main(argv): help="Arguments to pass to Nose, Python or shell") args = parser.parse_args(argv) + if args.lcov_html: + # generate C code coverage output + lcov_generate() + sys.exit(0) + if args.pythonpath: for p in reversed(args.pythonpath.split(os.pathsep)): sys.path.insert(0, p) + if args.gcov: + gcov_reset_counters() + if not args.no_build: site_dir = build_project(args) sys.path.insert(0, site_dir) @@ -194,6 +219,7 @@ def main(argv): else: sys.exit(1) + def build_project(args): """ Build a dev version of the project. @@ -220,10 +246,21 @@ def build_project(args): # Always use ccache, if installed env['PATH'] = os.pathsep.join(EXTRA_PATH + env.get('PATH', '').split(os.pathsep)) - if args.debug: + if args.debug or args.gcov: # assume everyone uses gcc/gfortran env['OPT'] = '-O0 -ggdb' env['FOPT'] = '-O0 -ggdb' + if args.gcov: + import distutils.sysconfig + cvars = distutils.sysconfig.get_config_vars() + env['OPT'] = '-O0 -ggdb' + env['FOPT'] = '-O0 -ggdb' + env['CC'] = cvars['CC'] + ' --coverage' + env['CXX'] = cvars['CXX'] + ' --coverage' + env['F77'] = 'gfortran --coverage ' + env['F90'] = 'gfortran --coverage ' + env['LDSHARED'] = cvars['LDSHARED'] + ' --coverage' + env['LDFLAGS'] = " ".join(cvars['LDSHARED'].split()[1:]) + ' --coverage' cmd += ["build"] cmd += ['install', '--prefix=' + dst_dir] @@ -270,6 +307,52 @@ def build_project(args): return site_dir + +# +# GCOV support +# +def gcov_reset_counters(): + print("Removing previous GCOV .gcda files...") + build_dir = os.path.join(ROOT_DIR, 'build') + for dirpath, dirnames, filenames in os.walk(build_dir): + for fn in filenames: + if fn.endswith('.gcda') or fn.endswith('.da'): + pth = os.path.join(dirpath, fn) + os.unlink(pth) + +# +# LCOV support +# + +LCOV_OUTPUT_FILE = os.path.join(ROOT_DIR, 'build', 'lcov.out') +LCOV_HTML_DIR = os.path.join(ROOT_DIR, 'build', 'lcov') + +def lcov_generate(): + try: os.unlink(LCOV_OUTPUT_FILE) + except OSError: pass + try: shutil.rmtree(LCOV_HTML_DIR) + except OSError: pass + + print("Capturing lcov info...") + subprocess.call(['lcov', '-q', '-c', + '-d', os.path.join(ROOT_DIR, 'build'), + '-b', ROOT_DIR, + '--output-file', LCOV_OUTPUT_FILE]) + + print("Generating lcov HTML output...") + ret = subprocess.call(['genhtml', '-q', LCOV_OUTPUT_FILE, + '--output-directory', LCOV_HTML_DIR, + '--legend', '--highlight']) + if ret != 0: + print("genhtml failed!") + else: + print("HTML output generated under build/lcov/") + + +# +# Python 3 support +# + if sys.version_info[0] >= 3: import builtins exec_ = getattr(builtins, "exec") |