|
|
|
@ -265,14 +265,14 @@ protected:
@@ -265,14 +265,14 @@ protected:
|
|
|
|
|
const unsigned char *data_; |
|
|
|
|
// Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
|
|
|
|
|
// make large performance gains on big, nested loops, but requires compile-time dimensions
|
|
|
|
|
conditional_t<Dynamic, const size_t *, std::array<size_t, (size_t) Dims>> |
|
|
|
|
shape_, strides_; |
|
|
|
|
conditional_t<Dynamic, const size_t *, std::array<size_t, (size_t) Dims>> shape_; |
|
|
|
|
conditional_t<Dynamic, const ssize_t *, std::array<ssize_t, (size_t) Dims>> strides_; |
|
|
|
|
const size_t dims_; |
|
|
|
|
|
|
|
|
|
friend class pybind11::array; |
|
|
|
|
// Constructor for compile-time dimensions:
|
|
|
|
|
template <bool Dyn = Dynamic> |
|
|
|
|
unchecked_reference(const void *data, const size_t *shape, const size_t *strides, enable_if_t<!Dyn, size_t>) |
|
|
|
|
unchecked_reference(const void *data, const size_t *shape, const ssize_t *strides, enable_if_t<!Dyn, size_t>) |
|
|
|
|
: data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} { |
|
|
|
|
for (size_t i = 0; i < dims_; i++) { |
|
|
|
|
shape_[i] = shape[i]; |
|
|
|
@ -281,7 +281,7 @@ protected:
@@ -281,7 +281,7 @@ protected:
|
|
|
|
|
} |
|
|
|
|
// Constructor for runtime dimensions:
|
|
|
|
|
template <bool Dyn = Dynamic> |
|
|
|
|
unchecked_reference(const void *data, const size_t *shape, const size_t *strides, enable_if_t<Dyn, size_t> dims) |
|
|
|
|
unchecked_reference(const void *data, const size_t *shape, const ssize_t *strides, enable_if_t<Dyn, size_t> dims) |
|
|
|
|
: data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides}, dims_{dims} {} |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
@ -573,12 +573,12 @@ public:
@@ -573,12 +573,12 @@ public:
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Strides of the array
|
|
|
|
|
const size_t* strides() const { |
|
|
|
|
return reinterpret_cast<const size_t *>(detail::array_proxy(m_ptr)->strides); |
|
|
|
|
const ssize_t* strides() const { |
|
|
|
|
return reinterpret_cast<const ssize_t *>(detail::array_proxy(m_ptr)->strides); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Stride along a given axis
|
|
|
|
|
size_t strides(size_t dim) const { |
|
|
|
|
ssize_t strides(size_t dim) const { |
|
|
|
|
if (dim >= ndim()) |
|
|
|
|
fail_dim_check(dim, "invalid axis"); |
|
|
|
|
return strides()[dim]; |
|
|
|
@ -702,9 +702,9 @@ protected:
@@ -702,9 +702,9 @@ protected:
|
|
|
|
|
throw std::domain_error("array is not writeable"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static std::vector<Py_intptr_t> default_strides(const std::vector<Py_intptr_t>& shape, size_t itemsize) { |
|
|
|
|
static std::vector<ssize_t> default_strides(const std::vector<size_t>& shape, size_t itemsize) { |
|
|
|
|
auto ndim = shape.size(); |
|
|
|
|
std::vector<Py_intptr_t> strides(ndim); |
|
|
|
|
std::vector<ssize_t> strides(ndim); |
|
|
|
|
if (ndim) { |
|
|
|
|
std::fill(strides.begin(), strides.end(), itemsize); |
|
|
|
|
for (size_t i = 0; i < ndim - 1; i++) |
|
|
|
@ -1133,7 +1133,7 @@ array_iterator<T> array_end(const buffer_info& buffer) {
@@ -1133,7 +1133,7 @@ array_iterator<T> array_end(const buffer_info& buffer) {
|
|
|
|
|
|
|
|
|
|
class common_iterator { |
|
|
|
|
public: |
|
|
|
|
using container_type = std::vector<size_t>; |
|
|
|
|
using container_type = std::vector<ssize_t>; |
|
|
|
|
using value_type = container_type::value_type; |
|
|
|
|
using size_type = container_type::size_type; |
|
|
|
|
|
|
|
|
@ -1175,7 +1175,7 @@ public:
@@ -1175,7 +1175,7 @@ public:
|
|
|
|
|
for (size_t i = 0; i < shape.size(); ++i) |
|
|
|
|
m_shape[i] = static_cast<container_type::value_type>(shape[i]); |
|
|
|
|
|
|
|
|
|
container_type strides(shape.size()); |
|
|
|
|
std::vector<ssize_t> strides(shape.size()); |
|
|
|
|
for (size_t i = 0; i < N; ++i) |
|
|
|
|
init_common_iterator(buffers[i], shape, m_common_iterator[i], strides); |
|
|
|
|
} |
|
|
|
@ -1203,7 +1203,7 @@ private:
@@ -1203,7 +1203,7 @@ private:
|
|
|
|
|
|
|
|
|
|
void init_common_iterator(const buffer_info &buffer, |
|
|
|
|
const std::vector<size_t> &shape, |
|
|
|
|
common_iter &iterator, container_type &strides) { |
|
|
|
|
common_iter &iterator, std::vector<ssize_t> &strides) { |
|
|
|
|
auto buffer_shape_iter = buffer.shape.rbegin(); |
|
|
|
|
auto buffer_strides_iter = buffer.strides.rbegin(); |
|
|
|
|
auto shape_iter = shape.rbegin(); |
|
|
|
@ -1211,7 +1211,7 @@ private:
@@ -1211,7 +1211,7 @@ private:
|
|
|
|
|
|
|
|
|
|
while (buffer_shape_iter != buffer.shape.rend()) { |
|
|
|
|
if (*shape_iter == *buffer_shape_iter) |
|
|
|
|
*strides_iter = static_cast<size_t>(*buffer_strides_iter); |
|
|
|
|
*strides_iter = *buffer_strides_iter; |
|
|
|
|
else |
|
|
|
|
*strides_iter = 0; |
|
|
|
|
|
|
|
|
@ -1283,10 +1283,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
@@ -1283,10 +1283,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
|
|
|
|
|
|
|
|
|
|
// Check for C contiguity (but only if previous inputs were also C contiguous)
|
|
|
|
|
if (trivial_broadcast_c) { |
|
|
|
|
size_t expect_stride = buffers[i].itemsize; |
|
|
|
|
ssize_t expect_stride = static_cast<ssize_t>(buffers[i].itemsize); |
|
|
|
|
auto end = buffers[i].shape.crend(); |
|
|
|
|
for (auto shape_iter = buffers[i].shape.crbegin(), stride_iter = buffers[i].strides.crbegin(); |
|
|
|
|
trivial_broadcast_c && shape_iter != end; ++shape_iter, ++stride_iter) { |
|
|
|
|
auto shape_iter = buffers[i].shape.crbegin(); |
|
|
|
|
auto stride_iter = buffers[i].strides.crbegin(); |
|
|
|
|
for (; trivial_broadcast_c && shape_iter != end; ++shape_iter, ++stride_iter) { |
|
|
|
|
if (expect_stride == *stride_iter) |
|
|
|
|
expect_stride *= *shape_iter; |
|
|
|
|
else |
|
|
|
@ -1296,10 +1297,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
@@ -1296,10 +1297,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
|
|
|
|
|
|
|
|
|
|
// Check for Fortran contiguity (if previous inputs were also F contiguous)
|
|
|
|
|
if (trivial_broadcast_f) { |
|
|
|
|
size_t expect_stride = buffers[i].itemsize; |
|
|
|
|
ssize_t expect_stride = static_cast<ssize_t>(buffers[i].itemsize); |
|
|
|
|
auto end = buffers[i].shape.cend(); |
|
|
|
|
for (auto shape_iter = buffers[i].shape.cbegin(), stride_iter = buffers[i].strides.cbegin(); |
|
|
|
|
trivial_broadcast_f && shape_iter != end; ++shape_iter, ++stride_iter) { |
|
|
|
|
auto shape_iter = buffers[i].shape.cbegin(); |
|
|
|
|
auto stride_iter = buffers[i].strides.cbegin(); |
|
|
|
|
for (; trivial_broadcast_f && shape_iter != end; ++shape_iter, ++stride_iter) { |
|
|
|
|
if (expect_stride == *stride_iter) |
|
|
|
|
expect_stride *= *shape_iter; |
|
|
|
|
else |
|
|
|
@ -1336,20 +1338,20 @@ struct vectorize_helper {
@@ -1336,20 +1338,20 @@ struct vectorize_helper {
|
|
|
|
|
auto trivial = broadcast(buffers, ndim, shape); |
|
|
|
|
|
|
|
|
|
size_t size = 1; |
|
|
|
|
std::vector<size_t> strides(ndim); |
|
|
|
|
std::vector<ssize_t> strides(ndim); |
|
|
|
|
if (ndim > 0) { |
|
|
|
|
if (trivial == broadcast_trivial::f_trivial) { |
|
|
|
|
strides[0] = sizeof(Return); |
|
|
|
|
strides[0] = static_cast<ssize_t>(sizeof(Return)); |
|
|
|
|
for (size_t i = 1; i < ndim; ++i) { |
|
|
|
|
strides[i] = strides[i - 1] * shape[i - 1]; |
|
|
|
|
strides[i] = strides[i - 1] * static_cast<ssize_t>(shape[i - 1]); |
|
|
|
|
size *= shape[i - 1]; |
|
|
|
|
} |
|
|
|
|
size *= shape[ndim - 1]; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
strides[ndim-1] = sizeof(Return); |
|
|
|
|
strides[ndim-1] = static_cast<ssize_t>(sizeof(Return)); |
|
|
|
|
for (size_t i = ndim - 1; i > 0; --i) { |
|
|
|
|
strides[i - 1] = strides[i] * shape[i]; |
|
|
|
|
strides[i - 1] = strides[i] * static_cast<ssize_t>(shape[i]); |
|
|
|
|
size *= shape[i]; |
|
|
|
|
} |
|
|
|
|
size *= shape[0]; |
|
|
|
|