summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/wheels.yml2
-rw-r--r--README.md2
-rw-r--r--doc/source/user/c-info.ufunc-tutorial.rst241
-rw-r--r--numpy/core/_add_newdocs.py19
-rw-r--r--numpy/core/setup.py7
-rw-r--r--numpy/core/src/multiarray/dragon4.c13
-rw-r--r--numpy/core/src/umath/ufunc_object.c8
-rw-r--r--numpy/core/tests/test_scalarprint.py1
-rw-r--r--numpy/core/tests/test_ufunc.py11
9 files changed, 168 insertions, 136 deletions
diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml
index afebe7f93..b17b478ab 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/wheels.yml
@@ -3,7 +3,7 @@
#
# if: github.repository == 'numpy/numpy'
#
-# in the get_commit_message job. Be sure to include [cd build] in your commit
+# in the get_commit_message job. Be sure to include [wheel build] in your commit
# message to trigger the build. All files related to wheel building are located
# at tools/wheels/
name: Wheel builder
diff --git a/README.md b/README.md
index 74586014a..6be1ee316 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ Code of Conduct
----------------------
NumPy is a community-driven open source project developed by a diverse group of
-[contributors](https://numpy.org/gallery/team.html). The NumPy leadership has made a strong
+[contributors](https://numpy.org/teams/). The NumPy leadership has made a strong
commitment to creating an open, inclusive, and positive community. Please read the
[NumPy Code of Conduct](https://numpy.org/code-of-conduct/) for guidance on how to interact
with others in a way that makes our community thrive.
diff --git a/doc/source/user/c-info.ufunc-tutorial.rst b/doc/source/user/c-info.ufunc-tutorial.rst
index 9bd01b963..3a406479b 100644
--- a/doc/source/user/c-info.ufunc-tutorial.rst
+++ b/doc/source/user/c-info.ufunc-tutorial.rst
@@ -71,11 +71,11 @@ Example Non-ufunc extension
pair: ufunc; adding new
For comparison and general edification of the reader we provide
-a simple implementation of a C extension of logit that uses no
+a simple implementation of a C extension of ``logit`` that uses no
numpy.
To do this we need two files. The first is the C file which contains
-the actual code, and the second is the setup.py file used to create
+the actual code, and the second is the ``setup.py`` file used to create
the module.
.. code-block:: c
@@ -99,8 +99,7 @@ the module.
/* This declares the logit function */
- static PyObject* spam_logit(PyObject *self, PyObject *args);
-
+ static PyObject *spam_logit(PyObject *self, PyObject *args);
/*
* This tells Python what methods this module has.
@@ -113,13 +112,12 @@ the module.
{NULL, NULL, 0, NULL}
};
-
/*
* This actually defines the logit function for
* input args from Python.
*/
- static PyObject* spam_logit(PyObject *self, PyObject *args)
+ static PyObject *spam_logit(PyObject *self, PyObject *args)
{
double p;
@@ -136,7 +134,6 @@ the module.
return Py_BuildValue("d", p);
}
-
/* This initiates the module using the above definitions. */
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
@@ -160,10 +157,10 @@ the module.
return m;
}
-To use the setup.py file, place setup.py and spammodule.c in the same
-folder. Then python setup.py build will build the module to import,
-or setup.py install will install the module to your site-packages
-directory.
+To use the ``setup.py file``, place ``setup.py`` and ``spammodule.c``
+in the same folder. Then ``python setup.py build`` will build the module to
+import, or ``python setup.py install`` will install the module to your
+site-packages directory.
.. code-block:: python
@@ -203,9 +200,9 @@ directory.
Once the spam module is imported into python, you can call logit
-via spam.logit. Note that the function used above cannot be applied
-as-is to numpy arrays. To do so we must call numpy.vectorize on it.
-For example, if a python interpreter is opened in the file containing
+via ``spam.logit``. Note that the function used above cannot be applied
+as-is to numpy arrays. To do so we must call :py:func:`numpy.vectorize`
+on it. For example, if a python interpreter is opened in the file containing
the spam library or spam has been installed, one can perform the
following commands:
@@ -225,10 +222,10 @@ TypeError: only length-1 arrays can be converted to Python scalars
array([ -inf, -2.07944154, -1.25276297, -0.69314718, -0.22314355,
0.22314355, 0.69314718, 1.25276297, 2.07944154, inf])
-THE RESULTING LOGIT FUNCTION IS NOT FAST! numpy.vectorize simply
-loops over spam.logit. The loop is done at the C level, but the numpy
+THE RESULTING LOGIT FUNCTION IS NOT FAST! ``numpy.vectorize`` simply
+loops over ``spam.logit``. The loop is done at the C level, but the numpy
array is constantly being parsed and build back up. This is expensive.
-When the author compared numpy.vectorize(spam.logit) against the
+When the author compared ``numpy.vectorize(spam.logit)`` against the
logit ufuncs constructed below, the logit ufuncs were almost exactly
4 times faster. Larger or smaller speedups are, of course, possible
depending on the nature of the function.
@@ -242,13 +239,14 @@ Example NumPy ufunc for one dtype
.. index::
pair: ufunc; adding new
-For simplicity we give a ufunc for a single dtype, the 'f8' double.
-As in the previous section, we first give the .c file and then the
-setup.py file used to create the module containing the ufunc.
+For simplicity we give a ufunc for a single dtype, the ``'f8'``
+``double``. As in the previous section, we first give the ``.c`` file
+and then the ``setup.py`` file used to create the module containing the
+ufunc.
The place in the code corresponding to the actual computations for
-the ufunc are marked with /\*BEGIN main ufunc computation\*/ and
-/\*END main ufunc computation\*/. The code in between those lines is
+the ufunc are marked with ``/\* BEGIN main ufunc computation \*/`` and
+``/\* END main ufunc computation \*/``. The code in between those lines is
the primary thing that must be changed to create your own ufunc.
.. code-block:: c
@@ -277,13 +275,13 @@ the primary thing that must be changed to create your own ufunc.
*/
static PyMethodDef LogitMethods[] = {
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
/* The loop definition must precede the PyMODINIT_FUNC. */
- static void double_logit(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void double_logit(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
@@ -293,25 +291,23 @@ the primary thing that must be changed to create your own ufunc.
double tmp;
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
+ /* BEGIN main ufunc computation */
tmp = *(double *)in;
- tmp /= 1-tmp;
+ tmp /= 1 - tmp;
*((double *)out) = log(tmp);
- /*END main ufunc computation*/
+ /* END main ufunc computation */
in += in_step;
out += out_step;
}
}
- /*This a pointer to the above function*/
+ /* This a pointer to the above function */
PyUFuncGenericFunction funcs[1] = {&double_logit};
/* These are the input and return dtypes of logit.*/
static char types[2] = {NPY_DOUBLE, NPY_DOUBLE};
- static void *data[1] = {NULL};
-
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"npufunc",
@@ -335,7 +331,7 @@ the primary thing that must be changed to create your own ufunc.
import_array();
import_umath();
- logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 1, 1,
+ logit = PyUFunc_FromFuncAndData(funcs, NULL, types, 1, 1, 1,
PyUFunc_None, "logit",
"logit_docstring", 0);
@@ -347,21 +343,23 @@ the primary thing that must be changed to create your own ufunc.
return m;
}
-This is a setup.py file for the above code. As before, the module
-can be build via calling python setup.py build at the command prompt,
-or installed to site-packages via python setup.py install.
+This is a ``setup.py file`` for the above code. As before, the module
+can be build via calling ``python setup.py build`` at the command prompt,
+or installed to site-packages via ``python setup.py install``. The module
+can also be placed into a local folder e.g. ``npufunc_directory`` below
+using ``python setup.py build_ext --inplace``.
.. code-block:: python
'''
- setup.py file for logit.c
+ setup.py file for single_type_logit.c
Note that since this is a numpy extension
we use numpy.distutils instead of
distutils from the python standard library.
Calling
$python setup.py build_ext --inplace
- will build the extension library in the current file.
+ will build the extension library in the npufunc_directory.
Calling
$python setup.py build
@@ -382,7 +380,6 @@ or installed to site-packages via python setup.py install.
def configuration(parent_package='', top_path=None):
- import numpy
from numpy.distutils.misc_util import Configuration
config = Configuration('npufunc_directory',
@@ -418,13 +415,13 @@ Example NumPy ufunc with multiple dtypes
We finally give an example of a full ufunc, with inner loops for
half-floats, floats, doubles, and long doubles. As in the previous
-sections we first give the .c file and then the corresponding
-setup.py file.
+sections we first give the ``.c`` file and then the corresponding
+``setup.py`` file.
The places in the code corresponding to the actual computations for
-the ufunc are marked with /\*BEGIN main ufunc computation\*/ and
-/\*END main ufunc computation\*/. The code in between those lines is
-the primary thing that must be changed to create your own ufunc.
+the ufunc are marked with ``/\* BEGIN main ufunc computation \*/`` and
+``/\* END main ufunc computation \*/``. The code in between those lines
+is the primary thing that must be changed to create your own ufunc.
.. code-block:: c
@@ -455,37 +452,36 @@ the primary thing that must be changed to create your own ufunc.
*
*/
-
static PyMethodDef LogitMethods[] = {
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
/* The loop definitions must precede the PyMODINIT_FUNC. */
- static void long_double_logit(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void long_double_logit(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
- char *in = args[0], *out=args[1];
+ char *in = args[0], *out = args[1];
npy_intp in_step = steps[0], out_step = steps[1];
long double tmp;
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
+ /* BEGIN main ufunc computation */
tmp = *(long double *)in;
- tmp /= 1-tmp;
+ tmp /= 1 - tmp;
*((long double *)out) = logl(tmp);
- /*END main ufunc computation*/
+ /* END main ufunc computation */
in += in_step;
out += out_step;
}
}
- static void double_logit(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void double_logit(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
@@ -495,33 +491,33 @@ the primary thing that must be changed to create your own ufunc.
double tmp;
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
+ /* BEGIN main ufunc computation */
tmp = *(double *)in;
- tmp /= 1-tmp;
+ tmp /= 1 - tmp;
*((double *)out) = log(tmp);
- /*END main ufunc computation*/
+ /* END main ufunc computation */
in += in_step;
out += out_step;
}
}
- static void float_logit(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void float_logit(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
- char *in=args[0], *out = args[1];
+ char *in = args[0], *out = args[1];
npy_intp in_step = steps[0], out_step = steps[1];
float tmp;
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
+ /* BEGIN main ufunc computation */
tmp = *(float *)in;
- tmp /= 1-tmp;
+ tmp /= 1 - tmp;
*((float *)out) = logf(tmp);
- /*END main ufunc computation*/
+ /* END main ufunc computation */
in += in_step;
out += out_step;
@@ -529,8 +525,8 @@ the primary thing that must be changed to create your own ufunc.
}
- static void half_float_logit(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void half_float_logit(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
@@ -541,13 +537,12 @@ the primary thing that must be changed to create your own ufunc.
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
- tmp = *(npy_half *)in;
- tmp = npy_half_to_float(tmp);
- tmp /= 1-tmp;
+ /* BEGIN main ufunc computation */
+ tmp = npy_half_to_float(*(npy_half *)in);
+ tmp /= 1 - tmp;
tmp = logf(tmp);
*((npy_half *)out) = npy_float_to_half(tmp);
- /*END main ufunc computation*/
+ /* END main ufunc computation */
in += in_step;
out += out_step;
@@ -562,10 +557,9 @@ the primary thing that must be changed to create your own ufunc.
&long_double_logit};
static char types[8] = {NPY_HALF, NPY_HALF,
- NPY_FLOAT, NPY_FLOAT,
- NPY_DOUBLE,NPY_DOUBLE,
- NPY_LONGDOUBLE, NPY_LONGDOUBLE};
- static void *data[4] = {NULL, NULL, NULL, NULL};
+ NPY_FLOAT, NPY_FLOAT,
+ NPY_DOUBLE, NPY_DOUBLE,
+ NPY_LONGDOUBLE, NPY_LONGDOUBLE};
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
@@ -590,7 +584,7 @@ the primary thing that must be changed to create your own ufunc.
import_array();
import_umath();
- logit = PyUFunc_FromFuncAndData(funcs, data, types, 4, 1, 1,
+ logit = PyUFunc_FromFuncAndData(funcs, NULL, types, 4, 1, 1,
PyUFunc_None, "logit",
"logit_docstring", 0);
@@ -602,14 +596,14 @@ the primary thing that must be changed to create your own ufunc.
return m;
}
-This is a setup.py file for the above code. As before, the module
-can be build via calling python setup.py build at the command prompt,
-or installed to site-packages via python setup.py install.
+This is a ``setup.py`` file for the above code. As before, the module
+can be build via calling ``python setup.py build`` at the command prompt,
+or installed to site-packages via ``python setup.py install``.
.. code-block:: python
'''
- setup.py file for logit.c
+ setup.py file for multi_type_logit.c
Note that since this is a numpy extension
we use numpy.distutils instead of
distutils from the python standard library.
@@ -637,9 +631,7 @@ or installed to site-packages via python setup.py install.
def configuration(parent_package='', top_path=None):
- import numpy
- from numpy.distutils.misc_util import Configuration
- from numpy.distutils.misc_util import get_info
+ from numpy.distutils.misc_util import Configuration, get_info
#Necessary for the half-float d-type.
info = get_info('npymath')
@@ -676,10 +668,10 @@ Example NumPy ufunc with multiple arguments/return values
Our final example is a ufunc with multiple arguments. It is a modification
of the code for a logit ufunc for data with a single dtype. We
-compute (A*B, logit(A*B)).
+compute ``(A * B, logit(A * B))``.
We only give the C code as the setup.py file is exactly the same as
-the setup.py file in `Example NumPy ufunc for one dtype`_, except that
+the ``setup.py`` file in `Example NumPy ufunc for one dtype`_, except that
the line
.. code-block:: python
@@ -692,9 +684,9 @@ is replaced with
config.add_extension('npufunc', ['multi_arg_logit.c'])
-The C file is given below. The ufunc generated takes two arguments A
-and B. It returns a tuple whose first element is A*B and whose second
-element is logit(A*B). Note that it automatically supports broadcasting,
+The C file is given below. The ufunc generated takes two arguments ``A``
+and ``B``. It returns a tuple whose first element is ``A * B`` and whose second
+element is ``logit(A * B)``. Note that it automatically supports broadcasting,
as well as all other properties of a ufunc.
.. code-block:: c
@@ -716,19 +708,17 @@ as well as all other properties of a ufunc.
*
* Details explaining the Python-C API can be found under
* 'Extending and Embedding' and 'Python/C API' at
- * docs.python.org .
- *
+ * docs.python.org.
*/
-
static PyMethodDef LogitMethods[] = {
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
/* The loop definition must precede the PyMODINIT_FUNC. */
- static void double_logitprod(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void double_logitprod(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
npy_intp n = dimensions[0];
@@ -740,12 +730,12 @@ as well as all other properties of a ufunc.
double tmp;
for (i = 0; i < n; i++) {
- /*BEGIN main ufunc computation*/
+ /* BEGIN main ufunc computation */
tmp = *(double *)in1;
tmp *= *(double *)in2;
*((double *)out1) = tmp;
- *((double *)out2) = log(tmp/(1-tmp));
- /*END main ufunc computation*/
+ *((double *)out2) = log(tmp / (1 - tmp));
+ /* END main ufunc computation */
in1 += in1_step;
in2 += in2_step;
@@ -754,7 +744,6 @@ as well as all other properties of a ufunc.
}
}
-
/*This a pointer to the above function*/
PyUFuncGenericFunction funcs[1] = {&double_logitprod};
@@ -763,9 +752,6 @@ as well as all other properties of a ufunc.
static char types[4] = {NPY_DOUBLE, NPY_DOUBLE,
NPY_DOUBLE, NPY_DOUBLE};
-
- static void *data[1] = {NULL};
-
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"npufunc",
@@ -789,7 +775,7 @@ as well as all other properties of a ufunc.
import_array();
import_umath();
- logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 2, 2,
+ logit = PyUFunc_FromFuncAndData(funcs, NULL, types, 1, 2, 2,
PyUFunc_None, "logit",
"logit_docstring", 0);
@@ -809,13 +795,13 @@ Example NumPy ufunc with structured array dtype arguments
This example shows how to create a ufunc for a structured array dtype.
For the example we show a trivial ufunc for adding two arrays with dtype
-'u8,u8,u8'. The process is a bit different from the other examples since
+``'u8,u8,u8'``. The process is a bit different from the other examples since
a call to :c:func:`PyUFunc_FromFuncAndData` doesn't fully register ufuncs for
custom dtypes and structured array dtypes. We need to also call
:c:func:`PyUFunc_RegisterLoopForDescr` to finish setting up the ufunc.
-We only give the C code as the setup.py file is exactly the same as
-the setup.py file in `Example NumPy ufunc for one dtype`_, except that
+We only give the C code as the ``setup.py`` file is exactly the same as
+the ``setup.py`` file in `Example NumPy ufunc for one dtype`_, except that
the line
.. code-block:: python
@@ -839,7 +825,6 @@ The C file is given below.
#include "numpy/npy_3kcompat.h"
#include <math.h>
-
/*
* add_triplet.c
* This is the C code for creating your own
@@ -847,7 +832,7 @@ The C file is given below.
*
* Details explaining the Python-C API can be found under
* 'Extending and Embedding' and 'Python/C API' at
- * docs.python.org .
+ * docs.python.org.
*/
static PyMethodDef StructUfuncTestMethods[] = {
@@ -856,25 +841,25 @@ The C file is given below.
/* The loop definition must precede the PyMODINIT_FUNC. */
- static void add_uint64_triplet(char **args, npy_intp *dimensions,
- npy_intp* steps, void* data)
+ static void add_uint64_triplet(char **args, const npy_intp *dimensions,
+ const npy_intp *steps, void *data)
{
npy_intp i;
- npy_intp is1=steps[0];
- npy_intp is2=steps[1];
- npy_intp os=steps[2];
- npy_intp n=dimensions[0];
+ npy_intp is1 = steps[0];
+ npy_intp is2 = steps[1];
+ npy_intp os = steps[2];
+ npy_intp n = dimensions[0];
uint64_t *x, *y, *z;
- char *i1=args[0];
- char *i2=args[1];
- char *op=args[2];
+ char *i1 = args[0];
+ char *i2 = args[1];
+ char *op = args[2];
for (i = 0; i < n; i++) {
- x = (uint64_t*)i1;
- y = (uint64_t*)i2;
- z = (uint64_t*)op;
+ x = (uint64_t *)i1;
+ y = (uint64_t *)i2;
+ z = (uint64_t *)op;
z[0] = x[0] + y[0];
z[1] = x[1] + y[1];
@@ -892,8 +877,6 @@ The C file is given below.
/* These are the input and return dtypes of add_uint64_triplet. */
static char types[3] = {NPY_UINT64, NPY_UINT64, NPY_UINT64};
- static void *data[1] = {NULL};
-
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"struct_ufunc_test",
@@ -924,11 +907,11 @@ The C file is given below.
/* Create a new ufunc object */
add_triplet = PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, 2, 1,
- PyUFunc_None, "add_triplet",
- "add_triplet_docstring", 0);
+ PyUFunc_None, "add_triplet",
+ "add_triplet_docstring", 0);
dtype_dict = Py_BuildValue("[(s, s), (s, s), (s, s)]",
- "f0", "u8", "f1", "u8", "f2", "u8");
+ "f0", "u8", "f1", "u8", "f2", "u8");
PyArray_DescrConverter(dtype_dict, &dtype);
Py_DECREF(dtype_dict);
@@ -938,10 +921,10 @@ The C file is given below.
/* Register ufunc for structured dtype */
PyUFunc_RegisterLoopForDescr(add_triplet,
- dtype,
- &add_uint64_triplet,
- dtypes,
- NULL);
+ dtype,
+ &add_uint64_triplet,
+ dtypes,
+ NULL);
d = PyModule_GetDict(m);
@@ -963,9 +946,9 @@ adapted from the umath module
static PyUFuncGenericFunction atan2_functions[] = {
PyUFunc_ff_f, PyUFunc_dd_d,
PyUFunc_gg_g, PyUFunc_OO_O_method};
- static void* atan2_data[] = {
- (void *)atan2f,(void *) atan2,
- (void *)atan2l,(void *)"arctan2"};
+ static void *atan2_data[] = {
+ (void *)atan2f, (void *)atan2,
+ (void *)atan2l, (void *)"arctan2"};
static char atan2_signatures[] = {
NPY_FLOAT, NPY_FLOAT, NPY_FLOAT,
NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE,
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py
index 523da75b3..a8d73af3f 100644
--- a/numpy/core/_add_newdocs.py
+++ b/numpy/core/_add_newdocs.py
@@ -2392,6 +2392,12 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('dtype',
"""
Data-type of the array's elements.
+ .. warning::
+
+ Setting ``arr.dtype`` is discouraged and may be deprecated in the
+ future. Setting will replace the ``dtype`` without modifying the
+ memory (see also `ndarray.view` and `ndarray.astype`).
+
Parameters
----------
None
@@ -2402,6 +2408,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('dtype',
See Also
--------
+ ndarray.astype : Cast the values contained in the array to a new data-type.
+ ndarray.view : Create a view of the same data but a different data-type.
numpy.dtype
Examples
@@ -2627,6 +2635,11 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('shape',
the array and the remaining dimensions. Reshaping an array in-place will
fail if a copy is required.
+ .. warning::
+
+ Setting ``arr.shape`` is discouraged and may be deprecated in the
+ future. Using `ndarray.reshape` is the preferred approach.
+
Examples
--------
>>> x = np.array([1, 2, 3, 4])
@@ -2697,6 +2710,12 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('strides',
A more detailed explanation of strides can be found in the
"ndarray.rst" file in the NumPy reference guide.
+ .. warning::
+
+ Setting ``arr.strides`` is discouraged and may be deprecated in the
+ future. `numpy.lib.stride_tricks.as_strided` should be preferred
+ to create a new view of the same data in a safer way.
+
Notes
-----
Imagine an array of 32-bit integers (each 4 bytes)::
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 0f2f3c210..a67a4cab6 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -24,6 +24,11 @@ NPY_RELAXED_STRIDES_CHECKING = (os.environ.get('NPY_RELAXED_STRIDES_CHECKING', "
NPY_RELAXED_STRIDES_DEBUG = (os.environ.get('NPY_RELAXED_STRIDES_DEBUG', "0") != "0")
NPY_RELAXED_STRIDES_DEBUG = NPY_RELAXED_STRIDES_DEBUG and NPY_RELAXED_STRIDES_CHECKING
+# Set NPY_DISABLE_SVML=1 in the environment to disable the vendored SVML
+# library. This option only has significance on a Linux x86_64 host and is most
+# useful to avoid improperly requiring SVML when cross compiling.
+NPY_DISABLE_SVML = (os.environ.get('NPY_DISABLE_SVML', "0") == "1")
+
# XXX: ugly, we use a class to avoid calling twice some expensive functions in
# config.h/numpyconfig.h. I don't see a better way because distutils force
# config.h generation inside an Extension class, and as such sharing
@@ -68,6 +73,8 @@ def can_link_svml():
"""SVML library is supported only on x86_64 architecture and currently
only on linux
"""
+ if NPY_DISABLE_SVML:
+ return False
machine = platform.machine()
system = platform.system()
return "x86_64" in machine and system == "Linux"
diff --git a/numpy/core/src/multiarray/dragon4.c b/numpy/core/src/multiarray/dragon4.c
index ce0293615..5d245b106 100644
--- a/numpy/core/src/multiarray/dragon4.c
+++ b/numpy/core/src/multiarray/dragon4.c
@@ -1809,9 +1809,16 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, BigInt *mantissa,
pos--;
numFractionDigits--;
}
- if (trim_mode == TrimMode_LeaveOneZero && buffer[pos-1] == '.') {
- buffer[pos++] = '0';
- numFractionDigits++;
+ if (buffer[pos-1] == '.') {
+ /* in TrimMode_LeaveOneZero, add trailing 0 back */
+ if (trim_mode == TrimMode_LeaveOneZero){
+ buffer[pos++] = '0';
+ numFractionDigits++;
+ }
+ /* in TrimMode_DptZeros, remove trailing decimal point */
+ else if (trim_mode == TrimMode_DptZeros) {
+ pos--;
+ }
}
}
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 52b354353..83e18a363 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2764,9 +2764,13 @@ reducelike_promote_and_resolve(PyUFuncObject *ufunc,
* The first operand and output should be the same array, so they should
* be identical. The second argument can be different for reductions,
* but is checked to be identical for accumulate and reduceat.
+ * Ideally, the type-resolver ensures that all are identical, but we do
+ * not enforce this here strictly. Otherwise correct handling of
+ * byte-order changes (or metadata) requires a lot of care; see gh-20699.
*/
- if (out_descrs[0] != out_descrs[2] || (
- enforce_uniform_args && out_descrs[0] != out_descrs[1])) {
+ if (!PyArray_EquivTypes(out_descrs[0], out_descrs[2]) || (
+ enforce_uniform_args && !PyArray_EquivTypes(
+ out_descrs[0], out_descrs[1]))) {
PyErr_Format(PyExc_TypeError,
"the resolved dtypes are not compatible with %s.%s. "
"Resolved (%R, %R, %R)",
diff --git a/numpy/core/tests/test_scalarprint.py b/numpy/core/tests/test_scalarprint.py
index ee21d4aa5..4deb5a0a4 100644
--- a/numpy/core/tests/test_scalarprint.py
+++ b/numpy/core/tests/test_scalarprint.py
@@ -306,6 +306,7 @@ class TestRealScalars:
assert_equal(fpos(tp('1.2'), unique=False, precision=4, trim='-'),
"1.2" if tp != np.float16 else "1.2002")
assert_equal(fpos(tp('1.'), trim='-'), "1")
+ assert_equal(fpos(tp('1.001'), precision=1, trim='-'), "1")
@pytest.mark.skipif(not platform.machine().startswith("ppc64"),
reason="only applies to ppc float128 values")
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 76e4cdcfd..9a9d46da0 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -2148,6 +2148,17 @@ class TestUfunc:
# It would be safe, but not equiv casting:
ufunc(a, c, out=out, casting="equiv")
+ def test_reducelike_byteorder_resolution(self):
+ # See gh-20699, byte-order changes need some extra care in the type
+ # resolution to make the following succeed:
+ arr_be = np.arange(10, dtype=">i8")
+ arr_le = np.arange(10, dtype="<i8")
+
+ assert np.add.reduce(arr_be) == np.add.reduce(arr_le)
+ assert_array_equal(np.add.accumulate(arr_be), np.add.accumulate(arr_le))
+ assert_array_equal(
+ np.add.reduceat(arr_be, [1]), np.add.reduceat(arr_le, [1]))
+
def test_reducelike_out_promotes(self):
# Check that the out argument to reductions is considered for
# promotion. See also gh-20455.