10000 ENH: Pass input strides and dimensions by pointer to const by eric-wieser · Pull Request #13693 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: Pass input strides and dimensions by pointer to const #13693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
ENH: Pass input strides and dimensions by pointer to const
This makes it possible to call these functions with constant data.
It also bakes the contract that the data passed via these pointers will not be changed into the function signatures.

This is backwards compatible, because T* can always be passed to a function expecting T const*.
  • Loading branch information
eric-wieser committed Jun 1, 2019
commit 458b5bd38aa50d4c903ff1117ea811a29f774709
10 changes: 10 additions & 0 deletions doc/release/1.17.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ or ``np.nan``) is now dropped.
C API changes
=============

dimension or stride input arguments are now passed by ``npy_intp const*``
-------------------------------------------------------------------------
Previously these function arguments were declared as the more strict
``npy_intp*``, which prevented the caller passing constant data.
This change is backwards compatible, but now allows code like::

npy_intp const fixed_dims[] = {1, 2, 3};
// no longer complains that the const-qualifier is discarded
npy_intp size = PyArray_MultiplyList(fixed_dims, 3);


New Features
============
Expand Down
33 changes: 17 additions & 16 deletions doc/source/reference/c-api.array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ From scratch
^^^^^^^^^^^^

.. c:function:: PyObject* PyArray_NewFromDescr( \
PyTypeObject* subtype, PyArray_Descr* descr, int nd, npy_intp* dims, \
npy_intp* strides, void* data, int flags, PyObject* obj)
PyTypeObject* subtype, PyArray_Descr* descr, int nd, npy_intp const* dims, \
npy_intp const* strides, void* data, int flags, PyObject* obj)

This function steals a reference to *descr*. The easiest way to get one
is using :c:func:`PyArray_DescrFromType`.
Expand Down Expand Up @@ -266,8 +266,9 @@ From scratch
base-class array.

.. c:function:: PyObject* PyArray_New( \
PyTypeObject* subtype, int nd, npy_intp* dims, int type_num, \
npy_intp* strides, void* data, int itemsize, int flags, PyObject* obj)
PyTypeObject* subtype, int nd, npy_intp const* dims, int type_num, \
npy_intp const* strides, void* data, int itemsize, int flags, \
PyObject* obj)

This is similar to :c:func:`PyArray_NewFromDescr` (...) except you
specify the data-type descriptor with *type_num* and *itemsize*,
Expand All @@ -288,7 +289,7 @@ From scratch
are passed in they must be consistent with the dimensions, the
itemsize, and the data of the array.

.. c:function:: PyObject* PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
.. c:function:: PyObject* PyArray_SimpleNew(int nd, npy_intp const* dims, int typenum)

Create a new uninitialized array of type, *typenum*, whose size in
each of *nd* dimensions is given by the integer array, *dims*.The memory
Expand All @@ -301,7 +302,7 @@ From scratch
used to create a flexible-type array (no itemsize given).

.. c:function:: PyObject* PyArray_SimpleNewFromData( \
int nd, npy_intp* dims, int typenum, void* data)
int nd, npy_intp const* dims, int typenum, void* data)

Create an array wrapper around *data* pointed to by the given
pointer. The array flags will have a default that the data area is
Expand All @@ -316,7 +317,7 @@ From scratch
as the ndarray is deallocated, set the OWNDATA flag on the returned ndarray.

.. c:function:: PyObject* PyArray_SimpleNewFromDescr( \
int nd, npy_intp* dims, PyArray_Descr* descr)
int nd, npy_int const* dims, PyArray_Descr* descr)

This function steals a reference to *descr*.

Expand All @@ -330,7 +331,7 @@ From scratch
This macro calls memset, so obj must be contiguous.

.. c:function:: PyObject* PyArray_Zeros( \
int nd, npy_intp* dims, PyArray_Descr* dtype, int fortran)
int nd, npy_intp const* dims, PyArray_Descr* dtype, int fortran)

Construct a new *nd* -dimensional array with shape given by *dims*
and data type given by *dtype*. If *fortran* is non-zero, then a
Expand All @@ -339,13 +340,13 @@ From scratch
corresponds to :c:type:`NPY_OBJECT` ).

.. c:function:: PyObject* PyArray_ZEROS( \
int nd, npy_intp* dims, int type_num, int fortran)
int nd, npy_intp const* dims, int type_num, int fortran)

Macro form of :c:func:`PyArray_Zeros` which takes a type-number instead
of a data-type object.

.. c:function:: PyObject* PyArray_Empty( \
int nd, npy_intp* dims, PyArray_Descr* dtype, int fortran)
int nd, npy_intp const* dims, PyArray_Descr* dtype, int fortran)

Construct a new *nd* -dimensional array with shape given by *dims*
and data type given by *dtype*. If *fortran* is non-zero, then a
Expand All @@ -355,7 +356,7 @@ From scratch
filled with :c:data:`Py_None`.

.. c:function:: PyObject* PyArray_EMPTY( \
int nd, npy_intp* dims, int typenum, int fortran)
int nd, npy_intp const* dims, int typenum, int fortran)

Macro form of :c:func:`PyArray_Empty` which takes a type-number,
*typenum*, instead of a data-type object.
Expand Down Expand Up @@ -2357,8 +2358,8 @@ Other functions
^^^^^^^^^^^^^^^

.. c:function:: Bool PyArray_CheckStrides( \
int elsize, int nd, npy_intp numbytes, npy_intp* dims, \
npy_intp* newstrides)
int elsize, int nd, npy_intp numbytes, npy_intp const* dims, \
npy_intp const* newstrides)

Determine if *newstrides* is a strides array consistent with the
memory of an *nd* -dimensional array with shape ``dims`` and
Expand All @@ -2370,14 +2371,14 @@ Other functions
*elsize* refer to a single-segment array. Return :c:data:`NPY_TRUE` if
*newstrides* is acceptable, otherwise return :c:data:`NPY_FALSE`.

.. c:function:: npy_intp PyArray_MultiplyList(npy_intp* seq, int n)
.. c:function:: npy_intp PyArray_MultiplyList(npy_intp const* seq, int n)

.. c:function:: int PyArray_MultiplyIntList(int* seq, int n)
.. c:function:: int PyArray_MultiplyIntList(int const* seq, int n)

Both of these routines multiply an *n* -length array, *seq*, of
integers and return the result. No overflow checking is performed.

.. c:function:: int PyArray_CompareLists(npy_intp* l1, npy_intp* l2, int n)
.. c:function:: int PyArray_CompareLists(npy_intp const* l1, npy_intp const* l2, int n)

Given two *n* -length arrays of integers, *l1*, and *l2*, return
1 if the lists are identical; otherwise, return 0.
Expand Down
4 changes: 2 additions & 2 deletions doc/source/reference/c-api.iterator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ Construction and Destruction
.. c:function:: NpyIter* NpyIter_AdvancedNew( \
npy_intp nop, PyArrayObject** op, npy_uint32 flags, NPY_ORDER order, \
NPY_CASTING casting, npy_uint32* op_flags, PyArray_Descr** op_dtypes, \
int oa_ndim, int** op_axes, npy_intp* itershape, npy_intp buffersize)
int oa_ndim, int** op_axes, npy_intp const* itershape, npy_intp buffersize)

Extends :c:func:`NpyIter_MultiNew` with several advanced options providing
more control over broadcasting and buffering.
Expand Down Expand Up @@ -867,7 +867,7 @@ Construction and Destruction
} while (iternext2(iter2));
} while (iternext1(iter1));

.. c:function:: int NpyIter_GotoMultiIndex(NpyIter* iter, npy_intp* multi_index)
.. c:function:: int NpyIter_GotoMultiIndex(NpyIter* iter, npy_intp const* multi_index)

Adjusts the iterator to point to the ``ndim`` indices
pointed to by ``multi_index``. Returns an error if a multi-index
Expand Down
33 changes: 18 additions & 15 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -944,10 +944,11 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
* be decrefed.
*/
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp *dims, npy_intp *strides, void *data,
int flags, PyObject *obj, PyObject *base, int zeroed,
int allow_emptystring)
PyArray_NewFromDescr_int(
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base, int zeroed,
int allow_emptystring)
{
PyArrayObject_fields *fa;
int i, is_empty;
Expand Down Expand Up @@ -1223,9 +1224,10 @@ PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
* true, dtype will be decrefed.
*/
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr,
int nd, npy_intp *dims, npy_intp *strides, void *data,
int flags, PyObject *obj)
PyArray_NewFromDescr(
PyTypeObject *subtype, PyArray_Descr *descr,
int nd, npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj)
{
return PyArray_NewFromDescrAndBase(
subtype, descr,
Expand All @@ -1239,7 +1241,7 @@ PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr,
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescrAndBase(
PyTypeObject *subtype, PyArray_Descr *descr,
int nd, npy_intp *dims, npy_intp *strides, void *data,
int nd, npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base)
{
return PyArray_NewFromDescr_int(subtype, descr, nd,
Expand Down Expand Up @@ -1267,7 +1269,7 @@ PyArray_NewFromDescrAndBase(
*/
NPY_NO_EXPORT PyObject *
PyArray_NewLikeArrayWithShape(PyArrayObject *prototype, NPY_ORDER order,
PyArray_Descr *dtype, int ndim, npy_intp *dims, int subok)
PyArray_Descr *dtype, int ndim, npy_intp const *dims, int subok)
{
PyObject *ret = NULL;

Expand Down Expand Up @@ -1375,9 +1377,10 @@ PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
* Generic new array creation routine.
*/
NPY_NO_EXPORT PyObject *
PyArray_New(PyTypeObject *subtype, int nd, npy_intp *dims, int type_num,
npy_intp *strides, void *data, int itemsize, int flags,
PyObject *obj)
PyArray_New(
PyTypeObject *subtype, int nd, npy_intp const *dims, int type_num,
npy_intp const *strides, void *data, int itemsize, int flags,
PyObject *obj)
{
PyArray_Descr *descr;
PyObject *new;
Expand Down Expand Up @@ -3135,7 +3138,7 @@ PyArray_CheckAxis(PyArrayObject *arr, int *axis, int flags)
* accepts NULL type
*/
NPY_NO_EXPORT PyObject *
PyArray_Zeros(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
PyArray_Zeros(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order)
{
PyArrayObject *ret;

Expand Down Expand Up @@ -3173,7 +3176,7 @@ PyArray_Zeros(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
* steals a reference to type
*/
NPY_NO_EXPORT PyObject *
PyArray_Empty(int nd, npy_intp *dims, PyArray_Descr *type, int is_f_order)
PyArray_Empty(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order)
{
PyArrayObject *ret;

Expand Down Expand Up @@ -4140,7 +4143,7 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
*/

NPY_NO_EXPORT void
_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
_array_fill_strides(npy_intp *strides, npy_intp const *dims, int nd, size_t itemsize,
int inflag, int *objflags)
{
int i;
Expand Down
33 changes: 19 additions & 14 deletions numpy/core/src/multiarray/ctors.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@
#define _NPY_ARRAY_CTORS_H_

NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp *dims, npy_intp *strides, void *data,
int flags, PyObject *obj);
PyArray_NewFromDescr(
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj);

NPY_NO_EXPORT PyObject *
PyArray_NewFromDescrAndBase(
PyTypeObject *subtype, PyArray_Descr *descr,
int nd, npy_intp *dims, npy_intp *strides, void *data,
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base);

NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr_int(PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp *dims, npy_intp *strides, void *data,
int flags, PyObject *obj, PyObject *base, int zeroed,
int allow_emptystring);
PyArray_NewFromDescr_int(
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base, int zeroed,
int allow_emptystring);

NPY_NO_EXPORT PyObject *
PyArray_NewLikeArrayWithShape(PyArrayObject *prototype, NPY_ORDER order,
PyArray_Descr *dtype, int ndim, npy_intp *dims, int subok);
PyArray_NewLikeArrayWithShape(
PyArrayObject *prototype, NPY_ORDER order,
PyArray_Descr *dtype, int ndim, npy_intp const *dims, int subok);

NPY_NO_EXPORT PyObject *PyArray_New(PyTypeObject *, int nd, npy_intp *,
int, npy_intp *, void *, int, int, PyObject *);
NPY_NO_EXPORT PyObject *
PyArray_New(
PyTypeObject *, int nd, npy_intp const *,
int, npy_intp const*, void *, int, int, PyObject *);

NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
Expand Down Expand Up @@ -68,7 +73,7 @@ PyArray_CopyAsFlat(PyArrayObject *dst, PyArrayObject *src,

/* FIXME: remove those from here */
NPY_NO_EXPORT void
_array_fill_strides(npy_intp *strides, npy_intp *dims, int nd, size_t itemsize,
_array_fill_strides(npy_intp *strides, npy_intp const *dims, int nd, size_t itemsize,
int inflag, int *objflags);

NPY_NO_EXPORT void
Expand Down
8 changes: 4 additions & 4 deletions numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ PyArray_GetPriority(PyObject *obj, double default_)
* Multiply a List of ints
*/
NPY_NO_EXPORT int
PyArray_MultiplyIntList(int *l1, int n)
PyArray_MultiplyIntList(int const *l1, int n)
{
int s = 1;

Expand All @@ -144,7 +144,7 @@ PyArray_MultiplyIntList(int *l1, int n)
* Multiply a List
*/
NPY_NO_EXPORT npy_intp
PyArray_MultiplyList(npy_intp *l1, int n)
PyArray_MultiplyList(npy_intp const *l1, int n)
{
npy_intp s = 1;

Expand Down Expand Up @@ -180,7 +180,7 @@ PyArray_OverflowMultiplyList(npy_intp *l1, int n)
* Produce a pointer into array
*/
NPY_NO_EXPORT void *
PyArray_GetPtr(PyArrayObject *obj, npy_intp* ind)
PyArray_GetPtr(PyArrayObject *obj, npy_intp const* ind)
{
int n = PyArray_NDIM(obj);
npy_intp *strides = PyArray_STRIDES(obj);
Expand All @@ -196,7 +196,7 @@ PyArray_GetPtr(PyArrayObject *obj, npy_intp* ind)
* Compare Lists
*/
NPY_NO_EXPORT int
PyArray_CompareLists(npy_intp *l1, npy_intp *l2, int n)
PyArray_CompareLists(npy_intp const *l1, npy_intp const *l2, int n)
{
int i;

Expand Down
2 changes: 1 addition & 1 deletion numpy/core/src/multiarray/nditer_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ NpyIter_ResetToIterIndexRange(NpyIter *iter,
* Returns NPY_SUCCEED on success, NPY_FAIL on failure.
*/
NPY_NO_EXPORT int
NpyIter_GotoMultiIndex(NpyIter *iter, npy_intp *multi_index)
NpyIter_GotoMultiIndex(NpyIter *iter, npy_intp const *multi_index)
{
npy_uint32 itflags = NIT_ITFLAGS(iter);
int idim, ndim = NIT_NDIM(iter);
Expand Down
0