diff --git a/include/boost/python/numpy/dtype.hpp b/include/boost/python/numpy/dtype.hpp index 4673745e57..d7831f87dc 100644 --- a/include/boost/python/numpy/dtype.hpp +++ b/include/boost/python/numpy/dtype.hpp @@ -47,7 +47,7 @@ class BOOST_NUMPY_DECL dtype : public object { template static dtype get_builtin(); /// @brief Return the size of the data type in bytes. - int get_itemsize() const; + boost::python::ssize_t get_itemsize() const; /** * @brief Compare two dtypes for equivalence. diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp index 1ce8c6ec32..3985af6046 100644 --- a/src/numpy/dtype.cpp +++ b/src/numpy/dtype.cpp @@ -98,7 +98,7 @@ python::detail::new_reference dtype::convert(object const & arg, bool align) return python::detail::new_reference(reinterpret_cast(obj)); } -int dtype::get_itemsize() const { +boost::python::ssize_t dtype::get_itemsize() const { #if NPY_ABI_VERSION < 0x02000000 return reinterpret_cast(ptr())->elsize; #else diff --git a/src/numpy/ndarray.cpp b/src/numpy/ndarray.cpp index af09ecc338..a85e2520ab 100644 --- a/src/numpy/ndarray.cpp +++ b/src/numpy/ndarray.cpp @@ -41,11 +41,15 @@ int bitflag_to_numpy(ndarray::bitflag f) bool is_c_contiguous(std::vector const & shape, std::vector const & strides, - int itemsize) -{ - std::vector::const_reverse_iterator j = strides.rbegin(); - int total = itemsize; - for (std::vector::const_reverse_iterator i = shape.rbegin(); i != shape.rend(); ++i, ++j) + boost::python::ssize_t const itemsize) +{ + // An itemsize less than 0 is not useful - default to non-contiguity. + if (0 > itemsize) return false; + // Check the strides (stride[n]) match the accumulated shapes as per C-style, + // i.e. starting from rightmost C-index (itemsize * prod_{i in [n, N)} shape[i]). + std::vector::const_reverse_iterator j = strides.crbegin(); + boost::python::ssize_t total = itemsize; + for (std::vector::const_reverse_iterator i = shape.crbegin(); i != shape.crend(); ++i, ++j) { if (total != *j) return false; total *= (*i); @@ -55,11 +59,15 @@ bool is_c_contiguous(std::vector const & shape, bool is_f_contiguous(std::vector const & shape, std::vector const & strides, - int itemsize) -{ - std::vector::const_iterator j = strides.begin(); - int total = itemsize; - for (std::vector::const_iterator i = shape.begin(); i != shape.end(); ++i, ++j) + boost::python::ssize_t const itemsize) +{ + // An itemsize less than 0 is not useful - default to non-contiguity. + if (0 > itemsize) return false; + // Check the strides (stride[n]) match the accumulated shapes as per Fortran-style, + // i.e. starting from leftmost C-index (itemsize * prod_{i in [0, n]} shape[i]). + std::vector::const_iterator j = strides.cbegin(); + boost::python::ssize_t total = itemsize; + for (std::vector::const_iterator i = shape.cbegin(); i != shape.cend(); ++i, ++j) { if (total != *j) return false; total *= (*i); @@ -68,9 +76,12 @@ bool is_f_contiguous(std::vector const & shape, } bool is_aligned(std::vector const & strides, - int itemsize) + boost::python::ssize_t const itemsize) { - for (std::vector::const_iterator i = strides.begin(); i != strides.end(); ++i) + // An itemsize less than 0 is not useful - default to non-aligned. + if (0 > itemsize) return false; + // Check all strides to be aligned to itemsize. + for (std::vector::const_iterator i = strides.cbegin(); i != strides.cend(); ++i) { if (*i % itemsize) return false; } @@ -117,7 +128,7 @@ ndarray from_data_impl(void * data, PyErr_SetString(PyExc_ValueError, "Length of shape and strides arrays do not match."); python::throw_error_already_set(); } - int itemsize = dt.get_itemsize(); + boost::python::ssize_t const itemsize = dt.get_itemsize(); int flags = 0; if (writeable) flags |= NPY_ARRAY_WRITEABLE; if (is_c_contiguous(shape, strides, itemsize)) flags |= NPY_ARRAY_C_CONTIGUOUS;