summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/_add_newdocs.py147
-rw-r--r--numpy/core/_internal.py2
-rw-r--r--numpy/core/code_generators/ufunc_docstrings.py4
-rw-r--r--numpy/core/fromnumeric.py23
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h4
-rw-r--r--numpy/core/multiarray.py18
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c173
-rw-r--r--numpy/core/src/multiarray/convert_datatype.h4
-rw-r--r--numpy/core/src/multiarray/dragon4.c38
-rw-r--r--numpy/core/src/multiarray/dragon4.h38
-rw-r--r--numpy/core/src/multiarray/item_selection.c20
-rw-r--r--numpy/core/src/npysort/radixsort.c.src10
-rw-r--r--numpy/core/src/umath/ufunc_object.c4
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c72
-rw-r--r--numpy/core/tests/test_api.py12
-rw-r--r--numpy/core/tests/test_deprecations.py7
-rw-r--r--numpy/core/tests/test_dtype.py16
-rw-r--r--numpy/core/tests/test_nditer.py2
-rw-r--r--numpy/core/tests/test_numeric.py53
19 files changed, 451 insertions, 196 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index 9f2b67a6b..84339ef23 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -936,11 +936,11 @@ add_newdoc('numpy.core.multiarray', 'empty',
--------
>>> np.empty([2, 2])
array([[ -9.74499359e+001, 6.69583040e-309],
- [ 2.13182611e-314, 3.06959433e-309]]) #random
+ [ 2.13182611e-314, 3.06959433e-309]]) #uninitialized
>>> np.empty([2, 2], dtype=int)
array([[-1073741821, -1067949133],
- [ 496041986, 19249760]]) #random
+ [ 496041986, 19249760]]) #uninitialized
""")
@@ -1041,9 +1041,14 @@ add_newdoc('numpy.core.multiarray', 'fromstring',
elements is also ignored.
.. deprecated:: 1.14
- If this argument is not provided, `fromstring` falls back on the
- behaviour of `frombuffer` after encoding unicode string inputs as
- either utf-8 (python 3), or the default encoding (python 2).
+ Passing ``sep=''``, the default, is deprecated since it will
+ trigger the deprecated binary mode of this function. This mode
+ interprets `string` as binary bytes, rather than ASCII text with
+ decimal numbers, an operation which is better spelt
+ ``frombuffer(string, dtype, count)``. If `string` contains unicode
+ text, the binary mode of `fromstring` will first encode it into
+ bytes using either utf-8 (python 3) or the default encoding
+ (python 2), neither of which produce sane results.
Returns
-------
@@ -2699,10 +2704,15 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('astype',
Notes
-----
- Starting in NumPy 1.9, astype method now returns an error if the string
- dtype to cast to is not long enough in 'safe' casting mode to hold the max
- value of integer/float array that is being casted. Previously the casting
- was allowed even if the result was truncated.
+ .. versionchanged:: 1.17.0
+ Casting between a simple data type and a structured one is possible only
+ for "unsafe" casting. Casting to multiple fields is allowed, but
+ casting from multiple fields is not.
+
+ .. versionchanged:: 1.9.0
+ Casting from numeric to string types in 'safe' casting mode requires
+ that the string dtype length is long enough to store the max
+ integer/float value converted.
Raises
------
@@ -5385,6 +5395,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('alignment',
More information is available in the C-API section of the manual.
+ Examples
+ --------
+
+ >>> x = np.dtype('i4')
+ >>> x.alignment
+ 4
+
+ >>> x = np.dtype(float)
+ >>> x.alignment
+ 8
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('byteorder',
@@ -5431,7 +5452,16 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('byteorder',
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('char',
- """A unique character code for each of the 21 different built-in types."""))
+ """A unique character code for each of the 21 different built-in types.
+
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.char
+ 'd'
+
+ """))
add_newdoc('numpy.core.multiarray', 'dtype', ('descr',
"""
@@ -5442,6 +5472,18 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('descr',
Warning: This attribute exists specifically for `__array_interface__`,
and is not a datatype description compatible with `np.dtype`.
+
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.descr
+ [('', '<f8')]
+
+ >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
+ >>> dt.descr
+ [('name', '<U16'), ('grades', '<f8', (2,))]
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('fields',
@@ -5482,6 +5524,18 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('flags',
of these flags is in C-API documentation; they are largely useful
for user-defined data-types.
+ The following example demonstrates that operations on this particular
+ dtype requires Python C-API.
+
+ Examples
+ --------
+
+ >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)])
+ >>> x.flags
+ 16
+ >>> np.core.multiarray.NEEDS_PYAPI
+ 16
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('hasobject',
@@ -5539,6 +5593,7 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('isalignedstruct',
field alignment. This flag is sticky, so when combining multiple
structs together, it is preserved and produces new dtypes which
are also aligned.
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('itemsize',
@@ -5548,6 +5603,19 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('itemsize',
For 18 of the 21 types this number is fixed by the data-type.
For the flexible data-types, this number can be anything.
+ Examples
+ --------
+
+ >>> arr = np.array([[1, 2], [3, 4]])
+ >>> arr.dtype
+ dtype('int64')
+ >>> arr.itemsize
+ 8
+
+ >>> dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
+ >>> dt.itemsize
+ 80
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('kind',
@@ -5568,6 +5636,19 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('kind',
V void
= ======================
+ Examples
+ --------
+
+ >>> dt = np.dtype('i4')
+ >>> dt.kind
+ 'i'
+ >>> dt = np.dtype('f8')
+ >>> dt.kind
+ 'f'
+ >>> dt = np.dtype([('field1', 'f8')])
+ >>> dt.kind
+ 'V'
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('name',
@@ -5576,6 +5657,16 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('name',
Un-sized flexible data-type objects do not have this attribute.
+ Examples
+ --------
+
+ >>> x = np.dtype(float)
+ >>> x.name
+ 'float64'
+ >>> x = np.dtype([('a', np.int32, 8), ('b', np.float64, 6)])
+ >>> x.name
+ 'void640'
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('names',
@@ -5599,6 +5690,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('num',
These are roughly ordered from least-to-most precision.
+ Examples
+ --------
+
+ >>> dt = np.dtype(str)
+ >>> dt.num
+ 19
+
+ >>> dt = np.dtype(float)
+ >>> dt.num
+ 12
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('shape',
@@ -5606,6 +5708,17 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('shape',
Shape tuple of the sub-array if this data type describes a sub-array,
and ``()`` otherwise.
+ Examples
+ --------
+
+ >>> dt = np.dtype(('i4', 4))
+ >>> dt.shape
+ (4,)
+
+ >>> dt = np.dtype(('i4', (2, 3)))
+ >>> dt.shape
+ (2, 3)
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('ndim',
@@ -5615,6 +5728,20 @@ add_newdoc('numpy.core.multiarray', 'dtype', ('ndim',
.. versionadded:: 1.13.0
+ Examples
+ --------
+ >>> x = np.dtype(float)
+ >>> x.ndim
+ 0
+
+ >>> x = np.dtype((float, 8))
+ >>> x.ndim
+ 1
+
+ >>> x = np.dtype(('i4', (3, 4)))
+ >>> x.ndim
+ 2
+
"""))
add_newdoc('numpy.core.multiarray', 'dtype', ('str',
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py
index ab5a64a1a..c70718cb6 100644
--- a/numpy/core/_internal.py
+++ b/numpy/core/_internal.py
@@ -146,7 +146,7 @@ def _reconstruct(subtype, shape, dtype):
# format_re was originally from numarray by J. Todd Miller
format_re = re.compile(br'(?P<order1>[<>|=]?)'
- br'(?P<repeats> *[(]?[ ,0-9L]*[)]? *)'
+ br'(?P<repeats> *[(]?[ ,0-9]*[)]? *)'
br'(?P<order2>[<>|=]?)'
br'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')
sep_re = re.compile(br'\s*,\s*')
diff --git a/numpy/core/code_generators/ufunc_docstrings.py b/numpy/core/code_generators/ufunc_docstrings.py
index 2a5646bd7..fb418aadc 100644
--- a/numpy/core/code_generators/ufunc_docstrings.py
+++ b/numpy/core/code_generators/ufunc_docstrings.py
@@ -2601,8 +2601,8 @@ add_newdoc('numpy.core.umath', 'matmul',
For other keyword-only arguments, see the
:ref:`ufunc docs <ufuncs.kwargs>`.
- ..versionadded:: 1.16
- Now handles ufunc kwargs
+ .. versionadded:: 1.16
+ Now handles ufunc kwargs
Returns
-------
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index f262f8552..08f17aae4 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1764,17 +1764,17 @@ def nonzero(a):
Returns a tuple of arrays, one for each dimension of `a`,
containing the indices of the non-zero elements in that
dimension. The values in `a` are always tested and returned in
- row-major, C-style order. The corresponding non-zero
- values can be obtained with::
+ row-major, C-style order.
- a[nonzero(a)]
+ To group the indices by element, rather than dimension, use `argwhere`,
+ which returns a row for each non-zero element.
- To group the indices by element, rather than dimension, use::
-
- transpose(nonzero(a))
+ .. note::
+ When called on a zero-d array or scalar, ``nonzero(a)`` is treated
+ as ``nonzero(atleast1d(a))``.
- The result of this is always a 2-D array, with a row for
- each non-zero element.
+ ..deprecated:: 1.17.0
+ Use `atleast1d` explicitly if this behavior is deliberate.
Parameters
----------
@@ -1795,11 +1795,12 @@ def nonzero(a):
Equivalent ndarray method.
count_nonzero :
Counts the number of non-zero elements in the input array.
-
+
Notes
-----
- To obtain the non-zero values, it is recommended to use ``x[x.astype(bool)]``
- which will correctly handle 0-d arrays.
+ While the nonzero values can be obtained with ``a[nonzero(a)]``, it is
+ recommended to use ``x[x.astype(bool)]`` or ``x[x != 0]`` instead, which
+ will correctly handle 0-d arrays.
Examples
--------
diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h
index 45f008b1d..2cc7ced35 100644
--- a/numpy/core/include/numpy/ndarrayobject.h
+++ b/numpy/core/include/numpy/ndarrayobject.h
@@ -233,10 +233,10 @@ static NPY_INLINE int
NPY_TITLE_KEY_check(PyObject *key, PyObject *value)
{
PyObject *title;
- if (PyTuple_GET_SIZE(value) != 3) {
+ if (PyTuple_Size(value) != 3) {
return 0;
}
- title = PyTuple_GET_ITEM(value, 2);
+ title = PyTuple_GetItem(value, 2);
if (key == title) {
return 1;
}
diff --git a/numpy/core/multiarray.py b/numpy/core/multiarray.py
index 8006dd9b5..4f2c5b78e 100644
--- a/numpy/core/multiarray.py
+++ b/numpy/core/multiarray.py
@@ -128,11 +128,11 @@ def empty_like(prototype, dtype=None, order=None, subok=None, shape=None):
--------
>>> a = ([1,2,3], [4,5,6]) # a is array-like
>>> np.empty_like(a)
- array([[-1073741821, -1073741821, 3], # random
+ array([[-1073741821, -1073741821, 3], # uninitialized
[ 0, 0, -1073741821]])
>>> a = np.array([[1., 2., 3.],[4.,5.,6.]])
>>> np.empty_like(a)
- array([[ -2.00000715e+000, 1.48219694e-323, -2.00000572e+000], # random
+ array([[ -2.00000715e+000, 1.48219694e-323, -2.00000572e+000], # uninitialized
[ 4.38791518e-305, -2.00000715e+000, 4.17269252e-309]])
"""
@@ -496,11 +496,15 @@ def can_cast(from_, to, casting=None):
Notes
-----
- Starting in NumPy 1.9, can_cast function now returns False in 'safe'
- casting mode for integer/float dtype and string dtype if the string dtype
- length is not long enough to store the max integer/float value converted
- to a string. Previously can_cast in 'safe' mode returned True for
- integer/float dtype and a string dtype of any length.
+ .. versionchanged:: 1.17.0
+ Casting between a simple data type and a structured one is possible only
+ for "unsafe" casting. Casting to multiple fields is allowed, but
+ casting from multiple fields is not.
+
+ .. versionchanged:: 1.9.0
+ Casting from numeric to string types in 'safe' casting mode requires
+ that the string dtype length is long enough to store the maximum
+ integer/float value converted.
See also
--------
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index c59979e75..025c66013 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -679,15 +679,82 @@ NPY_NO_EXPORT npy_bool
PyArray_CanCastTypeTo(PyArray_Descr *from, PyArray_Descr *to,
NPY_CASTING casting)
{
- /* Fast path for unsafe casts or basic types */
- if (casting == NPY_UNSAFE_CASTING ||
- (NPY_LIKELY(from->type_num < NPY_OBJECT) &&
- NPY_LIKELY(from->type_num == to->type_num) &&
- NPY_LIKELY(from->byteorder == to->byteorder))) {
+ /*
+ * Fast paths for equality and for basic types.
+ */
+ if (from == to ||
+ ((NPY_LIKELY(PyDataType_ISNUMBER(from)) ||
+ PyDataType_ISOBJECT(from)) &&
+ NPY_LIKELY(from->type_num == to->type_num) &&
+ NPY_LIKELY(from->byteorder == to->byteorder))) {
return 1;
}
- /* Equivalent types can be cast with any value of 'casting' */
- else if (PyArray_EquivTypenums(from->type_num, to->type_num)) {
+ /*
+ * Cases with subarrays and fields need special treatment.
+ */
+ if (PyDataType_HASFIELDS(from)) {
+ /*
+ * If from is a structured data type, then it can be cast to a simple
+ * non-object one only for unsafe casting *and* if it has a single
+ * field; recurse just in case the single field is itself structured.
+ */
+ if (!PyDataType_HASFIELDS(to) && !PyDataType_ISOBJECT(to)) {
+ if (casting == NPY_UNSAFE_CASTING &&
+ PyDict_Size(from->fields) == 1) {
+ Py_ssize_t ppos = 0;
+ PyObject *tuple;
+ PyArray_Descr *field;
+ PyDict_Next(from->fields, &ppos, NULL, &tuple);
+ field = (PyArray_Descr *)PyTuple_GET_ITEM(tuple, 0);
+ /*
+ * For a subarray, we need to get the underlying type;
+ * since we already are casting unsafely, we can ignore
+ * the shape.
+ */
+ if (PyDataType_HASSUBARRAY(field)) {
+ field = field->subarray->base;
+ }
+ return PyArray_CanCastTypeTo(field, to, casting);
+ }
+ else {
+ return 0;
+ }
+ }
+ /*
+ * Casting from one structured data type to another depends on the fields;
+ * we pass that case on to the EquivTypenums case below.
+ *
+ * TODO: move that part up here? Need to check whether equivalent type
+ * numbers is an addition constraint that is needed.
+ *
+ * TODO/FIXME: For now, always allow structured to structured for unsafe
+ * casting; this is not correct, but needed since the treatment in can_cast
+ * below got out of sync with astype; see gh-13667.
+ */
+ if (casting == NPY_UNSAFE_CASTING) {
+ return 1;
+ }
+ }
+ else if (PyDataType_HASFIELDS(to)) {
+ /*
+ * If "from" is a simple data type and "to" has fields, then only
+ * unsafe casting works (and that works always, even to multiple fields).
+ */
+ return casting == NPY_UNSAFE_CASTING;
+ }
+ /*
+ * Everything else we consider castable for unsafe for now.
+ * FIXME: ensure what we do here is consistent with "astype",
+ * i.e., deal more correctly with subarrays and user-defined dtype.
+ */
+ else if (casting == NPY_UNSAFE_CASTING) {
+ return 1;
+ }
+ /*
+ * Equivalent simple types can be cast with any value of 'casting', but
+ * we need to be careful about structured to structured.
+ */
+ if (PyArray_EquivTypenums(from->type_num, to->type_num)) {
/* For complicated case, use EquivTypes (for now) */
if (PyTypeNum_ISUSERDEF(from->type_num) ||
from->subarray != NULL) {
@@ -1700,46 +1767,22 @@ dtype_kind_to_simplified_ordering(char kind)
}
}
-/*NUMPY_API
- * Produces the result type of a bunch of inputs, using the UFunc
- * type promotion rules. Use this function when you have a set of
- * input arrays, and need to determine an output array dtype.
- *
- * If all the inputs are scalars (have 0 dimensions) or the maximum "kind"
- * of the scalars is greater than the maximum "kind" of the arrays, does
- * a regular type promotion.
- *
- * Otherwise, does a type promotion on the MinScalarType
- * of all the inputs. Data types passed directly are treated as array
- * types.
- *
+
+/*
+ * Determine if there is a mix of scalars and arrays/dtypes.
+ * If this is the case, the scalars should be handled as the minimum type
+ * capable of holding the value when the maximum "category" of the scalars
+ * surpasses the maximum "category" of the arrays/dtypes.
+ * If the scalars are of a lower or same category as the arrays, they may be
+ * demoted to a lower type within their category (the lowest type they can
+ * be cast to safely according to scalar casting rules).
*/
-NPY_NO_EXPORT PyArray_Descr *
-PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
- npy_intp ndtypes, PyArray_Descr **dtypes)
+NPY_NO_EXPORT int
+should_use_min_scalar(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes)
{
- npy_intp i;
- int use_min_scalar;
+ int use_min_scalar = 0;
- /* If there's just one type, pass it through */
- if (narrs + ndtypes == 1) {
- PyArray_Descr *ret = NULL;
- if (narrs == 1) {
- ret = PyArray_DESCR(arr[0]);
- }
- else {
- ret = dtypes[0];
- }
- Py_INCREF(ret);
- return ret;
- }
-
- /*
- * Determine if there are any scalars, and if so, whether
- * the maximum "kind" of the scalars surpasses the maximum
- * "kind" of the arrays
- */
- use_min_scalar = 0;
if (narrs > 0) {
int all_scalars;
int max_scalar_kind = -1;
@@ -1748,7 +1791,7 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
all_scalars = (ndtypes > 0) ? 0 : 1;
/* Compute the maximum "kinds" and whether everything is scalar */
- for (i = 0; i < narrs; ++i) {
+ for (npy_intp i = 0; i < narrs; ++i) {
if (PyArray_NDIM(arr[i]) == 0) {
int kind = dtype_kind_to_simplified_ordering(
PyArray_DESCR(arr[i])->kind);
@@ -1769,7 +1812,7 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
* If the max scalar kind is bigger than the max array kind,
* finish computing the max array kind
*/
- for (i = 0; i < ndtypes; ++i) {
+ for (npy_intp i = 0; i < ndtypes; ++i) {
int kind = dtype_kind_to_simplified_ordering(dtypes[i]->kind);
if (kind > max_array_kind) {
max_array_kind = kind;
@@ -1781,6 +1824,44 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
use_min_scalar = 1;
}
}
+ return use_min_scalar;
+}
+
+
+/*NUMPY_API
+ * Produces the result type of a bunch of inputs, using the UFunc
+ * type promotion rules. Use this function when you have a set of
+ * input arrays, and need to determine an output array dtype.
+ *
+ * If all the inputs are scalars (have 0 dimensions) or the maximum "kind"
+ * of the scalars is greater than the maximum "kind" of the arrays, does
+ * a regular type promotion.
+ *
+ * Otherwise, does a type promotion on the MinScalarType
+ * of all the inputs. Data types passed directly are treated as array
+ * types.
+ *
+ */
+NPY_NO_EXPORT PyArray_Descr *
+PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes)
+{
+ npy_intp i;
+
+ /* If there's just one type, pass it through */
+ if (narrs + ndtypes == 1) {
+ PyArray_Descr *ret = NULL;
+ if (narrs == 1) {
+ ret = PyArray_DESCR(arr[0]);
+ }
+ else {
+ ret = dtypes[0];
+ }
+ Py_INCREF(ret);
+ return ret;
+ }
+
+ int use_min_scalar = should_use_min_scalar(narrs, arr, ndtypes, dtypes);
/* Loop through all the types, promoting them */
if (!use_min_scalar) {
diff --git a/numpy/core/src/multiarray/convert_datatype.h b/numpy/core/src/multiarray/convert_datatype.h
index 653557161..72867ead8 100644
--- a/numpy/core/src/multiarray/convert_datatype.h
+++ b/numpy/core/src/multiarray/convert_datatype.h
@@ -18,6 +18,10 @@ NPY_NO_EXPORT npy_bool
can_cast_scalar_to(PyArray_Descr *scal_type, char *scal_data,
PyArray_Descr *to, NPY_CASTING casting);
+NPY_NO_EXPORT int
+should_use_min_scalar(npy_intp narrs, PyArrayObject **arr,
+ npy_intp ndtypes, PyArray_Descr **dtypes);
+
/*
* This function calls Py_DECREF on flex_dtype, and replaces it with
* a new dtype that has been adapted based on the values in data_dtype
diff --git a/numpy/core/src/multiarray/dragon4.c b/numpy/core/src/multiarray/dragon4.c
index 8d52672e3..1694596e9 100644
--- a/numpy/core/src/multiarray/dragon4.c
+++ b/numpy/core/src/multiarray/dragon4.c
@@ -1,31 +1,33 @@
/*
* Copyright (c) 2014 Ryan Juckett
- * http://www.ryanjuckett.com/
*
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
*
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
/*
* This file contains a modified version of Ryan Juckett's Dragon4
- * implementation, which has been ported from C++ to C and which has
+ * implementation, obtained from http://www.ryanjuckett.com,
+ * which has been ported from C++ to C and which has
* modifications specific to printing floats in numpy.
+ *
+ * Ryan Juckett's original code was under the Zlib license; he gave numpy
+ * permission to include it under the MIT license instead.
*/
#include "dragon4.h"
diff --git a/numpy/core/src/multiarray/dragon4.h b/numpy/core/src/multiarray/dragon4.h
index 2b8b4cef4..3a99bde6c 100644
--- a/numpy/core/src/multiarray/dragon4.h
+++ b/numpy/core/src/multiarray/dragon4.h
@@ -1,31 +1,33 @@
/*
* Copyright (c) 2014 Ryan Juckett
- * http://www.ryanjuckett.com/
*
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
*
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
/*
* This file contains a modified version of Ryan Juckett's Dragon4
- * implementation, which has been ported from C++ to C and which has
+ * implementation, obtained from http://www.ryanjuckett.com,
+ * which has been ported from C++ to C and which has
* modifications specific to printing floats in numpy.
+ *
+ * Ryan Juckett's original code was under the Zlib license; he gave numpy
+ * permission to include it under the MIT license instead.
*/
#ifndef _NPY_DRAGON4_H_
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index a6889ef8f..11c45dce5 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -2213,8 +2213,26 @@ PyArray_Nonzero(PyArrayObject *self)
NpyIter_GetMultiIndexFunc *get_multi_index;
char **dataptr;
- /* Special case - nonzero(zero_d) is nonzero(atleast1d(zero_d)) */
+ /* Special case - nonzero(zero_d) is nonzero(atleast_1d(zero_d)) */
if (ndim == 0) {
+ char const* msg;
+ if (PyArray_ISBOOL(self)) {
+ msg =
+ "Calling nonzero on 0d arrays is deprecated, as it behaves "
+ "surprisingly. Use `atleast_1d(cond).nonzero()` if the old "
+ "behavior was intended. If the context of this warning is of "
+ "the form `arr[nonzero(cond)]`, just use `arr[cond]`.";
+ }
+ else {
+ msg =
+ "Calling nonzero on 0d arrays is deprecated, as it behaves "
+ "surprisingly. Use `atleast_1d(arr).nonzero()` if the old "
+ "behavior was intended.";
+ }
+ if (DEPRECATE(msg) < 0) {
+ return NULL;
+ }
+
static npy_intp const zero_dim_shape[1] = {1};
static npy_intp const zero_dim_strides[1] = {0};
diff --git a/numpy/core/src/npysort/radixsort.c.src b/numpy/core/src/npysort/radixsort.c.src
index c1435bd96..c90b06974 100644
--- a/numpy/core/src/npysort/radixsort.c.src
+++ b/numpy/core/src/npysort/radixsort.c.src
@@ -50,9 +50,10 @@ nth_byte_@suff@(@type@ key, npy_intp l) {
radixsort0_@suff@(@type@ *arr, @type@ *aux, npy_intp num)
{
npy_intp cnt[sizeof(@type@)][1 << 8] = { { 0 } };
- npy_intp i, l;
+ npy_intp i;
+ size_t l;
@type@ key0 = KEY_OF(arr[0]);
- npy_intp ncols = 0;
+ size_t ncols = 0;
npy_ubyte cols[sizeof(@type@)];
for (i = 0; i < num; i++) {
@@ -139,9 +140,10 @@ npy_intp*
aradixsort0_@suff@(@type@ *arr, npy_intp *aux, npy_intp *tosort, npy_intp num)
{
npy_intp cnt[sizeof(@type@)][1 << 8] = { { 0 } };
- npy_intp i, l;
+ npy_intp i;
+ size_t l;
@type@ key0 = KEY_OF(arr[0]);
- npy_intp ncols = 0;
+ size_t ncols = 0;
npy_ubyte cols[sizeof(@type@)];
for (i = 0; i < num; i++) {
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 081c06813..cb24f2a70 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -654,8 +654,8 @@ _parse_signature(PyUFuncObject *ufunc, const char *signature)
PyErr_NoMemory();
goto fail;
}
- for (i = 0; i < len; i++) {
- ufunc->core_dim_flags[i] = 0;
+ for (size_t j = 0; j < len; j++) {
+ ufunc->core_dim_flags[j] = 0;
}
i = _next_non_white_space(signature, 0);
diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c
index 58f915c6e..25dd002ac 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.c
+++ b/numpy/core/src/umath/ufunc_type_resolution.c
@@ -24,6 +24,7 @@
#include "ufunc_type_resolution.h"
#include "ufunc_object.h"
#include "common.h"
+#include "convert_datatype.h"
#include "mem_overlap.h"
#if defined(HAVE_CBLAS)
@@ -1938,73 +1939,6 @@ type_tuple_userloop_type_resolver(PyUFuncObject *self,
return 0;
}
-/*
- * Provides an ordering for the dtype 'kind' character codes, to help
- * determine when to use the min_scalar_type function. This groups
- * 'kind' into boolean, integer, floating point, and everything else.
- */
-
-static int
-dtype_kind_to_simplified_ordering(char kind)
-{
- switch (kind) {
- /* Boolean kind */
- case 'b':
- return 0;
- /* Unsigned int kind */
- case 'u':
- /* Signed int kind */
- case 'i':
- return 1;
- /* Float kind */
- case 'f':
- /* Complex kind */
- case 'c':
- return 2;
- /* Anything else */
- default:
- return 3;
- }
-}
-
-static int
-should_use_min_scalar(PyArrayObject **op, int nop)
-{
- int i, use_min_scalar, kind;
- int all_scalars = 1, max_scalar_kind = -1, max_array_kind = -1;
-
- /*
- * Determine if there are any scalars, and if so, whether
- * the maximum "kind" of the scalars surpasses the maximum
- * "kind" of the arrays
- */
- use_min_scalar = 0;
- if (nop > 1) {
- for(i = 0; i < nop; ++i) {
- kind = dtype_kind_to_simplified_ordering(
- PyArray_DESCR(op[i])->kind);
- if (PyArray_NDIM(op[i]) == 0) {
- if (kind > max_scalar_kind) {
- max_scalar_kind = kind;
- }
- }
- else {
- all_scalars = 0;
- if (kind > max_array_kind) {
- max_array_kind = kind;
- }
-
- }
- }
-
- /* Indicate whether to use the min_scalar_type function */
- if (!all_scalars && max_array_kind >= max_scalar_kind) {
- use_min_scalar = 1;
- }
- }
-
- return use_min_scalar;
-}
/*
* Does a linear search for the best inner loop of the ufunc.
@@ -2030,7 +1964,7 @@ linear_search_type_resolver(PyUFuncObject *self,
ufunc_name = ufunc_get_name_cstr(self);
- use_min_scalar = should_use_min_scalar(op, nin);
+ use_min_scalar = should_use_min_scalar(nin, op, 0, NULL);
/* If the ufunc has userloops, search for them. */
if (self->userloops) {
@@ -2139,7 +2073,7 @@ type_tuple_type_resolver(PyUFuncObject *self,
ufunc_name = ufunc_get_name_cstr(self);
- use_min_scalar = should_use_min_scalar(op, nin);
+ use_min_scalar = should_use_min_scalar(nin, op, 0, NULL);
/* Fill in specified_types from the tuple or string */
if (PyTuple_Check(type_tup)) {
diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py
index 9755e7b36..32e2ea537 100644
--- a/numpy/core/tests/test_api.py
+++ b/numpy/core/tests/test_api.py
@@ -3,8 +3,10 @@ from __future__ import division, absolute_import, print_function
import sys
import numpy as np
+import pytest
from numpy.testing import (
- assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT
+ assert_, assert_equal, assert_array_equal, assert_raises, assert_warns,
+ HAS_REFCOUNT
)
# Switch between new behaviour when NPY_RELAXED_STRIDES_CHECKING is set.
@@ -289,6 +291,14 @@ def test_array_astype():
a = np.array(1000, dtype='i4')
assert_raises(TypeError, a.astype, 'U1', casting='safe')
+@pytest.mark.parametrize("t",
+ np.sctypes['uint'] + np.sctypes['int'] + np.sctypes['float']
+)
+def test_array_astype_warning(t):
+ # test ComplexWarning when casting from complex to float or int
+ a = np.array(10, dtype=np.complex)
+ assert_warns(np.ComplexWarning, a.astype, t)
+
def test_copyto_fromscalar():
a = np.arange(6, dtype='f4').reshape(2, 3)
diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py
index 346a0038a..6d71fcbd6 100644
--- a/numpy/core/tests/test_deprecations.py
+++ b/numpy/core/tests/test_deprecations.py
@@ -541,3 +541,10 @@ class TestShape1Fields(_DeprecationTestCase):
# 2019-05-20, 1.17.0
def test_shape_1_fields(self):
self.assert_deprecated(np.dtype, args=([('a', int, 1)],))
+
+
+class TestNonZero(_DeprecationTestCase):
+ # 2019-05-26, 1.17.0
+ def test_zerod(self):
+ self.assert_deprecated(lambda: np.nonzero(np.array(0)))
+ self.assert_deprecated(lambda: np.nonzero(np.array(1)))
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index 8f33a8daf..4031e7362 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -11,6 +11,7 @@ from numpy.core._rational_tests import rational
from numpy.testing import (
assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT)
from numpy.compat import pickle
+from itertools import permutations
def assert_dtype_equal(a, b):
assert_equal(a, b)
@@ -1178,3 +1179,18 @@ class TestFromCTypes(object):
self.check(ctypes.c_uint16.__ctype_be__, np.dtype('>u2'))
self.check(ctypes.c_uint8.__ctype_le__, np.dtype('u1'))
self.check(ctypes.c_uint8.__ctype_be__, np.dtype('u1'))
+
+ all_types = set(np.typecodes['All'])
+ all_pairs = permutations(all_types, 2)
+
+ @pytest.mark.parametrize("pair", all_pairs)
+ def test_pairs(self, pair):
+ """
+ Check that np.dtype('x,y') matches [np.dtype('x'), np.dtype('y')]
+ Example: np.dtype('d,I') -> dtype([('f0', '<f8'), ('f1', '<u4')])
+ """
+ # gh-5645: check that np.dtype('i,L') can be used
+ pair_type = np.dtype('{},{}'.format(*pair))
+ expected = np.dtype([('f0', pair[0]), ('f1', pair[1])])
+ assert_equal(pair_type, expected)
+
diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py
index 9499bedec..cf66751f8 100644
--- a/numpy/core/tests/test_nditer.py
+++ b/numpy/core/tests/test_nditer.py
@@ -1864,7 +1864,7 @@ def test_iter_buffered_cast_structured_type():
# make sure multi-field struct type -> simple doesn't work
sdt = [('a', 'f4'), ('b', 'i8'), ('d', 'O')]
a = np.array([(5.5, 7, 'test'), (8, 10, 11)], dtype=sdt)
- assert_raises(ValueError, lambda: (
+ assert_raises(TypeError, lambda: (
nditer(a, ['buffered', 'refs_ok'], ['readonly'],
casting='unsafe',
op_dtypes='i4')))
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
index 7b6357fe8..935b84234 100644
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -899,6 +899,41 @@ class TestTypes(object):
# Also test keyword arguments
assert_(np.can_cast(from_=np.int32, to=np.int64))
+ def test_can_cast_simple_to_structured(self):
+ # Non-structured can only be cast to structured in 'unsafe' mode.
+ assert_(not np.can_cast('i4', 'i4,i4'))
+ assert_(not np.can_cast('i4', 'i4,i2'))
+ assert_(np.can_cast('i4', 'i4,i4', casting='unsafe'))
+ assert_(np.can_cast('i4', 'i4,i2', casting='unsafe'))
+ # Even if there is just a single field which is OK.
+ assert_(not np.can_cast('i2', [('f1', 'i4')]))
+ assert_(not np.can_cast('i2', [('f1', 'i4')], casting='same_kind'))
+ assert_(np.can_cast('i2', [('f1', 'i4')], casting='unsafe'))
+ # It should be the same for recursive structured or subarrays.
+ assert_(not np.can_cast('i2', [('f1', 'i4,i4')]))
+ assert_(np.can_cast('i2', [('f1', 'i4,i4')], casting='unsafe'))
+ assert_(not np.can_cast('i2', [('f1', '(2,3)i4')]))
+ assert_(np.can_cast('i2', [('f1', '(2,3)i4')], casting='unsafe'))
+
+ def test_can_cast_structured_to_simple(self):
+ # Need unsafe casting for structured to simple.
+ assert_(not np.can_cast([('f1', 'i4')], 'i4'))
+ assert_(np.can_cast([('f1', 'i4')], 'i4', casting='unsafe'))
+ assert_(np.can_cast([('f1', 'i4')], 'i2', casting='unsafe'))
+ # Since it is unclear what is being cast, multiple fields to
+ # single should not work even for unsafe casting.
+ assert_(not np.can_cast('i4,i4', 'i4', casting='unsafe'))
+ # But a single field inside a single field is OK.
+ assert_(not np.can_cast([('f1', [('x', 'i4')])], 'i4'))
+ assert_(np.can_cast([('f1', [('x', 'i4')])], 'i4', casting='unsafe'))
+ # And a subarray is fine too - it will just take the first element
+ # (arguably not very consistently; might also take the first field).
+ assert_(not np.can_cast([('f0', '(3,)i4')], 'i4'))
+ assert_(np.can_cast([('f0', '(3,)i4')], 'i4', casting='unsafe'))
+ # But a structured subarray with multiple fields should fail.
+ assert_(not np.can_cast([('f0', ('i4,i4'), (2,))], 'i4',
+ casting='unsafe'))
+
def test_can_cast_values(self):
# gh-5917
for dt in np.sctypes['int'] + np.sctypes['uint']:
@@ -976,12 +1011,24 @@ class TestNonzero(object):
assert_equal(np.count_nonzero(np.array([], dtype='?')), 0)
assert_equal(np.nonzero(np.array([])), ([],))
+ assert_equal(np.count_nonzero(np.array([0])), 0)
+ assert_equal(np.count_nonzero(np.array([0], dtype='?')), 0)
+ assert_equal(np.nonzero(np.array([0])), ([],))
+
+ assert_equal(np.count_nonzero(np.array([1])), 1)
+ assert_equal(np.count_nonzero(np.array([1], dtype='?')), 1)
+ assert_equal(np.nonzero(np.array([1])), ([0],))
+
+ def test_nonzero_zerod(self):
assert_equal(np.count_nonzero(np.array(0)), 0)
assert_equal(np.count_nonzero(np.array(0, dtype='?')), 0)
- assert_equal(np.nonzero(np.array(0)), ([],))
+ with assert_warns(DeprecationWarning):
+ assert_equal(np.nonzero(np.array(0)), ([],))
+
assert_equal(np.count_nonzero(np.array(1)), 1)
assert_equal(np.count_nonzero(np.array(1, dtype='?')), 1)
- assert_equal(np.nonzero(np.array(1)), ([0],))
+ with assert_warns(DeprecationWarning):
+ assert_equal(np.nonzero(np.array(1)), ([0],))
def test_nonzero_onedim(self):
x = np.array([1, 0, 2, -1, 0, 0, 8])
@@ -1207,7 +1254,7 @@ class TestNonzero(object):
a = np.array([[False], [TrueThenFalse()]])
assert_raises(RuntimeError, np.nonzero, a)
-
+
class TestIndex(object):
def test_boolean(self):
a = rand(3, 5, 8)