Scarab  v2.9.1
Project 8 C++ Utility Library
numpy.h
Go to the documentation of this file.
1 /*
2  pybind11/numpy.h: Basic NumPy support, vectorize() wrapper
3 
4  Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #pragma once
11 
12 #include "pybind11.h"
13 #include "complex.h"
14 #include <numeric>
15 #include <algorithm>
16 #include <array>
17 #include <cstdint>
18 #include <cstdlib>
19 #include <cstring>
20 #include <sstream>
21 #include <string>
22 #include <functional>
23 #include <utility>
24 #include <vector>
25 #include <typeindex>
26 
27 #if defined(_MSC_VER)
28 # pragma warning(push)
29 # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
30 #endif
31 
32 /* This will be true on all flat address space platforms and allows us to reduce the
33  whole npy_intp / ssize_t / Py_intptr_t business down to just ssize_t for all size
34  and dimension types (e.g. shape, strides, indexing), instead of inflicting this
35  upon the library user. */
36 static_assert(sizeof(ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t");
37 
39 
40 class array; // Forward declaration
41 
42 NAMESPACE_BEGIN(detail)
43 template <typename type, typename SFINAE = void> struct npy_format_descriptor;
44 
46  PyObject_HEAD
47  PyObject *typeobj;
48  char kind;
49  char type;
50  char byteorder;
51  char flags;
52  int type_num;
53  int elsize;
54  int alignment;
55  char *subarray;
56  PyObject *fields;
57  PyObject *names;
58 };
59 
60 struct PyArray_Proxy {
61  PyObject_HEAD
62  char *data;
63  int nd;
66  PyObject *base;
67  PyObject *descr;
68  int flags;
69 };
70 
72  PyObject_VAR_HEAD
73  char *obval;
75  int flags;
76  PyObject *base;
77 };
78 
80  PyObject* dtype_ptr;
81  std::string format_str;
82 };
83 
85  std::unordered_map<std::type_index, numpy_type_info> registered_dtypes;
86 
87  numpy_type_info *get_type_info(const std::type_info& tinfo, bool throw_if_missing = true) {
88  auto it = registered_dtypes.find(std::type_index(tinfo));
89  if (it != registered_dtypes.end())
90  return &(it->second);
91  if (throw_if_missing)
92  pybind11_fail(std::string("NumPy type info missing for ") + tinfo.name());
93  return nullptr;
94  }
95 
96  template<typename T> numpy_type_info *get_type_info(bool throw_if_missing = true) {
97  return get_type_info(typeid(typename std::remove_cv<T>::type), throw_if_missing);
98  }
99 };
100 
101 inline PYBIND11_NOINLINE void load_numpy_internals(numpy_internals* &ptr) {
102  ptr = &get_or_create_shared_data<numpy_internals>("_numpy_internals");
103 }
104 
106  static numpy_internals* ptr = nullptr;
107  if (!ptr)
108  load_numpy_internals(ptr);
109  return *ptr;
110 }
111 
112 template <typename T> struct same_size {
113  template <typename U> using as = bool_constant<sizeof(T) == sizeof(U)>;
114 };
115 
116 // Lookup a type according to its size, and return a value corresponding to the NumPy typenum.
117 template <typename Concrete, typename... Check, typename... Int>
118 constexpr int platform_lookup(Int... codes) {
119  using code_index = std::integral_constant<int, constexpr_first<same_size<Concrete>::template as, Check...>()>;
120  static_assert(code_index::value != sizeof...(Check), "Unable to match type on this platform");
121  return std::get<code_index::value>(std::make_tuple(codes...));
122 }
123 
124 struct npy_api {
125  enum constants {
126  NPY_ARRAY_C_CONTIGUOUS_ = 0x0001,
127  NPY_ARRAY_F_CONTIGUOUS_ = 0x0002,
128  NPY_ARRAY_OWNDATA_ = 0x0004,
129  NPY_ARRAY_FORCECAST_ = 0x0010,
130  NPY_ARRAY_ENSUREARRAY_ = 0x0040,
131  NPY_ARRAY_ALIGNED_ = 0x0100,
132  NPY_ARRAY_WRITEABLE_ = 0x0400,
133  NPY_BOOL_ = 0,
134  NPY_BYTE_, NPY_UBYTE_,
135  NPY_SHORT_, NPY_USHORT_,
136  NPY_INT_, NPY_UINT_,
137  NPY_LONG_, NPY_ULONG_,
138  NPY_LONGLONG_, NPY_ULONGLONG_,
139  NPY_FLOAT_, NPY_DOUBLE_, NPY_LONGDOUBLE_,
140  NPY_CFLOAT_, NPY_CDOUBLE_, NPY_CLONGDOUBLE_,
141  NPY_OBJECT_ = 17,
142  NPY_STRING_, NPY_UNICODE_, NPY_VOID_,
143  // Platform-dependent normalization
144  NPY_INT8_ = NPY_BYTE_,
145  NPY_UINT8_ = NPY_UBYTE_,
146  NPY_INT16_ = NPY_SHORT_,
147  NPY_UINT16_ = NPY_USHORT_,
148  // `npy_common.h` defines the integer aliases. In order, it checks:
149  // NPY_BITSOF_LONG, NPY_BITSOF_LONGLONG, NPY_BITSOF_INT, NPY_BITSOF_SHORT, NPY_BITSOF_CHAR
150  // and assigns the alias to the first matching size, so we should check in this order.
151  NPY_INT32_ = platform_lookup<std::int32_t, long, int, short>(
152  NPY_LONG_, NPY_INT_, NPY_SHORT_),
153  NPY_UINT32_ = platform_lookup<std::uint32_t, unsigned long, unsigned int, unsigned short>(
154  NPY_ULONG_, NPY_UINT_, NPY_USHORT_),
155  NPY_INT64_ = platform_lookup<std::int64_t, long, long long, int>(
156  NPY_LONG_, NPY_LONGLONG_, NPY_INT_),
157  NPY_UINT64_ = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
158  NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
159  };
160 
161  typedef struct {
162  Py_intptr_t *ptr;
163  int len;
164  } PyArray_Dims;
165 
166  static npy_api& get() {
167  static npy_api api = lookup();
168  return api;
169  }
170 
171  bool PyArray_Check_(PyObject *obj) const {
172  return (bool) PyObject_TypeCheck(obj, PyArray_Type_);
173  }
174  bool PyArrayDescr_Check_(PyObject *obj) const {
175  return (bool) PyObject_TypeCheck(obj, PyArrayDescr_Type_);
176  }
177 
178  unsigned int (*PyArray_GetNDArrayCFeatureVersion_)();
179  PyObject *(*PyArray_DescrFromType_)(int);
180  PyObject *(*PyArray_NewFromDescr_)
181  (PyTypeObject *, PyObject *, int, Py_intptr_t *,
182  Py_intptr_t *, void *, int, PyObject *);
183  PyObject *(*PyArray_DescrNewFromType_)(int);
184  int (*PyArray_CopyInto_)(PyObject *, PyObject *);
185  PyObject *(*PyArray_NewCopy_)(PyObject *, int);
186  PyTypeObject *PyArray_Type_;
187  PyTypeObject *PyVoidArrType_Type_;
188  PyTypeObject *PyArrayDescr_Type_;
189  PyObject *(*PyArray_DescrFromScalar_)(PyObject *);
190  PyObject *(*PyArray_FromAny_) (PyObject *, PyObject *, int, int, int, PyObject *);
191  int (*PyArray_DescrConverter_) (PyObject *, PyObject **);
192  bool (*PyArray_EquivTypes_) (PyObject *, PyObject *);
193  int (*PyArray_GetArrayParamsFromObject_)(PyObject *, PyObject *, char, PyObject **, int *,
194  Py_ssize_t *, PyObject **, PyObject *);
195  PyObject *(*PyArray_Squeeze_)(PyObject *);
196  int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
197  PyObject* (*PyArray_Resize_)(PyObject*, PyArray_Dims*, int, int);
198 private:
199  enum functions {
200  API_PyArray_GetNDArrayCFeatureVersion = 211,
201  API_PyArray_Type = 2,
202  API_PyArrayDescr_Type = 3,
203  API_PyVoidArrType_Type = 39,
204  API_PyArray_DescrFromType = 45,
205  API_PyArray_DescrFromScalar = 57,
206  API_PyArray_FromAny = 69,
207  API_PyArray_Resize = 80,
208  API_PyArray_CopyInto = 82,
209  API_PyArray_NewCopy = 85,
210  API_PyArray_NewFromDescr = 94,
211  API_PyArray_DescrNewFromType = 9,
212  API_PyArray_DescrConverter = 174,
213  API_PyArray_EquivTypes = 182,
214  API_PyArray_GetArrayParamsFromObject = 278,
215  API_PyArray_Squeeze = 136,
216  API_PyArray_SetBaseObject = 282
217  };
218 
219  static npy_api lookup() {
220  module m = module::import("numpy.core.multiarray");
221  auto c = m.attr("_ARRAY_API");
222 #if PY_MAJOR_VERSION >= 3
223  void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
224 #else
225  void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr());
226 #endif
227  npy_api api;
228 #define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
229  DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
230  if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7)
231  pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
232  DECL_NPY_API(PyArray_Type);
233  DECL_NPY_API(PyVoidArrType_Type);
234  DECL_NPY_API(PyArrayDescr_Type);
235  DECL_NPY_API(PyArray_DescrFromType);
236  DECL_NPY_API(PyArray_DescrFromScalar);
237  DECL_NPY_API(PyArray_FromAny);
238  DECL_NPY_API(PyArray_Resize);
239  DECL_NPY_API(PyArray_CopyInto);
240  DECL_NPY_API(PyArray_NewCopy);
241  DECL_NPY_API(PyArray_NewFromDescr);
242  DECL_NPY_API(PyArray_DescrNewFromType);
243  DECL_NPY_API(PyArray_DescrConverter);
244  DECL_NPY_API(PyArray_EquivTypes);
245  DECL_NPY_API(PyArray_GetArrayParamsFromObject);
246  DECL_NPY_API(PyArray_Squeeze);
247  DECL_NPY_API(PyArray_SetBaseObject);
248 #undef DECL_NPY_API
249  return api;
250  }
251 };
252 
253 inline PyArray_Proxy* array_proxy(void* ptr) {
254  return reinterpret_cast<PyArray_Proxy*>(ptr);
255 }
256 
257 inline const PyArray_Proxy* array_proxy(const void* ptr) {
258  return reinterpret_cast<const PyArray_Proxy*>(ptr);
259 }
260 
262  return reinterpret_cast<PyArrayDescr_Proxy*>(ptr);
263 }
264 
265 inline const PyArrayDescr_Proxy* array_descriptor_proxy(const PyObject* ptr) {
266  return reinterpret_cast<const PyArrayDescr_Proxy*>(ptr);
267 }
268 
269 inline bool check_flags(const void* ptr, int flag) {
270  return (flag == (array_proxy(ptr)->flags & flag));
271 }
272 
273 template <typename T> struct is_std_array : std::false_type { };
274 template <typename T, size_t N> struct is_std_array<std::array<T, N>> : std::true_type { };
275 template <typename T> struct is_complex : std::false_type { };
276 template <typename T> struct is_complex<std::complex<T>> : std::true_type { };
277 
278 template <typename T> struct array_info_scalar {
279  typedef T type;
280  static constexpr bool is_array = false;
281  static constexpr bool is_empty = false;
282  static constexpr auto extents = _("");
283  static void append_extents(list& /* shape */) { }
284 };
285 // Computes underlying type and a comma-separated list of extents for array
286 // types (any mix of std::array and built-in arrays). An array of char is
287 // treated as scalar because it gets special handling.
288 template <typename T> struct array_info : array_info_scalar<T> { };
289 template <typename T, size_t N> struct array_info<std::array<T, N>> {
290  using type = typename array_info<T>::type;
291  static constexpr bool is_array = true;
292  static constexpr bool is_empty = (N == 0) || array_info<T>::is_empty;
293  static constexpr size_t extent = N;
294 
295  // appends the extents to shape
296  static void append_extents(list& shape) {
297  shape.append(N);
299  }
300 
301  static constexpr auto extents = _<array_info<T>::is_array>(
302  concat(_<N>(), array_info<T>::extents), _<N>()
303  );
304 };
305 // For numpy we have special handling for arrays of characters, so we don't include
306 // the size in the array extents.
307 template <size_t N> struct array_info<char[N]> : array_info_scalar<char[N]> { };
308 template <size_t N> struct array_info<std::array<char, N>> : array_info_scalar<std::array<char, N>> { };
309 template <typename T, size_t N> struct array_info<T[N]> : array_info<std::array<T, N>> { };
310 template <typename T> using remove_all_extents_t = typename array_info<T>::type;
311 
312 template <typename T> using is_pod_struct = all_of<
313  std::is_standard_layout<T>, // since we're accessing directly in memory we need a standard layout type
314 #if !defined(__GNUG__) || defined(_LIBCPP_VERSION) || defined(_GLIBCXX_USE_CXX11_ABI)
315  // _GLIBCXX_USE_CXX11_ABI indicates that we're using libstdc++ from GCC 5 or newer, independent
316  // of the actual compiler (Clang can also use libstdc++, but it always defines __GNUC__ == 4).
317  std::is_trivially_copyable<T>,
318 #else
319  // GCC 4 doesn't implement is_trivially_copyable, so approximate it
320  std::is_trivially_destructible<T>,
322 #endif
324 >;
325 
326 template <ssize_t Dim = 0, typename Strides> ssize_t byte_offset_unsafe(const Strides &) { return 0; }
327 template <ssize_t Dim = 0, typename Strides, typename... Ix>
328 ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index) {
329  return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
330 }
331 
337 template <typename T, ssize_t Dims>
339 protected:
340  static constexpr bool Dynamic = Dims < 0;
341  const unsigned char *data_;
342  // Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
343  // make large performance gains on big, nested loops, but requires compile-time dimensions
345  shape_, strides_;
346  const ssize_t dims_;
347 
348  friend class pybind11::array;
349  // Constructor for compile-time dimensions:
350  template <bool Dyn = Dynamic>
352  : data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} {
353  for (size_t i = 0; i < (size_t) dims_; i++) {
354  shape_[i] = shape[i];
355  strides_[i] = strides[i];
356  }
357  }
358  // Constructor for runtime dimensions:
359  template <bool Dyn = Dynamic>
361  : data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides}, dims_{dims} {}
362 
363 public:
369  template <typename... Ix> const T &operator()(Ix... index) const {
370  static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
371  "Invalid number of indices for unchecked array reference");
372  return *reinterpret_cast<const T *>(data_ + byte_offset_unsafe(strides_, ssize_t(index)...));
373  }
378  template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
379  const T &operator[](ssize_t index) const { return operator()(index); }
380 
382  template <typename... Ix> const T *data(Ix... ix) const { return &operator()(ssize_t(ix)...); }
383 
385  constexpr static ssize_t itemsize() { return sizeof(T); }
386 
388  ssize_t shape(ssize_t dim) const { return shape_[(size_t) dim]; }
389 
391  ssize_t ndim() const { return dims_; }
392 
394  template <bool Dyn = Dynamic>
396  return std::accumulate(shape_.begin(), shape_.end(), (ssize_t) 1, std::multiplies<ssize_t>());
397  }
398  template <bool Dyn = Dynamic>
400  return std::accumulate(shape_, shape_ + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
401  }
402 
405  ssize_t nbytes() const {
406  return size() * itemsize();
407  }
408 };
409 
410 template <typename T, ssize_t Dims>
412  friend class pybind11::array;
414  using ConstBase::ConstBase;
415  using ConstBase::Dynamic;
416 public:
418  template <typename... Ix> T& operator()(Ix... index) {
419  static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
420  "Invalid number of indices for unchecked array reference");
421  return const_cast<T &>(ConstBase::operator()(index...));
422  }
428  template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
429  T &operator[](ssize_t index) { return operator()(index); }
430 
432  template <typename... Ix> T *mutable_data(Ix... ix) { return &operator()(ssize_t(ix)...); }
433 };
434 
435 template <typename T, ssize_t Dim>
437  static_assert(Dim == 0 && Dim > 0 /* always fail */, "unchecked array proxy object is not castable");
438 };
439 template <typename T, ssize_t Dim>
440 struct type_caster<unchecked_mutable_reference<T, Dim>> : type_caster<unchecked_reference<T, Dim>> {};
441 
442 NAMESPACE_END(detail)
443 
444 class dtype : public object {
445 public:
446  PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_);
447 
448  explicit dtype(const buffer_info &info) {
449  dtype descr(_dtype_from_pep3118()(PYBIND11_STR_TYPE(info.format)));
450  // If info.itemsize == 0, use the value calculated from the format string
451  m_ptr = descr.strip_padding(info.itemsize ? info.itemsize : descr.itemsize()).release().ptr();
452  }
453 
454  explicit dtype(const std::string &format) {
455  m_ptr = from_args(pybind11::str(format)).release().ptr();
456  }
457 
458  dtype(const char *format) : dtype(std::string(format)) { }
459 
460  dtype(list names, list formats, list offsets, ssize_t itemsize) {
461  dict args;
462  args["names"] = names;
463  args["formats"] = formats;
464  args["offsets"] = offsets;
465  args["itemsize"] = pybind11::int_(itemsize);
466  m_ptr = from_args(args).release().ptr();
467  }
468 
470  static dtype from_args(object args) {
471  PyObject *ptr = nullptr;
472  if (!detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) || !ptr)
473  throw error_already_set();
474  return reinterpret_steal<dtype>(ptr);
475  }
476 
478  template <typename T> static dtype of() {
480  }
481 
483  ssize_t itemsize() const {
484  return detail::array_descriptor_proxy(m_ptr)->elsize;
485  }
486 
488  bool has_fields() const {
489  return detail::array_descriptor_proxy(m_ptr)->names != nullptr;
490  }
491 
493  char kind() const {
494  return detail::array_descriptor_proxy(m_ptr)->kind;
495  }
496 
497 private:
498  static object _dtype_from_pep3118() {
499  static PyObject *obj = module::import("numpy.core._internal")
500  .attr("_dtype_from_pep3118").cast<object>().release().ptr();
501  return reinterpret_borrow<object>(obj);
502  }
503 
505  // Recursively strip all void fields with empty names that are generated for
506  // padding fields (as of NumPy v1.11).
507  if (!has_fields())
508  return *this;
509 
510  struct field_descr { PYBIND11_STR_TYPE name; object format; pybind11::int_ offset; };
511  std::vector<field_descr> field_descriptors;
512 
513  for (auto field : attr("fields").attr("items")()) {
514  auto spec = field.cast<tuple>();
515  auto name = spec[0].cast<pybind11::str>();
516  auto format = spec[1].cast<tuple>()[0].cast<dtype>();
517  auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>();
518  if (!len(name) && format.kind() == 'V')
519  continue;
520  field_descriptors.push_back({(PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset});
521  }
522 
523  std::sort(field_descriptors.begin(), field_descriptors.end(),
524  [](const field_descr& a, const field_descr& b) {
525  return a.offset.cast<int>() < b.offset.cast<int>();
526  });
527 
528  list names, formats, offsets;
529  for (auto& descr : field_descriptors) {
530  names.append(descr.name);
531  formats.append(descr.format);
532  offsets.append(descr.offset);
533  }
534  return dtype(names, formats, offsets, itemsize);
535  }
536 };
537 
538 class array : public buffer {
539 public:
540  PYBIND11_OBJECT_CVT(array, buffer, detail::npy_api::get().PyArray_Check_, raw_array)
541 
542  enum {
543  c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
544  f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
545  forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
546  };
547 
548  array() : array({{0}}, static_cast<const double *>(nullptr)) {}
549 
552 
553  // Constructs an array taking shape/strides from arbitrary container types
555  const void *ptr = nullptr, handle base = handle()) {
556 
557  if (strides->empty())
558  *strides = c_strides(*shape, dt.itemsize());
559 
560  auto ndim = shape->size();
561  if (ndim != strides->size())
562  pybind11_fail("NumPy: shape ndim doesn't match strides ndim");
563  auto descr = dt;
564 
565  int flags = 0;
566  if (base && ptr) {
567  if (isinstance<array>(base))
568  /* Copy flags from base (except ownership bit) */
569  flags = reinterpret_borrow<array>(base).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
570  else
571  /* Writable by default, easy to downgrade later on if needed */
572  flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
573  }
574 
575  auto &api = detail::npy_api::get();
576  auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
577  api.PyArray_Type_, descr.release().ptr(), (int) ndim, shape->data(), strides->data(),
578  const_cast<void *>(ptr), flags, nullptr));
579  if (!tmp)
580  throw error_already_set();
581  if (ptr) {
582  if (base) {
583  api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr());
584  } else {
585  tmp = reinterpret_steal<object>(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */));
586  }
587  }
588  m_ptr = tmp.release().ptr();
589  }
590 
591  array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr = nullptr, handle base = handle())
592  : array(dt, std::move(shape), {}, ptr, base) { }
593 
595  array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle())
596  : array(dt, {{count}}, ptr, base) { }
597 
598  template <typename T>
599  array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle())
600  : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) { }
601 
602  template <typename T>
603  array(ShapeContainer shape, const T *ptr, handle base = handle())
604  : array(std::move(shape), {}, ptr, base) { }
605 
606  template <typename T>
607  explicit array(ssize_t count, const T *ptr, handle base = handle()) : array({count}, {}, ptr, base) { }
608 
609  explicit array(const buffer_info &info)
610  : array(pybind11::dtype(info), info.shape, info.strides, info.ptr) { }
611 
614  return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(m_ptr)->descr);
615  }
616 
618  ssize_t size() const {
619  return std::accumulate(shape(), shape() + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
620  }
621 
623  ssize_t itemsize() const {
625  }
626 
628  ssize_t nbytes() const {
629  return size() * itemsize();
630  }
631 
633  ssize_t ndim() const {
634  return detail::array_proxy(m_ptr)->nd;
635  }
636 
638  object base() const {
639  return reinterpret_borrow<object>(detail::array_proxy(m_ptr)->base);
640  }
641 
643  const ssize_t* shape() const {
644  return detail::array_proxy(m_ptr)->dimensions;
645  }
646 
648  ssize_t shape(ssize_t dim) const {
649  if (dim >= ndim())
650  fail_dim_check(dim, "invalid axis");
651  return shape()[dim];
652  }
653 
655  const ssize_t* strides() const {
656  return detail::array_proxy(m_ptr)->strides;
657  }
658 
660  ssize_t strides(ssize_t dim) const {
661  if (dim >= ndim())
662  fail_dim_check(dim, "invalid axis");
663  return strides()[dim];
664  }
665 
667  int flags() const {
668  return detail::array_proxy(m_ptr)->flags;
669  }
670 
672  bool writeable() const {
673  return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_);
674  }
675 
677  bool owndata() const {
678  return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_);
679  }
680 
683  template<typename... Ix> const void* data(Ix... index) const {
684  return static_cast<const void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
685  }
686 
690  template<typename... Ix> void* mutable_data(Ix... index) {
691  check_writeable();
692  return static_cast<void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
693  }
694 
697  template<typename... Ix> ssize_t offset_at(Ix... index) const {
698  if ((ssize_t) sizeof...(index) > ndim())
699  fail_dim_check(sizeof...(index), "too many indices for an array");
700  return byte_offset(ssize_t(index)...);
701  }
702 
703  ssize_t offset_at() const { return 0; }
704 
707  template<typename... Ix> ssize_t index_at(Ix... index) const {
708  return offset_at(index...) / itemsize();
709  }
710 
718  if (Dims >= 0 && ndim() != Dims)
719  throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) +
720  "; expected " + std::to_string(Dims));
721  return detail::unchecked_mutable_reference<T, Dims>(mutable_data(), shape(), strides(), ndim());
722  }
723 
731  template <typename T, ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const & {
732  if (Dims >= 0 && ndim() != Dims)
733  throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) +
734  "; expected " + std::to_string(Dims));
735  return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim());
736  }
737 
740  auto& api = detail::npy_api::get();
741  return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
742  }
743 
747  void resize(ShapeContainer new_shape, bool refcheck = true) {
749  new_shape->data(), int(new_shape->size())
750  };
751  // try to resize, set ordering param to -1 cause it's not used anyway
752  object new_array = reinterpret_steal<object>(
753  detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1)
754  );
755  if (!new_array) throw error_already_set();
756  if (isinstance<array>(new_array)) { *this = std::move(new_array); }
757  }
758 
761  static array ensure(handle h, int ExtraFlags = 0) {
762  auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags));
763  if (!result)
764  PyErr_Clear();
765  return result;
766  }
767 
768 protected:
769  template<typename, typename> friend struct detail::npy_format_descriptor;
770 
771  void fail_dim_check(ssize_t dim, const std::string& msg) const {
772  throw index_error(msg + ": " + std::to_string(dim) +
773  " (ndim = " + std::to_string(ndim()) + ")");
774  }
775 
776  template<typename... Ix> ssize_t byte_offset(Ix... index) const {
777  check_dimensions(index...);
778  return detail::byte_offset_unsafe(strides(), ssize_t(index)...);
779  }
780 
781  void check_writeable() const {
782  if (!writeable())
783  throw std::domain_error("array is not writeable");
784  }
785 
786  // Default, C-style strides
787  static std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
788  auto ndim = shape.size();
789  std::vector<ssize_t> strides(ndim, itemsize);
790  if (ndim > 0)
791  for (size_t i = ndim - 1; i > 0; --i)
792  strides[i - 1] = strides[i] * shape[i];
793  return strides;
794  }
795 
796  // F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
797  static std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
798  auto ndim = shape.size();
799  std::vector<ssize_t> strides(ndim, itemsize);
800  for (size_t i = 1; i < ndim; ++i)
801  strides[i] = strides[i - 1] * shape[i - 1];
802  return strides;
803  }
804 
805  template<typename... Ix> void check_dimensions(Ix... index) const {
806  check_dimensions_impl(ssize_t(0), shape(), ssize_t(index)...);
807  }
808 
809  void check_dimensions_impl(ssize_t, const ssize_t*) const { }
810 
811  template<typename... Ix> void check_dimensions_impl(ssize_t axis, const ssize_t* shape, ssize_t i, Ix... index) const {
812  if (i >= *shape) {
813  throw index_error(std::string("index ") + std::to_string(i) +
814  " is out of bounds for axis " + std::to_string(axis) +
815  " with size " + std::to_string(*shape));
816  }
817  check_dimensions_impl(axis + 1, shape + 1, index...);
818  }
819 
821  static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) {
822  if (ptr == nullptr) {
823  PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
824  return nullptr;
825  }
826  return detail::npy_api::get().PyArray_FromAny_(
827  ptr, nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr);
828  }
829 };
830 
831 template <typename T, int ExtraFlags = array::forcecast> class array_t : public array {
832 private:
833  struct private_ctor {};
834  // Delegating constructor needed when both moving and accessing in the same constructor
835  array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
836  : array(std::move(shape), std::move(strides), ptr, base) {}
837 public:
838  static_assert(!detail::array_info<T>::is_array, "Array types cannot be used with array_t");
839 
840  using value_type = T;
841 
842  array_t() : array(0, static_cast<const T *>(nullptr)) {}
845 
846  PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
847  array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) {
848  if (!m_ptr) PyErr_Clear();
849  if (!is_borrowed) Py_XDECREF(h.ptr());
850  }
851 
852  array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
853  if (!m_ptr) throw error_already_set();
854  }
855 
856  explicit array_t(const buffer_info& info) : array(info) { }
857 
858  array_t(ShapeContainer shape, StridesContainer strides, const T *ptr = nullptr, handle base = handle())
859  : array(std::move(shape), std::move(strides), ptr, base) { }
860 
861  explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle())
862  : array_t(private_ctor{}, std::move(shape),
863  ExtraFlags & f_style ? f_strides(*shape, itemsize()) : c_strides(*shape, itemsize()),
864  ptr, base) { }
865 
866  explicit array_t(size_t count, const T *ptr = nullptr, handle base = handle())
867  : array({count}, {}, ptr, base) { }
868 
869  constexpr ssize_t itemsize() const {
870  return sizeof(T);
871  }
872 
873  template<typename... Ix> ssize_t index_at(Ix... index) const {
874  return offset_at(index...) / itemsize();
875  }
876 
877  template<typename... Ix> const T* data(Ix... index) const {
878  return static_cast<const T*>(array::data(index...));
879  }
880 
881  template<typename... Ix> T* mutable_data(Ix... index) {
882  return static_cast<T*>(array::mutable_data(index...));
883  }
884 
885  // Reference to element at a given index
886  template<typename... Ix> const T& at(Ix... index) const {
887  if ((ssize_t) sizeof...(index) != ndim())
888  fail_dim_check(sizeof...(index), "index dimension mismatch");
889  return *(static_cast<const T*>(array::data()) + byte_offset(ssize_t(index)...) / itemsize());
890  }
891 
892  // Mutable reference to element at a given index
893  template<typename... Ix> T& mutable_at(Ix... index) {
894  if ((ssize_t) sizeof...(index) != ndim())
895  fail_dim_check(sizeof...(index), "index dimension mismatch");
896  return *(static_cast<T*>(array::mutable_data()) + byte_offset(ssize_t(index)...) / itemsize());
897  }
898 
906  return array::mutable_unchecked<T, Dims>();
907  }
908 
916  template <ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const & {
917  return array::unchecked<T, Dims>();
918  }
919 
922  static array_t ensure(handle h) {
923  auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr()));
924  if (!result)
925  PyErr_Clear();
926  return result;
927  }
928 
929  static bool check_(handle h) {
930  const auto &api = detail::npy_api::get();
931  return api.PyArray_Check_(h.ptr())
932  && api.PyArray_EquivTypes_(detail::array_proxy(h.ptr())->descr, dtype::of<T>().ptr());
933  }
934 
935 protected:
937  static PyObject *raw_array_t(PyObject *ptr) {
938  if (ptr == nullptr) {
939  PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
940  return nullptr;
941  }
942  return detail::npy_api::get().PyArray_FromAny_(
943  ptr, dtype::of<T>().release().ptr(), 0, 0,
944  detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr);
945  }
946 };
947 
948 template <typename T>
949 struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
950  static std::string format() {
952  }
953 };
954 
955 template <size_t N> struct format_descriptor<char[N]> {
956  static std::string format() { return std::to_string(N) + "s"; }
957 };
958 template <size_t N> struct format_descriptor<std::array<char, N>> {
959  static std::string format() { return std::to_string(N) + "s"; }
960 };
961 
962 template <typename T>
963 struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> {
964  static std::string format() {
965  return format_descriptor<
967  }
968 };
969 
970 template <typename T>
971 struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
972  static std::string format() {
973  using namespace detail;
974  static constexpr auto extents = _("(") + array_info<T>::extents + _(")");
975  return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
976  }
977 };
978 
979 NAMESPACE_BEGIN(detail)
980 template <typename T, int ExtraFlags>
981 struct pyobject_caster<array_t<T, ExtraFlags>> {
983 
984  bool load(handle src, bool convert) {
985  if (!convert && !type::check_(src))
986  return false;
987  value = type::ensure(src);
988  return static_cast<bool>(value);
989  }
990 
991  static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
992  return src.inc_ref();
993  }
995 };
996 
997 template <typename T>
998 struct compare_buffer_info<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
999  static bool compare(const buffer_info& b) {
1000  return npy_api::get().PyArray_EquivTypes_(dtype::of<T>().ptr(), dtype(b).ptr());
1001  }
1002 };
1003 
1004 template <typename T, typename = void>
1006 
1007 template <typename T>
1008 struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
1009  static constexpr auto name = _<std::is_same<T, bool>::value>(
1010  _("bool"), _<std::is_signed<T>::value>("int", "uint") + _<sizeof(T)*8>()
1011  );
1012 };
1013 
1014 template <typename T>
1015 struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
1017  _("float") + _<sizeof(T)*8>(), _("longdouble")
1018  );
1019 };
1020 
1021 template <typename T>
1025  _("complex") + _<sizeof(typename T::value_type)*16>(), _("longcomplex")
1026  );
1027 };
1028 
1029 template <typename T>
1032 private:
1033  // NB: the order here must match the one in common.h
1034  constexpr static const int values[15] = {
1035  npy_api::NPY_BOOL_,
1036  npy_api::NPY_BYTE_, npy_api::NPY_UBYTE_, npy_api::NPY_INT16_, npy_api::NPY_UINT16_,
1037  npy_api::NPY_INT32_, npy_api::NPY_UINT32_, npy_api::NPY_INT64_, npy_api::NPY_UINT64_,
1038  npy_api::NPY_FLOAT_, npy_api::NPY_DOUBLE_, npy_api::NPY_LONGDOUBLE_,
1039  npy_api::NPY_CFLOAT_, npy_api::NPY_CDOUBLE_, npy_api::NPY_CLONGDOUBLE_
1040  };
1041 
1042 public:
1043  static constexpr int value = values[detail::is_fmt_numeric<T>::index];
1044 
1046  if (auto ptr = npy_api::get().PyArray_DescrFromType_(value))
1047  return reinterpret_steal<pybind11::dtype>(ptr);
1048  pybind11_fail("Unsupported buffer format!");
1049  }
1050 };
1051 
1052 #define PYBIND11_DECL_CHAR_FMT \
1053  static constexpr auto name = _("S") + _<N>(); \
1054  static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); }
1055 template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_FMT };
1056 template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT };
1057 #undef PYBIND11_DECL_CHAR_FMT
1058 
1059 template<typename T> struct npy_format_descriptor<T, enable_if_t<array_info<T>::is_array>> {
1060 private:
1062 public:
1063  static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
1064 
1065  static constexpr auto name = _("(") + array_info<T>::extents + _(")") + base_descr::name;
1067  list shape;
1069  return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape));
1070  }
1071 };
1072 
1073 template<typename T> struct npy_format_descriptor<T, enable_if_t<std::is_enum<T>::value>> {
1074 private:
1076 public:
1077  static constexpr auto name = base_descr::name;
1078  static pybind11::dtype dtype() { return base_descr::dtype(); }
1079 };
1080 
1082  const char *name;
1085  std::string format;
1087 };
1088 
1089 inline PYBIND11_NOINLINE void register_structured_dtype(
1091  const std::type_info& tinfo, ssize_t itemsize,
1092  bool (*direct_converter)(PyObject *, void *&)) {
1093 
1095  if (numpy_internals.get_type_info(tinfo, false))
1096  pybind11_fail("NumPy: dtype is already registered");
1097 
1098  // Use ordered fields because order matters as of NumPy 1.14:
1099  // https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
1100  std::vector<field_descriptor> ordered_fields(std::move(fields));
1101  std::sort(ordered_fields.begin(), ordered_fields.end(),
1102  [](const field_descriptor &a, const field_descriptor &b) { return a.offset < b.offset; });
1103 
1104  list names, formats, offsets;
1105  for (auto& field : ordered_fields) {
1106  if (!field.descr)
1107  pybind11_fail(std::string("NumPy: unsupported field dtype: `") +
1108  field.name + "` @ " + tinfo.name());
1109  names.append(PYBIND11_STR_TYPE(field.name));
1110  formats.append(field.descr);
1111  offsets.append(pybind11::int_(field.offset));
1112  }
1113  auto dtype_ptr = pybind11::dtype(names, formats, offsets, itemsize).release().ptr();
1114 
1115  // There is an existing bug in NumPy (as of v1.11): trailing bytes are
1116  // not encoded explicitly into the format string. This will supposedly
1117  // get fixed in v1.12; for further details, see these:
1118  // - https://github.com/numpy/numpy/issues/7797
1119  // - https://github.com/numpy/numpy/pull/7798
1120  // Because of this, we won't use numpy's logic to generate buffer format
1121  // strings and will just do it ourselves.
1122  ssize_t offset = 0;
1123  std::ostringstream oss;
1124  // mark the structure as unaligned with '^', because numpy and C++ don't
1125  // always agree about alignment (particularly for complex), and we're
1126  // explicitly listing all our padding. This depends on none of the fields
1127  // overriding the endianness. Putting the ^ in front of individual fields
1128  // isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
1129  oss << "^T{";
1130  for (auto& field : ordered_fields) {
1131  if (field.offset > offset)
1132  oss << (field.offset - offset) << 'x';
1133  oss << field.format << ':' << field.name << ':';
1134  offset = field.offset + field.size;
1135  }
1136  if (itemsize > offset)
1137  oss << (itemsize - offset) << 'x';
1138  oss << '}';
1139  auto format_str = oss.str();
1140 
1141  // Sanity check: verify that NumPy properly parses our buffer format string
1142  auto& api = npy_api::get();
1143  auto arr = array(buffer_info(nullptr, itemsize, format_str, 1));
1144  if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr()))
1145  pybind11_fail("NumPy: invalid buffer descriptor!");
1146 
1147  auto tindex = std::type_index(tinfo);
1148  numpy_internals.registered_dtypes[tindex] = { dtype_ptr, format_str };
1149  get_internals().direct_conversions[tindex].push_back(direct_converter);
1150 }
1151 
1152 template <typename T, typename SFINAE> struct npy_format_descriptor {
1153  static_assert(is_pod_struct<T>::value, "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1154 
1155  static constexpr auto name = make_caster<T>::name;
1156 
1158  return reinterpret_borrow<pybind11::dtype>(dtype_ptr());
1159  }
1160 
1161  static std::string format() {
1162  static auto format_str = get_numpy_internals().get_type_info<T>(true)->format_str;
1163  return format_str;
1164  }
1165 
1167  register_structured_dtype(std::move(fields), typeid(typename std::remove_cv<T>::type),
1168  sizeof(T), &direct_converter);
1169  }
1170 
1171 private:
1172  static PyObject* dtype_ptr() {
1173  static PyObject* ptr = get_numpy_internals().get_type_info<T>(true)->dtype_ptr;
1174  return ptr;
1175  }
1176 
1177  static bool direct_converter(PyObject *obj, void*& value) {
1178  auto& api = npy_api::get();
1179  if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_))
1180  return false;
1181  if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1182  if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
1183  value = ((PyVoidScalarObject_Proxy *) obj)->obval;
1184  return true;
1185  }
1186  }
1187  return false;
1188  }
1189 };
1190 
1191 #ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code)
1192 # define PYBIND11_NUMPY_DTYPE(Type, ...) ((void)0)
1193 # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void)0)
1194 #else
1195 
1196 #define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
1197  ::pybind11::detail::field_descriptor { \
1198  Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
1199  ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
1200  ::pybind11::detail::npy_format_descriptor<decltype(std::declval<T>().Field)>::dtype() \
1201  }
1202 
1203 // Extract name, offset and format descriptor for a struct field
1204 #define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, #Field)
1205 
1206 // The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
1207 // (C) William Swanson, Paul Fultz
1208 #define PYBIND11_EVAL0(...) __VA_ARGS__
1209 #define PYBIND11_EVAL1(...) PYBIND11_EVAL0 (PYBIND11_EVAL0 (PYBIND11_EVAL0 (__VA_ARGS__)))
1210 #define PYBIND11_EVAL2(...) PYBIND11_EVAL1 (PYBIND11_EVAL1 (PYBIND11_EVAL1 (__VA_ARGS__)))
1211 #define PYBIND11_EVAL3(...) PYBIND11_EVAL2 (PYBIND11_EVAL2 (PYBIND11_EVAL2 (__VA_ARGS__)))
1212 #define PYBIND11_EVAL4(...) PYBIND11_EVAL3 (PYBIND11_EVAL3 (PYBIND11_EVAL3 (__VA_ARGS__)))
1213 #define PYBIND11_EVAL(...) PYBIND11_EVAL4 (PYBIND11_EVAL4 (PYBIND11_EVAL4 (__VA_ARGS__)))
1214 #define PYBIND11_MAP_END(...)
1215 #define PYBIND11_MAP_OUT
1216 #define PYBIND11_MAP_COMMA ,
1217 #define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END
1218 #define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
1219 #define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0 (test, next, 0)
1220 #define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1 (PYBIND11_MAP_GET_END test, next)
1221 #ifdef _MSC_VER // MSVC is not as eager to expand macros, hence this workaround
1222 #define PYBIND11_MAP_LIST_NEXT1(test, next) \
1223  PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0))
1224 #else
1225 #define PYBIND11_MAP_LIST_NEXT1(test, next) \
1226  PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)
1227 #endif
1228 #define PYBIND11_MAP_LIST_NEXT(test, next) \
1229  PYBIND11_MAP_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next)
1230 #define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \
1231  f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST1) (f, t, peek, __VA_ARGS__)
1232 #define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
1233  f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST0) (f, t, peek, __VA_ARGS__)
1234 // PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ...
1235 #define PYBIND11_MAP_LIST(f, t, ...) \
1236  PYBIND11_EVAL (PYBIND11_MAP_LIST1 (f, t, __VA_ARGS__, (), 0))
1237 
1238 #define PYBIND11_NUMPY_DTYPE(Type, ...) \
1239  ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \
1240  (::std::vector<::pybind11::detail::field_descriptor> \
1241  {PYBIND11_MAP_LIST (PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
1242 
1243 #ifdef _MSC_VER
1244 #define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1245  PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0))
1246 #else
1247 #define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1248  PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)
1249 #endif
1250 #define PYBIND11_MAP2_LIST_NEXT(test, next) \
1251  PYBIND11_MAP2_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next)
1252 #define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
1253  f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST1) (f, t, peek, __VA_ARGS__)
1254 #define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
1255  f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST0) (f, t, peek, __VA_ARGS__)
1256 // PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ...
1257 #define PYBIND11_MAP2_LIST(f, t, ...) \
1258  PYBIND11_EVAL (PYBIND11_MAP2_LIST1 (f, t, __VA_ARGS__, (), 0))
1259 
1260 #define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
1261  ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \
1262  (::std::vector<::pybind11::detail::field_descriptor> \
1263  {PYBIND11_MAP2_LIST (PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
1264 
1265 #endif // __CLION_IDE__
1266 
1267 template <class T>
1269 
1270 template <class T>
1272  return array_iterator<T>(reinterpret_cast<T*>(buffer.ptr));
1273 }
1274 
1275 template <class T>
1277  return array_iterator<T>(reinterpret_cast<T*>(buffer.ptr) + buffer.size);
1278 }
1279 
1281 public:
1282  using container_type = std::vector<ssize_t>;
1283  using value_type = container_type::value_type;
1284  using size_type = container_type::size_type;
1285 
1286  common_iterator() : p_ptr(0), m_strides() {}
1287 
1288  common_iterator(void* ptr, const container_type& strides, const container_type& shape)
1289  : p_ptr(reinterpret_cast<char*>(ptr)), m_strides(strides.size()) {
1290  m_strides.back() = static_cast<value_type>(strides.back());
1291  for (size_type i = m_strides.size() - 1; i != 0; --i) {
1292  size_type j = i - 1;
1293  value_type s = static_cast<value_type>(shape[i]);
1294  m_strides[j] = strides[j] + m_strides[i] - strides[i] * s;
1295  }
1296  }
1297 
1298  void increment(size_type dim) {
1299  p_ptr += m_strides[dim];
1300  }
1301 
1302  void* data() const {
1303  return p_ptr;
1304  }
1305 
1306 private:
1307  char* p_ptr;
1309 };
1310 
1311 template <size_t N> class multi_array_iterator {
1312 public:
1313  using container_type = std::vector<ssize_t>;
1314 
1315  multi_array_iterator(const std::array<buffer_info, N> &buffers,
1316  const container_type &shape)
1317  : m_shape(shape.size()), m_index(shape.size(), 0),
1318  m_common_iterator() {
1319 
1320  // Manual copy to avoid conversion warning if using std::copy
1321  for (size_t i = 0; i < shape.size(); ++i)
1322  m_shape[i] = shape[i];
1323 
1324  container_type strides(shape.size());
1325  for (size_t i = 0; i < N; ++i)
1326  init_common_iterator(buffers[i], shape, m_common_iterator[i], strides);
1327  }
1328 
1330  for (size_t j = m_index.size(); j != 0; --j) {
1331  size_t i = j - 1;
1332  if (++m_index[i] != m_shape[i]) {
1333  increment_common_iterator(i);
1334  break;
1335  } else {
1336  m_index[i] = 0;
1337  }
1338  }
1339  return *this;
1340  }
1341 
1342  template <size_t K, class T = void> T* data() const {
1343  return reinterpret_cast<T*>(m_common_iterator[K].data());
1344  }
1345 
1346 private:
1347 
1349 
1351  const container_type &shape,
1353  container_type &strides) {
1354  auto buffer_shape_iter = buffer.shape.rbegin();
1355  auto buffer_strides_iter = buffer.strides.rbegin();
1356  auto shape_iter = shape.rbegin();
1357  auto strides_iter = strides.rbegin();
1358 
1359  while (buffer_shape_iter != buffer.shape.rend()) {
1360  if (*shape_iter == *buffer_shape_iter)
1361  *strides_iter = *buffer_strides_iter;
1362  else
1363  *strides_iter = 0;
1364 
1365  ++buffer_shape_iter;
1366  ++buffer_strides_iter;
1367  ++shape_iter;
1368  ++strides_iter;
1369  }
1370 
1371  std::fill(strides_iter, strides.rend(), 0);
1372  iterator = common_iter(buffer.ptr, strides, shape);
1373  }
1374 
1375  void increment_common_iterator(size_t dim) {
1376  for (auto &iter : m_common_iterator)
1377  iter.increment(dim);
1378  }
1379 
1382  std::array<common_iter, N> m_common_iterator;
1383 };
1384 
1386 
1387 // Populates the shape and number of dimensions for the set of buffers. Returns a broadcast_trivial
1388 // enum value indicating whether the broadcast is "trivial"--that is, has each buffer being either a
1389 // singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous (`f_trivial`) storage
1390 // buffer; returns `non_trivial` otherwise.
1391 template <size_t N>
1392 broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &ndim, std::vector<ssize_t> &shape) {
1393  ndim = std::accumulate(buffers.begin(), buffers.end(), ssize_t(0), [](ssize_t res, const buffer_info &buf) {
1394  return std::max(res, buf.ndim);
1395  });
1396 
1397  shape.clear();
1398  shape.resize((size_t) ndim, 1);
1399 
1400  // Figure out the output size, and make sure all input arrays conform (i.e. are either size 1 or
1401  // the full size).
1402  for (size_t i = 0; i < N; ++i) {
1403  auto res_iter = shape.rbegin();
1404  auto end = buffers[i].shape.rend();
1405  for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != end; ++shape_iter, ++res_iter) {
1406  const auto &dim_size_in = *shape_iter;
1407  auto &dim_size_out = *res_iter;
1408 
1409  // Each input dimension can either be 1 or `n`, but `n` values must match across buffers
1410  if (dim_size_out == 1)
1411  dim_size_out = dim_size_in;
1412  else if (dim_size_in != 1 && dim_size_in != dim_size_out)
1413  pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!");
1414  }
1415  }
1416 
1417  bool trivial_broadcast_c = true;
1418  bool trivial_broadcast_f = true;
1419  for (size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
1420  if (buffers[i].size == 1)
1421  continue;
1422 
1423  // Require the same number of dimensions:
1424  if (buffers[i].ndim != ndim)
1425  return broadcast_trivial::non_trivial;
1426 
1427  // Require all dimensions be full-size:
1428  if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin()))
1429  return broadcast_trivial::non_trivial;
1430 
1431  // Check for C contiguity (but only if previous inputs were also C contiguous)
1432  if (trivial_broadcast_c) {
1433  ssize_t expect_stride = buffers[i].itemsize;
1434  auto end = buffers[i].shape.crend();
1435  for (auto shape_iter = buffers[i].shape.crbegin(), stride_iter = buffers[i].strides.crbegin();
1436  trivial_broadcast_c && shape_iter != end; ++shape_iter, ++stride_iter) {
1437  if (expect_stride == *stride_iter)
1438  expect_stride *= *shape_iter;
1439  else
1440  trivial_broadcast_c = false;
1441  }
1442  }
1443 
1444  // Check for Fortran contiguity (if previous inputs were also F contiguous)
1445  if (trivial_broadcast_f) {
1446  ssize_t expect_stride = buffers[i].itemsize;
1447  auto end = buffers[i].shape.cend();
1448  for (auto shape_iter = buffers[i].shape.cbegin(), stride_iter = buffers[i].strides.cbegin();
1449  trivial_broadcast_f && shape_iter != end; ++shape_iter, ++stride_iter) {
1450  if (expect_stride == *stride_iter)
1451  expect_stride *= *shape_iter;
1452  else
1453  trivial_broadcast_f = false;
1454  }
1455  }
1456  }
1457 
1458  return
1459  trivial_broadcast_c ? broadcast_trivial::c_trivial :
1460  trivial_broadcast_f ? broadcast_trivial::f_trivial :
1461  broadcast_trivial::non_trivial;
1462 }
1463 
1464 template <typename T>
1466  static_assert(!std::is_rvalue_reference<T>::value, "Functions with rvalue reference arguments cannot be vectorized");
1467  // The wrapped function gets called with this type:
1469  // Is this a vectorized argument?
1470  static constexpr bool vectorize =
1475  // Accept this type: an array for vectorized types, otherwise the type as-is:
1477 };
1478 
1479 template <typename Func, typename Return, typename... Args>
1481 private:
1482  static constexpr size_t N = sizeof...(Args);
1483  static constexpr size_t NVectorized = constexpr_sum(vectorize_arg<Args>::vectorize...);
1484  static_assert(NVectorized >= 1,
1485  "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1486 
1487 public:
1488  template <typename T>
1489  explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) { }
1490 
1492  return run(args...,
1496  }
1497 
1498 private:
1500 
1501  // Internal compiler error in MSVC 19.16.27025.1 (Visual Studio 2017 15.9.4), when compiling with "/permissive-" flag
1502  // when arg_call_types is manually inlined.
1503  using arg_call_types = std::tuple<typename vectorize_arg<Args>::call_type...>;
1504  template <size_t Index> using param_n_t = typename std::tuple_element<Index, arg_call_types>::type;
1505 
1506  // Runs a vectorized function given arguments tuple and three index sequences:
1507  // - Index is the full set of 0 ... (N-1) argument indices;
1508  // - VIndex is the subset of argument indices with vectorized parameters, letting us access
1509  // vectorized arguments (anything not in this sequence is passed through)
1510  // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that
1511  // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at
1512  // index BIndex in the array).
1513  template <size_t... Index, size_t... VIndex, size_t... BIndex> object run(
1514  typename vectorize_arg<Args>::type &...args,
1516 
1517  // Pointers to values the function was called with; the vectorized ones set here will start
1518  // out as array_t<T> pointers, but they will be changed them to T pointers before we make
1519  // call the wrapped function. Non-vectorized pointers are left as-is.
1520  std::array<void *, N> params{{ &args... }};
1521 
1522  // The array of `buffer_info`s of vectorized arguments:
1523  std::array<buffer_info, NVectorized> buffers{{ reinterpret_cast<array *>(params[VIndex])->request()... }};
1524 
1525  /* Determine dimensions parameters of output array */
1526  ssize_t nd = 0;
1527  std::vector<ssize_t> shape(0);
1528  auto trivial = broadcast(buffers, nd, shape);
1529  size_t ndim = (size_t) nd;
1530 
1531  size_t size = std::accumulate(shape.begin(), shape.end(), (size_t) 1, std::multiplies<size_t>());
1532 
1533  // If all arguments are 0-dimension arrays (i.e. single values) return a plain value (i.e.
1534  // not wrapped in an array).
1535  if (size == 1 && ndim == 0) {
1536  PYBIND11_EXPAND_SIDE_EFFECTS(params[VIndex] = buffers[BIndex].ptr);
1537  return cast(f(*reinterpret_cast<param_n_t<Index> *>(params[Index])...));
1538  }
1539 
1540  array_t<Return> result;
1541  if (trivial == broadcast_trivial::f_trivial) result = array_t<Return, array::f_style>(shape);
1542  else result = array_t<Return>(shape);
1543 
1544  if (size == 0) return std::move(result);
1545 
1546  /* Call the function */
1547  if (trivial == broadcast_trivial::non_trivial)
1548  apply_broadcast(buffers, params, result, i_seq, vi_seq, bi_seq);
1549  else
1550  apply_trivial(buffers, params, result.mutable_data(), size, i_seq, vi_seq, bi_seq);
1551 
1552  return std::move(result);
1553  }
1554 
1555  template <size_t... Index, size_t... VIndex, size_t... BIndex>
1556  void apply_trivial(std::array<buffer_info, NVectorized> &buffers,
1557  std::array<void *, N> &params,
1558  Return *out,
1559  size_t size,
1561 
1562  // Initialize an array of mutable byte references and sizes with references set to the
1563  // appropriate pointer in `params`; as we iterate, we'll increment each pointer by its size
1564  // (except for singletons, which get an increment of 0).
1565  std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{{
1566  std::pair<unsigned char *&, const size_t>(
1567  reinterpret_cast<unsigned char *&>(params[VIndex] = buffers[BIndex].ptr),
1568  buffers[BIndex].size == 1 ? 0 : sizeof(param_n_t<VIndex>)
1569  )...
1570  }};
1571 
1572  for (size_t i = 0; i < size; ++i) {
1573  out[i] = f(*reinterpret_cast<param_n_t<Index> *>(params[Index])...);
1574  for (auto &x : vecparams) x.first += x.second;
1575  }
1576  }
1577 
1578  template <size_t... Index, size_t... VIndex, size_t... BIndex>
1579  void apply_broadcast(std::array<buffer_info, NVectorized> &buffers,
1580  std::array<void *, N> &params,
1581  array_t<Return> &output_array,
1583 
1584  buffer_info output = output_array.request();
1585  multi_array_iterator<NVectorized> input_iter(buffers, output.shape);
1586 
1587  for (array_iterator<Return> iter = array_begin<Return>(output), end = array_end<Return>(output);
1588  iter != end;
1589  ++iter, ++input_iter) {
1591  params[VIndex] = input_iter.template data<BIndex>()
1592  ));
1593  *iter = f(*reinterpret_cast<param_n_t<Index> *>(std::get<Index>(params))...);
1594  }
1595  }
1596 };
1597 
1598 template <typename Func, typename Return, typename... Args>
1599 vectorize_helper<Func, Return, Args...>
1600 vectorize_extractor(const Func &f, Return (*) (Args ...)) {
1601  return detail::vectorize_helper<Func, Return, Args...>(f);
1602 }
1603 
1604 template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
1605  static constexpr auto name = _("numpy.ndarray[") + npy_format_descriptor<T>::name + _("]");
1606 };
1607 
1608 NAMESPACE_END(detail)
1609 
1610 // Vanilla pointer vectorizer:
1611 template <typename Return, typename... Args>
1612 detail::vectorize_helper<Return (*)(Args...), Return, Args...>
1613 vectorize(Return (*f) (Args ...)) {
1614  return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f);
1615 }
1616 
1617 // lambda vectorizer:
1619 auto vectorize(Func &&f) -> decltype(
1620  detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr)) {
1621  return detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr);
1622 }
1623 
1624 // Vectorize a class method (non-const):
1625 template <typename Return, typename Class, typename... Args,
1626  typename Helper = detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())), Return, Class *, Args...>>
1627 Helper vectorize(Return (Class::*f)(Args...)) {
1628  return Helper(std::mem_fn(f));
1629 }
1630 
1631 // Vectorize a class method (const):
1632 template <typename Return, typename Class, typename... Args,
1633  typename Helper = detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...) const>())), Return, const Class *, Args...>>
1634 Helper vectorize(Return (Class::*f)(Args...) const) {
1635  return Helper(std::mem_fn(f));
1636 }
1637 
1639 
1640 #if defined(_MSC_VER)
1641 #pragma warning(pop)
1642 #endif
enable_if_t< Dyn, ssize_t > size() const
Definition: numpy.h:399
void * mutable_data(Ix... index)
Definition: numpy.h:690
static dtype of()
Return dtype associated with a C++ type.
Definition: numpy.h:478
void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const
Definition: numpy.h:811
array_t(handle h, stolen_t)
Definition: numpy.h:844
ssize_t index_at(Ix... index) const
Definition: numpy.h:707
object operator()(typename vectorize_arg< Args >::type... args)
Definition: numpy.h:1491
void increment_common_iterator(size_t dim)
Definition: numpy.h:1375
typename std::add_pointer< T >::type array_iterator
Definition: numpy.h:1268
const ssize_t * strides() const
Strides of the array.
Definition: numpy.h:655
#define PYBIND11_NAMESPACE
Definition: detail/common.h:26
std::tuple< typename vectorize_arg< Args >::call_type... > arg_call_types
Definition: numpy.h:1503
dtype(const std::string &format)
Definition: numpy.h:454
PyObject * ptr() const
Return the underlying PyObject * pointer.
Definition: pytypes.h:182
std::size_t size_t
string release
Definition: conf.py:66
ssize_t shape(ssize_t dim) const
Dimension along a given axis.
Definition: numpy.h:648
typename select_indices_impl< index_sequence<>, 0, Bs... >::type select_indices
object run(typename vectorize_arg< Args >::type &...args, index_sequence< Index... > i_seq, index_sequence< VIndex... > vi_seq, index_sequence< BIndex... > bi_seq)
Definition: numpy.h:1513
tuple make_tuple()
Definition: cast.h:1753
T * mutable_data(Ix... ix)
Mutable pointer access to the data at the given indices.
Definition: numpy.h:432
array(const buffer_info &info)
Definition: numpy.h:609
array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
Definition: numpy.h:835
glibc defines I as a macro which breaks things, e.g., boost template names
Definition: attr.h:15
static std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: numpy.h:787
static bool check_(handle h)
Definition: numpy.h:929
static npy_api lookup()
Definition: numpy.h:219
#define DECL_NPY_API(Func)
char kind() const
Single-character type code.
Definition: numpy.h:493
object operator()(Args &&...args) const
Definition: cast.h:2109
std::vector< ssize_t > container_type
Definition: numpy.h:1282
const std::type_info ssize_t bool(* direct_converter)(PyObject *, void *&))
Definition: numpy.h:1092
STL namespace.
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
static dtype from_args(object args)
This is essentially the same as calling numpy.dtype(args) in Python.
Definition: numpy.h:470
static object _dtype_from_pep3118()
Definition: numpy.h:498
PyObject_HEAD char * data
Definition: numpy.h:62
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Definition: numpy.h:717
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:554
void increment(size_type dim)
Definition: numpy.h:1298
array(ssize_t count, const T *ptr, handle base=handle())
Definition: numpy.h:607
size_t len(handle h)
Definition: pytypes.h:1361
const PyArrayDescr_Proxy * array_descriptor_proxy(const PyObject *ptr)
Definition: numpy.h:265
ssize_t itemsize() const
Byte size of a single element.
Definition: numpy.h:623
void fail_dim_check(ssize_t dim, const std::string &msg) const
Definition: numpy.h:771
ssize_t offset_at(const arr &a, Ix... idx)
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > &>(), fmt, tp), std::basic_string< CharT >
Definition: date.h:5663
std::vector< ssize_t > strides
Definition: buffer_info.h:24
pybind11::dtype dtype() const
Array descriptor (dtype)
Definition: numpy.h:613
constexpr descr< N - 1 > _(char const(&text)[N])
Definition: descr.h:54
static std::string format()
Definition: numpy.h:956
arr data(const arr &a, Ix... index)
detail::unchecked_reference< T, Dims > unchecked() const &
Definition: numpy.h:731
def msg()
Definition: conftest.py:165
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun)
Definition: pytypes.h:789
PyTypeObject * PyArrayDescr_Type_
Definition: numpy.h:188
ssize_t offset_at(Ix... index) const
Definition: numpy.h:697
Information record describing a Python buffer object.
Definition: buffer_info.h:17
typename std::tuple_element< Index, arg_call_types >::type param_n_t
Definition: numpy.h:1504
Wrapper for Python extension modules.
Definition: pybind11.h:789
std::vector< ssize_t > shape
Definition: buffer_info.h:23
#define PYBIND11_NOINLINE
Definition: detail/common.h:86
typename std::enable_if< B, T >::type enable_if_t
Definition: CLI11.hpp:918
ssize_t strides(ssize_t dim) const
Stride along a given axis.
Definition: numpy.h:660
bool Dims mutable_unchecked() &
Definition: numpy.h:905
enable_if_t<!Dyn, ssize_t > size() const
Returns the total number of elements in the referenced array, i.e. the product of the shapes...
Definition: numpy.h:395
obj_attr_accessor attr(handle key) const
Definition: pytypes.h:1410
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
Definition: numpy.h:324
dtype(const char *format)
Definition: numpy.h:458
PyTypeObject * PyArray_Type_
Definition: numpy.h:186
bool has_fields() const
Returns true for structured data types.
Definition: numpy.h:488
ssize_t nbytes() const
Total number of bytes.
Definition: numpy.h:628
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > strides_
Definition: numpy.h:345
const void * data(Ix... index) const
Definition: numpy.h:683
static handle cast(const handle &src, return_value_policy, handle)
Definition: numpy.h:991
ssize_t byte_offset(Ix... index) const
Definition: numpy.h:776
op_< op_int, op_u, self_t, undefined_t > int_(const self_t &)
Definition: operators.h:154
ssize_t itemsize() const
Size of the data type in bytes.
Definition: numpy.h:483
conditional_t< vectorize, array_t< remove_cv_t< call_type >, array::forcecast >, T > type
Definition: numpy.h:1476
const T * data(Ix... ix) const
Pointer access to the data at the given indices.
Definition: numpy.h:382
#define NAMESPACE_END(name)
Definition: detail/common.h:16
dtype strip_padding(ssize_t itemsize)
Definition: numpy.h:504
const T & operator()(Ix... index) const
Definition: numpy.h:369
Helper vectorize(Return(Class::*f)(Args...))
Definition: numpy.h:1627
void resize(ShapeContainer new_shape, bool refcheck=true)
Definition: numpy.h:747
std::unordered_map< std::type_index, numpy_type_info > registered_dtypes
Definition: numpy.h:85
void apply_trivial(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > &params, Return *out, size_t size, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
Definition: numpy.h:1556
object base() const
Base object.
Definition: numpy.h:638
static PyObject * raw_array_t(PyObject *ptr)
Create array from any object – always returns a new reference.
Definition: numpy.h:937
unsigned int(* PyArray_GetNDArrayCFeatureVersion_)()
Definition: numpy.h:178
array(ShapeContainer shape, const T *ptr, handle base=handle())
Definition: numpy.h:603
dtype(list names, list formats, list offsets, ssize_t itemsize)
Definition: numpy.h:460
remove_reference_t< T > call_type
Definition: numpy.h:1468
ssize_t offset_at() const
Definition: numpy.h:703
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun)
Definition: pytypes.h:807
const unsigned char * data_
Definition: numpy.h:341
numpy_type_info * get_type_info(bool throw_if_missing=true)
Definition: numpy.h:96
#define PYBIND11_DECL_CHAR_FMT
Definition: numpy.h:1052
const std::type_info ssize_t itemsize
Definition: numpy.h:1091
remove_reference_t< Func > f
Definition: numpy.h:1499
#define PYBIND11_STR_TYPE
void check_writeable() const
Definition: numpy.h:781
common_iterator(void *ptr, const container_type &strides, const container_type &shape)
Definition: numpy.h:1288
ssize_t ndim() const
Number of dimensions.
Definition: numpy.h:633
vectorize_helper< Func, Return, Args... > vectorize_extractor(const Func &f, Return(*)(Args ...))
Definition: numpy.h:1600
ssize_t shape(ssize_t dim) const
Returns the shape (i.e. size) of dimension dim
Definition: numpy.h:388
typename make_index_sequence_impl< N >::type make_index_sequence
container_type::value_type value_type
Definition: numpy.h:1283
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN)
constexpr size_t constexpr_sum()
Compile-time integer sum.
dtype(const buffer_info &info)
Definition: numpy.h:448
PyObject_VAR_HEAD char * obval
Definition: numpy.h:73
const x_value & at(const std::map< x_key, x_value > &a_map, const x_key &a_key, const x_value &a_default)
std::vector< ssize_t > container_type
Definition: numpy.h:1313
void init_common_iterator(const buffer_info &buffer, const container_type &shape, common_iter &iterator, container_type &strides)
Definition: numpy.h:1350
typename std::remove_reference< T >::type remove_reference_t
ssize_t index_at(const arr &a, Ix... idx)
array(const pybind11::dtype &dt, T count, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:595
PyTypeObject * PyVoidArrType_Type_
Definition: numpy.h:187
def d(s)
Definition: mkdoc.py:69
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t >)
Definition: numpy.h:351
void apply_broadcast(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > &params, array_t< Return > &output_array, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
Definition: numpy.h:1579
array_iterator< T > array_end(const buffer_info &buffer)
Definition: numpy.h:1276
typename std::conditional< B, T, F >::type conditional_t
static PyObject * raw_array(PyObject *ptr, int ExtraFlags=0)
Create array from any object – always returns a new reference.
Definition: numpy.h:821
void check_dimensions_impl(ssize_t, const ssize_t *) const
Definition: numpy.h:809
bool PyArray_Check_(PyObject *obj) const
Definition: numpy.h:171
container_type::size_type size_type
Definition: numpy.h:1284
const T & operator[](ssize_t index) const
Definition: numpy.h:379
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:591
bool_constant< sizeof(T)==sizeof(U)> as
Definition: numpy.h:113
std::array< common_iter, N > m_common_iterator
Definition: numpy.h:1382
static bool direct_converter(PyObject *obj, void *&value)
Definition: numpy.h:1177
ssize_t ndim() const
Returns the number of dimensions of the array.
Definition: numpy.h:391
array_iterator< T > array_begin(const buffer_info &buffer)
Definition: numpy.h:1271
test_initializer buffers("buffers", test_submodule_buffers)
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers. ...
multi_array_iterator(const std::array< buffer_info, N > &buffers, const container_type &shape)
Definition: numpy.h:1315
Annotation indicating that a class derives from another given type.
Definition: attr.h:39
static array_t ensure(handle h)
Definition: numpy.h:922
const detail::type_info * type
Definition: cast.h:453
Annotation for function names.
Definition: attr.h:33
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t< Dyn, ssize_t > dims)
Definition: numpy.h:360
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1685
handle release()
Definition: pytypes.h:247
int flags() const
Return the NumPy array flags.
Definition: numpy.h:667
bool check_flags(const void *ptr, int flag)
Definition: numpy.h:269
array squeeze()
Return a new view with all of the dimensions of length 1 removed.
Definition: numpy.h:739
#define PYBIND11_DEPRECATED(reason)
Definition: detail/common.h:92
detail::unchecked_reference< T, Dims > unchecked() const &
Definition: numpy.h:916
ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index)
Definition: numpy.h:328
static std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: numpy.h:797
static void append_extents(list &)
Definition: numpy.h:283
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
Definition: numpy.h:672
array_t(handle h, borrowed_t)
Definition: numpy.h:843
#define NAMESPACE_BEGIN(name)
Definition: detail/common.h:13
iterator iter(handle obj)
Definition: pytypes.h:1394
T & operator()(Ix... index)
Mutable, unchecked access to data at the given indices.
Definition: numpy.h:418
T cast() const &
T cast(const handle &handle)
Definition: cast.h:1659
numpy_internals & get_numpy_internals()
Definition: numpy.h:105
const ssize_t * shape() const
Dimensions of the array.
Definition: numpy.h:643
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
Definition: numpy.h:1392
constexpr int platform_lookup(Int... codes)
Definition: numpy.h:118
conditional_t< std::is_function< F >::value, F, typename conditional_t< std::is_pointer< F >::value||std::is_member_pointer< F >::value, std::remove_pointer< F >, strip_function_object< F > >::type > function_signature_t
ssize_t size() const
Total number of elements.
Definition: numpy.h:618
PyObject_HEAD PyObject * typeobj
Definition: numpy.h:47
const PyArray_Proxy * array_proxy(const void *ptr)
Definition: numpy.h:257
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base=handle())
Definition: numpy.h:599
const std::type_info & tinfo
Definition: numpy.h:1091
std::string format
Definition: buffer_info.h:21
#define PYBIND11_TYPE_CASTER(type, py_name)
Definition: cast.h:942
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
bool PyArrayDescr_Check_(PyObject *obj) const
Definition: numpy.h:174
const handle & inc_ref() const &
Definition: pytypes.h:190
typename array_info< T >::type remove_all_extents_t
Definition: numpy.h:310
static pybind11::dtype dtype()
Definition: numpy.h:1157
auto to_string(T &&value) -> decltype(std::forward< T >(value))
Convert an object to a string (directly forward if this can become a string)
Definition: CLI11.hpp:1028
static constexpr ssize_t itemsize()
Returns the item size, i.e. sizeof(T)
Definition: numpy.h:385
void check_dimensions(Ix... index) const
Definition: numpy.h:805
Py_ssize_t ssize_t
static void register_dtype(any_container< field_descriptor > fields)
Definition: numpy.h:1166
typename array_info< T >::type type
Definition: numpy.h:290
constexpr descr< 0 > concat()
Definition: descr.h:83
numpy_type_info * get_type_info(const std::type_info &tinfo, bool throw_if_missing=true)
Definition: numpy.h:87
bool owndata() const
If set, the array owns the data (will be freed when the array is deleted)
Definition: numpy.h:677
static array ensure(handle h, int ExtraFlags=0)
Definition: numpy.h:761
multi_array_iterator & operator++()
Definition: numpy.h:1329