summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2013-04-14 07:23:52 -0700
committerCharles Harris <charlesr.harris@gmail.com>2013-04-14 07:23:52 -0700
commitf62bc39d25eb827b4245ddfeb25b2ff6afbb838d (patch)
treedce6f8fe69b44cb5734ff678eede2b369780efd0
parent01ed88af5b784d52f4fcf383e319cde67c8a22fb (diff)
parent5cdf8410fc4d2ed05d22e6831023c40a30d9ebe7 (diff)
downloadnumpy-f62bc39d25eb827b4245ddfeb25b2ff6afbb838d.tar.gz
Merge pull request #3221 from seberg/document-relaxed-strides
DOC: Document NPY_RELAXED_STRIDES_CHECKING changes
-rw-r--r--doc/release/1.8.0-notes.rst33
-rw-r--r--doc/source/reference/arrays.ndarray.rst44
-rw-r--r--doc/source/reference/c-api.array.rst32
-rw-r--r--doc/source/reference/ufuncs.rst6
-rw-r--r--numpy/add_newdocs.py13
5 files changed, 112 insertions, 16 deletions
diff --git a/doc/release/1.8.0-notes.rst b/doc/release/1.8.0-notes.rst
index ad33b5513..c2fc57e6c 100644
--- a/doc/release/1.8.0-notes.rst
+++ b/doc/release/1.8.0-notes.rst
@@ -42,6 +42,39 @@ case, now indicates a 0-D iteration and ``op_axes`` being NULL and the old
usage is deprecated. This does not effect the ``NpyIter_New`` or
``NpyIter_MultiNew`` functions.
+NPY_RELAXED_STRIDES_CHECKING
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+There is a new compile time environment variable
+``NPY_RELAXED_STRIDES_CHECKING``. If this variable is set to 1, then
+numpy will consider more arrays to be C- or F-contiguous -- for
+example, it becomes possible to have a column vector which is
+considered both C- and F-contiguous simultaneously. The new definition
+is more accurate, allows for faster code that makes fewer unnecessary
+copies, and simplifies numpy's code internally. However, it may also
+break third-party libraries that make too-strong assumptions about the
+stride values of C- and F-contiguous arrays. (It is also currently
+known that this breaks Cython code using memoryviews, which will be
+fixed in Cython.) THIS WILL BECOME THE DEFAULT IN A FUTURE RELEASE, SO
+PLEASE TEST YOUR CODE NOW AGAINST NUMPY BUILT WITH::
+
+ NPY_RELAXED_STRIDES_CHECKING=1 python setup.py install
+
+You can check whether NPY_RELAXED_STRIDES_CHECKING is in effect by
+running::
+
+ np.ones((10, 1), order="C").flags.f_contiguous
+
+This will be ``True`` if relaxed strides checking is enabled, and
+``False`` otherwise. The typical problem we've seen so far is C code
+that works with C-contiguous arrays, and assumes that the itemsize can
+be accessed by looking at the last element in the ``PyArray_STRIDES(arr)``
+array. When relaxed strides are in effect, this is not true (and in
+fact, it never was true in some corner cases). Instead, use
+``PyArray_ITEMSIZE(arr)``.
+
+For more information check the "Internal memory layout of an ndarray"
+section in the documentation.
+
New Features
============
diff --git a/doc/source/reference/arrays.ndarray.rst b/doc/source/reference/arrays.ndarray.rst
index 535ce8faa..5a528cbf6 100644
--- a/doc/source/reference/arrays.ndarray.rst
+++ b/doc/source/reference/arrays.ndarray.rst
@@ -115,7 +115,7 @@ array. Here, :math:`s_k` are integers which specify the :obj:`strides
<ndarray.strides>` of the array. The :term:`column-major` order (used,
for example, in the Fortran language and in *Matlab*) and
:term:`row-major` order (used in C) schemes are just specific kinds of
-strided scheme, and correspond to the strides:
+strided scheme, and correspond to memory that can be *addressed* by the strides:
.. math::
@@ -124,12 +124,51 @@ strided scheme, and correspond to the strides:
.. index:: single-segment, contiguous, non-contiguous
-where :math:`d_j` = `self.itemsize * self.shape[j]`.
+where :math:`d_j` `= self.itemsize * self.shape[j]`.
Both the C and Fortran orders are :term:`contiguous`, *i.e.,*
:term:`single-segment`, memory layouts, in which every part of the
memory block can be accessed by some combination of the indices.
+While a C-style and Fortran-style contiguous array, which has the corresponding
+flags set, can be addressed with the above strides, the actual strides may be
+different. This can happen in two cases:
+ 1. If ``self.shape[k] == 1`` then for any legal index ``index[k] == 0``.
+ This means that in the formula for the offset
+ :math:`n_k = 0` and thus :math:`s_k n_k = 0` and the value of
+ :math:`s_k` `= self.strides[k]` is arbitrary.
+ 2. If an array has no elements (``self.size == 0``) there is no legal index
+ and the strides are never used. Any array with no elements may be
+ considered C-style and Fortran-style contiguous.
+
+Point 1. means that ``self``and ``self.squeeze()`` always have the same
+contiguity and :term:`aligned` flags value. This also means that even a high
+dimensional array could be C-style and Fortran-style contiguous at the same
+time.
+
+.. index:: aligned
+
+An array is considered aligned if the memory offsets for all elements and the
+base offset itself is a multiple of `self.itemsize`.
+
+.. note::
+
+ Points (1) and (2) are not yet applied by default. Beginning with
+ Numpy 1.8.0, they are applied consistently only if the environment
+ variable ``NPY_RELAXED_STRIDES_CHECKING=1`` was defined when NumPy
+ was built. Eventually this will become the default.
+
+ You can check whether this option was enabled when your NumPy was
+ built by looking at the value of ``np.ones((10,1),
+ order='C').flags.f_contiguous``. If this is ``True``, then your
+ NumPy has relaxed strides checking enabled.
+
+.. warning::
+
+ It does *not* generally hold that ``self.strides[-1] == self.itemsize``
+ for C-style contiguous arrays or ``self.strides[0] == self.itemsize`` for
+ Fortran-style contiguous arrays is true.
+
Data in new :class:`ndarrays <ndarray>` is in the :term:`row-major`
(C) order, unless otherwise specified, but, for example, :ref:`basic
array slicing <arrays.indexing>` often produces :term:`views <view>`
@@ -144,7 +183,6 @@ in a different scheme.
irregularly strided array is passed in to such algorithms, a copy
is automatically made.
-
.. _arrays.ndarray.attributes:
Array attributes
diff --git a/doc/source/reference/c-api.array.rst b/doc/source/reference/c-api.array.rst
index 85cf3c317..8b918f9dd 100644
--- a/doc/source/reference/c-api.array.rst
+++ b/doc/source/reference/c-api.array.rst
@@ -1310,11 +1310,21 @@ of the constant names is deprecated in 1.7.
The data area is in Fortran-style contiguous order (first index varies
the fastest).
-Notice that contiguous 1-d arrays are always both Fortran contiguous
-and C contiguous. Both of these flags can be checked and are convenience
-flags only as whether or not an array is :cdata:`NPY_ARRAY_C_CONTIGUOUS`
-or :cdata:`NPY_ARRAY_F_CONTIGUOUS` can be determined by the ``strides``,
-``dimensions``, and ``itemsize`` attributes.
+.. note::
+
+ Arrays can be both C-style and Fortran-style contiguous simultaneously.
+ This is clear for 1-dimensional arrays, but can also be true for higher
+ dimensional arrays.
+
+ Even for contiguous arrays a stride for a given dimension
+ ``arr.strides[dim]`` may be *arbitrary* if ``arr.shape[dim] == 1``
+ or the array has no elements.
+ It does *not* generally hold that ``self.strides[-1] == self.itemsize``
+ for C-style contiguous arrays or ``self.strides[0] == self.itemsize`` for
+ Fortran-style contiguous arrays is true. The correct way to access the
+ ``itemsize`` of an array from the C API is ``PyArray_ITEMSIZE(arr)``.
+
+ .. seealso:: :ref:`Internal memory layout of an ndarray <arrays.ndarray>`
.. cvar:: NPY_ARRAY_OWNDATA
@@ -1322,7 +1332,7 @@ or :cdata:`NPY_ARRAY_F_CONTIGUOUS` can be determined by the ``strides``,
.. cvar:: NPY_ARRAY_ALIGNED
- The data area is aligned appropriately (for all strides).
+ The data area and all array elements are aligned appropriately.
.. cvar:: NPY_ARRAY_WRITEABLE
@@ -1432,14 +1442,20 @@ For all of these macros *arr* must be an instance of a (subclass of)
:cdata:`NPY_ARRAY_OWNDATA`, :cdata:`NPY_ARRAY_ALIGNED`,
:cdata:`NPY_ARRAY_WRITEABLE`, :cdata:`NPY_ARRAY_UPDATEIFCOPY`.
-.. cfunction:: PyArray_ISCONTIGUOUS(arr)
+.. cfunction:: PyArray_IS_C_CONTIGUOUS(arr)
Evaluates true if *arr* is C-style contiguous.
-.. cfunction:: PyArray_ISFORTRAN(arr)
+.. cfunction:: PyArray_IS_F_CONTIGUOUS(arr)
Evaluates true if *arr* is Fortran-style contiguous.
+.. cfunction:: PyArray_ISFORTRAN(arr)
+
+ Evaluates true if *arr* is Fortran-style contiguous and *not*
+ C-style contiguous. :cfunc:`PyArray_IS_F_CONTIGUOUS`
+ is the correct way to test for Fortran-style contiguity.
+
.. cfunction:: PyArray_ISWRITEABLE(arr)
Evaluates true if the data area of *arr* can be written to
diff --git a/doc/source/reference/ufuncs.rst b/doc/source/reference/ufuncs.rst
index afcb1302b..dcd4ae6d0 100644
--- a/doc/source/reference/ufuncs.rst
+++ b/doc/source/reference/ufuncs.rst
@@ -321,9 +321,9 @@ advanced usage and will not typically be used.
Specifies the calculation iteration order/memory layout of the output array.
Defaults to 'K'. 'C' means the output should be C-contiguous, 'F' means
- F-contiguous, 'A' means F-contiguous if the inputs are F-contiguous, C-contiguous
- otherwise, and 'K' means to match the element ordering of the inputs
- as closely as possible.
+ F-contiguous, 'A' means F-contiguous if the inputs are F-contiguous and
+ not also not C-contiguous, C-contiguous otherwise, and 'K' means to match
+ the element ordering of the inputs as closely as possible.
*dtype*
diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py
index 24d4c2134..ae07f05da 100644
--- a/numpy/add_newdocs.py
+++ b/numpy/add_newdocs.py
@@ -2614,12 +2614,11 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('flags',
created writeable view onto it.) Attempting to change a non-writeable
array raises a RuntimeError exception.
ALIGNED (A)
- The data and strides are aligned appropriately for the hardware.
+ The data and all elements are aligned appropriately for the hardware.
UPDATEIFCOPY (U)
This array is a copy of some other array. When this array is
deallocated, the base array will be updated with the contents of
this array.
-
FNC
F_CONTIGUOUS and not C_CONTIGUOUS.
FORC
@@ -2649,6 +2648,16 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('flags',
or the ultimate owner of the memory exposes a writeable buffer
interface or is a string.
+ Arrays can be both C-style and Fortran-style contiguous simultaneously.
+ This is clear for 1-dimensional arrays, but can also be true for higher
+ dimensional arrays.
+
+ Even for contiguous arrays a stride for a given dimension
+ ``arr.strides[dim]`` may be *arbitrary* if ``arr.shape[dim] == 1``
+ or the array has no elements.
+ It does *not* generally hold that ``self.strides[-1] == self.itemsize``
+ for C-style contiguous arrays or ``self.strides[0] == self.itemsize`` for
+ Fortran-style contiguous arrays is true.
"""))