diff --git a/docs/source/array_tensor.rst b/docs/source/array_tensor.rst index e00889f..0166b99 100644 --- a/docs/source/array_tensor.rst +++ b/docs/source/array_tensor.rst @@ -4,8 +4,8 @@ The full license is in the file LICENSE, distributed with this software. -Arrays and tensors -================== +Arrays, Tensors and NumPy Views +=============================== ``xtensor-python`` provides two container types wrapping numpy arrays: ``pyarray`` and ``pytensor``. They are the counterparts to ``xarray`` and ``xtensor`` containers. @@ -25,3 +25,21 @@ Like ``xtensor``, ``pytensor`` has a static stack-allocated shape. This means th the shape of the ``pytensor`` upon creation. As a consequence, reshapes are not reflected across languages. However, this drawback is offset by a more effective computation of shape and broadcast. +NumPy views +----------- + +If you are trying to call a xtensor function with a NumPy view, you might read the following: +"passing container with wrong strides for static layout". This means, that the *static layout* +of the pytensor does not match the layout of the NumPy array (or view) that you are using to +call the function. + +One fix for this is to choose the ``dynamic`` layout for your pyarray or pytensor: + +.. code:: + + void my_function(xt::pyarray input) + +When choosing the dynamic layout, you can pass any NumPy container (with Fortran order, or +an arbitrary view). +Note that iterators on a pyarray with dynamic layout are generally slower! + diff --git a/include/xtensor-python/pyarray.hpp b/include/xtensor-python/pyarray.hpp index ec70d6a..e479cb2 100644 --- a/include/xtensor-python/pyarray.hpp +++ b/include/xtensor-python/pyarray.hpp @@ -23,7 +23,7 @@ namespace xt { - template + template class pyarray; } @@ -682,7 +682,7 @@ namespace xt if (!tmp) { - throw std::runtime_error("NumPy: unable to create ndarray"); + throw std::runtime_error("pyarray: unable to create ndarray"); } this->m_ptr = tmp.release().ptr(); @@ -771,7 +771,7 @@ namespace xt if (!tmp) { - throw std::runtime_error("NumPy: unable to create ndarray"); + throw std::runtime_error("pyarray: unable to create ndarray"); } this->m_ptr = tmp.release().ptr(); @@ -793,7 +793,7 @@ namespace xt if (L != layout_type::dynamic && !do_strides_match(m_shape, m_strides, L, 1)) { - throw std::runtime_error("NumPy: passing container with bad strides for layout (is it a view?)."); + throw std::runtime_error("pyarray: passing container with wrong strides for static layout. If you are trying to pass a view, set the pytensor layout template parameter to `layout_type::dynamic`, or `layout_type::column_major` for col major."); } m_backstrides = backstrides_type(*this); diff --git a/include/xtensor-python/pytensor.hpp b/include/xtensor-python/pytensor.hpp index 0f0cac4..1e2b346 100644 --- a/include/xtensor-python/pytensor.hpp +++ b/include/xtensor-python/pytensor.hpp @@ -24,7 +24,7 @@ namespace xt { - template + template class pytensor; } @@ -431,7 +431,7 @@ namespace xt if (!tmp) { - throw std::runtime_error("NumPy: unable to create ndarray"); + throw std::runtime_error("pytensor: unable to create ndarray"); } this->m_ptr = tmp.release().ptr(); @@ -452,7 +452,7 @@ namespace xt if (PyArray_NDIM(this->python_array()) != N) { - throw std::runtime_error("NumPy: ndarray has incorrect number of dimensions"); + throw std::runtime_error("pytensor: ndarray has incorrect number of dimensions"); } std::copy(PyArray_DIMS(this->python_array()), PyArray_DIMS(this->python_array()) + N, m_shape.begin()); @@ -462,7 +462,7 @@ namespace xt if (L != layout_type::dynamic && !do_strides_match(m_shape, m_strides, L, 1)) { - throw std::runtime_error("NumPy: passing container with bad strides for layout (is it a view?)."); + throw std::runtime_error("pytensor: passing container with wrong strides for static layout. If you are trying to pass a view, set the pytensor layout template parameter to `layout_type::dynamic`, or `layout_type::column_major` for col major."); } m_storage = storage_type(reinterpret_cast(PyArray_DATA(this->python_array())),