From feeced6f755c32cd64776e15893de73ccb549abf Mon Sep 17 00:00:00 2001 From: jmabille Date: Fri, 19 Feb 2016 22:26:56 +0100 Subject: [PATCH] short_vector removed and code formatting --- include/pybind11/array_iterator.h | 177 ----------------------- include/pybind11/numpy.h | 231 ++++++++++++++++++++++-------- include/pybind11/short_vector.h | 98 ------------- 3 files changed, 168 insertions(+), 338 deletions(-) delete mode 100644 include/pybind11/array_iterator.h delete mode 100644 include/pybind11/short_vector.h diff --git a/include/pybind11/array_iterator.h b/include/pybind11/array_iterator.h deleted file mode 100644 index 04fd4a748..000000000 --- a/include/pybind11/array_iterator.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - pybind11/array_iter.h: Array iteration support - - Copyright (c) 2016 Johan Mabille - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ -#pragma once - -#include "pybind11.h" -#include "short_vector.h" - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -#endif - -/* - WARNING: These iterators are not a binding to numpy.nditer, they're convenient classes for broadcasting in vectorize -*/ - -NAMESPACE_BEGIN(pybind11) - -template -using array_iterator = typename std::add_pointer::type; - -template -array_iterator array_begin(const buffer_info& buffer) -{ - return array_iterator(reinterpret_cast(buffer.ptr)); -} - -template -array_iterator array_end(const buffer_info& buffer) -{ - return array_iterator(reinterpret_cast(buffer.ptr) + buffer.size); -} - -NAMESPACE_BEGIN(detail) - -template -class common_iterator -{ - -public: - - using container_type = C; - using value_type = typename container_type::value_type; - using size_type = typename container_type::size_type; - - common_iterator() : p_ptr(0), m_strides() {} - common_iterator(void* ptr, const container_type& strides, const std::vector& shape) - : p_ptr(reinterpret_cast(ptr)), m_strides(strides.size()) - { - m_strides.back() = static_cast(strides.back()); - for (size_type i = m_strides.size() - 1; i != 0; --i) - { - size_type j = i - 1; - value_type s = static_cast(shape[i]); - m_strides[j] = strides[j] + m_strides[i] - strides[i] * s; - } - } - - void increment(size_type dim) - { - p_ptr += m_strides[dim]; - } - - void* data() const - { - return p_ptr; - } - -private: - - char* p_ptr; - container_type m_strides; -}; - -NAMESPACE_END(detail) - -template -class multi_array_iterator -{ - -public: - - using container_type = C; - - multi_array_iterator(const std::array& buffers, - const std::vector& shape) - : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() - { - // Manual copy to avoid conversion warning if using std::copy - for (size_t i = 0; i < shape.size(); ++i) - { - m_shape[i] = static_cast(shape[i]); - } - - container_type strides(shape.size()); - for (size_t i = 0; i < N; ++i) - { - init_common_iterator(buffers[i], shape, m_common_iterator[i], strides); - } - } - - multi_array_iterator& operator++() - { - for (size_t j = m_index.size(); j != 0; --j) - { - size_t i = j - 1; - if (++m_index[i] != m_shape[i]) - { - increment_common_iterator(i); - break; - } - else - { - m_index[i] = 0; - } - } - return *this; - } - - template - const T& data() const - { - return *reinterpret_cast(m_common_iterator[K].data()); - } - -private: - - using common_iter = detail::common_iterator; - - void init_common_iterator(const buffer_info& buffer, const std::vector& shape, common_iter& iterator, container_type& strides) - { - auto buffer_shape_iter = buffer.shape.rbegin(); - auto buffer_strides_iter = buffer.strides.rbegin(); - auto shape_iter = shape.rbegin(); - auto strides_iter = strides.rbegin(); - - while (buffer_shape_iter != buffer.shape.rend()) - { - if (*shape_iter == *buffer_shape_iter) - *strides_iter = static_cast(*buffer_strides_iter); - else - *strides_iter = 0; - - ++buffer_shape_iter; - ++buffer_strides_iter; - ++shape_iter; - ++strides_iter; - } - - std::fill(strides_iter, strides.rend(), 0); - iterator = common_iter(buffer.ptr, strides, shape); - } - - void increment_common_iterator(size_t dim) - { - std::for_each(m_common_iterator.begin(), m_common_iterator.end(), [=](common_iter& iter) - { - iter.increment(dim); - }); - } - - container_type m_shape; - container_type m_index; - std::array m_common_iterator; -}; - -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index b1506fd45..44a0cb1c4 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -11,8 +11,8 @@ #include "pybind11.h" #include "complex.h" -#include "array_iterator.h" #include +#include #if defined(_MSC_VER) #pragma warning(push) @@ -148,37 +148,154 @@ DECL_FMT(std::complex, NPY_CDOUBLE_); NAMESPACE_BEGIN(detail) +template +using array_iterator = typename std::add_pointer::type; + +template +array_iterator array_begin(const buffer_info& buffer) { + return array_iterator(reinterpret_cast(buffer.ptr)); +} + +template +array_iterator array_end(const buffer_info& buffer) { + return array_iterator(reinterpret_cast(buffer.ptr) + buffer.size); +} + +class common_iterator { + +public: + + using container_type = std::vector; + using value_type = container_type::value_type; + using size_type = container_type::size_type; + + common_iterator() : p_ptr(0), m_strides() {} + common_iterator(void* ptr, const container_type& strides, const std::vector& shape) + : p_ptr(reinterpret_cast(ptr)), m_strides(strides.size()) { + m_strides.back() = static_cast(strides.back()); + for (size_type i = m_strides.size() - 1; i != 0; --i) { + size_type j = i - 1; + value_type s = static_cast(shape[i]); + m_strides[j] = strides[j] + m_strides[i] - strides[i] * s; + } + } + + void increment(size_type dim) { + p_ptr += m_strides[dim]; + } + + void* data() const { + return p_ptr; + } + +private: + + char* p_ptr; + container_type m_strides; +}; + +template +class multi_array_iterator { + +public: + + using container_type = std::vector; + + multi_array_iterator(const std::array& buffers, + const std::vector& shape) + : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() { + // Manual copy to avoid conversion warning if using std::copy + for (size_t i = 0; i < shape.size(); ++i) { + m_shape[i] = static_cast(shape[i]); + } + + container_type strides(shape.size()); + for (size_t i = 0; i < N; ++i) { + init_common_iterator(buffers[i], shape, m_common_iterator[i], strides); + } + } + + multi_array_iterator& operator++() { + for (size_t j = m_index.size(); j != 0; --j) { + size_t i = j - 1; + if (++m_index[i] != m_shape[i]) { + increment_common_iterator(i); + break; + } + else { + m_index[i] = 0; + } + } + return *this; + } + + template + const T& data() const { + return *reinterpret_cast(m_common_iterator[K].data()); + } + +private: + + using common_iter = common_iterator; + + void init_common_iterator(const buffer_info& buffer, const std::vector& shape, common_iter& iterator, container_type& strides) { + auto buffer_shape_iter = buffer.shape.rbegin(); + auto buffer_strides_iter = buffer.strides.rbegin(); + auto shape_iter = shape.rbegin(); + auto strides_iter = strides.rbegin(); + + while (buffer_shape_iter != buffer.shape.rend()) { + if (*shape_iter == *buffer_shape_iter) + *strides_iter = static_cast(*buffer_strides_iter); + else + *strides_iter = 0; + + ++buffer_shape_iter; + ++buffer_strides_iter; + ++shape_iter; + ++strides_iter; + } + + std::fill(strides_iter, strides.rend(), 0); + iterator = common_iter(buffer.ptr, strides, shape); + } + + void increment_common_iterator(size_t dim) { + std::for_each(m_common_iterator.begin(), m_common_iterator.end(), [=](common_iter& iter) { + iter.increment(dim); + }); + } + + container_type m_shape; + container_type m_index; + std::array m_common_iterator; +}; + template struct handle_type_name> { static PYBIND11_DESCR name() { return _("array[") + type_caster::name() + _("]"); } }; template -bool broadcast(const std::array& buffers, int& ndim, std::vector& shape) -{ - ndim = std::accumulate(buffers.begin(), buffers.end(), 0, [](int res, const buffer_info& buf) - { - return std::max(res, buf.ndim); +bool broadcast(const std::array& buffers, int& ndim, std::vector& shape) { + ndim = std::accumulate(buffers.begin(), buffers.end(), 0, [](int res, const buffer_info& buf) { + return std::max(res, buf.ndim); }); shape = std::vector(static_cast(ndim), 1); bool trivial_broadcast = true; - for (size_t i = 0; i < N; ++i) - { - auto res_iter = shape.rbegin(); - bool i_trivial_broadcast = (buffers[i].size == 1) || (buffers[i].ndim == ndim); - for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != buffers[i].shape.rend(); ++shape_iter, ++res_iter) - { - if (*res_iter == 1) - { + for (size_t i = 0; i < N; ++i) { + auto res_iter = shape.rbegin(); + bool i_trivial_broadcast = (buffers[i].size == 1) || (buffers[i].ndim == ndim); + for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != buffers[i].shape.rend(); ++shape_iter, ++res_iter) { + if (*res_iter == 1) { *res_iter = *shape_iter; - } - else if ((*shape_iter != 1) && (*res_iter != *shape_iter)) - { + } + else if ((*shape_iter != 1) && (*res_iter != *shape_iter)) { pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!"); - } - i_trivial_broadcast = i_trivial_broadcast && (*res_iter == *shape_iter); - } - trivial_broadcast = trivial_broadcast && i_trivial_broadcast; + } + i_trivial_broadcast = i_trivial_broadcast && (*res_iter == *shape_iter); + } + trivial_broadcast = trivial_broadcast && i_trivial_broadcast; } return trivial_broadcast; } @@ -197,26 +314,23 @@ struct vectorize_helper { template object run(array_t&... args, index_sequence index) { /* Request buffers from all parameters */ const size_t N = sizeof...(Args); - constexpr size_t SMALL_DIM = 4; std::array buffers {{ args.request()... }}; /* Determine dimensions parameters of output array */ - int ndim = 0; - std::vector shape(0); - bool trivial_broadcast = broadcast(buffers, ndim, shape); - - size_t size = 1; + int ndim = 0; + std::vector shape(0); + bool trivial_broadcast = broadcast(buffers, ndim, shape); + + size_t size = 1; std::vector strides(ndim); - if (ndim > 0) - { + if (ndim > 0) { strides[ndim-1] = sizeof(Return); - for (int i = ndim - 1; i > 0; --i) - { - strides[i - 1] = strides[i] * shape[i]; - size *= shape[i]; - } - size *= shape[0]; + for (int i = ndim - 1; i > 0; --i) { + strides[i - 1] = strides[i] * shape[i]; + size *= shape[i]; + } + size *= shape[0]; } if (size == 1) @@ -229,41 +343,32 @@ struct vectorize_helper { buffer_info buf = result.request(); Return *output = (Return *) buf.ptr; - if(trivial_broadcast) - { - /* Call the function */ - for (size_t i=0; i, N, Index...>(buffers, buf, index); - } - else - { - apply_broadcast, N, Index...>(buffers, buf, index); - } + } + else { + apply_broadcast(buffers, buf, index); + } return result; } - template - void apply_broadcast(const std::array& buffers, buffer_info& output, index_sequence) - { - using input_iterator = multi_array_iterator; - using output_iterator = array_iterator; + template + void apply_broadcast(const std::array& buffers, buffer_info& output, index_sequence) { + using input_iterator = multi_array_iterator; + using output_iterator = array_iterator; - input_iterator input_iter(buffers, output.shape); - output_iterator output_end = array_end(output); + input_iterator input_iter(buffers, output.shape); + output_iterator output_end = array_end(output); - for (output_iterator iter = array_begin(output); iter != output_end; ++iter, ++input_iter) - { - *iter = f((input_iter.template data())...); - } + for (output_iterator iter = array_begin(output); iter != output_end; ++iter, ++input_iter) { + *iter = f((input_iter.template data())...); + } } }; diff --git a/include/pybind11/short_vector.h b/include/pybind11/short_vector.h deleted file mode 100644 index 5df02ef3e..000000000 --- a/include/pybind11/short_vector.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - pybind11/short_vector.h: similar to std::array but with dynamic size - - Copyright (c) 2016 Johan Mabille - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include -#include - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -#endif - -NAMESPACE_BEGIN(pybind11) - -template -class short_vector -{ - -public: - - using data_type = std::array; - using value_type = typename data_type::value_type; - using size_type = typename data_type::size_type; - using difference_type = typename data_type::difference_type; - using reference = typename data_type::reference; - using const_reference = typename data_type::const_reference; - using pointer = typename data_type::pointer; - using const_pointer = typename data_type::const_pointer; - using iterator = typename data_type::iterator; - using const_iterator = typename data_type::const_iterator; - using reverse_iterator = typename data_type::reverse_iterator; - using const_reverse_iterator = typename data_type::const_reverse_iterator; - - short_vector() : m_data(), m_size(0) {} - explicit short_vector(size_type size) : m_data(), m_size(size) {} - short_vector(size_type size, const_reference t) : m_data(), m_size(size) - { - std::fill(begin(), end(), t); - } - - size_type size() const noexcept { return m_size; } - constexpr size_type max_size() const noexcept { return m_data.max_size(); } - bool empty() const noexcept { return m_size == 0; } - - void resize(size_type size) { m_size = size; } - void resize(size_type size, const_reference t) - { - size_type old_size = m_size; - resize(size); - std::fill(begin() + old_size, end(), t); - } - - reference operator[](size_type i) { return m_data[i]; } - const_reference operator[](size_type i) const { return m_data[i]; } - - reference front() { return m_data[0]; } - const_reference front() const { return m_data[0]; } - - reference back() { return m_data[m_size - 1]; } - const_reference back() const { return m_data[m_size - 1]; } - - void fill(const_reference t) { std::fill(begin(), end(), t); } - - iterator begin() noexcept { return m_data.begin(); } - const_iterator begin() const noexcept { return m_data.begin(); } - iterator end() noexcept { return begin() + m_size; } - const_iterator end() const noexcept { return begin() + m_size(); } - - reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - - const_iterator cbegin() const noexcept { return begin(); } - const_iterator cend() const noexcept { return end(); } - const_reverse_iterator crbegin() const noexcept { return rbegin(); } - const_reverse_iterator crend() const noexcept { return rend(); } - -private: - - data_type m_data; - size_type m_size; - -}; - -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif