33static_assert(
sizeof(::pybind11::ssize_t) ==
sizeof(Py_intptr_t),
"ssize_t != Py_intptr_t");
34static_assert(std::is_signed<Py_intptr_t>::value,
"Py_intptr_t must be signed");
48template <
typename type,
typename SFINAE =
void>
97 if (throw_if_missing) {
98 pybind11_fail(std::string(
"NumPy type info missing for ") + tinfo.name());
103 template <
typename T>
105 return get_type_info(
typeid(
typename std::remove_cv<T>::type), throw_if_missing);
110 ptr = &get_or_create_shared_data<numpy_internals>(
"_numpy_internals");
123 template <
typename U>
127template <
typename Concrete>
133template <
typename Concrete,
typename T,
typename... Ts,
typename... Ints>
135 return sizeof(Concrete) ==
sizeof(T) ? I :
platform_lookup<Concrete, Ts...>(Is...);
178 NPY_UINT32_ = platform_lookup<std::uint32_t, unsigned long, unsigned int, unsigned short>(
183 = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
205 PyObject *(*PyArray_DescrFromType_)(int);
206 PyObject *(*PyArray_NewFromDescr_)(PyTypeObject *,
215 PyObject *(*PyArray_DescrNewFromType_)(int);
217 PyObject *(*PyArray_NewCopy_)(PyObject *, int);
221 PyObject *(*PyArray_DescrFromScalar_)(PyObject *);
222 PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int, int, int, PyObject *);
233 PyObject *(*PyArray_Squeeze_)(PyObject *);
238 PyObject *(*PyArray_View_)(PyObject *, PyObject *, PyObject *);
265 auto c = m.attr(
"_ARRAY_API");
266#if PY_MAJOR_VERSION >= 3
267 void **api_ptr = (
void **) PyCapsule_GetPointer(c.ptr(), NULL);
269 void **api_ptr = (
void **) PyCObject_AsVoidPtr(c.ptr());
272#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
274 if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
275 pybind11_fail(
"pybind11 numpy support requires numpy >= 1.7.0");
321template <
typename T,
size_t N>
341template <
typename T,
size_t N>
346 static constexpr size_t extent = N;
354 static constexpr auto extents = const_name<array_info<T>::is_array>(
363template <
typename T,
size_t N>
372#if defined(__GLIBCXX__) \
373 && (__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20150426 || __GLIBCXX__ == 20150623 \
374 || __GLIBCXX__ == 20150626 || __GLIBCXX__ == 20160803)
377 std::is_trivially_destructible<T>,
380 std::is_trivially_copyable<T>,
394template <s
size_t Dim = 0,
typename Str
ides>
398template <
ssize_t Dim = 0,
typename Strides,
typename... Ix>
400 return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
408template <
typename T, s
size_t Dims>
420 template <
bool Dyn = Dynamic>
425 :
data_{reinterpret_cast<const unsigned char *>(
data)},
dims_{Dims} {
432 template <
bool Dyn = Dynamic>
446 template <
typename... Ix>
449 "Invalid number of indices for unchecked array reference");
450 return *
reinterpret_cast<const T *
>(
data_
457 template <s
size_t D = Dims,
typename = enable_if_t<D == 1 || Dynamic>>
463 template <
typename... Ix>
464 const T *
data(Ix... ix)
const {
479 template <
bool Dyn = Dynamic>
481 return std::accumulate(
484 template <
bool Dyn = Dynamic>
495template <
typename T, s
size_t Dims>
499 using ConstBase::ConstBase;
504 using ConstBase::operator();
505 using ConstBase::operator[];
508 template <
typename... Ix>
511 "Invalid number of indices for unchecked array reference");
519 template <s
size_t D = Dims,
typename = enable_if_t<D == 1 || Dynamic>>
525 template <
typename... Ix>
531template <
typename T, s
size_t Dim>
533 static_assert(Dim == 0 && Dim > 0 ,
534 "unchecked array proxy object is not castable");
536template <
typename T, s
size_t Dim>
554 explicit dtype(
const std::string &format) {
555 m_ptr = from_args(pybind11::str(format)).release().ptr();
562 args[
"names"] = std::move(names);
563 args[
"formats"] = std::move(formats);
564 args[
"offsets"] = std::move(offsets);
565 args[
"itemsize"] = pybind11::int_(itemsize);
566 m_ptr = from_args(std::move(
args)).release().ptr();
571 PyObject *ptr =
nullptr;
572 if ((detail::npy_api::get().PyArray_DescrConverter_(
args.
ptr(), &ptr) == 0) || !ptr) {
575 return reinterpret_steal<dtype>(ptr);
579 template <
typename T>
581 return detail::npy_format_descriptor<typename std::remove_cv<T>::type>
::dtype();
588 bool has_fields()
const {
return detail::array_descriptor_proxy(m_ptr)->names !=
nullptr; }
592 char kind()
const {
return detail::array_descriptor_proxy(m_ptr)->kind; }
600 return detail::array_descriptor_proxy(m_ptr)->type;
606 .attr(
"_dtype_from_pep3118")
610 return reinterpret_borrow<object>(obj);
623 pybind11::int_ offset;
625 std::vector<field_descr> field_descriptors;
627 for (
auto field : attr(
"fields").attr(
"items")()) {
628 auto spec = field.cast<
tuple>();
629 auto name = spec[0].cast<pybind11::str>();
630 auto format = spec[1].cast<
tuple>()[0].cast<dtype>();
631 auto offset = spec[1].cast<
tuple>()[1].cast<pybind11::int_>();
632 if ((
len(
name) == 0u) && format.kind() ==
'V') {
635 field_descriptors.push_back(
639 std::sort(field_descriptors.begin(),
640 field_descriptors.end(),
641 [](
const field_descr &a,
const field_descr &b) {
642 return a.offset.cast<int>() < b.offset.cast<int>();
645 list names, formats, offsets;
646 for (
auto &
descr : field_descriptors) {
651 return dtype(std::move(names), std::move(formats), std::move(offsets), itemsize);
660 c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
661 f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
662 forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
674 const void *
ptr =
nullptr,
683 pybind11_fail(
"NumPy: shape ndim doesn't match strides ndim");
689 if (isinstance<array>(
base)) {
691 flags = reinterpret_borrow<array>(
base).flags()
695 flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
699 auto &api = detail::npy_api::get();
700 auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
702 descr.release().ptr(),
705 reinterpret_cast<Py_intptr_t *
>(
shape->data()),
706 reinterpret_cast<Py_intptr_t *
>(
strides->data()),
707 const_cast<void *
>(
ptr),
715 api.PyArray_SetBaseObject_(tmp.ptr(),
base.inc_ref().ptr());
717 tmp = reinterpret_steal<object>(
718 api.PyArray_NewCopy_(tmp.ptr(), -1 ));
721 m_ptr = tmp.release().ptr();
726 const void *
ptr =
nullptr,
730 template <
typename T,
732 = detail::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
736 template <
typename T>
740 template <
typename T>
744 template <
typename T>
753 return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(
m_ptr)->
descr);
763 return detail::array_descriptor_proxy(detail::array_proxy(
m_ptr)->
descr)->elsize;
773 object base()
const {
return reinterpret_borrow<object>(detail::array_proxy(
m_ptr)->
base); }
798 int flags()
const {
return detail::array_proxy(
m_ptr)->flags; }
802 return detail::check_flags(
m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_);
807 return detail::check_flags(
m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_);
812 template <
typename... Ix>
813 const void *
data(Ix... index)
const {
814 return static_cast<const void *
>(detail::array_proxy(
m_ptr)->data +
offset_at(index...));
820 template <
typename... Ix>
823 return static_cast<void *
>(detail::array_proxy(
m_ptr)->data +
offset_at(index...));
828 template <
typename... Ix>
831 fail_dim_check(
sizeof...(index),
"too many indices for an array");
840 template <
typename... Ix>
851 template <
typename T,
ssize_t Dims = -1>
854 throw std::domain_error(
"array has incorrect number of dimensions: "
855 + std::to_string(
ndim()) +
"; expected "
856 + std::to_string(Dims));
858 return detail::unchecked_mutable_reference<T, Dims>(
869 template <
typename T,
ssize_t Dims = -1>
870 detail::unchecked_reference<T, Dims>
unchecked() const & {
872 throw std::domain_error(
"array has incorrect number of dimensions: "
873 + std::to_string(
ndim()) +
"; expected "
874 + std::to_string(Dims));
881 auto &api = detail::npy_api::get();
882 return reinterpret_steal<array>(api.PyArray_Squeeze_(
m_ptr));
889 detail::npy_api::PyArray_Dims d
891 reinterpret_cast<Py_intptr_t *
>(new_shape->data()),
892 int(new_shape->size())};
894 auto new_array = reinterpret_steal<object>(
895 detail::npy_api::get().PyArray_Resize_(
m_ptr, &d,
int(refcheck), -1));
899 if (isinstance<array>(new_array)) {
900 *
this = std::move(new_array);
906 detail::npy_api::PyArray_Dims d
907 = {
reinterpret_cast<Py_intptr_t *
>(new_shape->data()),
int(new_shape->size())};
909 = reinterpret_steal<array>(detail::npy_api::get().PyArray_Newshape_(
m_ptr, &d, 0));
922 auto &api = detail::npy_api::get();
923 auto new_view = reinterpret_steal<array>(api.PyArray_View_(
934 auto result = reinterpret_steal<array>(
raw_array(h.
ptr(), ExtraFlags));
942 template <
typename,
typename>
946 throw index_error(msg +
": " + std::to_string(dim) +
" (ndim = " + std::to_string(
ndim())
950 template <
typename... Ix>
958 throw std::domain_error(
"array is not writeable");
962 template <
typename... Ix>
969 template <
typename... Ix>
972 throw index_error(std::string(
"index ") + std::to_string(i)
973 +
" is out of bounds for axis " + std::to_string(axis)
974 +
" with size " + std::to_string(*
shape));
981 if (
ptr ==
nullptr) {
982 PyErr_SetString(PyExc_ValueError,
"cannot create a pybind11::array from a nullptr");
985 return detail::npy_api::get().PyArray_FromAny_(
986 ptr,
nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags,
nullptr);
990template <
typename T,
int ExtraFlags = array::forcecast>
1003 static_assert(!detail::array_info<T>::is_array,
"Array types cannot be used with array_t");
1017 Py_XDECREF(h.ptr());
1032 const T *
ptr =
nullptr,
1049 template <
typename... Ix>
1054 template <
typename... Ix>
1056 return static_cast<const T *
>(
array::data(index...));
1059 template <
typename... Ix>
1065 template <
typename... Ix>
1066 const T &
at(Ix... index)
const {
1075 template <
typename... Ix>
1092 return array::mutable_unchecked<T, Dims>();
1104 return array::unchecked<T, Dims>();
1118 const auto &api = detail::npy_api::get();
1119 return api.PyArray_Check_(h.
ptr())
1120 && api.PyArray_EquivTypes_(detail::array_proxy(h.
ptr())->descr,
1121 dtype::of<T>().ptr())
1128 if (
ptr ==
nullptr) {
1129 PyErr_SetString(PyExc_ValueError,
"cannot create a pybind11::array_t from a nullptr");
1132 return detail::npy_api::get().PyArray_FromAny_(
ptr,
1136 detail::npy_api::NPY_ARRAY_ENSUREARRAY_
1142template <
typename T>
1145 return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::format();
1151 static std::string
format() {
return std::to_string(N) +
"s"; }
1155 static std::string
format() {
return std::to_string(N) +
"s"; }
1158template <
typename T>
1162 typename std::remove_cv<typename std::underlying_type<T>::type>
::type>::format();
1166template <
typename T>
1169 using namespace detail;
1176template <
typename T,
int ExtraFlags>
1181 if (!convert && !type::check_(src)) {
1184 value = type::ensure(src);
1185 return static_cast<bool>(value);
1194template <
typename T>
1201template <
typename T,
typename =
void>
1204template <
typename T>
1206 static constexpr auto name = const_name<std::is_same<T, bool>::value>(
1208 const_name<std::is_signed<T>::value>(
"numpy.int",
"numpy.uint")
1209 + const_name<
sizeof(T) * 8>());
1212template <
typename T>
1214 static constexpr auto name = const_name < std::is_same<T, float>::value
1215 || std::is_same<T, const float>::value
1216 || std::is_same<T, double>::value
1217 || std::is_same<T, const double>::value
1218 > (
const_name(
"numpy.float") + const_name<sizeof(T) * 8>(),
1222template <
typename T>
1224 static constexpr auto name = const_name < std::is_same<typename T::value_type, float>::value
1225 || std::is_same<typename T::value_type, const float>::value
1226 || std::is_same<typename T::value_type, double>::value
1227 || std::is_same<typename T::value_type, const double>::value
1229 + const_name<sizeof(typename T::value_type) * 16>(),
1233template <
typename T>
1257 static constexpr int value = values[detail::is_fmt_numeric<T>::index];
1260 if (
auto *ptr =
npy_api::get().PyArray_DescrFromType_(value)) {
1261 return reinterpret_steal<pybind11::dtype>(ptr);
1267#define PYBIND11_DECL_CHAR_FMT \
1268 static constexpr auto name = const_name("S") + const_name<N>(); \
1269 static pybind11::dtype dtype() { \
1270 return pybind11::dtype(std::string("S") + std::to_string(N)); \
1280#undef PYBIND11_DECL_CHAR_FMT
1282template <
typename T>
1295 return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape));
1299template <
typename T>
1305 static constexpr auto name = base_descr::name;
1306 static pybind11::dtype
dtype() {
return base_descr::dtype(); }
1318 const std::type_info &tinfo,
1320 bool (*direct_converter)(PyObject *,
void *&)) {
1329 std::vector<field_descriptor> ordered_fields(std::move(fields));
1331 ordered_fields.begin(),
1332 ordered_fields.end(),
1335 list names, formats, offsets;
1336 for (
auto &field : ordered_fields) {
1338 pybind11_fail(std::string(
"NumPy: unsupported field dtype: `") + field.name +
"` @ "
1342 formats.
append(field.descr);
1343 offsets.
append(pybind11::int_(field.offset));
1346 = pybind11::dtype(std::move(names), std::move(formats), std::move(offsets), itemsize)
1358 std::ostringstream oss;
1365 for (
auto &field : ordered_fields) {
1366 if (field.offset > offset) {
1367 oss << (field.offset - offset) <<
'x';
1369 oss << field.format <<
':' << field.name <<
':';
1370 offset = field.offset + field.size;
1372 if (itemsize > offset) {
1373 oss << (itemsize - offset) <<
'x';
1376 auto format_str = oss.str();
1381 if (!api.PyArray_EquivTypes_(dtype_ptr,
arr.dtype().ptr())) {
1385 auto tindex = std::type_index(tinfo);
1390template <
typename T,
typename SFINAE>
1393 "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1397 static pybind11::dtype
dtype() {
return reinterpret_borrow<pybind11::dtype>(
dtype_ptr()); }
1406 typeid(
typename std::remove_cv<T>::type),
1419 if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) {
1422 if (
auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1433# define PYBIND11_NUMPY_DTYPE(Type, ...) ((void) 0)
1434# define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void) 0)
1437# define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
1438 ::pybind11::detail::field_descriptor { \
1439 Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
1440 ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
1441 ::pybind11::detail::npy_format_descriptor< \
1442 decltype(std::declval<T>().Field)>::dtype() \
1446# define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, # Field)
1450# define PYBIND11_EVAL0(...) __VA_ARGS__
1451# define PYBIND11_EVAL1(...) PYBIND11_EVAL0(PYBIND11_EVAL0(PYBIND11_EVAL0(__VA_ARGS__)))
1452# define PYBIND11_EVAL2(...) PYBIND11_EVAL1(PYBIND11_EVAL1(PYBIND11_EVAL1(__VA_ARGS__)))
1453# define PYBIND11_EVAL3(...) PYBIND11_EVAL2(PYBIND11_EVAL2(PYBIND11_EVAL2(__VA_ARGS__)))
1454# define PYBIND11_EVAL4(...) PYBIND11_EVAL3(PYBIND11_EVAL3(PYBIND11_EVAL3(__VA_ARGS__)))
1455# define PYBIND11_EVAL(...) PYBIND11_EVAL4(PYBIND11_EVAL4(PYBIND11_EVAL4(__VA_ARGS__)))
1456# define PYBIND11_MAP_END(...)
1457# define PYBIND11_MAP_OUT
1458# define PYBIND11_MAP_COMMA ,
1459# define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END
1460# define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
1461# define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0(test, next, 0)
1462# define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1(PYBIND11_MAP_GET_END test, next)
1463# if defined(_MSC_VER) \
1464 && !defined(__clang__)
1465# define PYBIND11_MAP_LIST_NEXT1(test, next) \
1466 PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1468# define PYBIND11_MAP_LIST_NEXT1(test, next) \
1469 PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1471# define PYBIND11_MAP_LIST_NEXT(test, next) \
1472 PYBIND11_MAP_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1473# define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \
1474 f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST1)(f, t, peek, __VA_ARGS__)
1475# define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
1476 f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST0)(f, t, peek, __VA_ARGS__)
1478# define PYBIND11_MAP_LIST(f, t, ...) \
1479 PYBIND11_EVAL(PYBIND11_MAP_LIST1(f, t, __VA_ARGS__, (), 0))
1481# define PYBIND11_NUMPY_DTYPE(Type, ...) \
1482 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1483 ::std::vector<::pybind11::detail::field_descriptor>{ \
1484 PYBIND11_MAP_LIST(PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
1486# if defined(_MSC_VER) && !defined(__clang__)
1487# define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1488 PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1490# define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1491 PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1493# define PYBIND11_MAP2_LIST_NEXT(test, next) \
1494 PYBIND11_MAP2_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1495# define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
1496 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST1)(f, t, peek, __VA_ARGS__)
1497# define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
1498 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST0)(f, t, peek, __VA_ARGS__)
1500# define PYBIND11_MAP2_LIST(f, t, ...) \
1501 PYBIND11_EVAL(PYBIND11_MAP2_LIST1(f, t, __VA_ARGS__, (), 0))
1503# define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
1504 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1505 ::std::vector<::pybind11::detail::field_descriptor>{ \
1506 PYBIND11_MAP2_LIST(PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
1519 :
p_ptr(reinterpret_cast<char *>(ptr)),
m_strides(strides.size()) {
1546 for (
size_t i = 0; i < shape.size(); ++i) {
1551 for (
size_t i = 0; i < N; ++i) {
1557 for (
size_t j =
m_index.size(); j != 0; --j) {
1568 template <
size_t K,
class T =
void>
1580 auto buffer_shape_iter =
buffer.shape.rbegin();
1581 auto buffer_strides_iter =
buffer.strides.rbegin();
1582 auto shape_iter = shape.rbegin();
1583 auto strides_iter = strides.rbegin();
1585 while (buffer_shape_iter !=
buffer.shape.rend()) {
1586 if (*shape_iter == *buffer_shape_iter) {
1587 *strides_iter = *buffer_strides_iter;
1592 ++buffer_shape_iter;
1593 ++buffer_strides_iter;
1598 std::fill(strides_iter, strides.rend(), 0);
1604 iter.increment(dim);
1621broadcast(
const std::array<buffer_info, N> &buffers,
ssize_t &ndim, std::vector<ssize_t> &shape) {
1622 ndim = std::accumulate(
1624 return std::max(res, buf.
ndim);
1628 shape.resize((
size_t) ndim, 1);
1632 for (
size_t i = 0; i < N; ++i) {
1633 auto res_iter = shape.rbegin();
1634 auto end = buffers[i].shape.rend();
1635 for (
auto shape_iter = buffers[i].shape.rbegin(); shape_iter != end;
1636 ++shape_iter, ++res_iter) {
1637 const auto &dim_size_in = *shape_iter;
1638 auto &dim_size_out = *res_iter;
1642 if (dim_size_out == 1) {
1643 dim_size_out = dim_size_in;
1644 }
else if (dim_size_in != 1 && dim_size_in != dim_size_out) {
1645 pybind11_fail(
"pybind11::vectorize: incompatible size/dimension of inputs!");
1650 bool trivial_broadcast_c =
true;
1651 bool trivial_broadcast_f =
true;
1652 for (
size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
1653 if (buffers[i].size == 1) {
1658 if (buffers[i].ndim != ndim) {
1663 if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin())) {
1668 if (trivial_broadcast_c) {
1669 ssize_t expect_stride = buffers[i].itemsize;
1670 auto end = buffers[i].shape.crend();
1671 for (
auto shape_iter = buffers[i].shape.crbegin(),
1672 stride_iter = buffers[i].strides.crbegin();
1673 trivial_broadcast_c && shape_iter != end;
1674 ++shape_iter, ++stride_iter) {
1675 if (expect_stride == *stride_iter) {
1676 expect_stride *= *shape_iter;
1678 trivial_broadcast_c =
false;
1684 if (trivial_broadcast_f) {
1685 ssize_t expect_stride = buffers[i].itemsize;
1686 auto end = buffers[i].shape.cend();
1687 for (
auto shape_iter = buffers[i].shape.cbegin(),
1688 stride_iter = buffers[i].strides.cbegin();
1689 trivial_broadcast_f && shape_iter != end;
1690 ++shape_iter, ++stride_iter) {
1691 if (expect_stride == *stride_iter) {
1692 expect_stride *= *shape_iter;
1694 trivial_broadcast_f =
false;
1705template <
typename T>
1707 static_assert(!std::is_rvalue_reference<T>::value,
1708 "Functions with rvalue reference arguments cannot be vectorized");
1718 std::is_enum>::value
1719 && (!std::is_reference<T>::value
1720 || (std::is_lvalue_reference<T>::value && std::is_const<call_type>::value));
1726template <
typename Func,
typename Return,
typename... Args>
1731 if (trivial == broadcast_trivial::f_trivial) {
1741 static void call(Return *out,
size_t i, Func &f, Args &...
args) { out[i] = f(
args...); }
1745template <
typename Func,
typename... Args>
1753 static detail::void_type
call(Func &f, Args &...
args) {
1761template <
typename Func,
typename Return,
typename... Args>
1771 static constexpr size_t N =
sizeof...(Args);
1775 "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1778 template <
typename T,
1780 typename = detail::enable_if_t<
1781 !std::is_same<vectorize_helper, typename std::decay<T>::type>::value>>
1797 template <
size_t Index>
1798 using param_n_t =
typename std::tuple_element<Index, arg_call_types>::type;
1809 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
1818 std::array<void *, N> params{{&
args...}};
1821 std::array<buffer_info, NVectorized> buffers{
1822 {
reinterpret_cast<array *
>(params[VIndex])->request()...}};
1826 std::vector<ssize_t> shape(0);
1827 auto trivial =
broadcast(buffers, nd, shape);
1831 = std::accumulate(shape.begin(), shape.end(), (
size_t) 1, std::multiplies<size_t>());
1835 if (size == 1 && ndim == 0) {
1844 return std::move(result);
1849 if (trivial == broadcast_trivial::non_trivial) {
1850 apply_broadcast(buffers, params, mutable_data, size, shape, i_seq, vi_seq, bi_seq);
1852 apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
1855 return std::move(result);
1858 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
1860 std::array<void *, N> ¶ms,
1870 std::array<std::pair<unsigned char *&, const size_t>,
NVectorized> vecparams{
1871 {std::pair<unsigned char *&, const size_t>(
1872 reinterpret_cast<unsigned char *&
>(params[VIndex] = buffers[BIndex].ptr),
1875 for (
size_t i = 0; i < size; ++i) {
1878 for (
auto &x : vecparams) {
1879 x.first += x.second;
1884 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
1886 std::array<void *, N> ¶ms,
1889 const std::vector<ssize_t> &output_shape,
1896 for (
size_t i = 0; i < size; ++i, ++input_iter) {
1904template <
typename Func,
typename Return,
typename... Args>
1906 return detail::vectorize_helper<Func, Return, Args...>(f);
1909template <
typename T,
int Flags>
1918template <
typename Return,
typename... Args>
1919detail::vectorize_helper<Return (*)(Args...), Return, Args...>
vectorize(Return (*f)(Args...)) {
1920 return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f);
1924template <typename Func, detail::enable_if_t<detail::is_lambda<Func>::value,
int> = 0>
1926 ->
decltype(detail::vectorize_extractor(std::forward<Func>(f),
1927 (detail::function_signature_t<Func> *)
nullptr)) {
1928 return detail::vectorize_extractor(std::forward<Func>(f),
1929 (detail::function_signature_t<Func> *)
nullptr);
1933template <
typename Return,
1936 typename Helper = detail::vectorize_helper<
1937 decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())),
1942 return Helper(std::mem_fn(f));
1946template <
typename Return,
1949 typename Helper = detail::vectorize_helper<
1950 decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)
const>())),
1954Helper
vectorize(Return (Class::*f)(Args...)
const) {
1955 return Helper(std::mem_fn(f));
array_t(handle h, borrowed_t)
const T * data(Ix... index) const
T * mutable_data(Ix... index)
ssize_t index_at(Ix... index) const
const T & at(Ix... index) const
array_t(ssize_t count, const T *ptr=nullptr, handle base=handle())
static PyObject * raw_array_t(PyObject *ptr)
Create array from any object – always returns a new reference.
T & mutable_at(Ix... index)
constexpr ssize_t itemsize() const
array_t(handle h, stolen_t)
array_t(ShapeContainer shape, const T *ptr=nullptr, handle base=handle())
static bool check_(handle h)
static array_t ensure(handle h)
Ensure that the argument is a NumPy array of the correct dtype (and if not, try to convert it).
array_t(ShapeContainer shape, StridesContainer strides, const T *ptr=nullptr, handle base=handle())
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Returns a proxy object that provides access to the array's data without bounds or dimensionality chec...
detail::unchecked_reference< T, Dims > unchecked() const &
Returns a proxy object that provides const access to the array's data without bounds or dimensionalit...
array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
array_t(const buffer_info &info, handle base=handle())
ssize_t offset_at(Ix... index) const
Byte offset from beginning of the array to a given index (full or partial).
void fail_dim_check(ssize_t dim, const std::string &msg) const
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr=nullptr, handle base=handle())
ssize_t nbytes() const
Total number of bytes.
static PyObject * raw_array(PyObject *ptr, int ExtraFlags=0)
Create array from any object – always returns a new reference.
void check_dimensions(Ix... index) const
array reshape(ShapeContainer new_shape)
Optional order parameter omitted, to be added as needed.
ssize_t ndim() const
Number of dimensions.
array(ShapeContainer shape, const T *ptr, handle base=handle())
const ssize_t * strides() const
Strides of the array.
friend struct detail::npy_format_descriptor
ssize_t byte_offset(Ix... index) const
detail::any_container< ssize_t > ShapeContainer
object base() const
Base object.
ssize_t size() const
Total number of elements.
void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const
int flags() const
Return the NumPy array flags.
detail::unchecked_reference< T, Dims > unchecked() const &
Returns a proxy object that provides const access to the array's data without bounds or dimensionalit...
void resize(ShapeContainer new_shape, bool refcheck=true)
Resize array to given shape If refcheck is true and more that one reference exist to this array then ...
array(ssize_t count, const T *ptr, handle base=handle())
ssize_t index_at(Ix... index) const
Item count from beginning of the array to a given index (full or partial).
pybind11::dtype dtype() const
Array descriptor (dtype)
static array ensure(handle h, int ExtraFlags=0)
Ensure that the argument is a NumPy array In case of an error, nullptr is returned and the Python err...
array(const buffer_info &info, handle base=handle())
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, const void *ptr=nullptr, handle base=handle())
const ssize_t * shape() const
Dimensions of the array.
void check_dimensions_impl(ssize_t, const ssize_t *) const
detail::any_container< ssize_t > StridesContainer
array view(const std::string &dtype)
Create a view of an array in a different data type.
void check_writeable() const
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Returns a proxy object that provides access to the array's data without bounds or dimensionality chec...
bool owndata() const
If set, the array owns the data (will be freed when the array is deleted)
void * mutable_data(Ix... index)
Mutable pointer to the contained data.
array(const pybind11::dtype &dt, T count, const void *ptr=nullptr, handle base=handle())
ssize_t itemsize() const
Byte size of a single element.
ssize_t shape(ssize_t dim) const
Dimension along a given axis.
ssize_t offset_at() const
const void * data(Ix... index) const
Pointer to the contained data.
array squeeze()
Return a new view with all of the dimensions of length 1 removed.
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base=handle())
ssize_t strides(ssize_t dim) const
Stride along a given axis.
container_type::size_type size_type
common_iterator(void *ptr, const container_type &strides, const container_type &shape)
std::vector< ssize_t > container_type
void increment(size_type dim)
container_type::value_type value_type
static dtype of()
Return dtype associated with a C++ type.
char kind() const
Single-character code for dtype's kind.
dtype(const buffer_info &info)
dtype strip_padding(ssize_t itemsize)
PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_)
ssize_t itemsize() const
Size of the data type in bytes.
static object _dtype_from_pep3118()
dtype(list names, list formats, list offsets, ssize_t itemsize)
dtype(const char *format)
static dtype from_args(object args)
This is essentially the same as calling numpy.dtype(args) in Python.
char char_() const
Single-character for dtype's type.
bool has_fields() const
Returns true for structured data types.
dtype(const std::string &format)
Fetch and hold an error which was already set in Python.
\rst Holds a reference to a Python object (no reference counting)
const handle & inc_ref() const &
\rst Manually increase the reference count of the Python object.
handle()=default
The default constructor creates a handle with a nullptr-valued pointer.
PyObject * ptr() const
Return the underlying PyObject * pointer.
\rst Wraps a Python iterator so that it can also be used as a C++ input iterator
Wrapper for Python extension modules.
static module_ import(const char *name)
Import and return a module or throws error_already_set.
void increment_common_iterator(size_t dim)
common_iterator common_iter
multi_array_iterator & operator++()
multi_array_iterator(const std::array< buffer_info, N > &buffers, const container_type &shape)
void init_common_iterator(const buffer_info &buffer, const container_type &shape, common_iter &iterator, container_type &strides)
std::array< common_iter, N > m_common_iterator
std::vector< ssize_t > container_type
handle release()
\rst Resets the internal pointer to nullptr without decreasing the object's reference count.
T & operator[](ssize_t index)
Mutable, unchecked access data at the given index; this operator only participates if the reference i...
T * mutable_data(Ix... ix)
Mutable pointer access to the data at the given indices.
friend class pybind11::array
T & operator()(Ix... index)
Mutable, unchecked access to data at the given indices.
static constexpr bool Dynamic
Proxy class providing unsafe, unchecked const access to array data.
const T & operator()(Ix... index) const
Unchecked const reference access to data at the given indices.
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > strides_
const T * data(Ix... ix) const
Pointer access to the data at the given indices.
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > shape_
const T & operator[](ssize_t index) const
Unchecked const reference access to data; this operator only participates if the reference is to a 1-...
ssize_t shape(ssize_t dim) const
Returns the shape (i.e. size) of dimension dim
const unsigned char * data_
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t< Dyn, ssize_t > dims)
ssize_t ndim() const
Returns the number of dimensions of the array.
ssize_t nbytes() const
Returns the total number of bytes used by the referenced data.
friend class pybind11::array
enable_if_t<!Dyn, ssize_t > size() const
Returns the total number of elements in the referenced array, i.e.
enable_if_t< Dyn, ssize_t > size() const
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t >)
static constexpr bool Dynamic
static constexpr ssize_t itemsize()
Returns the item size, i.e. sizeof(T)
iterator iter(handle obj)
size_t len(handle h)
Get the length of a Python object.
std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
T cast(const handle &handle)
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers.
PYBIND11_NOINLINE void pybind11_fail(const char *reason)
Thrown when pybind11::cast or.
#define PYBIND11_NOINLINE
#define PYBIND11_STR_TYPE
typename std::remove_reference< T >::type remove_reference_t
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN)
constexpr size_t constexpr_sum()
Compile-time integer sum.
#define PYBIND11_NAMESPACE_END(name)
#define PYBIND11_NAMESPACE_BEGIN(name)
typename make_index_sequence_impl< N >::type make_index_sequence
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
typename std::conditional< B, T, F >::type conditional_t
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
@ move
Use std::move to move the return value contents into a new instance that will be owned by Python.
#define PYBIND11_DEPRECATED(reason)
#define PYBIND11_SILENCE_MSVC_C4127(...)
typename select_indices_impl< index_sequence<>, 0, Bs... >::type select_indices
constexpr descr< N - 1 > const_name(char const (&text)[N])
constexpr descr< 0 > concat()
PYBIND11_NOINLINE internals & get_internals()
Return a reference to the current internals data.
PyArray_Proxy * array_proxy(void *ptr)
all_of< std::is_standard_layout< T >, std::is_trivial< T > > is_pod
detail::vectorize_helper< Return(*)(Args...), Return, Args... > vectorize(Return(*f)(Args...))
numpy_internals & get_numpy_internals()
vectorize_helper< Func, Return, Args... > vectorize_extractor(const Func &f, Return(*)(Args...))
ssize_t byte_offset_unsafe(const Strides &)
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
PYBIND11_NOINLINE void register_structured_dtype(any_container< field_descriptor > fields, const std::type_info &tinfo, ssize_t itemsize, bool(*direct_converter)(PyObject *, void *&))
PYBIND11_NOINLINE void load_numpy_internals(numpy_internals *&ptr)
PyArrayDescr_Proxy * array_descriptor_proxy(PyObject *ptr)
bool check_flags(const void *ptr, int flag)
constexpr int platform_lookup()
typename array_info< T >::type remove_all_extents_t
all_of< std::is_standard_layout< T >, std::is_trivially_copyable< T >, satisfies_none_of< T, std::is_reference, std::is_array, is_std_array, std::is_arithmetic, is_complex, std::is_enum > > is_pod_struct
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun)
#define PYBIND11_DECL_CHAR_FMT
numpy_internals & get_numpy_internals()
#define DECL_NPY_API(Func)
ssize_t byte_offset_unsafe(const Strides &)
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
PYBIND11_NOINLINE void register_structured_dtype(any_container< field_descriptor > fields, const std::type_info &tinfo, ssize_t itemsize, bool(*direct_converter)(PyObject *, void *&))
PyObject_HEAD char * data
PyObject_HEAD PyObject * typeobj
PyArrayDescr_Proxy * descr
PyObject_VAR_HEAD char * obval
static void append_extents(list &shape)
static constexpr bool is_empty
static constexpr auto extents
static constexpr bool is_array
static void append_extents(list &)
Annotation indicating that a class derives from another given type.
Information record describing a Python buffer object.
static bool compare(const buffer_info &b)
type_map< std::vector< bool(*)(PyObject *, void *&)> > direct_conversions
Annotation for function names.
int(* PyArray_DescrConverter_)(PyObject *, PyObject **)
int(* PyArray_SetBaseObject_)(PyObject *, PyObject *)
PyTypeObject * PyArray_Type_
PyTypeObject * PyArrayDescr_Type_
@ NPY_ARRAY_C_CONTIGUOUS_
@ NPY_ARRAY_F_CONTIGUOUS_
@ API_PyArray_SetBaseObject
@ API_PyArray_NewFromDescr
@ API_PyArray_DescrFromScalar
@ API_PyArray_DescrConverter
@ API_PyArray_DescrFromType
@ API_PyArray_GetNDArrayCFeatureVersion
@ API_PyArray_DescrNewFromType
@ API_PyArray_GetArrayParamsFromObject
unsigned int(* PyArray_GetNDArrayCFeatureVersion_)()
int(* PyArray_GetArrayParamsFromObject_)(PyObject *, PyObject *, unsigned char, PyObject **, int *, Py_intptr_t *, PyObject **, PyObject *)
bool(* PyArray_EquivTypes_)(PyObject *, PyObject *)
bool PyArrayDescr_Check_(PyObject *obj) const
int(* PyArray_CopyInto_)(PyObject *, PyObject *)
PyTypeObject * PyVoidArrType_Type_
bool PyArray_Check_(PyObject *obj) const
numpy_type_info * get_type_info(bool throw_if_missing=true)
numpy_type_info * get_type_info(const std::type_info &tinfo, bool throw_if_missing=true)
std::unordered_map< std::type_index, numpy_type_info > registered_dtypes
bool_constant< sizeof(T)==sizeof(U)> as
conditional_t< vectorize, array_t< remove_cv_t< call_type >, array::forcecast >, T > type
remove_reference_t< T > call_type
static constexpr bool vectorize
object operator()(typename vectorize_arg< Args >::type... args)
typename std::tuple_element< Index, arg_call_types >::type param_n_t
void apply_trivial(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > ¶ms, Return *out, size_t size, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
object run(typename vectorize_arg< Args >::type &...args, index_sequence< Index... > i_seq, index_sequence< VIndex... > vi_seq, index_sequence< BIndex... > bi_seq)
static constexpr size_t NVectorized
void apply_broadcast(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > ¶ms, Return *out, size_t size, const std::vector< ssize_t > &output_shape, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
static constexpr size_t N
remove_reference_t< Func > f
std::tuple< typename vectorize_arg< Args >::call_type... > arg_call_types
static detail::void_type call(Func &f, Args &...args)
static Type create(broadcast_trivial, const std::vector< ssize_t > &)
static void call(void *, size_t, Func &f, Args &...args)
static void * mutable_data(Type &)
static Return call(Func &f, Args &...args)
static void call(Return *out, size_t i, Func &f, Args &...args)
static Return * mutable_data(Type &array)
static Type create(broadcast_trivial trivial, const std::vector< ssize_t > &shape)