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 
15 #include <algorithm>
16 #include <array>
17 #include <cstdint>
18 #include <cstdlib>
19 #include <cstring>
20 #include <functional>
21 #include <numeric>
22 #include <sstream>
23 #include <string>
24 #include <type_traits>
25 #include <typeindex>
26 #include <utility>
27 #include <vector>
28 
29 /* This will be true on all flat address space platforms and allows us to reduce the
30  whole npy_intp / ssize_t / Py_intptr_t business down to just ssize_t for all size
31  and dimension types (e.g. shape, strides, indexing), instead of inflicting this
32  upon the library user. */
33 static_assert(sizeof(::pybind11::ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t");
34 static_assert(std::is_signed<Py_intptr_t>::value, "Py_intptr_t must be signed");
35 // We now can reinterpret_cast between py::ssize_t and Py_intptr_t (MSVC + PyPy cares)
36 
38 
39 class array; // Forward declaration
40 
42 
43 template <>
45  static constexpr auto name = const_name("numpy.ndarray");
46 };
47 
48 template <typename type, typename SFINAE = void>
50 
52  PyObject_HEAD
53  PyObject *typeobj;
54  char kind;
55  char type;
56  char byteorder;
57  char flags;
58  int type_num;
59  int elsize;
60  int alignment;
61  char *subarray;
62  PyObject *fields;
63  PyObject *names;
64 };
65 
66 struct PyArray_Proxy {
67  PyObject_HEAD
68  char *data;
69  int nd;
72  PyObject *base;
73  PyObject *descr;
74  int flags;
75 };
76 
78  PyObject_VAR_HEAD char *obval;
80  int flags;
81  PyObject *base;
82 };
83 
85  PyObject *dtype_ptr;
86  std::string format_str;
87 };
88 
90  std::unordered_map<std::type_index, numpy_type_info> registered_dtypes;
91 
92  numpy_type_info *get_type_info(const std::type_info &tinfo, bool throw_if_missing = true) {
93  auto it = registered_dtypes.find(std::type_index(tinfo));
94  if (it != registered_dtypes.end()) {
95  return &(it->second);
96  }
97  if (throw_if_missing) {
98  pybind11_fail(std::string("NumPy type info missing for ") + tinfo.name());
99  }
100  return nullptr;
101  }
102 
103  template <typename T>
104  numpy_type_info *get_type_info(bool throw_if_missing = true) {
105  return get_type_info(typeid(typename std::remove_cv<T>::type), throw_if_missing);
106  }
107 };
108 
110  ptr = &get_or_create_shared_data<numpy_internals>("_numpy_internals");
111 }
112 
114  static numpy_internals *ptr = nullptr;
115  if (!ptr) {
117  }
118  return *ptr;
119 }
120 
121 template <typename T>
122 struct same_size {
123  template <typename U>
125 };
126 
127 template <typename Concrete>
128 constexpr int platform_lookup() {
129  return -1;
130 }
131 
132 // Lookup a type according to its size, and return a value corresponding to the NumPy typenum.
133 template <typename Concrete, typename T, typename... Ts, typename... Ints>
134 constexpr int platform_lookup(int I, Ints... Is) {
135  return sizeof(Concrete) == sizeof(T) ? I : platform_lookup<Concrete, Ts...>(Is...);
136 }
137 
138 struct npy_api {
139  enum constants {
140  NPY_ARRAY_C_CONTIGUOUS_ = 0x0001,
141  NPY_ARRAY_F_CONTIGUOUS_ = 0x0002,
142  NPY_ARRAY_OWNDATA_ = 0x0004,
143  NPY_ARRAY_FORCECAST_ = 0x0010,
144  NPY_ARRAY_ENSUREARRAY_ = 0x0040,
145  NPY_ARRAY_ALIGNED_ = 0x0100,
146  NPY_ARRAY_WRITEABLE_ = 0x0400,
147  NPY_BOOL_ = 0,
164  NPY_OBJECT_ = 17,
168  // Platform-dependent normalization
169  NPY_INT8_ = NPY_BYTE_,
170  NPY_UINT8_ = NPY_UBYTE_,
171  NPY_INT16_ = NPY_SHORT_,
172  NPY_UINT16_ = NPY_USHORT_,
173  // `npy_common.h` defines the integer aliases. In order, it checks:
174  // NPY_BITSOF_LONG, NPY_BITSOF_LONGLONG, NPY_BITSOF_INT, NPY_BITSOF_SHORT, NPY_BITSOF_CHAR
175  // and assigns the alias to the first matching size, so we should check in this order.
176  NPY_INT32_
177  = platform_lookup<std::int32_t, long, int, short>(NPY_LONG_, NPY_INT_, NPY_SHORT_),
178  NPY_UINT32_ = platform_lookup<std::uint32_t, unsigned long, unsigned int, unsigned short>(
179  NPY_ULONG_, NPY_UINT_, NPY_USHORT_),
180  NPY_INT64_
181  = platform_lookup<std::int64_t, long, long long, int>(NPY_LONG_, NPY_LONGLONG_, NPY_INT_),
182  NPY_UINT64_
183  = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
184  NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
185  };
186 
187  struct PyArray_Dims {
188  Py_intptr_t *ptr;
189  int len;
190  };
191 
192  static npy_api &get() {
193  static npy_api api = lookup();
194  return api;
195  }
196 
197  bool PyArray_Check_(PyObject *obj) const {
198  return PyObject_TypeCheck(obj, PyArray_Type_) != 0;
199  }
200  bool PyArrayDescr_Check_(PyObject *obj) const {
201  return PyObject_TypeCheck(obj, PyArrayDescr_Type_) != 0;
202  }
203 
204  unsigned int (*PyArray_GetNDArrayCFeatureVersion_)();
205  PyObject *(*PyArray_DescrFromType_)(int);
206  PyObject *(*PyArray_NewFromDescr_)(PyTypeObject *,
207  PyObject *,
208  int,
209  Py_intptr_t const *,
210  Py_intptr_t const *,
211  void *,
212  int,
213  PyObject *);
214  // Unused. Not removed because that affects ABI of the class.
215  PyObject *(*PyArray_DescrNewFromType_)(int);
216  int (*PyArray_CopyInto_)(PyObject *, PyObject *);
217  PyObject *(*PyArray_NewCopy_)(PyObject *, int);
218  PyTypeObject *PyArray_Type_;
219  PyTypeObject *PyVoidArrType_Type_;
220  PyTypeObject *PyArrayDescr_Type_;
221  PyObject *(*PyArray_DescrFromScalar_)(PyObject *);
222  PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int, int, int, PyObject *);
223  int (*PyArray_DescrConverter_)(PyObject *, PyObject **);
224  bool (*PyArray_EquivTypes_)(PyObject *, PyObject *);
225  int (*PyArray_GetArrayParamsFromObject_)(PyObject *,
226  PyObject *,
227  unsigned char,
228  PyObject **,
229  int *,
230  Py_intptr_t *,
231  PyObject **,
232  PyObject *);
233  PyObject *(*PyArray_Squeeze_)(PyObject *);
234  // Unused. Not removed because that affects ABI of the class.
235  int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
236  PyObject *(*PyArray_Resize_)(PyObject *, PyArray_Dims *, int, int);
237  PyObject *(*PyArray_Newshape_)(PyObject *, PyArray_Dims *, int);
238  PyObject *(*PyArray_View_)(PyObject *, PyObject *, PyObject *);
239 
240 private:
241  enum functions {
242  API_PyArray_GetNDArrayCFeatureVersion = 211,
243  API_PyArray_Type = 2,
244  API_PyArrayDescr_Type = 3,
245  API_PyVoidArrType_Type = 39,
246  API_PyArray_DescrFromType = 45,
247  API_PyArray_DescrFromScalar = 57,
248  API_PyArray_FromAny = 69,
249  API_PyArray_Resize = 80,
250  API_PyArray_CopyInto = 82,
251  API_PyArray_NewCopy = 85,
252  API_PyArray_NewFromDescr = 94,
253  API_PyArray_DescrNewFromType = 96,
254  API_PyArray_Newshape = 135,
255  API_PyArray_Squeeze = 136,
256  API_PyArray_View = 137,
257  API_PyArray_DescrConverter = 174,
258  API_PyArray_EquivTypes = 182,
259  API_PyArray_GetArrayParamsFromObject = 278,
260  API_PyArray_SetBaseObject = 282
261  };
262 
263  static npy_api lookup() {
264  module_ m = module_::import("numpy.core.multiarray");
265  auto c = m.attr("_ARRAY_API");
266  void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), nullptr);
267  npy_api api;
268 #define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
269  DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
270  if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
271  pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
272  }
273  DECL_NPY_API(PyArray_Type);
274  DECL_NPY_API(PyVoidArrType_Type);
275  DECL_NPY_API(PyArrayDescr_Type);
276  DECL_NPY_API(PyArray_DescrFromType);
277  DECL_NPY_API(PyArray_DescrFromScalar);
278  DECL_NPY_API(PyArray_FromAny);
279  DECL_NPY_API(PyArray_Resize);
280  DECL_NPY_API(PyArray_CopyInto);
281  DECL_NPY_API(PyArray_NewCopy);
282  DECL_NPY_API(PyArray_NewFromDescr);
283  DECL_NPY_API(PyArray_DescrNewFromType);
284  DECL_NPY_API(PyArray_Newshape);
285  DECL_NPY_API(PyArray_Squeeze);
286  DECL_NPY_API(PyArray_View);
287  DECL_NPY_API(PyArray_DescrConverter);
288  DECL_NPY_API(PyArray_EquivTypes);
289  DECL_NPY_API(PyArray_GetArrayParamsFromObject);
290  DECL_NPY_API(PyArray_SetBaseObject);
291 
292 #undef DECL_NPY_API
293  return api;
294  }
295 };
296 
297 inline PyArray_Proxy *array_proxy(void *ptr) { return reinterpret_cast<PyArray_Proxy *>(ptr); }
298 
299 inline const PyArray_Proxy *array_proxy(const void *ptr) {
300  return reinterpret_cast<const PyArray_Proxy *>(ptr);
301 }
302 
304  return reinterpret_cast<PyArrayDescr_Proxy *>(ptr);
305 }
306 
307 inline const PyArrayDescr_Proxy *array_descriptor_proxy(const PyObject *ptr) {
308  return reinterpret_cast<const PyArrayDescr_Proxy *>(ptr);
309 }
310 
311 inline bool check_flags(const void *ptr, int flag) {
312  return (flag == (array_proxy(ptr)->flags & flag));
313 }
314 
315 template <typename T>
316 struct is_std_array : std::false_type {};
317 template <typename T, size_t N>
318 struct is_std_array<std::array<T, N>> : std::true_type {};
319 template <typename T>
320 struct is_complex : std::false_type {};
321 template <typename T>
322 struct is_complex<std::complex<T>> : std::true_type {};
323 
324 template <typename T>
326  using type = T;
327  static constexpr bool is_array = false;
328  static constexpr bool is_empty = false;
329  static constexpr auto extents = const_name("");
330  static void append_extents(list & /* shape */) {}
331 };
332 // Computes underlying type and a comma-separated list of extents for array
333 // types (any mix of std::array and built-in arrays). An array of char is
334 // treated as scalar because it gets special handling.
335 template <typename T>
337 template <typename T, size_t N>
338 struct array_info<std::array<T, N>> {
339  using type = typename array_info<T>::type;
340  static constexpr bool is_array = true;
341  static constexpr bool is_empty = (N == 0) || array_info<T>::is_empty;
342  static constexpr size_t extent = N;
343 
344  // appends the extents to shape
345  static void append_extents(list &shape) {
346  shape.append(N);
348  }
349 
350  static constexpr auto extents = const_name<array_info<T>::is_array>(
351  concat(const_name<N>(), array_info<T>::extents), const_name<N>());
352 };
353 // For numpy we have special handling for arrays of characters, so we don't include
354 // the size in the array extents.
355 template <size_t N>
356 struct array_info<char[N]> : array_info_scalar<char[N]> {};
357 template <size_t N>
358 struct array_info<std::array<char, N>> : array_info_scalar<std::array<char, N>> {};
359 template <typename T, size_t N>
360 struct array_info<T[N]> : array_info<std::array<T, N>> {};
361 template <typename T>
363 
364 template <typename T>
365 using is_pod_struct
366  = all_of<std::is_standard_layout<T>, // since we're accessing directly in memory
367  // we need a standard layout type
368 #if defined(__GLIBCXX__) \
369  && (__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20150426 || __GLIBCXX__ == 20150623 \
370  || __GLIBCXX__ == 20150626 || __GLIBCXX__ == 20160803)
371  // libstdc++ < 5 (including versions 4.8.5, 4.9.3 and 4.9.4 which were released after
372  // 5) don't implement is_trivially_copyable, so approximate it
373  std::is_trivially_destructible<T>,
375 #else
376  std::is_trivially_copyable<T>,
377 #endif
379  std::is_reference,
380  std::is_array,
381  is_std_array,
382  std::is_arithmetic,
383  is_complex,
384  std::is_enum>>;
385 
386 // Replacement for std::is_pod (deprecated in C++20)
387 template <typename T>
388 using is_pod = all_of<std::is_standard_layout<T>, std::is_trivial<T>>;
389 
390 template <ssize_t Dim = 0, typename Strides>
391 ssize_t byte_offset_unsafe(const Strides &) {
392  return 0;
393 }
394 template <ssize_t Dim = 0, typename Strides, typename... Ix>
395 ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index) {
396  return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
397 }
398 
404 template <typename T, ssize_t Dims>
406 protected:
407  static constexpr bool Dynamic = Dims < 0;
408  const unsigned char *data_;
409  // Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
410  // make large performance gains on big, nested loops, but requires compile-time dimensions
412  const ssize_t dims_;
413 
414  friend class pybind11::array;
415  // Constructor for compile-time dimensions:
416  template <bool Dyn = Dynamic>
418  const ssize_t *shape,
419  const ssize_t *strides,
421  : data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} {
422  for (size_t i = 0; i < (size_t) dims_; i++) {
423  shape_[i] = shape[i];
424  strides_[i] = strides[i];
425  }
426  }
427  // Constructor for runtime dimensions:
428  template <bool Dyn = Dynamic>
430  const ssize_t *shape,
431  const ssize_t *strides,
433  : data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides},
434  dims_{dims} {}
435 
436 public:
442  template <typename... Ix>
443  const T &operator()(Ix... index) const {
444  static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
445  "Invalid number of indices for unchecked array reference");
446  return *reinterpret_cast<const T *>(data_
447  + byte_offset_unsafe(strides_, ssize_t(index)...));
448  }
453  template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
454  const T &operator[](ssize_t index) const {
455  return operator()(index);
456  }
457 
459  template <typename... Ix>
460  const T *data(Ix... ix) const {
461  return &operator()(ssize_t(ix)...);
462  }
463 
465  constexpr static ssize_t itemsize() { return sizeof(T); }
466 
468  ssize_t shape(ssize_t dim) const { return shape_[(size_t) dim]; }
469 
471  ssize_t ndim() const { return dims_; }
472 
475  template <bool Dyn = Dynamic>
477  return std::accumulate(
478  shape_.begin(), shape_.end(), (ssize_t) 1, std::multiplies<ssize_t>());
479  }
480  template <bool Dyn = Dynamic>
482  return std::accumulate(shape_, shape_ + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
483  }
484 
488  ssize_t nbytes() const { return size() * itemsize(); }
489 };
490 
491 template <typename T, ssize_t Dims>
493  friend class pybind11::array;
495  using ConstBase::ConstBase;
496  using ConstBase::Dynamic;
497 
498 public:
499  // Bring in const-qualified versions from base class
500  using ConstBase::operator();
501  using ConstBase::operator[];
502 
504  template <typename... Ix>
505  T &operator()(Ix... index) {
506  static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
507  "Invalid number of indices for unchecked array reference");
508  return const_cast<T &>(ConstBase::operator()(index...));
509  }
515  template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
516  T &operator[](ssize_t index) {
517  return operator()(index);
518  }
519 
521  template <typename... Ix>
522  T *mutable_data(Ix... ix) {
523  return &operator()(ssize_t(ix)...);
524  }
525 };
526 
527 template <typename T, ssize_t Dim>
529  static_assert(Dim == 0 && Dim > 0 /* always fail */,
530  "unchecked array proxy object is not castable");
531 };
532 template <typename T, ssize_t Dim>
534  : type_caster<unchecked_reference<T, Dim>> {};
535 
537 
538 class dtype : public object {
539 public:
540  PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_);
541 
542  explicit dtype(const buffer_info &info) {
543  dtype descr(_dtype_from_pep3118()(pybind11::str(info.format)));
544  // If info.itemsize == 0, use the value calculated from the format string
545  m_ptr = descr.strip_padding(info.itemsize != 0 ? info.itemsize : descr.itemsize())
546  .release()
547  .ptr();
548  }
549 
550  explicit dtype(const pybind11::str &format) : dtype(from_args(format)) {}
551 
552  explicit dtype(const std::string &format) : dtype(pybind11::str(format)) {}
553 
554  explicit dtype(const char *format) : dtype(pybind11::str(format)) {}
555 
556  dtype(list names, list formats, list offsets, ssize_t itemsize) {
557  dict args;
558  args["names"] = std::move(names);
559  args["formats"] = std::move(formats);
560  args["offsets"] = std::move(offsets);
561  args["itemsize"] = pybind11::int_(itemsize);
562  m_ptr = from_args(args).release().ptr();
563  }
564 
565  explicit dtype(int typenum)
566  : object(detail::npy_api::get().PyArray_DescrFromType_(typenum), stolen_t{}) {
567  if (m_ptr == nullptr) {
568  throw error_already_set();
569  }
570  }
571 
573  static dtype from_args(const object &args) {
574  PyObject *ptr = nullptr;
575  if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr) {
576  throw error_already_set();
577  }
578  return reinterpret_steal<dtype>(ptr);
579  }
580 
582  template <typename T>
583  static dtype of() {
585  }
586 
589 
591  bool has_fields() const { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; }
592 
595  char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; }
596 
599  char char_() const {
600  // Note: The signature, `dtype::char_` follows the naming of NumPy's
601  // public Python API (i.e., ``dtype.char``), rather than its internal
602  // C API (``PyArray_Descr::type``).
603  return detail::array_descriptor_proxy(m_ptr)->type;
604  }
605 
607  int num() const {
608  // Note: The signature, `dtype::num` follows the naming of NumPy's public
609  // Python API (i.e., ``dtype.num``), rather than its internal
610  // C API (``PyArray_Descr::type_num``).
612  }
613 
615  char byteorder() const { return detail::array_descriptor_proxy(m_ptr)->byteorder; }
616 
618  int alignment() const { return detail::array_descriptor_proxy(m_ptr)->alignment; }
619 
621  char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
622 
623 private:
624  static object _dtype_from_pep3118() {
625  static PyObject *obj = module_::import("numpy.core._internal")
626  .attr("_dtype_from_pep3118")
627  .cast<object>()
628  .release()
629  .ptr();
630  return reinterpret_borrow<object>(obj);
631  }
632 
634  // Recursively strip all void fields with empty names that are generated for
635  // padding fields (as of NumPy v1.11).
636  if (!has_fields()) {
637  return *this;
638  }
639 
640  struct field_descr {
642  object format;
643  pybind11::int_ offset;
644  field_descr(pybind11::str &&name, object &&format, pybind11::int_ &&offset)
645  : name{std::move(name)}, format{std::move(format)}, offset{std::move(offset)} {};
646  };
647  auto field_dict = attr("fields").cast<dict>();
648  std::vector<field_descr> field_descriptors;
649  field_descriptors.reserve(field_dict.size());
650 
651  for (auto field : field_dict.attr("items")()) {
652  auto spec = field.cast<tuple>();
653  auto name = spec[0].cast<pybind11::str>();
654  auto spec_fo = spec[1].cast<tuple>();
655  auto format = spec_fo[0].cast<dtype>();
656  auto offset = spec_fo[1].cast<pybind11::int_>();
657  if ((len(name) == 0u) && format.kind() == 'V') {
658  continue;
659  }
660  field_descriptors.emplace_back(
661  std::move(name), format.strip_padding(format.itemsize()), std::move(offset));
662  }
663 
664  std::sort(field_descriptors.begin(),
665  field_descriptors.end(),
666  [](const field_descr &a, const field_descr &b) {
667  return a.offset.cast<int>() < b.offset.cast<int>();
668  });
669 
670  list names, formats, offsets;
671  for (auto &descr : field_descriptors) {
672  names.append(std::move(descr.name));
673  formats.append(std::move(descr.format));
674  offsets.append(std::move(descr.offset));
675  }
676  return dtype(std::move(names), std::move(formats), std::move(offsets), itemsize);
677  }
678 };
679 
680 class array : public buffer {
681 public:
682  PYBIND11_OBJECT_CVT(array, buffer, detail::npy_api::get().PyArray_Check_, raw_array)
683 
684  enum {
685  c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
686  f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
687  forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
688  };
689 
690  array() : array(0, static_cast<const double *>(nullptr)) {}
691 
692  using ShapeContainer = detail::any_container<ssize_t>;
693  using StridesContainer = detail::any_container<ssize_t>;
694 
695  // Constructs an array taking shape/strides from arbitrary container types
696  array(const pybind11::dtype &dt,
697  ShapeContainer shape,
699  const void *ptr = nullptr,
700  handle base = handle()) {
701 
702  if (strides->empty()) {
703  *strides = detail::c_strides(*shape, dt.itemsize());
704  }
705 
706  auto ndim = shape->size();
707  if (ndim != strides->size()) {
708  pybind11_fail("NumPy: shape ndim doesn't match strides ndim");
709  }
710  auto descr = dt;
711 
712  int flags = 0;
713  if (base && ptr) {
714  if (isinstance<array>(base)) {
715  /* Copy flags from base (except ownership bit) */
716  flags = reinterpret_borrow<array>(base).flags()
718  } else {
719  /* Writable by default, easy to downgrade later on if needed */
720  flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
721  }
722  }
723 
724  auto &api = detail::npy_api::get();
725  auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
726  api.PyArray_Type_,
727  descr.release().ptr(),
728  (int) ndim,
729  // Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
730  reinterpret_cast<Py_intptr_t *>(shape->data()),
731  reinterpret_cast<Py_intptr_t *>(strides->data()),
732  const_cast<void *>(ptr),
733  flags,
734  nullptr));
735  if (!tmp) {
736  throw error_already_set();
737  }
738  if (ptr) {
739  if (base) {
740  api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr());
741  } else {
742  tmp = reinterpret_steal<object>(
743  api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */));
744  }
745  }
746  m_ptr = tmp.release().ptr();
747  }
748 
749  array(const pybind11::dtype &dt,
750  ShapeContainer shape,
751  const void *ptr = nullptr,
752  handle base = handle())
753  : array(dt, std::move(shape), {}, ptr, base) {}
754 
755  template <typename T,
756  typename
758  array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle())
759  : array(dt, {{count}}, ptr, base) {}
760 
761  template <typename T>
762  array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle())
763  : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) {}
764 
765  template <typename T>
766  array(ShapeContainer shape, const T *ptr, handle base = handle())
767  : array(std::move(shape), {}, ptr, base) {}
768 
769  template <typename T>
770  explicit array(ssize_t count, const T *ptr, handle base = handle())
771  : array({count}, {}, ptr, base) {}
772 
773  explicit array(const buffer_info &info, handle base = handle())
774  : array(pybind11::dtype(info), info.shape, info.strides, info.ptr, base) {}
775 
777  pybind11::dtype dtype() const {
778  return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(m_ptr)->descr);
779  }
780 
782  ssize_t size() const {
783  return std::accumulate(shape(), shape() + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
784  }
785 
787  ssize_t itemsize() const {
789  }
790 
792  ssize_t nbytes() const { return size() * itemsize(); }
793 
795  ssize_t ndim() const { return detail::array_proxy(m_ptr)->nd; }
796 
798  object base() const { return reinterpret_borrow<object>(detail::array_proxy(m_ptr)->base); }
799 
801  const ssize_t *shape() const { return detail::array_proxy(m_ptr)->dimensions; }
802 
804  ssize_t shape(ssize_t dim) const {
805  if (dim >= ndim()) {
806  fail_dim_check(dim, "invalid axis");
807  }
808  return shape()[dim];
809  }
810 
812  const ssize_t *strides() const { return detail::array_proxy(m_ptr)->strides; }
813 
815  ssize_t strides(ssize_t dim) const {
816  if (dim >= ndim()) {
817  fail_dim_check(dim, "invalid axis");
818  }
819  return strides()[dim];
820  }
821 
823  int flags() const { return detail::array_proxy(m_ptr)->flags; }
824 
826  bool writeable() const {
827  return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_);
828  }
829 
831  bool owndata() const {
832  return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_);
833  }
834 
837  template <typename... Ix>
838  const void *data(Ix... index) const {
839  return static_cast<const void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
840  }
841 
845  template <typename... Ix>
846  void *mutable_data(Ix... index) {
847  check_writeable();
848  return static_cast<void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
849  }
850 
853  template <typename... Ix>
854  ssize_t offset_at(Ix... index) const {
855  if ((ssize_t) sizeof...(index) > ndim()) {
856  fail_dim_check(sizeof...(index), "too many indices for an array");
857  }
858  return byte_offset(ssize_t(index)...);
859  }
860 
861  ssize_t offset_at() const { return 0; }
862 
865  template <typename... Ix>
866  ssize_t index_at(Ix... index) const {
867  return offset_at(index...) / itemsize();
868  }
869 
876  template <typename T, ssize_t Dims = -1>
877  detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
878  if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
879  throw std::domain_error("array has incorrect number of dimensions: "
880  + std::to_string(ndim()) + "; expected "
881  + std::to_string(Dims));
882  }
883  return detail::unchecked_mutable_reference<T, Dims>(
884  mutable_data(), shape(), strides(), ndim());
885  }
886 
894  template <typename T, ssize_t Dims = -1>
895  detail::unchecked_reference<T, Dims> unchecked() const & {
896  if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
897  throw std::domain_error("array has incorrect number of dimensions: "
898  + std::to_string(ndim()) + "; expected "
899  + std::to_string(Dims));
900  }
901  return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim());
902  }
903 
906  auto &api = detail::npy_api::get();
907  return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
908  }
909 
913  void resize(ShapeContainer new_shape, bool refcheck = true) {
914  detail::npy_api::PyArray_Dims d
915  = {// Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
916  reinterpret_cast<Py_intptr_t *>(new_shape->data()),
917  int(new_shape->size())};
918  // try to resize, set ordering param to -1 cause it's not used anyway
919  auto new_array = reinterpret_steal<object>(
920  detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1));
921  if (!new_array) {
922  throw error_already_set();
923  }
924  if (isinstance<array>(new_array)) {
925  *this = std::move(new_array);
926  }
927  }
928 
931  detail::npy_api::PyArray_Dims d
932  = {reinterpret_cast<Py_intptr_t *>(new_shape->data()), int(new_shape->size())};
933  auto new_array
934  = reinterpret_steal<array>(detail::npy_api::get().PyArray_Newshape_(m_ptr, &d, 0));
935  if (!new_array) {
936  throw error_already_set();
937  }
938  return new_array;
939  }
940 
946  array view(const std::string &dtype) {
947  auto &api = detail::npy_api::get();
948  auto new_view = reinterpret_steal<array>(api.PyArray_View_(
949  m_ptr, dtype::from_args(pybind11::str(dtype)).release().ptr(), nullptr));
950  if (!new_view) {
951  throw error_already_set();
952  }
953  return new_view;
954  }
955 
958  static array ensure(handle h, int ExtraFlags = 0) {
959  auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags));
960  if (!result) {
961  PyErr_Clear();
962  }
963  return result;
964  }
965 
966 protected:
967  template <typename, typename>
968  friend struct detail::npy_format_descriptor;
969 
970  void fail_dim_check(ssize_t dim, const std::string &msg) const {
971  throw index_error(msg + ": " + std::to_string(dim) + " (ndim = " + std::to_string(ndim())
972  + ')');
973  }
974 
975  template <typename... Ix>
976  ssize_t byte_offset(Ix... index) const {
977  check_dimensions(index...);
978  return detail::byte_offset_unsafe(strides(), ssize_t(index)...);
979  }
980 
981  void check_writeable() const {
982  if (!writeable()) {
983  throw std::domain_error("array is not writeable");
984  }
985  }
986 
987  template <typename... Ix>
988  void check_dimensions(Ix... index) const {
989  check_dimensions_impl(ssize_t(0), shape(), ssize_t(index)...);
990  }
991 
992  void check_dimensions_impl(ssize_t, const ssize_t *) const {}
993 
994  template <typename... Ix>
995  void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const {
996  if (i >= *shape) {
997  throw index_error(std::string("index ") + std::to_string(i)
998  + " is out of bounds for axis " + std::to_string(axis)
999  + " with size " + std::to_string(*shape));
1000  }
1001  check_dimensions_impl(axis + 1, shape + 1, index...);
1002  }
1003 
1005  static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) {
1006  if (ptr == nullptr) {
1007  PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
1008  return nullptr;
1009  }
1010  return detail::npy_api::get().PyArray_FromAny_(
1011  ptr, nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr);
1012  }
1013 };
1014 
1015 template <typename T, int ExtraFlags = array::forcecast>
1016 class array_t : public array {
1017 private:
1018  struct private_ctor {};
1019  // Delegating constructor needed when both moving and accessing in the same constructor
1020  array_t(private_ctor,
1021  ShapeContainer &&shape,
1022  StridesContainer &&strides,
1023  const T *ptr,
1024  handle base)
1025  : array(std::move(shape), std::move(strides), ptr, base) {}
1026 
1027 public:
1028  static_assert(!detail::array_info<T>::is_array, "Array types cannot be used with array_t");
1029 
1030  using value_type = T;
1031 
1032  array_t() : array(0, static_cast<const T *>(nullptr)) {}
1035 
1036  PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
1037  array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) {
1038  if (!m_ptr) {
1039  PyErr_Clear();
1040  }
1041  if (!is_borrowed) {
1042  Py_XDECREF(h.ptr());
1043  }
1044  }
1045 
1046  // NOLINTNEXTLINE(google-explicit-constructor)
1047  array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
1048  if (!m_ptr) {
1049  throw error_already_set();
1050  }
1051  }
1052 
1053  explicit array_t(const buffer_info &info, handle base = handle()) : array(info, base) {}
1054 
1056  StridesContainer strides,
1057  const T *ptr = nullptr,
1058  handle base = handle())
1059  : array(std::move(shape), std::move(strides), ptr, base) {}
1060 
1061  explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle())
1062  : array_t(private_ctor{},
1063  std::move(shape),
1064  (ExtraFlags & f_style) != 0 ? detail::f_strides(*shape, itemsize())
1065  : detail::c_strides(*shape, itemsize()),
1066  ptr,
1067  base) {}
1068 
1069  explicit array_t(ssize_t count, const T *ptr = nullptr, handle base = handle())
1070  : array({count}, {}, ptr, base) {}
1071 
1072  constexpr ssize_t itemsize() const { return sizeof(T); }
1073 
1074  template <typename... Ix>
1075  ssize_t index_at(Ix... index) const {
1076  return offset_at(index...) / itemsize();
1077  }
1078 
1079  template <typename... Ix>
1080  const T *data(Ix... index) const {
1081  return static_cast<const T *>(array::data(index...));
1082  }
1083 
1084  template <typename... Ix>
1085  T *mutable_data(Ix... index) {
1086  return static_cast<T *>(array::mutable_data(index...));
1087  }
1088 
1089  // Reference to element at a given index
1090  template <typename... Ix>
1091  const T &at(Ix... index) const {
1092  if ((ssize_t) sizeof...(index) != ndim()) {
1093  fail_dim_check(sizeof...(index), "index dimension mismatch");
1094  }
1095  return *(static_cast<const T *>(array::data())
1096  + byte_offset(ssize_t(index)...) / itemsize());
1097  }
1098 
1099  // Mutable reference to element at a given index
1100  template <typename... Ix>
1101  T &mutable_at(Ix... index) {
1102  if ((ssize_t) sizeof...(index) != ndim()) {
1103  fail_dim_check(sizeof...(index), "index dimension mismatch");
1104  }
1105  return *(static_cast<T *>(array::mutable_data())
1106  + byte_offset(ssize_t(index)...) / itemsize());
1107  }
1108 
1115  template <ssize_t Dims = -1>
1116  detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
1117  return array::mutable_unchecked<T, Dims>();
1118  }
1119 
1127  template <ssize_t Dims = -1>
1128  detail::unchecked_reference<T, Dims> unchecked() const & {
1129  return array::unchecked<T, Dims>();
1130  }
1131 
1135  auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr()));
1136  if (!result) {
1137  PyErr_Clear();
1138  }
1139  return result;
1140  }
1141 
1142  static bool check_(handle h) {
1143  const auto &api = detail::npy_api::get();
1144  return api.PyArray_Check_(h.ptr())
1145  && api.PyArray_EquivTypes_(detail::array_proxy(h.ptr())->descr,
1146  dtype::of<T>().ptr())
1147  && detail::check_flags(h.ptr(), ExtraFlags & (array::c_style | array::f_style));
1148  }
1149 
1150 protected:
1152  static PyObject *raw_array_t(PyObject *ptr) {
1153  if (ptr == nullptr) {
1154  PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
1155  return nullptr;
1156  }
1157  return detail::npy_api::get().PyArray_FromAny_(ptr,
1158  dtype::of<T>().release().ptr(),
1159  0,
1160  0,
1161  detail::npy_api::NPY_ARRAY_ENSUREARRAY_
1162  | ExtraFlags,
1163  nullptr);
1164  }
1165 };
1166 
1167 template <typename T>
1168 struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1169  static std::string format() {
1171  }
1172 };
1173 
1174 template <size_t N>
1175 struct format_descriptor<char[N]> {
1176  static std::string format() { return std::to_string(N) + 's'; }
1177 };
1178 template <size_t N>
1179 struct format_descriptor<std::array<char, N>> {
1180  static std::string format() { return std::to_string(N) + 's'; }
1181 };
1182 
1183 template <typename T>
1184 struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> {
1185  static std::string format() {
1186  return format_descriptor<
1188  }
1189 };
1190 
1191 template <typename T>
1192 struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
1193  static std::string format() {
1194  using namespace detail;
1195  static constexpr auto extents = const_name("(") + array_info<T>::extents + const_name(")");
1196  return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
1197  }
1198 };
1199 
1201 template <typename T, int ExtraFlags>
1202 struct pyobject_caster<array_t<T, ExtraFlags>> {
1204 
1205  bool load(handle src, bool convert) {
1206  if (!convert && !type::check_(src)) {
1207  return false;
1208  }
1209  value = type::ensure(src);
1210  return static_cast<bool>(value);
1211  }
1212 
1213  static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
1214  return src.inc_ref();
1215  }
1217 };
1218 
1219 template <typename T>
1220 struct compare_buffer_info<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1221  static bool compare(const buffer_info &b) {
1222  return npy_api::get().PyArray_EquivTypes_(dtype::of<T>().ptr(), dtype(b).ptr());
1223  }
1224 };
1225 
1226 template <typename T, typename = void>
1228 
1229 template <typename T>
1232  const_name("bool"),
1233  const_name<std::is_signed<T>::value>("numpy.int", "numpy.uint")
1234  + const_name<sizeof(T) * 8>());
1235 };
1236 
1237 template <typename T>
1238 struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
1243  > (const_name("numpy.float") + const_name<sizeof(T) * 8>(),
1244  const_name("numpy.longdouble"));
1245 };
1246 
1247 template <typename T>
1253  > (const_name("numpy.complex")
1254  + const_name<sizeof(typename T::value_type) * 16>(),
1255  const_name("numpy.longcomplex"));
1256 };
1257 
1258 template <typename T>
1260  T,
1261  enable_if_t<satisfies_any_of<T, std::is_arithmetic, is_complex>::value>>
1263 private:
1264  // NB: the order here must match the one in common.h
1265  constexpr static const int values[15] = {npy_api::NPY_BOOL_,
1280 
1281 public:
1282  static constexpr int value = values[detail::is_fmt_numeric<T>::index];
1283 
1284  static pybind11::dtype dtype() {
1285  if (auto *ptr = npy_api::get().PyArray_DescrFromType_(value)) {
1286  return reinterpret_steal<pybind11::dtype>(ptr);
1287  }
1288  pybind11_fail("Unsupported buffer format!");
1289  }
1290 };
1291 
1292 #define PYBIND11_DECL_CHAR_FMT \
1293  static constexpr auto name = const_name("S") + const_name<N>(); \
1294  static pybind11::dtype dtype() { \
1295  return pybind11::dtype(std::string("S") + std::to_string(N)); \
1296  }
1297 template <size_t N>
1298 struct npy_format_descriptor<char[N]> {
1300 };
1301 template <size_t N>
1302 struct npy_format_descriptor<std::array<char, N>> {
1303  PYBIND11_DECL_CHAR_FMT
1304 };
1305 #undef PYBIND11_DECL_CHAR_FMT
1306 
1307 template <typename T>
1309 private:
1311 
1312 public:
1313  static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
1314 
1315  static constexpr auto name
1317  static pybind11::dtype dtype() {
1318  list shape;
1320  return pybind11::dtype::from_args(
1321  pybind11::make_tuple(base_descr::dtype(), std::move(shape)));
1322  }
1323 };
1324 
1325 template <typename T>
1327 private:
1329 
1330 public:
1331  static constexpr auto name = base_descr::name;
1332  static pybind11::dtype dtype() { return base_descr::dtype(); }
1333 };
1334 
1336  const char *name;
1339  std::string format;
1341 };
1342 
1344  const std::type_info &tinfo,
1345  ssize_t itemsize,
1346  bool (*direct_converter)(PyObject *, void *&)) {
1347 
1349  if (numpy_internals.get_type_info(tinfo, false)) {
1350  pybind11_fail("NumPy: dtype is already registered");
1351  }
1352 
1353  // Use ordered fields because order matters as of NumPy 1.14:
1354  // https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
1355  std::vector<field_descriptor> ordered_fields(std::move(fields));
1356  std::sort(
1357  ordered_fields.begin(),
1358  ordered_fields.end(),
1359  [](const field_descriptor &a, const field_descriptor &b) { return a.offset < b.offset; });
1360 
1361  list names, formats, offsets;
1362  for (auto &field : ordered_fields) {
1363  if (!field.descr) {
1364  pybind11_fail(std::string("NumPy: unsupported field dtype: `") + field.name + "` @ "
1365  + tinfo.name());
1366  }
1367  names.append(pybind11::str(field.name));
1368  formats.append(field.descr);
1369  offsets.append(pybind11::int_(field.offset));
1370  }
1371  auto *dtype_ptr
1372  = pybind11::dtype(std::move(names), std::move(formats), std::move(offsets), itemsize)
1373  .release()
1374  .ptr();
1375 
1376  // There is an existing bug in NumPy (as of v1.11): trailing bytes are
1377  // not encoded explicitly into the format string. This will supposedly
1378  // get fixed in v1.12; for further details, see these:
1379  // - https://github.com/numpy/numpy/issues/7797
1380  // - https://github.com/numpy/numpy/pull/7798
1381  // Because of this, we won't use numpy's logic to generate buffer format
1382  // strings and will just do it ourselves.
1383  ssize_t offset = 0;
1384  std::ostringstream oss;
1385  // mark the structure as unaligned with '^', because numpy and C++ don't
1386  // always agree about alignment (particularly for complex), and we're
1387  // explicitly listing all our padding. This depends on none of the fields
1388  // overriding the endianness. Putting the ^ in front of individual fields
1389  // isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
1390  oss << "^T{";
1391  for (auto &field : ordered_fields) {
1392  if (field.offset > offset) {
1393  oss << (field.offset - offset) << 'x';
1394  }
1395  oss << field.format << ':' << field.name << ':';
1396  offset = field.offset + field.size;
1397  }
1398  if (itemsize > offset) {
1399  oss << (itemsize - offset) << 'x';
1400  }
1401  oss << '}';
1402  auto format_str = oss.str();
1403 
1404  // Sanity check: verify that NumPy properly parses our buffer format string
1405  auto &api = npy_api::get();
1406  auto arr = array(buffer_info(nullptr, itemsize, format_str, 1));
1407  if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) {
1408  pybind11_fail("NumPy: invalid buffer descriptor!");
1409  }
1410 
1411  auto tindex = std::type_index(tinfo);
1412  numpy_internals.registered_dtypes[tindex] = {dtype_ptr, std::move(format_str)};
1413  get_internals().direct_conversions[tindex].push_back(direct_converter);
1414 }
1415 
1416 template <typename T, typename SFINAE>
1417 struct npy_format_descriptor {
1418  static_assert(is_pod_struct<T>::value,
1419  "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1420 
1421  static constexpr auto name = make_caster<T>::name;
1422 
1423  static pybind11::dtype dtype() { return reinterpret_borrow<pybind11::dtype>(dtype_ptr()); }
1424 
1425  static std::string format() {
1426  static auto format_str = get_numpy_internals().get_type_info<T>(true)->format_str;
1427  return format_str;
1428  }
1429 
1431  register_structured_dtype(std::move(fields),
1432  typeid(typename std::remove_cv<T>::type),
1433  sizeof(T),
1434  &direct_converter);
1435  }
1436 
1437 private:
1438  static PyObject *dtype_ptr() {
1439  static PyObject *ptr = get_numpy_internals().get_type_info<T>(true)->dtype_ptr;
1440  return ptr;
1441  }
1442 
1443  static bool direct_converter(PyObject *obj, void *&value) {
1444  auto &api = npy_api::get();
1445  if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) {
1446  return false;
1447  }
1448  if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1449  if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
1450  value = ((PyVoidScalarObject_Proxy *) obj)->obval;
1451  return true;
1452  }
1453  }
1454  return false;
1455  }
1456 };
1457 
1458 #ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code)
1459 # define PYBIND11_NUMPY_DTYPE(Type, ...) ((void) 0)
1460 # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void) 0)
1461 #else
1462 
1463 # define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
1464  ::pybind11::detail::field_descriptor { \
1465  Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
1466  ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
1467  ::pybind11::detail::npy_format_descriptor< \
1468  decltype(std::declval<T>().Field)>::dtype() \
1469  }
1470 
1471 // Extract name, offset and format descriptor for a struct field
1472 # define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, # Field)
1473 
1474 // The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
1475 // (C) William Swanson, Paul Fultz
1476 # define PYBIND11_EVAL0(...) __VA_ARGS__
1477 # define PYBIND11_EVAL1(...) PYBIND11_EVAL0(PYBIND11_EVAL0(PYBIND11_EVAL0(__VA_ARGS__)))
1478 # define PYBIND11_EVAL2(...) PYBIND11_EVAL1(PYBIND11_EVAL1(PYBIND11_EVAL1(__VA_ARGS__)))
1479 # define PYBIND11_EVAL3(...) PYBIND11_EVAL2(PYBIND11_EVAL2(PYBIND11_EVAL2(__VA_ARGS__)))
1480 # define PYBIND11_EVAL4(...) PYBIND11_EVAL3(PYBIND11_EVAL3(PYBIND11_EVAL3(__VA_ARGS__)))
1481 # define PYBIND11_EVAL(...) PYBIND11_EVAL4(PYBIND11_EVAL4(PYBIND11_EVAL4(__VA_ARGS__)))
1482 # define PYBIND11_MAP_END(...)
1483 # define PYBIND11_MAP_OUT
1484 # define PYBIND11_MAP_COMMA ,
1485 # define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END
1486 # define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
1487 # define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0(test, next, 0)
1488 # define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1(PYBIND11_MAP_GET_END test, next)
1489 # if defined(_MSC_VER) \
1490  && !defined(__clang__) // MSVC is not as eager to expand macros, hence this workaround
1491 # define PYBIND11_MAP_LIST_NEXT1(test, next) \
1492  PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1493 # else
1494 # define PYBIND11_MAP_LIST_NEXT1(test, next) \
1495  PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1496 # endif
1497 # define PYBIND11_MAP_LIST_NEXT(test, next) \
1498  PYBIND11_MAP_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1499 # define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \
1500  f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST1)(f, t, peek, __VA_ARGS__)
1501 # define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
1502  f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST0)(f, t, peek, __VA_ARGS__)
1503 // PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ...
1504 # define PYBIND11_MAP_LIST(f, t, ...) \
1505  PYBIND11_EVAL(PYBIND11_MAP_LIST1(f, t, __VA_ARGS__, (), 0))
1506 
1507 # define PYBIND11_NUMPY_DTYPE(Type, ...) \
1508  ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1509  ::std::vector<::pybind11::detail::field_descriptor>{ \
1510  PYBIND11_MAP_LIST(PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
1511 
1512 # if defined(_MSC_VER) && !defined(__clang__)
1513 # define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1514  PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1515 # else
1516 # define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1517  PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1518 # endif
1519 # define PYBIND11_MAP2_LIST_NEXT(test, next) \
1520  PYBIND11_MAP2_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1521 # define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
1522  f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST1)(f, t, peek, __VA_ARGS__)
1523 # define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
1524  f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST0)(f, t, peek, __VA_ARGS__)
1525 // PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ...
1526 # define PYBIND11_MAP2_LIST(f, t, ...) \
1527  PYBIND11_EVAL(PYBIND11_MAP2_LIST1(f, t, __VA_ARGS__, (), 0))
1528 
1529 # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
1530  ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1531  ::std::vector<::pybind11::detail::field_descriptor>{ \
1532  PYBIND11_MAP2_LIST(PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
1533 
1534 #endif // __CLION_IDE__
1535 
1537 public:
1538  using container_type = std::vector<ssize_t>;
1539  using value_type = container_type::value_type;
1540  using size_type = container_type::size_type;
1541 
1542  common_iterator() : m_strides() {}
1543 
1544  common_iterator(void *ptr, const container_type &strides, const container_type &shape)
1545  : p_ptr(reinterpret_cast<char *>(ptr)), m_strides(strides.size()) {
1546  m_strides.back() = static_cast<value_type>(strides.back());
1547  for (size_type i = m_strides.size() - 1; i != 0; --i) {
1548  size_type j = i - 1;
1549  auto s = static_cast<value_type>(shape[i]);
1550  m_strides[j] = strides[j] + m_strides[i] - strides[i] * s;
1551  }
1552  }
1553 
1554  void increment(size_type dim) { p_ptr += m_strides[dim]; }
1555 
1556  void *data() const { return p_ptr; }
1557 
1558 private:
1559  char *p_ptr{nullptr};
1561 };
1562 
1563 template <size_t N>
1565 public:
1566  using container_type = std::vector<ssize_t>;
1567 
1568  multi_array_iterator(const std::array<buffer_info, N> &buffers, const container_type &shape)
1569  : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() {
1570 
1571  // Manual copy to avoid conversion warning if using std::copy
1572  for (size_t i = 0; i < shape.size(); ++i) {
1573  m_shape[i] = shape[i];
1574  }
1575 
1576  container_type strides(shape.size());
1577  for (size_t i = 0; i < N; ++i) {
1578  init_common_iterator(buffers[i], shape, m_common_iterator[i], strides);
1579  }
1580  }
1581 
1583  for (size_t j = m_index.size(); j != 0; --j) {
1584  size_t i = j - 1;
1585  if (++m_index[i] != m_shape[i]) {
1586  increment_common_iterator(i);
1587  break;
1588  }
1589  m_index[i] = 0;
1590  }
1591  return *this;
1592  }
1593 
1594  template <size_t K, class T = void>
1595  T *data() const {
1596  return reinterpret_cast<T *>(m_common_iterator[K].data());
1597  }
1598 
1599 private:
1601 
1603  const container_type &shape,
1605  container_type &strides) {
1606  auto buffer_shape_iter = buffer.shape.rbegin();
1607  auto buffer_strides_iter = buffer.strides.rbegin();
1608  auto shape_iter = shape.rbegin();
1609  auto strides_iter = strides.rbegin();
1610 
1611  while (buffer_shape_iter != buffer.shape.rend()) {
1612  if (*shape_iter == *buffer_shape_iter) {
1613  *strides_iter = *buffer_strides_iter;
1614  } else {
1615  *strides_iter = 0;
1616  }
1617 
1618  ++buffer_shape_iter;
1619  ++buffer_strides_iter;
1620  ++shape_iter;
1621  ++strides_iter;
1622  }
1623 
1624  std::fill(strides_iter, strides.rend(), 0);
1625  iterator = common_iter(buffer.ptr, strides, shape);
1626  }
1627 
1628  void increment_common_iterator(size_t dim) {
1629  for (auto &iter : m_common_iterator) {
1630  iter.increment(dim);
1631  }
1632  }
1633 
1636  std::array<common_iter, N> m_common_iterator;
1637 };
1638 
1640 
1641 // Populates the shape and number of dimensions for the set of buffers. Returns a
1642 // broadcast_trivial enum value indicating whether the broadcast is "trivial"--that is, has each
1643 // buffer being either a singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous
1644 // (`f_trivial`) storage buffer; returns `non_trivial` otherwise.
1645 template <size_t N>
1647 broadcast(const std::array<buffer_info, N> &buffers, ssize_t &ndim, std::vector<ssize_t> &shape) {
1648  ndim = std::accumulate(
1649  buffers.begin(), buffers.end(), ssize_t(0), [](ssize_t res, const buffer_info &buf) {
1650  return std::max(res, buf.ndim);
1651  });
1652 
1653  shape.clear();
1654  shape.resize((size_t) ndim, 1);
1655 
1656  // Figure out the output size, and make sure all input arrays conform (i.e. are either size 1
1657  // or the full size).
1658  for (size_t i = 0; i < N; ++i) {
1659  auto res_iter = shape.rbegin();
1660  auto end = buffers[i].shape.rend();
1661  for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != end;
1662  ++shape_iter, ++res_iter) {
1663  const auto &dim_size_in = *shape_iter;
1664  auto &dim_size_out = *res_iter;
1665 
1666  // Each input dimension can either be 1 or `n`, but `n` values must match across
1667  // buffers
1668  if (dim_size_out == 1) {
1669  dim_size_out = dim_size_in;
1670  } else if (dim_size_in != 1 && dim_size_in != dim_size_out) {
1671  pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!");
1672  }
1673  }
1674  }
1675 
1676  bool trivial_broadcast_c = true;
1677  bool trivial_broadcast_f = true;
1678  for (size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
1679  if (buffers[i].size == 1) {
1680  continue;
1681  }
1682 
1683  // Require the same number of dimensions:
1684  if (buffers[i].ndim != ndim) {
1686  }
1687 
1688  // Require all dimensions be full-size:
1689  if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin())) {
1691  }
1692 
1693  // Check for C contiguity (but only if previous inputs were also C contiguous)
1694  if (trivial_broadcast_c) {
1695  ssize_t expect_stride = buffers[i].itemsize;
1696  auto end = buffers[i].shape.crend();
1697  for (auto shape_iter = buffers[i].shape.crbegin(),
1698  stride_iter = buffers[i].strides.crbegin();
1699  trivial_broadcast_c && shape_iter != end;
1700  ++shape_iter, ++stride_iter) {
1701  if (expect_stride == *stride_iter) {
1702  expect_stride *= *shape_iter;
1703  } else {
1704  trivial_broadcast_c = false;
1705  }
1706  }
1707  }
1708 
1709  // Check for Fortran contiguity (if previous inputs were also F contiguous)
1710  if (trivial_broadcast_f) {
1711  ssize_t expect_stride = buffers[i].itemsize;
1712  auto end = buffers[i].shape.cend();
1713  for (auto shape_iter = buffers[i].shape.cbegin(),
1714  stride_iter = buffers[i].strides.cbegin();
1715  trivial_broadcast_f && shape_iter != end;
1716  ++shape_iter, ++stride_iter) {
1717  if (expect_stride == *stride_iter) {
1718  expect_stride *= *shape_iter;
1719  } else {
1720  trivial_broadcast_f = false;
1721  }
1722  }
1723  }
1724  }
1725 
1726  return trivial_broadcast_c ? broadcast_trivial::c_trivial
1727  : trivial_broadcast_f ? broadcast_trivial::f_trivial
1729 }
1730 
1731 template <typename T>
1733  static_assert(!std::is_rvalue_reference<T>::value,
1734  "Functions with rvalue reference arguments cannot be vectorized");
1735  // The wrapped function gets called with this type:
1737  // Is this a vectorized argument?
1738  static constexpr bool vectorize
1741  std::is_pointer,
1742  std::is_array,
1743  is_std_array,
1744  std::is_enum>::value
1747  // Accept this type: an array for vectorized types, otherwise the type as-is:
1749 };
1750 
1751 // py::vectorize when a return type is present
1752 template <typename Func, typename Return, typename... Args>
1755 
1756  static Type create(broadcast_trivial trivial, const std::vector<ssize_t> &shape) {
1757  if (trivial == broadcast_trivial::f_trivial) {
1758  return array_t<Return, array::f_style>(shape);
1759  }
1760  return array_t<Return>(shape);
1761  }
1762 
1763  static Return *mutable_data(Type &array) { return array.mutable_data(); }
1764 
1765  static Return call(Func &f, Args &...args) { return f(args...); }
1766 
1767  static void call(Return *out, size_t i, Func &f, Args &...args) { out[i] = f(args...); }
1768 };
1769 
1770 // py::vectorize when a return type is not present
1771 template <typename Func, typename... Args>
1772 struct vectorize_returned_array<Func, void, Args...> {
1773  using Type = none;
1774 
1775  static Type create(broadcast_trivial, const std::vector<ssize_t> &) { return none(); }
1776 
1777  static void *mutable_data(Type &) { return nullptr; }
1778 
1779  static detail::void_type call(Func &f, Args &...args) {
1780  f(args...);
1781  return {};
1782  }
1783 
1784  static void call(void *, size_t, Func &f, Args &...args) { f(args...); }
1785 };
1786 
1787 template <typename Func, typename Return, typename... Args>
1789 
1790 // NVCC for some reason breaks if NVectorized is private
1791 #ifdef __CUDACC__
1792 public:
1793 #else
1794 private:
1795 #endif
1796 
1797  static constexpr size_t N = sizeof...(Args);
1798  static constexpr size_t NVectorized = constexpr_sum(vectorize_arg<Args>::vectorize...);
1799  static_assert(
1800  NVectorized >= 1,
1801  "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1802 
1803 public:
1804  template <typename T,
1805  // SFINAE to prevent shadowing the copy constructor.
1806  typename = detail::enable_if_t<
1808  explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) {}
1809 
1811  return run(args...,
1815  }
1816 
1817 private:
1819 
1820  // Internal compiler error in MSVC 19.16.27025.1 (Visual Studio 2017 15.9.4), when compiling
1821  // with "/permissive-" flag when arg_call_types is manually inlined.
1822  using arg_call_types = std::tuple<typename vectorize_arg<Args>::call_type...>;
1823  template <size_t Index>
1825 
1826  using returned_array = vectorize_returned_array<Func, Return, Args...>;
1827 
1828  // Runs a vectorized function given arguments tuple and three index sequences:
1829  // - Index is the full set of 0 ... (N-1) argument indices;
1830  // - VIndex is the subset of argument indices with vectorized parameters, letting us access
1831  // vectorized arguments (anything not in this sequence is passed through)
1832  // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that
1833  // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at
1834  // index BIndex in the array).
1835  template <size_t... Index, size_t... VIndex, size_t... BIndex>
1836  object run(typename vectorize_arg<Args>::type &...args,
1839  index_sequence<BIndex...> bi_seq) {
1840 
1841  // Pointers to values the function was called with; the vectorized ones set here will start
1842  // out as array_t<T> pointers, but they will be changed them to T pointers before we make
1843  // call the wrapped function. Non-vectorized pointers are left as-is.
1844  std::array<void *, N> params{{&args...}};
1845 
1846  // The array of `buffer_info`s of vectorized arguments:
1847  std::array<buffer_info, NVectorized> buffers{
1848  {reinterpret_cast<array *>(params[VIndex])->request()...}};
1849 
1850  /* Determine dimensions parameters of output array */
1851  ssize_t nd = 0;
1852  std::vector<ssize_t> shape(0);
1853  auto trivial = broadcast(buffers, nd, shape);
1854  auto ndim = (size_t) nd;
1855 
1856  size_t size
1857  = std::accumulate(shape.begin(), shape.end(), (size_t) 1, std::multiplies<size_t>());
1858 
1859  // If all arguments are 0-dimension arrays (i.e. single values) return a plain value (i.e.
1860  // not wrapped in an array).
1861  if (size == 1 && ndim == 0) {
1862  PYBIND11_EXPAND_SIDE_EFFECTS(params[VIndex] = buffers[BIndex].ptr);
1863  return cast(
1864  returned_array::call(f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...));
1865  }
1866 
1867  auto result = returned_array::create(trivial, shape);
1868 
1869  if (size == 0) {
1870  return std::move(result);
1871  }
1872 
1873  /* Call the function */
1874  auto *mutable_data = returned_array::mutable_data(result);
1875  if (trivial == broadcast_trivial::non_trivial) {
1876  apply_broadcast(buffers, params, mutable_data, size, shape, i_seq, vi_seq, bi_seq);
1877  } else {
1878  apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
1879  }
1880 
1881  return std::move(result);
1882  }
1883 
1884  template <size_t... Index, size_t... VIndex, size_t... BIndex>
1885  void apply_trivial(std::array<buffer_info, NVectorized> &buffers,
1886  std::array<void *, N> &params,
1887  Return *out,
1888  size_t size,
1892 
1893  // Initialize an array of mutable byte references and sizes with references set to the
1894  // appropriate pointer in `params`; as we iterate, we'll increment each pointer by its size
1895  // (except for singletons, which get an increment of 0).
1896  std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{
1897  {std::pair<unsigned char *&, const size_t>(
1898  reinterpret_cast<unsigned char *&>(params[VIndex] = buffers[BIndex].ptr),
1899  buffers[BIndex].size == 1 ? 0 : sizeof(param_n_t<VIndex>))...}};
1900 
1901  for (size_t i = 0; i < size; ++i) {
1902  returned_array::call(
1903  out, i, f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...);
1904  for (auto &x : vecparams) {
1905  x.first += x.second;
1906  }
1907  }
1908  }
1909 
1910  template <size_t... Index, size_t... VIndex, size_t... BIndex>
1911  void apply_broadcast(std::array<buffer_info, NVectorized> &buffers,
1912  std::array<void *, N> &params,
1913  Return *out,
1914  size_t size,
1915  const std::vector<ssize_t> &output_shape,
1919 
1920  multi_array_iterator<NVectorized> input_iter(buffers, output_shape);
1921 
1922  for (size_t i = 0; i < size; ++i, ++input_iter) {
1923  PYBIND11_EXPAND_SIDE_EFFECTS((params[VIndex] = input_iter.template data<BIndex>()));
1924  returned_array::call(
1925  out, i, f, *reinterpret_cast<param_n_t<Index> *>(std::get<Index>(params))...);
1926  }
1927  }
1928 };
1929 
1930 template <typename Func, typename Return, typename... Args>
1931 vectorize_helper<Func, Return, Args...> vectorize_extractor(const Func &f, Return (*)(Args...)) {
1932  return detail::vectorize_helper<Func, Return, Args...>(f);
1933 }
1934 
1935 template <typename T, int Flags>
1936 struct handle_type_name<array_t<T, Flags>> {
1937  static constexpr auto name
1939 };
1940 
1942 
1943 // Vanilla pointer vectorizer:
1944 template <typename Return, typename... Args>
1945 detail::vectorize_helper<Return (*)(Args...), Return, Args...> vectorize(Return (*f)(Args...)) {
1946  return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f);
1947 }
1948 
1949 // lambda vectorizer:
1951 auto vectorize(Func &&f)
1952  -> decltype(detail::vectorize_extractor(std::forward<Func>(f),
1953  (detail::function_signature_t<Func> *) nullptr)) {
1954  return detail::vectorize_extractor(std::forward<Func>(f),
1955  (detail::function_signature_t<Func> *) nullptr);
1956 }
1957 
1958 // Vectorize a class method (non-const):
1959 template <typename Return,
1960  typename Class,
1961  typename... Args,
1962  typename Helper = detail::vectorize_helper<
1963  decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())),
1964  Return,
1965  Class *,
1966  Args...>>
1967 Helper vectorize(Return (Class::*f)(Args...)) {
1968  return Helper(std::mem_fn(f));
1969 }
1970 
1971 // Vectorize a class method (const):
1972 template <typename Return,
1973  typename Class,
1974  typename... Args,
1975  typename Helper = detail::vectorize_helper<
1976  decltype(std::mem_fn(std::declval<Return (Class::*)(Args...) const>())),
1977  Return,
1978  const Class *,
1979  Args...>>
1980 Helper vectorize(Return (Class::*f)(Args...) const) {
1981  return Helper(std::mem_fn(f));
1982 }
1983 
typename std::conditional< B, T, F >::type conditional_t
PYBIND11_NOINLINE detail::type_info * get_type_info(PyTypeObject *type)
void * ptr
Definition: buffer_info.h:44
Matrix3f m
detail::unchecked_reference< T, Dims > unchecked() const &
Definition: numpy.h:895
int array[24]
void apply_broadcast(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > &params, Return *out, size_t size, const std::vector< ssize_t > &output_shape, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
Definition: numpy.h:1911
array(ssize_t count, const T *ptr, handle base=handle())
Definition: numpy.h:770
int nd
Definition: numpy.h:69
ssize_t ndim() const
Number of dimensions.
Definition: numpy.h:795
functions
Definition: numpy.h:241
array view(const std::string &dtype)
Definition: numpy.h:946
std::vector< Eigen::Index > Dims
constants
Definition: numpy.h:139
enable_if_t<!Dyn, ssize_t > size() const
Definition: numpy.h:476
#define max(a, b)
Definition: datatypes.h:20
#define I
Definition: main.h:112
ssize_t * strides
Definition: numpy.h:71
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:384
void * mutable_data(Ix... index)
Definition: numpy.h:846
PyObject * descr
Definition: numpy.h:73
static Type create(broadcast_trivial, const std::vector< ssize_t > &)
Definition: numpy.h:1775
detail::any_container< ssize_t > ShapeContainer
Definition: numpy.h:692
ssize_t * dimensions
Definition: numpy.h:70
static void register_dtype(any_container< field_descriptor > fields)
Definition: numpy.h:1430
static std::string format()
Definition: numpy.h:1425
int flags() const
Return the NumPy array flags.
Definition: numpy.h:823
static void call(void *, size_t, Func &f, Args &...args)
Definition: numpy.h:1784
Definition: numpy.h:538
Scalar * b
Definition: benchVecAdd.cpp:17
ssize_t nbytes() const
Definition: numpy.h:488
T cast() const &
static dtype from_args(const object &args)
This is essentially the same as calling numpy.dtype(args) in Python.
Definition: numpy.h:573
std::vector< ssize_t > strides
Definition: buffer_info.h:51
ssize_t offset_at(Ix... index) const
Definition: numpy.h:854
const ssize_t * strides() const
Strides of the array.
Definition: numpy.h:812
vectorize_helper< Func, Return, Args... > vectorize_extractor(const Func &f, Return(*)(Args...))
Definition: numpy.h:1931
static handle cast(const handle &src, return_value_policy, handle)
Definition: numpy.h:1213
ssize_t index_at(Ix... index) const
Definition: numpy.h:866
PYBIND11_NOINLINE void register_structured_dtype(any_container< field_descriptor > fields, const std::type_info &tinfo, ssize_t itemsize, bool(*direct_converter)(PyObject *, void *&))
Definition: numpy.h:1343
ssize_t itemsize() const
Byte size of a single element.
Definition: numpy.h:787
tuple make_tuple()
Definition: cast.h:1209
PYBIND11_NOINLINE void load_numpy_internals(numpy_internals *&ptr)
Definition: numpy.h:109
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base=handle())
Definition: numpy.h:762
PYBIND11_DEPRECATED("make_simple_namespace should be replaced with " "py::module_::import(\ypes\.attr(\impleNamespace\ ") object make_simple_namespace(Args &&...args_)
Definition: pybind11.h:1276
constexpr int platform_lookup()
Definition: numpy.h:128
std::ofstream out("Result.txt")
const T & at(Ix... index) const
Definition: numpy.h:1091
const ssize_t * shape() const
Dimensions of the array.
Definition: numpy.h:801
ssize_t size
Definition: numpy.h:1338
std::array< common_iter, N > m_common_iterator
Definition: numpy.h:1636
PyTypeObject * PyArray_Type_
Definition: numpy.h:218
Definition: numpy.h:138
static std::string format()
Definition: numpy.h:1176
Definition: pytypes.h:2012
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN)
Definition: numpy.h:680
#define PYBIND11_SILENCE_MSVC_C4127(...)
std::tuple< typename vectorize_arg< Args >::call_type... > arg_call_types
Definition: numpy.h:1822
static Return call(Func &f, Args &...args)
Definition: numpy.h:1765
static object _dtype_from_pep3118()
Definition: numpy.h:624
PYBIND11_NOINLINE internals & get_internals()
Return a reference to the current internals data.
Definition: internals.h:405
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:696
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
char byteorder
Definition: numpy.h:56
#define DECL_NPY_API(Func)
array_t(const object &o)
Definition: numpy.h:1047
PyArrayDescr_Proxy * descr
Definition: numpy.h:79
leaf::MyValues values
broadcast_trivial
Definition: numpy.h:1639
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate offset
Wrapper for Python extension modules.
Definition: pybind11.h:1136
std::string format
Definition: numpy.h:1339
array_t(ShapeContainer shape, StridesContainer strides, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1055
static Cal3_S2 K(500, 500, 0.1, 640/2, 480/2)
Definition: BFloat16.h:88
void check_dimensions(Ix... index) const
Definition: numpy.h:988
iterator iter(handle obj)
Definition: pytypes.h:2273
dtype strip_padding(ssize_t itemsize)
Definition: numpy.h:633
bool owndata() const
If set, the array owns the data (will be freed when the array is deleted)
Definition: numpy.h:831
py::array arr
#define N
Definition: gksort.c:12
T * data() const
Definition: numpy.h:1595
static void append_extents(list &shape)
Definition: numpy.h:345
PyObject_HEAD char * data
Definition: numpy.h:68
array_t(handle h, borrowed_t)
Definition: numpy.h:1033
remove_reference_t< T > call_type
Definition: numpy.h:1736
Definition: pytypes.h:1614
T * mutable_data(Ix... ix)
Mutable pointer access to the data at the given indices.
Definition: numpy.h:522
multi_array_iterator & operator++()
Definition: numpy.h:1582
static Type create(broadcast_trivial trivial, const std::vector< ssize_t > &shape)
Definition: numpy.h:1756
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun)
Definition: pytypes.h:1252
PyObject_HEAD PyObject * typeobj
Definition: numpy.h:53
constexpr size_t constexpr_sum()
Compile-time integer sum.
void increment(size_type dim)
Definition: numpy.h:1554
unsigned int(* PyArray_GetNDArrayCFeatureVersion_)()
Definition: numpy.h:204
static const SmartProjectionParams params
PyObject * fields
Definition: numpy.h:62
static Return * mutable_data(Type &array)
Definition: numpy.h:1763
const double dt
PyExc_RuntimeError [[noreturn]] PYBIND11_NOINLINE void pybind11_fail(const char *reason)
Used internally.
bool has_fields() const
Returns true for structured data types.
Definition: numpy.h:591
bool PyArray_Check_(PyObject *obj) const
Definition: numpy.h:197
array()
Definition: numpy.h:690
else if n * info
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
const handle & inc_ref() const &
Definition: pytypes.h:246
static pybind11::dtype dtype()
Definition: numpy.h:1423
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
constexpr ssize_t itemsize() const
Definition: numpy.h:1072
dtype(const pybind11::str &format)
Definition: numpy.h:550
static void call(Return *out, size_t i, Func &f, Args &...args)
Definition: numpy.h:1767
PyArrayDescr_Proxy * array_descriptor_proxy(PyObject *ptr)
Definition: numpy.h:303
typename select_indices_impl< index_sequence<>, 0, Bs... >::type select_indices
Definition: descr.h:25
void init_common_iterator(const buffer_info &buffer, const container_type &shape, common_iter &iterator, container_type &strides)
Definition: numpy.h:1602
ssize_t itemsize
Definition: buffer_info.h:45
detail::vectorize_helper< Return(*)(Args...), Return, Args... > vectorize(Return(*f)(Args...))
Definition: numpy.h:1945
container_type m_shape
Definition: numpy.h:1634
typename std::tuple_element< Index, arg_call_types >::type param_n_t
Definition: numpy.h:1824
std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:19
Values result
ssize_t nbytes() const
Total number of bytes.
Definition: numpy.h:792
numpy_type_info * get_type_info(bool throw_if_missing=true)
Definition: numpy.h:104
vectorize_helper(T &&f)
Definition: numpy.h:1808
std::string format
Definition: buffer_info.h:47
PyObject_VAR_HEAD char * obval
Definition: numpy.h:78
detail::unchecked_reference< T, Dims > unchecked() const &
Definition: numpy.h:1128
void append(T &&val)
Definition: pytypes.h:2000
std::vector< ssize_t > container_type
Definition: numpy.h:1538
multi_array_iterator(const std::array< buffer_info, N > &buffers, const container_type &shape)
Definition: numpy.h:1568
static npy_api & get()
Definition: numpy.h:192
PyObject * base
Definition: numpy.h:81
static detail::void_type call(Func &f, Args &...args)
Definition: numpy.h:1779
Definition: pytypes.h:1403
void * data() const
Definition: numpy.h:1556
array(ShapeContainer shape, const T *ptr, handle base=handle())
Definition: numpy.h:766
array_t(const buffer_info &info, handle base=handle())
Definition: numpy.h:1053
EIGEN_ALWAYS_INLINE DSizes< IndexType, NumDims > strides(const DSizes< IndexType, NumDims > &dimensions)
Definition: TensorBlock.h:26
PyObject * dtype_ptr
Definition: numpy.h:85
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74
ssize_t offset_at() const
Definition: numpy.h:861
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:1836
type_map< std::vector< bool(*)(PyObject *, void *&)> > direct_conversions
Definition: internals.h:158
array_t()
Definition: numpy.h:1032
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t< Dyn, ssize_t > dims)
Definition: numpy.h:429
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers. ...
EIGEN_DEVICE_FUNC NewType cast(const OldType &x)
Eigen::Triplet< double > T
enable_if_t< Dyn, ssize_t > size() const
Definition: numpy.h:481
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun)
Definition: pytypes.h:1290
int data[]
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
#define PYBIND11_DECL_CHAR_FMT
Definition: numpy.h:1292
container_type::value_type value_type
Definition: numpy.h:1539
std::unordered_map< std::type_index, numpy_type_info > registered_dtypes
Definition: numpy.h:90
RealScalar s
dtype(const std::string &format)
Definition: numpy.h:552
typename std::remove_reference< T >::type remove_reference_t
std::vector< ssize_t > container_type
Definition: numpy.h:1566
ssize_t byte_offset_unsafe(const Strides &)
Definition: numpy.h:391
constexpr descr< 0 > concat()
Definition: descr.h:139
detail::any_container< ssize_t > StridesContainer
Definition: numpy.h:693
array(const buffer_info &info, handle base=handle())
Definition: numpy.h:773
static void append_extents(list &)
Definition: numpy.h:330
int num() const
type number of dtype.
Definition: numpy.h:607
char char_() const
Definition: numpy.h:599
static dtype of()
Return dtype associated with a C++ type.
Definition: numpy.h:583
static array_t ensure(handle h)
Definition: numpy.h:1134
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:749
std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:31
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > strides_
Definition: numpy.h:411
const unsigned char * data_
Definition: numpy.h:408
array(const pybind11::dtype &dt, T count, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:758
T & operator[](ssize_t index)
Definition: numpy.h:516
std::vector< ssize_t > shape
Definition: buffer_info.h:50
static constexpr ssize_t itemsize()
Returns the item size, i.e. sizeof(T)
Definition: numpy.h:465
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set offsets
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t >)
Definition: numpy.h:417
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:1885
T & operator()(Ix... index)
Mutable, unchecked access to data at the given indices.
Definition: numpy.h:505
void increment_common_iterator(size_t dim)
Definition: numpy.h:1628
PyTypeObject * PyArrayDescr_Type_
Definition: numpy.h:220
Py_intptr_t * ptr
Definition: numpy.h:188
static PyObject * raw_array(PyObject *ptr, int ExtraFlags=0)
Create array from any object – always returns a new reference.
Definition: numpy.h:1005
Definition: pytypes.h:1979
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
static npy_api lookup()
Definition: numpy.h:263
const T * data(Ix... index) const
Definition: numpy.h:1080
T * mutable_data(Ix... index)
Definition: numpy.h:1085
pybind11::dtype dtype() const
Array descriptor (dtype)
Definition: numpy.h:777
const T & operator[](ssize_t index) const
Definition: numpy.h:454
remove_reference_t< Func > f
Definition: numpy.h:1818
ssize_t byte_offset(Ix... index) const
Definition: numpy.h:976
const double h
object operator()(typename vectorize_arg< Args >::type... args)
Definition: numpy.h:1810
static array ensure(handle h, int ExtraFlags=0)
Definition: numpy.h:958
const char * name
Definition: numpy.h:1336
ssize_t size() const
Total number of elements.
Definition: numpy.h:782
std::string format_str
Definition: numpy.h:86
PyObject * names
Definition: numpy.h:63
const T & operator()(Ix... index) const
Definition: numpy.h:443
ADT create(const Signature &signature)
static module_ import(const char *name)
Import and return a module or throws error_already_set.
Definition: pybind11.h:1194
array_t(handle h, stolen_t)
Definition: numpy.h:1034
static bool check_(handle h)
Definition: numpy.h:1142
int alignment() const
Alignment of the data type.
Definition: numpy.h:618
static PyObject * dtype_ptr()
Definition: numpy.h:1438
static EIGEN_DEPRECATED const end_t end
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Definition: numpy.h:1116
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
dtype(const buffer_info &info)
Definition: numpy.h:542
bool load(handle src, bool convert)
Definition: numpy.h:1205
array reshape(ShapeContainer new_shape)
Optional order parameter omitted, to be added as needed.
Definition: numpy.h:930
bool PyArrayDescr_Check_(PyObject *obj) const
Definition: numpy.h:200
void check_dimensions_impl(ssize_t, const ssize_t *) const
Definition: numpy.h:992
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Definition: numpy.h:877
void check_writeable() const
Definition: numpy.h:981
ssize_t offset
Definition: numpy.h:1337
T & mutable_at(Ix... index)
Definition: numpy.h:1101
conditional_t< vectorize, array_t< remove_cv_t< call_type >, array::forcecast >, T > type
Definition: numpy.h:1748
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
dtype(const char *format)
Definition: numpy.h:554
numpy_type_info * get_type_info(const std::type_info &tinfo, bool throw_if_missing=true)
Definition: numpy.h:92
void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const
Definition: numpy.h:995
char kind() const
Definition: numpy.h:595
PyObject * base
Definition: numpy.h:72
ssize_t index_at(Ix... index) const
Definition: numpy.h:1075
Definition: pytypes.h:1924
container_type m_strides
Definition: numpy.h:1560
array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
Definition: numpy.h:1020
array squeeze()
Return a new view with all of the dimensions of length 1 removed.
Definition: numpy.h:905
Annotation for function names.
Definition: attr.h:48
array_t(ssize_t count, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1069
Annotation indicating that a class derives from another given type.
Definition: attr.h:61
int flags
Definition: numpy.h:74
const int Dynamic
Definition: Constants.h:22
const void * data(Ix... index) const
Definition: numpy.h:838
Information record describing a Python buffer object.
Definition: buffer_info.h:43
common_iterator(void *ptr, const container_type &strides, const container_type &shape)
Definition: numpy.h:1544
PyObject * ptr() const
Return the underlying PyObject * pointer.
Definition: pytypes.h:238
char byteorder() const
Single character for byteorder.
Definition: numpy.h:615
py::ssize_t offset_at(const arr &a, Ix... idx)
ssize_t ndim() const
Returns the number of dimensions of the array.
Definition: numpy.h:471
Container::iterator get(Container &c, Position position)
dtype(int typenum)
Definition: numpy.h:565
all_of< std::is_standard_layout< T >, std::is_trivial< T > > is_pod
Definition: numpy.h:388
bool check_flags(const void *ptr, int flag)
Definition: numpy.h:311
PyTypeObject * PyVoidArrType_Type_
Definition: numpy.h:219
bool_constant< sizeof(T)==sizeof(U)> as
Definition: numpy.h:124
static PyObject * raw_array_t(PyObject *ptr)
Create array from any object – always returns a new reference.
Definition: numpy.h:1152
numpy_internals & get_numpy_internals()
Definition: numpy.h:113
bool equal(const T &obj1, const T &obj2, double tol)
Definition: Testable.h:85
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2244
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
ssize_t itemsize() const
Size of the data type in bytes.
Definition: numpy.h:588
const T * data(Ix... ix) const
Pointer access to the data at the given indices.
Definition: numpy.h:460
container_type::size_type size_type
Definition: numpy.h:1540
internal::enable_if< internal::valid_indexed_view_overload< RowIndices, ColIndices >::value &&internal::traits< typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::ReturnAsIndexedView, typename EIGEN_INDEXED_VIEW_METHOD_TYPE< RowIndices, ColIndices >::type >::type operator()(const RowIndices &rowIndices, const ColIndices &colIndices) EIGEN_INDEXED_VIEW_METHOD_CONST
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
void fail_dim_check(ssize_t dim, const std::string &msg) const
Definition: numpy.h:970
typename make_index_sequence_impl< N >::type make_index_sequence
static bool direct_converter(PyObject *obj, void *&value)
Definition: numpy.h:1443
array_t(ShapeContainer shape, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1061
static constexpr auto name
Definition: cast.h:870
void resize(ShapeContainer new_shape, bool refcheck=true)
Definition: numpy.h:913
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
dtype(list names, list formats, list offsets, ssize_t itemsize)
Definition: numpy.h:556
const ssize_t dims_
Definition: numpy.h:412
#define PYBIND11_TYPE_CASTER(type, py_name)
Definition: cast.h:82
char flags() const
Flags for the array descriptor.
Definition: numpy.h:621
std::ptrdiff_t j
#define PYBIND11_NAMESPACE_END(name)
static BinaryMeasurement< Rot3 > convert(const BetweenFactor< Pose3 >::shared_ptr &f)
container_type m_index
Definition: numpy.h:1635
char * subarray
Definition: numpy.h:61
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
Definition: numpy.h:1647
Definition: pytypes.h:1370
#define PYBIND11_NAMESPACE_BEGIN(name)
ssize_t shape(ssize_t dim) const
Dimension along a given axis.
Definition: numpy.h:804
PyArray_Proxy * array_proxy(void *ptr)
Definition: numpy.h:297
object base() const
Base object.
Definition: numpy.h:798
typename array_info< T >::type remove_all_extents_t
Definition: numpy.h:362
ssize_t shape(ssize_t dim) const
Returns the shape (i.e. size) of dimension dim
Definition: numpy.h:468
bool(* PyArray_EquivTypes_)(PyObject *, PyObject *)
Definition: numpy.h:224
ssize_t strides(ssize_t dim) const
Stride along a given axis.
Definition: numpy.h:815
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
Definition: numpy.h:826


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:58