μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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. */
33static_assert(sizeof(::pybind11::ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t");
34static_assert(std::is_signed<Py_intptr_t>::value, "Py_intptr_t must be signed");
35// We now can reinterpret_cast between py::ssize_t and Py_intptr_t (MSVC + PyPy cares)
36
38
39class array; // Forward declaration
40
42
43template <>
45 static constexpr auto name = const_name("numpy.ndarray");
46};
47
48template <typename type, typename SFINAE = void>
50
52 PyObject_HEAD
53 PyObject *typeobj;
54 char kind;
55 char type;
57 char flags;
59 int elsize;
61 char *subarray;
62 PyObject *fields;
63 PyObject *names;
64};
65
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
121template <typename T>
122struct same_size {
123 template <typename U>
124 using as = bool_constant<sizeof(T) == sizeof(U)>;
125};
126
127template <typename Concrete>
128constexpr 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.
133template <typename Concrete, typename T, typename... Ts, typename... Ints>
134constexpr int platform_lookup(int I, Ints... Is) {
135 return sizeof(Concrete) == sizeof(T) ? I : platform_lookup<Concrete, Ts...>(Is...);
136}
137
138struct npy_api {
168 // Platform-dependent normalization
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.
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>(
181 = platform_lookup<std::int64_t, long, long long, int>(NPY_LONG_, NPY_LONGLONG_, NPY_INT_),
183 = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
185 };
186
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
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 *);
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
240private:
261 };
262
263 static npy_api lookup() {
264 module_ m = module_::import("numpy.core.multiarray");
265 auto c = m.attr("_ARRAY_API");
266#if PY_MAJOR_VERSION >= 3
267 void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
268#else
269 void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr());
270#endif
271 npy_api api;
272#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
273 DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
274 if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
275 pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
276 }
277 DECL_NPY_API(PyArray_Type);
278 DECL_NPY_API(PyVoidArrType_Type);
279 DECL_NPY_API(PyArrayDescr_Type);
280 DECL_NPY_API(PyArray_DescrFromType);
281 DECL_NPY_API(PyArray_DescrFromScalar);
282 DECL_NPY_API(PyArray_FromAny);
283 DECL_NPY_API(PyArray_Resize);
284 DECL_NPY_API(PyArray_CopyInto);
285 DECL_NPY_API(PyArray_NewCopy);
286 DECL_NPY_API(PyArray_NewFromDescr);
287 DECL_NPY_API(PyArray_DescrNewFromType);
288 DECL_NPY_API(PyArray_Newshape);
289 DECL_NPY_API(PyArray_Squeeze);
290 DECL_NPY_API(PyArray_View);
291 DECL_NPY_API(PyArray_DescrConverter);
292 DECL_NPY_API(PyArray_EquivTypes);
293 DECL_NPY_API(PyArray_GetArrayParamsFromObject);
294 DECL_NPY_API(PyArray_SetBaseObject);
295
296#undef DECL_NPY_API
297 return api;
298 }
299};
300
301inline PyArray_Proxy *array_proxy(void *ptr) { return reinterpret_cast<PyArray_Proxy *>(ptr); }
302
303inline const PyArray_Proxy *array_proxy(const void *ptr) {
304 return reinterpret_cast<const PyArray_Proxy *>(ptr);
305}
306
308 return reinterpret_cast<PyArrayDescr_Proxy *>(ptr);
309}
310
311inline const PyArrayDescr_Proxy *array_descriptor_proxy(const PyObject *ptr) {
312 return reinterpret_cast<const PyArrayDescr_Proxy *>(ptr);
313}
314
315inline bool check_flags(const void *ptr, int flag) {
316 return (flag == (array_proxy(ptr)->flags & flag));
317}
318
319template <typename T>
320struct is_std_array : std::false_type {};
321template <typename T, size_t N>
322struct is_std_array<std::array<T, N>> : std::true_type {};
323template <typename T>
324struct is_complex : std::false_type {};
325template <typename T>
326struct is_complex<std::complex<T>> : std::true_type {};
327
328template <typename T>
330 using type = T;
331 static constexpr bool is_array = false;
332 static constexpr bool is_empty = false;
333 static constexpr auto extents = const_name("");
334 static void append_extents(list & /* shape */) {}
335};
336// Computes underlying type and a comma-separated list of extents for array
337// types (any mix of std::array and built-in arrays). An array of char is
338// treated as scalar because it gets special handling.
339template <typename T>
341template <typename T, size_t N>
342struct array_info<std::array<T, N>> {
343 using type = typename array_info<T>::type;
344 static constexpr bool is_array = true;
345 static constexpr bool is_empty = (N == 0) || array_info<T>::is_empty;
346 static constexpr size_t extent = N;
347
348 // appends the extents to shape
349 static void append_extents(list &shape) {
350 shape.append(N);
352 }
353
354 static constexpr auto extents = const_name<array_info<T>::is_array>(
355 concat(const_name<N>(), array_info<T>::extents), const_name<N>());
356};
357// For numpy we have special handling for arrays of characters, so we don't include
358// the size in the array extents.
359template <size_t N>
360struct array_info<char[N]> : array_info_scalar<char[N]> {};
361template <size_t N>
362struct array_info<std::array<char, N>> : array_info_scalar<std::array<char, N>> {};
363template <typename T, size_t N>
364struct array_info<T[N]> : array_info<std::array<T, N>> {};
365template <typename T>
367
368template <typename T>
370 = all_of<std::is_standard_layout<T>, // since we're accessing directly in memory
371 // we need a standard layout type
372#if defined(__GLIBCXX__) \
373 && (__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20150426 || __GLIBCXX__ == 20150623 \
374 || __GLIBCXX__ == 20150626 || __GLIBCXX__ == 20160803)
375 // libstdc++ < 5 (including versions 4.8.5, 4.9.3 and 4.9.4 which were released after
376 // 5) don't implement is_trivially_copyable, so approximate it
377 std::is_trivially_destructible<T>,
379#else
380 std::is_trivially_copyable<T>,
381#endif
383 std::is_reference,
384 std::is_array,
386 std::is_arithmetic,
388 std::is_enum>>;
389
390// Replacement for std::is_pod (deprecated in C++20)
391template <typename T>
392using is_pod = all_of<std::is_standard_layout<T>, std::is_trivial<T>>;
393
394template <ssize_t Dim = 0, typename Strides>
395ssize_t byte_offset_unsafe(const Strides &) {
396 return 0;
397}
398template <ssize_t Dim = 0, typename Strides, typename... Ix>
399ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index) {
400 return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
401}
402
408template <typename T, ssize_t Dims>
410protected:
411 static constexpr bool Dynamic = Dims < 0;
412 const unsigned char *data_;
413 // Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
414 // make large performance gains on big, nested loops, but requires compile-time dimensions
415 conditional_t<Dynamic, const ssize_t *, std::array<ssize_t, (size_t) Dims>> shape_, strides_;
417
418 friend class pybind11::array;
419 // Constructor for compile-time dimensions:
420 template <bool Dyn = Dynamic>
422 const ssize_t *shape,
423 const ssize_t *strides,
425 : data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} {
426 for (size_t i = 0; i < (size_t) dims_; i++) {
427 shape_[i] = shape[i];
428 strides_[i] = strides[i];
429 }
430 }
431 // Constructor for runtime dimensions:
432 template <bool Dyn = Dynamic>
434 const ssize_t *shape,
435 const ssize_t *strides,
437 : data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides},
438 dims_{dims} {}
439
440public:
446 template <typename... Ix>
447 const T &operator()(Ix... index) const {
448 static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
449 "Invalid number of indices for unchecked array reference");
450 return *reinterpret_cast<const T *>(data_
451 + byte_offset_unsafe(strides_, ssize_t(index)...));
452 }
457 template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
458 const T &operator[](ssize_t index) const {
459 return operator()(index);
460 }
461
463 template <typename... Ix>
464 const T *data(Ix... ix) const {
465 return &operator()(ssize_t(ix)...);
466 }
467
469 constexpr static ssize_t itemsize() { return sizeof(T); }
470
472 ssize_t shape(ssize_t dim) const { return shape_[(size_t) dim]; }
473
475 ssize_t ndim() const { return dims_; }
476
479 template <bool Dyn = Dynamic>
481 return std::accumulate(
482 shape_.begin(), shape_.end(), (ssize_t) 1, std::multiplies<ssize_t>());
483 }
484 template <bool Dyn = Dynamic>
486 return std::accumulate(shape_, shape_ + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
487 }
488
492 ssize_t nbytes() const { return size() * itemsize(); }
493};
494
495template <typename T, ssize_t Dims>
497 friend class pybind11::array;
499 using ConstBase::ConstBase;
500 using ConstBase::Dynamic;
501
502public:
503 // Bring in const-qualified versions from base class
504 using ConstBase::operator();
505 using ConstBase::operator[];
506
508 template <typename... Ix>
509 T &operator()(Ix... index) {
510 static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
511 "Invalid number of indices for unchecked array reference");
512 return const_cast<T &>(ConstBase::operator()(index...));
513 }
519 template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
520 T &operator[](ssize_t index) {
521 return operator()(index);
522 }
523
525 template <typename... Ix>
526 T *mutable_data(Ix... ix) {
527 return &operator()(ssize_t(ix)...);
528 }
529};
530
531template <typename T, ssize_t Dim>
533 static_assert(Dim == 0 && Dim > 0 /* always fail */,
534 "unchecked array proxy object is not castable");
535};
536template <typename T, ssize_t Dim>
538 : type_caster<unchecked_reference<T, Dim>> {};
539
541
542class dtype : public object {
543public:
544 PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_);
545
546 explicit dtype(const buffer_info &info) {
547 dtype descr(_dtype_from_pep3118()(PYBIND11_STR_TYPE(info.format)));
548 // If info.itemsize == 0, use the value calculated from the format string
549 m_ptr = descr.strip_padding(info.itemsize != 0 ? info.itemsize : descr.itemsize())
550 .release()
551 .ptr();
552 }
553
554 explicit dtype(const std::string &format) {
555 m_ptr = from_args(pybind11::str(format)).release().ptr();
556 }
557
558 explicit dtype(const char *format) : dtype(std::string(format)) {}
559
560 dtype(list names, list formats, list offsets, ssize_t itemsize) {
561 dict args;
562 args["names"] = std::move(names);
563 args["formats"] = std::move(formats);
564 args["offsets"] = std::move(offsets);
565 args["itemsize"] = pybind11::int_(itemsize);
566 m_ptr = from_args(std::move(args)).release().ptr();
567 }
568
570 static dtype from_args(object args) {
571 PyObject *ptr = nullptr;
572 if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr) {
573 throw error_already_set();
574 }
575 return reinterpret_steal<dtype>(ptr);
576 }
577
579 template <typename T>
580 static dtype of() {
581 return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::dtype();
582 }
583
585 ssize_t itemsize() const { return detail::array_descriptor_proxy(m_ptr)->elsize; }
586
588 bool has_fields() const { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; }
589
592 char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; }
593
596 char char_() const {
597 // Note: The signature, `dtype::char_` follows the naming of NumPy's
598 // public Python API (i.e., ``dtype.char``), rather than its internal
599 // C API (``PyArray_Descr::type``).
600 return detail::array_descriptor_proxy(m_ptr)->type;
601 }
602
603private:
604 static object _dtype_from_pep3118() {
605 static PyObject *obj = module_::import("numpy.core._internal")
606 .attr("_dtype_from_pep3118")
607 .cast<object>()
608 .release()
609 .ptr();
610 return reinterpret_borrow<object>(obj);
611 }
612
614 // Recursively strip all void fields with empty names that are generated for
615 // padding fields (as of NumPy v1.11).
616 if (!has_fields()) {
617 return *this;
618 }
619
620 struct field_descr {
622 object format;
623 pybind11::int_ offset;
624 };
625 std::vector<field_descr> field_descriptors;
626
627 for (auto field : attr("fields").attr("items")()) {
628 auto spec = field.cast<tuple>();
629 auto name = spec[0].cast<pybind11::str>();
630 auto format = spec[1].cast<tuple>()[0].cast<dtype>();
631 auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>();
632 if ((len(name) == 0u) && format.kind() == 'V') {
633 continue;
634 }
635 field_descriptors.push_back(
636 {(PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset});
637 }
638
639 std::sort(field_descriptors.begin(),
640 field_descriptors.end(),
641 [](const field_descr &a, const field_descr &b) {
642 return a.offset.cast<int>() < b.offset.cast<int>();
643 });
644
645 list names, formats, offsets;
646 for (auto &descr : field_descriptors) {
647 names.append(descr.name);
648 formats.append(descr.format);
649 offsets.append(descr.offset);
650 }
651 return dtype(std::move(names), std::move(formats), std::move(offsets), itemsize);
652 }
653};
654
655class array : public buffer {
656public:
657 PYBIND11_OBJECT_CVT(array, buffer, detail::npy_api::get().PyArray_Check_, raw_array)
658
659 enum {
660 c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
661 f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
662 forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
663 };
664
665 array() : array(0, static_cast<const double *>(nullptr)) {}
666
667 using ShapeContainer = detail::any_container<ssize_t>;
668 using StridesContainer = detail::any_container<ssize_t>;
669
670 // Constructs an array taking shape/strides from arbitrary container types
671 array(const pybind11::dtype &dt,
674 const void *ptr = nullptr,
675 handle base = handle()) {
676
677 if (strides->empty()) {
678 *strides = detail::c_strides(*shape, dt.itemsize());
679 }
680
681 auto ndim = shape->size();
682 if (ndim != strides->size()) {
683 pybind11_fail("NumPy: shape ndim doesn't match strides ndim");
684 }
685 auto descr = dt;
686
687 int flags = 0;
688 if (base && ptr) {
689 if (isinstance<array>(base)) {
690 /* Copy flags from base (except ownership bit) */
691 flags = reinterpret_borrow<array>(base).flags()
693 } else {
694 /* Writable by default, easy to downgrade later on if needed */
695 flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
696 }
697 }
698
699 auto &api = detail::npy_api::get();
700 auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
701 api.PyArray_Type_,
702 descr.release().ptr(),
703 (int) ndim,
704 // Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
705 reinterpret_cast<Py_intptr_t *>(shape->data()),
706 reinterpret_cast<Py_intptr_t *>(strides->data()),
707 const_cast<void *>(ptr),
708 flags,
709 nullptr));
710 if (!tmp) {
711 throw error_already_set();
712 }
713 if (ptr) {
714 if (base) {
715 api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr());
716 } else {
717 tmp = reinterpret_steal<object>(
718 api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */));
719 }
720 }
721 m_ptr = tmp.release().ptr();
722 }
723
724 array(const pybind11::dtype &dt,
726 const void *ptr = nullptr,
727 handle base = handle())
728 : array(dt, std::move(shape), {}, ptr, base) {}
729
730 template <typename T,
731 typename
732 = detail::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
733 array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle())
734 : array(dt, {{count}}, ptr, base) {}
735
736 template <typename T>
738 : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) {}
739
740 template <typename T>
742 : array(std::move(shape), {}, ptr, base) {}
743
744 template <typename T>
745 explicit array(ssize_t count, const T *ptr, handle base = handle())
746 : array({count}, {}, ptr, base) {}
747
748 explicit array(const buffer_info &info, handle base = handle())
749 : array(pybind11::dtype(info), info.shape, info.strides, info.ptr, base) {}
750
752 pybind11::dtype dtype() const {
753 return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(m_ptr)->descr);
754 }
755
757 ssize_t size() const {
758 return std::accumulate(shape(), shape() + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
759 }
760
763 return detail::array_descriptor_proxy(detail::array_proxy(m_ptr)->descr)->elsize;
764 }
765
767 ssize_t nbytes() const { return size() * itemsize(); }
768
770 ssize_t ndim() const { return detail::array_proxy(m_ptr)->nd; }
771
773 object base() const { return reinterpret_borrow<object>(detail::array_proxy(m_ptr)->base); }
774
776 const ssize_t *shape() const { return detail::array_proxy(m_ptr)->dimensions; }
777
779 ssize_t shape(ssize_t dim) const {
780 if (dim >= ndim()) {
781 fail_dim_check(dim, "invalid axis");
782 }
783 return shape()[dim];
784 }
785
787 const ssize_t *strides() const { return detail::array_proxy(m_ptr)->strides; }
788
791 if (dim >= ndim()) {
792 fail_dim_check(dim, "invalid axis");
793 }
794 return strides()[dim];
795 }
796
798 int flags() const { return detail::array_proxy(m_ptr)->flags; }
799
801 bool writeable() const {
802 return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_);
803 }
804
806 bool owndata() const {
807 return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_);
808 }
809
812 template <typename... Ix>
813 const void *data(Ix... index) const {
814 return static_cast<const void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
815 }
816
820 template <typename... Ix>
821 void *mutable_data(Ix... index) {
823 return static_cast<void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
824 }
825
828 template <typename... Ix>
829 ssize_t offset_at(Ix... index) const {
830 if ((ssize_t) sizeof...(index) > ndim()) {
831 fail_dim_check(sizeof...(index), "too many indices for an array");
832 }
833 return byte_offset(ssize_t(index)...);
834 }
835
836 ssize_t offset_at() const { return 0; }
837
840 template <typename... Ix>
841 ssize_t index_at(Ix... index) const {
842 return offset_at(index...) / itemsize();
843 }
844
851 template <typename T, ssize_t Dims = -1>
852 detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
853 if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
854 throw std::domain_error("array has incorrect number of dimensions: "
855 + std::to_string(ndim()) + "; expected "
856 + std::to_string(Dims));
857 }
858 return detail::unchecked_mutable_reference<T, Dims>(
859 mutable_data(), shape(), strides(), ndim());
860 }
861
869 template <typename T, ssize_t Dims = -1>
870 detail::unchecked_reference<T, Dims> unchecked() const & {
871 if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) {
872 throw std::domain_error("array has incorrect number of dimensions: "
873 + std::to_string(ndim()) + "; expected "
874 + std::to_string(Dims));
875 }
876 return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim());
877 }
878
881 auto &api = detail::npy_api::get();
882 return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
883 }
884
888 void resize(ShapeContainer new_shape, bool refcheck = true) {
889 detail::npy_api::PyArray_Dims d
890 = {// Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
891 reinterpret_cast<Py_intptr_t *>(new_shape->data()),
892 int(new_shape->size())};
893 // try to resize, set ordering param to -1 cause it's not used anyway
894 auto new_array = reinterpret_steal<object>(
895 detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1));
896 if (!new_array) {
897 throw error_already_set();
898 }
899 if (isinstance<array>(new_array)) {
900 *this = std::move(new_array);
901 }
902 }
903
906 detail::npy_api::PyArray_Dims d
907 = {reinterpret_cast<Py_intptr_t *>(new_shape->data()), int(new_shape->size())};
908 auto new_array
909 = reinterpret_steal<array>(detail::npy_api::get().PyArray_Newshape_(m_ptr, &d, 0));
910 if (!new_array) {
911 throw error_already_set();
912 }
913 return new_array;
914 }
915
921 array view(const std::string &dtype) {
922 auto &api = detail::npy_api::get();
923 auto new_view = reinterpret_steal<array>(api.PyArray_View_(
924 m_ptr, dtype::from_args(pybind11::str(dtype)).release().ptr(), nullptr));
925 if (!new_view) {
926 throw error_already_set();
927 }
928 return new_view;
929 }
930
933 static array ensure(handle h, int ExtraFlags = 0) {
934 auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags));
935 if (!result) {
936 PyErr_Clear();
937 }
938 return result;
939 }
940
941protected:
942 template <typename, typename>
944
945 void fail_dim_check(ssize_t dim, const std::string &msg) const {
946 throw index_error(msg + ": " + std::to_string(dim) + " (ndim = " + std::to_string(ndim())
947 + ")");
948 }
949
950 template <typename... Ix>
951 ssize_t byte_offset(Ix... index) const {
952 check_dimensions(index...);
953 return detail::byte_offset_unsafe(strides(), ssize_t(index)...);
954 }
955
956 void check_writeable() const {
957 if (!writeable()) {
958 throw std::domain_error("array is not writeable");
959 }
960 }
961
962 template <typename... Ix>
963 void check_dimensions(Ix... index) const {
964 check_dimensions_impl(ssize_t(0), shape(), ssize_t(index)...);
965 }
966
967 void check_dimensions_impl(ssize_t, const ssize_t *) const {}
968
969 template <typename... Ix>
970 void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const {
971 if (i >= *shape) {
972 throw index_error(std::string("index ") + std::to_string(i)
973 + " is out of bounds for axis " + std::to_string(axis)
974 + " with size " + std::to_string(*shape));
975 }
976 check_dimensions_impl(axis + 1, shape + 1, index...);
977 }
978
980 static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) {
981 if (ptr == nullptr) {
982 PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
983 return nullptr;
984 }
985 return detail::npy_api::get().PyArray_FromAny_(
986 ptr, nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr);
987 }
988};
989
990template <typename T, int ExtraFlags = array::forcecast>
991class array_t : public array {
992private:
993 struct private_ctor {};
994 // Delegating constructor needed when both moving and accessing in the same constructor
998 const T *ptr,
999 handle base)
1000 : array(std::move(shape), std::move(strides), ptr, base) {}
1001
1002public:
1003 static_assert(!detail::array_info<T>::is_array, "Array types cannot be used with array_t");
1004
1005 using value_type = T;
1006
1007 array_t() : array(0, static_cast<const T *>(nullptr)) {}
1010
1011 PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
1013 if (!m_ptr) {
1014 PyErr_Clear();
1015 }
1016 if (!is_borrowed) {
1017 Py_XDECREF(h.ptr());
1018 }
1019 }
1020
1021 // NOLINTNEXTLINE(google-explicit-constructor)
1022 array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
1023 if (!m_ptr) {
1024 throw error_already_set();
1025 }
1026 }
1027
1028 explicit array_t(const buffer_info &info, handle base = handle()) : array(info, base) {}
1029
1032 const T *ptr = nullptr,
1033 handle base = handle())
1034 : array(std::move(shape), std::move(strides), ptr, base) {}
1035
1036 explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle())
1038 std::move(shape),
1039 (ExtraFlags & f_style) != 0 ? detail::f_strides(*shape, itemsize())
1040 : detail::c_strides(*shape, itemsize()),
1041 ptr,
1042 base) {}
1043
1044 explicit array_t(ssize_t count, const T *ptr = nullptr, handle base = handle())
1045 : array({count}, {}, ptr, base) {}
1046
1047 constexpr ssize_t itemsize() const { return sizeof(T); }
1048
1049 template <typename... Ix>
1050 ssize_t index_at(Ix... index) const {
1051 return offset_at(index...) / itemsize();
1052 }
1053
1054 template <typename... Ix>
1055 const T *data(Ix... index) const {
1056 return static_cast<const T *>(array::data(index...));
1057 }
1058
1059 template <typename... Ix>
1060 T *mutable_data(Ix... index) {
1061 return static_cast<T *>(array::mutable_data(index...));
1062 }
1063
1064 // Reference to element at a given index
1065 template <typename... Ix>
1066 const T &at(Ix... index) const {
1067 if ((ssize_t) sizeof...(index) != ndim()) {
1068 fail_dim_check(sizeof...(index), "index dimension mismatch");
1069 }
1070 return *(static_cast<const T *>(array::data())
1071 + byte_offset(ssize_t(index)...) / itemsize());
1072 }
1073
1074 // Mutable reference to element at a given index
1075 template <typename... Ix>
1076 T &mutable_at(Ix... index) {
1077 if ((ssize_t) sizeof...(index) != ndim()) {
1078 fail_dim_check(sizeof...(index), "index dimension mismatch");
1079 }
1080 return *(static_cast<T *>(array::mutable_data())
1081 + byte_offset(ssize_t(index)...) / itemsize());
1082 }
1083
1090 template <ssize_t Dims = -1>
1091 detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
1092 return array::mutable_unchecked<T, Dims>();
1093 }
1094
1102 template <ssize_t Dims = -1>
1103 detail::unchecked_reference<T, Dims> unchecked() const & {
1104 return array::unchecked<T, Dims>();
1105 }
1106
1110 auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr()));
1111 if (!result) {
1112 PyErr_Clear();
1113 }
1114 return result;
1115 }
1116
1117 static bool check_(handle h) {
1118 const auto &api = detail::npy_api::get();
1119 return api.PyArray_Check_(h.ptr())
1120 && api.PyArray_EquivTypes_(detail::array_proxy(h.ptr())->descr,
1121 dtype::of<T>().ptr())
1122 && detail::check_flags(h.ptr(), ExtraFlags & (array::c_style | array::f_style));
1123 }
1124
1125protected:
1127 static PyObject *raw_array_t(PyObject *ptr) {
1128 if (ptr == nullptr) {
1129 PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
1130 return nullptr;
1131 }
1132 return detail::npy_api::get().PyArray_FromAny_(ptr,
1133 dtype::of<T>().release().ptr(),
1134 0,
1135 0,
1136 detail::npy_api::NPY_ARRAY_ENSUREARRAY_
1137 | ExtraFlags,
1138 nullptr);
1139 }
1140};
1141
1142template <typename T>
1143struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1144 static std::string format() {
1145 return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::format();
1146 }
1147};
1148
1149template <size_t N>
1150struct format_descriptor<char[N]> {
1151 static std::string format() { return std::to_string(N) + "s"; }
1152};
1153template <size_t N>
1154struct format_descriptor<std::array<char, N>> {
1155 static std::string format() { return std::to_string(N) + "s"; }
1156};
1157
1158template <typename T>
1159struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> {
1160 static std::string format() {
1161 return format_descriptor<
1162 typename std::remove_cv<typename std::underlying_type<T>::type>::type>::format();
1163 }
1164};
1165
1166template <typename T>
1167struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
1168 static std::string format() {
1169 using namespace detail;
1170 static constexpr auto extents = const_name("(") + array_info<T>::extents + const_name(")");
1171 return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
1172 }
1173};
1174
1176template <typename T, int ExtraFlags>
1177struct pyobject_caster<array_t<T, ExtraFlags>> {
1179
1180 bool load(handle src, bool convert) {
1181 if (!convert && !type::check_(src)) {
1182 return false;
1183 }
1184 value = type::ensure(src);
1185 return static_cast<bool>(value);
1186 }
1187
1188 static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
1189 return src.inc_ref();
1190 }
1192};
1193
1194template <typename T>
1195struct compare_buffer_info<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1196 static bool compare(const buffer_info &b) {
1197 return npy_api::get().PyArray_EquivTypes_(dtype::of<T>().ptr(), dtype(b).ptr());
1198 }
1199};
1200
1201template <typename T, typename = void>
1203
1204template <typename T>
1205struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
1206 static constexpr auto name = const_name<std::is_same<T, bool>::value>(
1207 const_name("bool"),
1208 const_name<std::is_signed<T>::value>("numpy.int", "numpy.uint")
1209 + const_name<sizeof(T) * 8>());
1210};
1211
1212template <typename T>
1213struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
1214 static constexpr auto name = const_name < std::is_same<T, float>::value
1215 || std::is_same<T, const float>::value
1216 || std::is_same<T, double>::value
1217 || std::is_same<T, const double>::value
1218 > (const_name("numpy.float") + const_name<sizeof(T) * 8>(),
1219 const_name("numpy.longdouble"));
1220};
1221
1222template <typename T>
1224 static constexpr auto name = const_name < std::is_same<typename T::value_type, float>::value
1225 || std::is_same<typename T::value_type, const float>::value
1226 || std::is_same<typename T::value_type, double>::value
1227 || std::is_same<typename T::value_type, const double>::value
1228 > (const_name("numpy.complex")
1229 + const_name<sizeof(typename T::value_type) * 16>(),
1230 const_name("numpy.longcomplex"));
1231};
1232
1233template <typename T>
1235 T,
1236 enable_if_t<satisfies_any_of<T, std::is_arithmetic, is_complex>::value>>
1238private:
1239 // NB: the order here must match the one in common.h
1240 constexpr static const int values[15] = {npy_api::NPY_BOOL_,
1255
1256public:
1257 static constexpr int value = values[detail::is_fmt_numeric<T>::index];
1258
1259 static pybind11::dtype dtype() {
1260 if (auto *ptr = npy_api::get().PyArray_DescrFromType_(value)) {
1261 return reinterpret_steal<pybind11::dtype>(ptr);
1262 }
1263 pybind11_fail("Unsupported buffer format!");
1264 }
1265};
1266
1267#define PYBIND11_DECL_CHAR_FMT \
1268 static constexpr auto name = const_name("S") + const_name<N>(); \
1269 static pybind11::dtype dtype() { \
1270 return pybind11::dtype(std::string("S") + std::to_string(N)); \
1271 }
1272template <size_t N>
1273struct npy_format_descriptor<char[N]> {
1275};
1276template <size_t N>
1279};
1280#undef PYBIND11_DECL_CHAR_FMT
1281
1282template <typename T>
1284private:
1286
1287public:
1288 static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
1289
1290 static constexpr auto name
1291 = const_name("(") + array_info<T>::extents + const_name(")") + base_descr::name;
1292 static pybind11::dtype dtype() {
1293 list shape;
1295 return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape));
1296 }
1297};
1298
1299template <typename T>
1300struct npy_format_descriptor<T, enable_if_t<std::is_enum<T>::value>> {
1301private:
1303
1304public:
1305 static constexpr auto name = base_descr::name;
1306 static pybind11::dtype dtype() { return base_descr::dtype(); }
1307};
1308
1310 const char *name;
1313 std::string format;
1315};
1316
1318 const std::type_info &tinfo,
1319 ssize_t itemsize,
1320 bool (*direct_converter)(PyObject *, void *&)) {
1321
1323 if (numpy_internals.get_type_info(tinfo, false)) {
1324 pybind11_fail("NumPy: dtype is already registered");
1325 }
1326
1327 // Use ordered fields because order matters as of NumPy 1.14:
1328 // https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
1329 std::vector<field_descriptor> ordered_fields(std::move(fields));
1330 std::sort(
1331 ordered_fields.begin(),
1332 ordered_fields.end(),
1333 [](const field_descriptor &a, const field_descriptor &b) { return a.offset < b.offset; });
1334
1335 list names, formats, offsets;
1336 for (auto &field : ordered_fields) {
1337 if (!field.descr) {
1338 pybind11_fail(std::string("NumPy: unsupported field dtype: `") + field.name + "` @ "
1339 + tinfo.name());
1340 }
1341 names.append(PYBIND11_STR_TYPE(field.name));
1342 formats.append(field.descr);
1343 offsets.append(pybind11::int_(field.offset));
1344 }
1345 auto *dtype_ptr
1346 = pybind11::dtype(std::move(names), std::move(formats), std::move(offsets), itemsize)
1347 .release()
1348 .ptr();
1349
1350 // There is an existing bug in NumPy (as of v1.11): trailing bytes are
1351 // not encoded explicitly into the format string. This will supposedly
1352 // get fixed in v1.12; for further details, see these:
1353 // - https://github.com/numpy/numpy/issues/7797
1354 // - https://github.com/numpy/numpy/pull/7798
1355 // Because of this, we won't use numpy's logic to generate buffer format
1356 // strings and will just do it ourselves.
1357 ssize_t offset = 0;
1358 std::ostringstream oss;
1359 // mark the structure as unaligned with '^', because numpy and C++ don't
1360 // always agree about alignment (particularly for complex), and we're
1361 // explicitly listing all our padding. This depends on none of the fields
1362 // overriding the endianness. Putting the ^ in front of individual fields
1363 // isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
1364 oss << "^T{";
1365 for (auto &field : ordered_fields) {
1366 if (field.offset > offset) {
1367 oss << (field.offset - offset) << 'x';
1368 }
1369 oss << field.format << ':' << field.name << ':';
1370 offset = field.offset + field.size;
1371 }
1372 if (itemsize > offset) {
1373 oss << (itemsize - offset) << 'x';
1374 }
1375 oss << '}';
1376 auto format_str = oss.str();
1377
1378 // Sanity check: verify that NumPy properly parses our buffer format string
1379 auto &api = npy_api::get();
1380 auto arr = array(buffer_info(nullptr, itemsize, format_str, 1));
1381 if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) {
1382 pybind11_fail("NumPy: invalid buffer descriptor!");
1383 }
1384
1385 auto tindex = std::type_index(tinfo);
1386 numpy_internals.registered_dtypes[tindex] = {dtype_ptr, format_str};
1387 get_internals().direct_conversions[tindex].push_back(direct_converter);
1388}
1389
1390template <typename T, typename SFINAE>
1391struct npy_format_descriptor {
1392 static_assert(is_pod_struct<T>::value,
1393 "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1394
1395 static constexpr auto name = make_caster<T>::name;
1396
1397 static pybind11::dtype dtype() { return reinterpret_borrow<pybind11::dtype>(dtype_ptr()); }
1398
1399 static std::string format() {
1400 static auto format_str = get_numpy_internals().get_type_info<T>(true)->format_str;
1401 return format_str;
1402 }
1403
1405 register_structured_dtype(std::move(fields),
1406 typeid(typename std::remove_cv<T>::type),
1407 sizeof(T),
1409 }
1410
1411private:
1412 static PyObject *dtype_ptr() {
1413 static PyObject *ptr = get_numpy_internals().get_type_info<T>(true)->dtype_ptr;
1414 return ptr;
1415 }
1416
1417 static bool direct_converter(PyObject *obj, void *&value) {
1418 auto &api = npy_api::get();
1419 if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) {
1420 return false;
1421 }
1422 if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1423 if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
1424 value = ((PyVoidScalarObject_Proxy *) obj)->obval;
1425 return true;
1426 }
1427 }
1428 return false;
1429 }
1430};
1431
1432#ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code)
1433# define PYBIND11_NUMPY_DTYPE(Type, ...) ((void) 0)
1434# define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void) 0)
1435#else
1436
1437# define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
1438 ::pybind11::detail::field_descriptor { \
1439 Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
1440 ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
1441 ::pybind11::detail::npy_format_descriptor< \
1442 decltype(std::declval<T>().Field)>::dtype() \
1443 }
1444
1445// Extract name, offset and format descriptor for a struct field
1446# define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, # Field)
1447
1448// The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
1449// (C) William Swanson, Paul Fultz
1450# define PYBIND11_EVAL0(...) __VA_ARGS__
1451# define PYBIND11_EVAL1(...) PYBIND11_EVAL0(PYBIND11_EVAL0(PYBIND11_EVAL0(__VA_ARGS__)))
1452# define PYBIND11_EVAL2(...) PYBIND11_EVAL1(PYBIND11_EVAL1(PYBIND11_EVAL1(__VA_ARGS__)))
1453# define PYBIND11_EVAL3(...) PYBIND11_EVAL2(PYBIND11_EVAL2(PYBIND11_EVAL2(__VA_ARGS__)))
1454# define PYBIND11_EVAL4(...) PYBIND11_EVAL3(PYBIND11_EVAL3(PYBIND11_EVAL3(__VA_ARGS__)))
1455# define PYBIND11_EVAL(...) PYBIND11_EVAL4(PYBIND11_EVAL4(PYBIND11_EVAL4(__VA_ARGS__)))
1456# define PYBIND11_MAP_END(...)
1457# define PYBIND11_MAP_OUT
1458# define PYBIND11_MAP_COMMA ,
1459# define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END
1460# define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
1461# define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0(test, next, 0)
1462# define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1(PYBIND11_MAP_GET_END test, next)
1463# if defined(_MSC_VER) \
1464 && !defined(__clang__) // MSVC is not as eager to expand macros, hence this workaround
1465# define PYBIND11_MAP_LIST_NEXT1(test, next) \
1466 PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1467# else
1468# define PYBIND11_MAP_LIST_NEXT1(test, next) \
1469 PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1470# endif
1471# define PYBIND11_MAP_LIST_NEXT(test, next) \
1472 PYBIND11_MAP_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1473# define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \
1474 f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST1)(f, t, peek, __VA_ARGS__)
1475# define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
1476 f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST0)(f, t, peek, __VA_ARGS__)
1477// PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ...
1478# define PYBIND11_MAP_LIST(f, t, ...) \
1479 PYBIND11_EVAL(PYBIND11_MAP_LIST1(f, t, __VA_ARGS__, (), 0))
1480
1481# define PYBIND11_NUMPY_DTYPE(Type, ...) \
1482 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1483 ::std::vector<::pybind11::detail::field_descriptor>{ \
1484 PYBIND11_MAP_LIST(PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
1485
1486# if defined(_MSC_VER) && !defined(__clang__)
1487# define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1488 PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1489# else
1490# define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1491 PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1492# endif
1493# define PYBIND11_MAP2_LIST_NEXT(test, next) \
1494 PYBIND11_MAP2_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1495# define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
1496 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST1)(f, t, peek, __VA_ARGS__)
1497# define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
1498 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST0)(f, t, peek, __VA_ARGS__)
1499// PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ...
1500# define PYBIND11_MAP2_LIST(f, t, ...) \
1501 PYBIND11_EVAL(PYBIND11_MAP2_LIST1(f, t, __VA_ARGS__, (), 0))
1502
1503# define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
1504 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1505 ::std::vector<::pybind11::detail::field_descriptor>{ \
1506 PYBIND11_MAP2_LIST(PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
1507
1508#endif // __CLION_IDE__
1509
1511public:
1512 using container_type = std::vector<ssize_t>;
1513 using value_type = container_type::value_type;
1514 using size_type = container_type::size_type;
1515
1517
1518 common_iterator(void *ptr, const container_type &strides, const container_type &shape)
1519 : p_ptr(reinterpret_cast<char *>(ptr)), m_strides(strides.size()) {
1520 m_strides.back() = static_cast<value_type>(strides.back());
1521 for (size_type i = m_strides.size() - 1; i != 0; --i) {
1522 size_type j = i - 1;
1523 auto s = static_cast<value_type>(shape[i]);
1524 m_strides[j] = strides[j] + m_strides[i] - strides[i] * s;
1525 }
1526 }
1527
1528 void increment(size_type dim) { p_ptr += m_strides[dim]; }
1529
1530 void *data() const { return p_ptr; }
1531
1532private:
1533 char *p_ptr{0};
1535};
1536
1537template <size_t N>
1539public:
1540 using container_type = std::vector<ssize_t>;
1541
1542 multi_array_iterator(const std::array<buffer_info, N> &buffers, const container_type &shape)
1543 : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() {
1544
1545 // Manual copy to avoid conversion warning if using std::copy
1546 for (size_t i = 0; i < shape.size(); ++i) {
1547 m_shape[i] = shape[i];
1548 }
1549
1550 container_type strides(shape.size());
1551 for (size_t i = 0; i < N; ++i) {
1552 init_common_iterator(buffers[i], shape, m_common_iterator[i], strides);
1553 }
1554 }
1555
1557 for (size_t j = m_index.size(); j != 0; --j) {
1558 size_t i = j - 1;
1559 if (++m_index[i] != m_shape[i]) {
1561 break;
1562 }
1563 m_index[i] = 0;
1564 }
1565 return *this;
1566 }
1567
1568 template <size_t K, class T = void>
1569 T *data() const {
1570 return reinterpret_cast<T *>(m_common_iterator[K].data());
1571 }
1572
1573private:
1575
1577 const container_type &shape,
1579 container_type &strides) {
1580 auto buffer_shape_iter = buffer.shape.rbegin();
1581 auto buffer_strides_iter = buffer.strides.rbegin();
1582 auto shape_iter = shape.rbegin();
1583 auto strides_iter = strides.rbegin();
1584
1585 while (buffer_shape_iter != buffer.shape.rend()) {
1586 if (*shape_iter == *buffer_shape_iter) {
1587 *strides_iter = *buffer_strides_iter;
1588 } else {
1589 *strides_iter = 0;
1590 }
1591
1592 ++buffer_shape_iter;
1593 ++buffer_strides_iter;
1594 ++shape_iter;
1595 ++strides_iter;
1596 }
1597
1598 std::fill(strides_iter, strides.rend(), 0);
1599 iterator = common_iter(buffer.ptr, strides, shape);
1600 }
1601
1602 void increment_common_iterator(size_t dim) {
1603 for (auto &iter : m_common_iterator) {
1604 iter.increment(dim);
1605 }
1606 }
1607
1610 std::array<common_iter, N> m_common_iterator;
1611};
1612
1614
1615// Populates the shape and number of dimensions for the set of buffers. Returns a
1616// broadcast_trivial enum value indicating whether the broadcast is "trivial"--that is, has each
1617// buffer being either a singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous
1618// (`f_trivial`) storage buffer; returns `non_trivial` otherwise.
1619template <size_t N>
1621broadcast(const std::array<buffer_info, N> &buffers, ssize_t &ndim, std::vector<ssize_t> &shape) {
1622 ndim = std::accumulate(
1623 buffers.begin(), buffers.end(), ssize_t(0), [](ssize_t res, const buffer_info &buf) {
1624 return std::max(res, buf.ndim);
1625 });
1626
1627 shape.clear();
1628 shape.resize((size_t) ndim, 1);
1629
1630 // Figure out the output size, and make sure all input arrays conform (i.e. are either size 1
1631 // or the full size).
1632 for (size_t i = 0; i < N; ++i) {
1633 auto res_iter = shape.rbegin();
1634 auto end = buffers[i].shape.rend();
1635 for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != end;
1636 ++shape_iter, ++res_iter) {
1637 const auto &dim_size_in = *shape_iter;
1638 auto &dim_size_out = *res_iter;
1639
1640 // Each input dimension can either be 1 or `n`, but `n` values must match across
1641 // buffers
1642 if (dim_size_out == 1) {
1643 dim_size_out = dim_size_in;
1644 } else if (dim_size_in != 1 && dim_size_in != dim_size_out) {
1645 pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!");
1646 }
1647 }
1648 }
1649
1650 bool trivial_broadcast_c = true;
1651 bool trivial_broadcast_f = true;
1652 for (size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
1653 if (buffers[i].size == 1) {
1654 continue;
1655 }
1656
1657 // Require the same number of dimensions:
1658 if (buffers[i].ndim != ndim) {
1660 }
1661
1662 // Require all dimensions be full-size:
1663 if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin())) {
1665 }
1666
1667 // Check for C contiguity (but only if previous inputs were also C contiguous)
1668 if (trivial_broadcast_c) {
1669 ssize_t expect_stride = buffers[i].itemsize;
1670 auto end = buffers[i].shape.crend();
1671 for (auto shape_iter = buffers[i].shape.crbegin(),
1672 stride_iter = buffers[i].strides.crbegin();
1673 trivial_broadcast_c && shape_iter != end;
1674 ++shape_iter, ++stride_iter) {
1675 if (expect_stride == *stride_iter) {
1676 expect_stride *= *shape_iter;
1677 } else {
1678 trivial_broadcast_c = false;
1679 }
1680 }
1681 }
1682
1683 // Check for Fortran contiguity (if previous inputs were also F contiguous)
1684 if (trivial_broadcast_f) {
1685 ssize_t expect_stride = buffers[i].itemsize;
1686 auto end = buffers[i].shape.cend();
1687 for (auto shape_iter = buffers[i].shape.cbegin(),
1688 stride_iter = buffers[i].strides.cbegin();
1689 trivial_broadcast_f && shape_iter != end;
1690 ++shape_iter, ++stride_iter) {
1691 if (expect_stride == *stride_iter) {
1692 expect_stride *= *shape_iter;
1693 } else {
1694 trivial_broadcast_f = false;
1695 }
1696 }
1697 }
1698 }
1699
1700 return trivial_broadcast_c ? broadcast_trivial::c_trivial
1701 : trivial_broadcast_f ? broadcast_trivial::f_trivial
1703}
1704
1705template <typename T>
1707 static_assert(!std::is_rvalue_reference<T>::value,
1708 "Functions with rvalue reference arguments cannot be vectorized");
1709 // The wrapped function gets called with this type:
1711 // Is this a vectorized argument?
1712 static constexpr bool vectorize
1715 std::is_pointer,
1716 std::is_array,
1718 std::is_enum>::value
1719 && (!std::is_reference<T>::value
1720 || (std::is_lvalue_reference<T>::value && std::is_const<call_type>::value));
1721 // Accept this type: an array for vectorized types, otherwise the type as-is:
1723};
1724
1725// py::vectorize when a return type is present
1726template <typename Func, typename Return, typename... Args>
1729
1730 static Type create(broadcast_trivial trivial, const std::vector<ssize_t> &shape) {
1731 if (trivial == broadcast_trivial::f_trivial) {
1732 return array_t<Return, array::f_style>(shape);
1733 }
1734 return array_t<Return>(shape);
1735 }
1736
1737 static Return *mutable_data(Type &array) { return array.mutable_data(); }
1738
1739 static Return call(Func &f, Args &...args) { return f(args...); }
1740
1741 static void call(Return *out, size_t i, Func &f, Args &...args) { out[i] = f(args...); }
1742};
1743
1744// py::vectorize when a return type is not present
1745template <typename Func, typename... Args>
1746struct vectorize_returned_array<Func, void, Args...> {
1747 using Type = none;
1748
1749 static Type create(broadcast_trivial, const std::vector<ssize_t> &) { return none(); }
1750
1751 static void *mutable_data(Type &) { return nullptr; }
1752
1753 static detail::void_type call(Func &f, Args &...args) {
1754 f(args...);
1755 return {};
1756 }
1757
1758 static void call(void *, size_t, Func &f, Args &...args) { f(args...); }
1759};
1760
1761template <typename Func, typename Return, typename... Args>
1763
1764// NVCC for some reason breaks if NVectorized is private
1765#ifdef __CUDACC__
1766public:
1767#else
1768private:
1769#endif
1770
1771 static constexpr size_t N = sizeof...(Args);
1773 static_assert(
1774 NVectorized >= 1,
1775 "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1776
1777public:
1778 template <typename T,
1779 // SFINAE to prevent shadowing the copy constructor.
1780 typename = detail::enable_if_t<
1781 !std::is_same<vectorize_helper, typename std::decay<T>::type>::value>>
1782 explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) {}
1783
1785 return run(args...,
1789 }
1790
1791private:
1793
1794 // Internal compiler error in MSVC 19.16.27025.1 (Visual Studio 2017 15.9.4), when compiling
1795 // with "/permissive-" flag when arg_call_types is manually inlined.
1796 using arg_call_types = std::tuple<typename vectorize_arg<Args>::call_type...>;
1797 template <size_t Index>
1798 using param_n_t = typename std::tuple_element<Index, arg_call_types>::type;
1799
1800 using returned_array = vectorize_returned_array<Func, Return, Args...>;
1801
1802 // Runs a vectorized function given arguments tuple and three index sequences:
1803 // - Index is the full set of 0 ... (N-1) argument indices;
1804 // - VIndex is the subset of argument indices with vectorized parameters, letting us access
1805 // vectorized arguments (anything not in this sequence is passed through)
1806 // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that
1807 // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at
1808 // index BIndex in the array).
1809 template <size_t... Index, size_t... VIndex, size_t... BIndex>
1814
1815 // Pointers to values the function was called with; the vectorized ones set here will start
1816 // out as array_t<T> pointers, but they will be changed them to T pointers before we make
1817 // call the wrapped function. Non-vectorized pointers are left as-is.
1818 std::array<void *, N> params{{&args...}};
1819
1820 // The array of `buffer_info`s of vectorized arguments:
1821 std::array<buffer_info, NVectorized> buffers{
1822 {reinterpret_cast<array *>(params[VIndex])->request()...}};
1823
1824 /* Determine dimensions parameters of output array */
1825 ssize_t nd = 0;
1826 std::vector<ssize_t> shape(0);
1827 auto trivial = broadcast(buffers, nd, shape);
1828 auto ndim = (size_t) nd;
1829
1830 size_t size
1831 = std::accumulate(shape.begin(), shape.end(), (size_t) 1, std::multiplies<size_t>());
1832
1833 // If all arguments are 0-dimension arrays (i.e. single values) return a plain value (i.e.
1834 // not wrapped in an array).
1835 if (size == 1 && ndim == 0) {
1836 PYBIND11_EXPAND_SIDE_EFFECTS(params[VIndex] = buffers[BIndex].ptr);
1837 return cast(
1838 returned_array::call(f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...));
1839 }
1840
1841 auto result = returned_array::create(trivial, shape);
1842
1843 if (size == 0) {
1844 return std::move(result);
1845 }
1846
1847 /* Call the function */
1848 auto *mutable_data = returned_array::mutable_data(result);
1849 if (trivial == broadcast_trivial::non_trivial) {
1850 apply_broadcast(buffers, params, mutable_data, size, shape, i_seq, vi_seq, bi_seq);
1851 } else {
1852 apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
1853 }
1854
1855 return std::move(result);
1856 }
1857
1858 template <size_t... Index, size_t... VIndex, size_t... BIndex>
1859 void apply_trivial(std::array<buffer_info, NVectorized> &buffers,
1860 std::array<void *, N> &params,
1861 Return *out,
1862 size_t size,
1866
1867 // Initialize an array of mutable byte references and sizes with references set to the
1868 // appropriate pointer in `params`; as we iterate, we'll increment each pointer by its size
1869 // (except for singletons, which get an increment of 0).
1870 std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{
1871 {std::pair<unsigned char *&, const size_t>(
1872 reinterpret_cast<unsigned char *&>(params[VIndex] = buffers[BIndex].ptr),
1873 buffers[BIndex].size == 1 ? 0 : sizeof(param_n_t<VIndex>))...}};
1874
1875 for (size_t i = 0; i < size; ++i) {
1877 out, i, f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...);
1878 for (auto &x : vecparams) {
1879 x.first += x.second;
1880 }
1881 }
1882 }
1883
1884 template <size_t... Index, size_t... VIndex, size_t... BIndex>
1885 void apply_broadcast(std::array<buffer_info, NVectorized> &buffers,
1886 std::array<void *, N> &params,
1887 Return *out,
1888 size_t size,
1889 const std::vector<ssize_t> &output_shape,
1893
1894 multi_array_iterator<NVectorized> input_iter(buffers, output_shape);
1895
1896 for (size_t i = 0; i < size; ++i, ++input_iter) {
1897 PYBIND11_EXPAND_SIDE_EFFECTS((params[VIndex] = input_iter.template data<BIndex>()));
1899 out, i, f, *reinterpret_cast<param_n_t<Index> *>(std::get<Index>(params))...);
1900 }
1901 }
1902};
1903
1904template <typename Func, typename Return, typename... Args>
1905vectorize_helper<Func, Return, Args...> vectorize_extractor(const Func &f, Return (*)(Args...)) {
1906 return detail::vectorize_helper<Func, Return, Args...>(f);
1907}
1908
1909template <typename T, int Flags>
1910struct handle_type_name<array_t<T, Flags>> {
1911 static constexpr auto name
1912 = const_name("numpy.ndarray[") + npy_format_descriptor<T>::name + const_name("]");
1913};
1914
1916
1917// Vanilla pointer vectorizer:
1918template <typename Return, typename... Args>
1919detail::vectorize_helper<Return (*)(Args...), Return, Args...> vectorize(Return (*f)(Args...)) {
1920 return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f);
1921}
1922
1923// lambda vectorizer:
1924template <typename Func, detail::enable_if_t<detail::is_lambda<Func>::value, int> = 0>
1925auto vectorize(Func &&f)
1926 -> decltype(detail::vectorize_extractor(std::forward<Func>(f),
1927 (detail::function_signature_t<Func> *) nullptr)) {
1928 return detail::vectorize_extractor(std::forward<Func>(f),
1929 (detail::function_signature_t<Func> *) nullptr);
1930}
1931
1932// Vectorize a class method (non-const):
1933template <typename Return,
1934 typename Class,
1935 typename... Args,
1936 typename Helper = detail::vectorize_helper<
1937 decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())),
1938 Return,
1939 Class *,
1940 Args...>>
1941Helper vectorize(Return (Class::*f)(Args...)) {
1942 return Helper(std::mem_fn(f));
1943}
1944
1945// Vectorize a class method (const):
1946template <typename Return,
1947 typename Class,
1948 typename... Args,
1949 typename Helper = detail::vectorize_helper<
1950 decltype(std::mem_fn(std::declval<Return (Class::*)(Args...) const>())),
1951 Return,
1952 const Class *,
1953 Args...>>
1954Helper vectorize(Return (Class::*f)(Args...) const) {
1955 return Helper(std::mem_fn(f));
1956}
1957
Definition: pytypes.h:1776
Definition: numpy.h:991
array_t(handle h, borrowed_t)
Definition: numpy.h:1008
const T * data(Ix... index) const
Definition: numpy.h:1055
T * mutable_data(Ix... index)
Definition: numpy.h:1060
ssize_t index_at(Ix... index) const
Definition: numpy.h:1050
const T & at(Ix... index) const
Definition: numpy.h:1066
array_t(ssize_t count, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1044
static PyObject * raw_array_t(PyObject *ptr)
Create array from any object – always returns a new reference.
Definition: numpy.h:1127
T & mutable_at(Ix... index)
Definition: numpy.h:1076
constexpr ssize_t itemsize() const
Definition: numpy.h:1047
array_t(handle h, stolen_t)
Definition: numpy.h:1009
array_t(const object &o)
Definition: numpy.h:1022
T value_type
Definition: numpy.h:1005
array_t()
Definition: numpy.h:1007
array_t(ShapeContainer shape, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1036
static bool check_(handle h)
Definition: numpy.h:1117
static array_t ensure(handle h)
Ensure that the argument is a NumPy array of the correct dtype (and if not, try to convert it).
Definition: numpy.h:1109
array_t(ShapeContainer shape, StridesContainer strides, const T *ptr=nullptr, handle base=handle())
Definition: numpy.h:1030
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Returns a proxy object that provides access to the array's data without bounds or dimensionality chec...
Definition: numpy.h:1091
detail::unchecked_reference< T, Dims > unchecked() const &
Returns a proxy object that provides const access to the array's data without bounds or dimensionalit...
Definition: numpy.h:1103
array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
Definition: numpy.h:995
array_t(const buffer_info &info, handle base=handle())
Definition: numpy.h:1028
Definition: numpy.h:655
ssize_t offset_at(Ix... index) const
Byte offset from beginning of the array to a given index (full or partial).
Definition: numpy.h:829
void fail_dim_check(ssize_t dim, const std::string &msg) const
Definition: numpy.h:945
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:724
ssize_t nbytes() const
Total number of bytes.
Definition: numpy.h:767
static PyObject * raw_array(PyObject *ptr, int ExtraFlags=0)
Create array from any object – always returns a new reference.
Definition: numpy.h:980
void check_dimensions(Ix... index) const
Definition: numpy.h:963
array reshape(ShapeContainer new_shape)
Optional order parameter omitted, to be added as needed.
Definition: numpy.h:905
ssize_t ndim() const
Number of dimensions.
Definition: numpy.h:770
array(ShapeContainer shape, const T *ptr, handle base=handle())
Definition: numpy.h:741
const ssize_t * strides() const
Strides of the array.
Definition: numpy.h:787
friend struct detail::npy_format_descriptor
Definition: numpy.h:943
ssize_t byte_offset(Ix... index) const
Definition: numpy.h:951
detail::any_container< ssize_t > ShapeContainer
Definition: numpy.h:667
object base() const
Base object.
Definition: numpy.h:773
ssize_t size() const
Total number of elements.
Definition: numpy.h:757
void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const
Definition: numpy.h:970
int flags() const
Return the NumPy array flags.
Definition: numpy.h:798
detail::unchecked_reference< T, Dims > unchecked() const &
Returns a proxy object that provides const access to the array's data without bounds or dimensionalit...
Definition: numpy.h:870
void resize(ShapeContainer new_shape, bool refcheck=true)
Resize array to given shape If refcheck is true and more that one reference exist to this array then ...
Definition: numpy.h:888
array(ssize_t count, const T *ptr, handle base=handle())
Definition: numpy.h:745
ssize_t index_at(Ix... index) const
Item count from beginning of the array to a given index (full or partial).
Definition: numpy.h:841
pybind11::dtype dtype() const
Array descriptor (dtype)
Definition: numpy.h:752
static array ensure(handle h, int ExtraFlags=0)
Ensure that the argument is a NumPy array In case of an error, nullptr is returned and the Python err...
Definition: numpy.h:933
array(const buffer_info &info, handle base=handle())
Definition: numpy.h:748
@ forcecast
Definition: numpy.h:662
@ c_style
Definition: numpy.h:660
@ f_style
Definition: numpy.h:661
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:671
const ssize_t * shape() const
Dimensions of the array.
Definition: numpy.h:776
void check_dimensions_impl(ssize_t, const ssize_t *) const
Definition: numpy.h:967
detail::any_container< ssize_t > StridesContainer
Definition: numpy.h:668
array view(const std::string &dtype)
Create a view of an array in a different data type.
Definition: numpy.h:921
void check_writeable() const
Definition: numpy.h:956
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
Definition: numpy.h:801
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
Returns a proxy object that provides access to the array's data without bounds or dimensionality chec...
Definition: numpy.h:852
bool owndata() const
If set, the array owns the data (will be freed when the array is deleted)
Definition: numpy.h:806
void * mutable_data(Ix... index)
Mutable pointer to the contained data.
Definition: numpy.h:821
array(const pybind11::dtype &dt, T count, const void *ptr=nullptr, handle base=handle())
Definition: numpy.h:733
array()
Definition: numpy.h:665
ssize_t itemsize() const
Byte size of a single element.
Definition: numpy.h:762
ssize_t shape(ssize_t dim) const
Dimension along a given axis.
Definition: numpy.h:779
ssize_t offset_at() const
Definition: numpy.h:836
const void * data(Ix... index) const
Pointer to the contained data.
Definition: numpy.h:813
array squeeze()
Return a new view with all of the dimensions of length 1 removed.
Definition: numpy.h:880
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base=handle())
Definition: numpy.h:737
ssize_t strides(ssize_t dim) const
Stride along a given axis.
Definition: numpy.h:790
container_type::size_type size_type
Definition: numpy.h:1514
container_type m_strides
Definition: numpy.h:1534
common_iterator(void *ptr, const container_type &strides, const container_type &shape)
Definition: numpy.h:1518
std::vector< ssize_t > container_type
Definition: numpy.h:1512
void increment(size_type dim)
Definition: numpy.h:1528
void * data() const
Definition: numpy.h:1530
char * p_ptr
Definition: numpy.h:1533
container_type::value_type value_type
Definition: numpy.h:1513
Definition: pytypes.h:1694
Definition: numpy.h:542
static dtype of()
Return dtype associated with a C++ type.
Definition: numpy.h:580
char kind() const
Single-character code for dtype's kind.
Definition: numpy.h:592
dtype(const buffer_info &info)
Definition: numpy.h:546
dtype strip_padding(ssize_t itemsize)
Definition: numpy.h:613
PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_)
ssize_t itemsize() const
Size of the data type in bytes.
Definition: numpy.h:585
static object _dtype_from_pep3118()
Definition: numpy.h:604
dtype(list names, list formats, list offsets, ssize_t itemsize)
Definition: numpy.h:560
dtype(const char *format)
Definition: numpy.h:558
static dtype from_args(object args)
This is essentially the same as calling numpy.dtype(args) in Python.
Definition: numpy.h:570
char char_() const
Single-character for dtype's type.
Definition: numpy.h:596
bool has_fields() const
Returns true for structured data types.
Definition: numpy.h:588
dtype(const std::string &format)
Definition: numpy.h:554
Fetch and hold an error which was already set in Python.
Definition: pytypes.h:379
\rst Holds a reference to a Python object (no reference counting)
Definition: pytypes.h:194
PyObject * m_ptr
Definition: pytypes.h:246
const handle & inc_ref() const &
\rst Manually increase the reference count of the Python object.
Definition: pytypes.h:211
handle()=default
The default constructor creates a handle with a nullptr-valued pointer.
PyObject * ptr() const
Return the underlying PyObject * pointer.
Definition: pytypes.h:203
\rst Wraps a Python iterator so that it can also be used as a C++ input iterator
Definition: pytypes.h:1102
Definition: pytypes.h:1746
void append(T &&val)
Definition: pytypes.h:1764
Wrapper for Python extension modules.
Definition: pybind11.h:1145
static module_ import(const char *name)
Import and return a module or throws error_already_set.
Definition: pybind11.h:1200
void increment_common_iterator(size_t dim)
Definition: numpy.h:1602
container_type m_index
Definition: numpy.h:1609
common_iterator common_iter
Definition: numpy.h:1574
multi_array_iterator & operator++()
Definition: numpy.h:1556
T * data() const
Definition: numpy.h:1569
multi_array_iterator(const std::array< buffer_info, N > &buffers, const container_type &shape)
Definition: numpy.h:1542
void init_common_iterator(const buffer_info &buffer, const container_type &shape, common_iter &iterator, container_type &strides)
Definition: numpy.h:1576
std::array< common_iter, N > m_common_iterator
Definition: numpy.h:1610
std::vector< ssize_t > container_type
Definition: numpy.h:1540
container_type m_shape
Definition: numpy.h:1608
Definition: pytypes.h:1422
handle release()
\rst Resets the internal pointer to nullptr without decreasing the object's reference count.
Definition: pytypes.h:283
bool is_borrowed
Definition: pytypes.h:265
T cast() const &
Definition: pytypes.h:1167
T & operator[](ssize_t index)
Mutable, unchecked access data at the given index; this operator only participates if the reference i...
Definition: numpy.h:520
T * mutable_data(Ix... ix)
Mutable pointer access to the data at the given indices.
Definition: numpy.h:526
friend class pybind11::array
Definition: numpy.h:497
T & operator()(Ix... index)
Mutable, unchecked access to data at the given indices.
Definition: numpy.h:509
static constexpr bool Dynamic
Definition: numpy.h:411
Proxy class providing unsafe, unchecked const access to array data.
Definition: numpy.h:409
const T & operator()(Ix... index) const
Unchecked const reference access to data at the given indices.
Definition: numpy.h:447
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > strides_
Definition: numpy.h:415
const T * data(Ix... ix) const
Pointer access to the data at the given indices.
Definition: numpy.h:464
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > shape_
Definition: numpy.h:415
const ssize_t dims_
Definition: numpy.h:416
const T & operator[](ssize_t index) const
Unchecked const reference access to data; this operator only participates if the reference is to a 1-...
Definition: numpy.h:458
ssize_t shape(ssize_t dim) const
Returns the shape (i.e. size) of dimension dim
Definition: numpy.h:472
const unsigned char * data_
Definition: numpy.h:412
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t< Dyn, ssize_t > dims)
Definition: numpy.h:433
ssize_t ndim() const
Returns the number of dimensions of the array.
Definition: numpy.h:475
ssize_t nbytes() const
Returns the total number of bytes used by the referenced data.
Definition: numpy.h:492
friend class pybind11::array
Definition: numpy.h:418
enable_if_t<!Dyn, ssize_t > size() const
Returns the total number of elements in the referenced array, i.e.
Definition: numpy.h:480
enable_if_t< Dyn, ssize_t > size() const
Definition: numpy.h:485
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t >)
Definition: numpy.h:421
static constexpr bool Dynamic
Definition: numpy.h:411
static constexpr ssize_t itemsize()
Returns the item size, i.e. sizeof(T)
Definition: numpy.h:469
iterator iter(handle obj)
Definition: pytypes.h:2042
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2002
std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:31
std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:19
T cast(const handle &handle)
Definition: cast.h:1050
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
Definition: common.h:625
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers.
Definition: common.h:678
PYBIND11_NOINLINE void pybind11_fail(const char *reason)
Thrown when pybind11::cast or.
Definition: common.h:992
#define PYBIND11_NOINLINE
Definition: common.h:129
#define PYBIND11_STR_TYPE
Definition: common.h:320
typename std::remove_reference< T >::type remove_reference_t
Definition: common.h:631
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN)
Definition: common.h:948
std::size_t size_t
Definition: common.h:461
constexpr size_t constexpr_sum()
Compile-time integer sum.
Definition: common.h:786
#define PYBIND11_NAMESPACE_END(name)
Definition: common.h:21
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: common.h:20
typename make_index_sequence_impl< N >::type make_index_sequence
Definition: common.h:660
Py_ssize_t ssize_t
Definition: common.h:460
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
Definition: common.h:707
typename std::conditional< B, T, F >::type conditional_t
Definition: common.h:627
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
Definition: common.h:470
@ move
Use std::move to move the return value contents into a new instance that will be owned by Python.
#define PYBIND11_DEPRECATED(reason)
Definition: common.h:139
#define PYBIND11_SILENCE_MSVC_C4127(...)
Definition: common.h:1206
typename select_indices_impl< index_sequence<>, 0, Bs... >::type select_indices
Definition: common.h:674
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
constexpr descr< 0 > concat()
Definition: descr.h:139
PYBIND11_NOINLINE internals & get_internals()
Return a reference to the current internals data.
Definition: internals.h:416
PyArray_Proxy * array_proxy(void *ptr)
Definition: numpy.h:301
all_of< std::is_standard_layout< T >, std::is_trivial< T > > is_pod
Definition: numpy.h:392
detail::vectorize_helper< Return(*)(Args...), Return, Args... > vectorize(Return(*f)(Args...))
Definition: numpy.h:1919
numpy_internals & get_numpy_internals()
Definition: numpy.h:113
vectorize_helper< Func, Return, Args... > vectorize_extractor(const Func &f, Return(*)(Args...))
Definition: numpy.h:1905
ssize_t byte_offset_unsafe(const Strides &)
Definition: numpy.h:395
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
Definition: numpy.h:1621
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:1317
broadcast_trivial
Definition: numpy.h:1613
PYBIND11_NOINLINE void load_numpy_internals(numpy_internals *&ptr)
Definition: numpy.h:109
PyArrayDescr_Proxy * array_descriptor_proxy(PyObject *ptr)
Definition: numpy.h:307
bool check_flags(const void *ptr, int flag)
Definition: numpy.h:315
constexpr int platform_lookup()
Definition: numpy.h:128
typename array_info< T >::type remove_all_extents_t
Definition: numpy.h:366
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:388
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun)
Definition: pytypes.h:1049
py::array arr
#define PYBIND11_DECL_CHAR_FMT
Definition: numpy.h:1294
numpy_internals & get_numpy_internals()
Definition: numpy.h:115
#define DECL_NPY_API(Func)
ssize_t byte_offset_unsafe(const Strides &)
Definition: numpy.h:393
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
Definition: numpy.h:1649
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:1345
broadcast_trivial
Definition: numpy.h:1641
PyObject * descr
Definition: numpy.h:73
int flags
Definition: numpy.h:74
ssize_t * strides
Definition: numpy.h:71
PyObject_HEAD char * data
Definition: numpy.h:68
ssize_t * dimensions
Definition: numpy.h:70
PyObject * base
Definition: numpy.h:72
int nd
Definition: numpy.h:69
PyObject * names
Definition: numpy.h:63
PyObject * fields
Definition: numpy.h:62
char byteorder
Definition: numpy.h:56
char * subarray
Definition: numpy.h:61
PyObject_HEAD PyObject * typeobj
Definition: numpy.h:53
PyArrayDescr_Proxy * descr
Definition: numpy.h:79
PyObject_VAR_HEAD char * obval
Definition: numpy.h:78
PyObject * base
Definition: numpy.h:81
static void append_extents(list &shape)
Definition: numpy.h:349
static constexpr bool is_empty
Definition: numpy.h:332
static constexpr auto extents
Definition: numpy.h:333
static constexpr bool is_array
Definition: numpy.h:331
static void append_extents(list &)
Definition: numpy.h:334
Annotation indicating that a class derives from another given type.
Definition: attr.h:60
Information record describing a Python buffer object.
Definition: buffer_info.h:43
ssize_t ndim
Definition: buffer_info.h:49
ssize_t itemsize
Definition: buffer_info.h:45
std::string format
Definition: buffer_info.h:47
Definition: descr.h:25
ssize_t offset
Definition: numpy.h:1311
const char * name
Definition: numpy.h:1310
std::string format
Definition: numpy.h:1313
ssize_t size
Definition: numpy.h:1312
static std::string format()
Definition: numpy.h:1151
Index sequences.
Definition: common.h:652
type_map< std::vector< bool(*)(PyObject *, void *&)> > direct_conversions
Definition: internals.h:158
Annotation for function names.
Definition: attr.h:47
Py_intptr_t * ptr
Definition: numpy.h:188
Definition: numpy.h:138
int(* PyArray_DescrConverter_)(PyObject *, PyObject **)
Definition: numpy.h:223
int(* PyArray_SetBaseObject_)(PyObject *, PyObject *)
Definition: numpy.h:235
PyTypeObject * PyArray_Type_
Definition: numpy.h:218
PyTypeObject * PyArrayDescr_Type_
Definition: numpy.h:220
constants
Definition: numpy.h:139
@ NPY_LONG_
Definition: numpy.h:154
@ NPY_INT32_
Definition: numpy.h:176
@ NPY_UNICODE_
Definition: numpy.h:166
@ NPY_CLONGDOUBLE_
Definition: numpy.h:163
@ NPY_UINT32_
Definition: numpy.h:178
@ NPY_CDOUBLE_
Definition: numpy.h:162
@ NPY_CFLOAT_
Definition: numpy.h:161
@ NPY_ULONGLONG_
Definition: numpy.h:157
@ NPY_INT16_
Definition: numpy.h:171
@ NPY_STRING_
Definition: numpy.h:165
@ NPY_ARRAY_ENSUREARRAY_
Definition: numpy.h:144
@ NPY_UINT64_
Definition: numpy.h:182
@ NPY_UINT_
Definition: numpy.h:153
@ NPY_UINT16_
Definition: numpy.h:172
@ NPY_DOUBLE_
Definition: numpy.h:159
@ NPY_OBJECT_
Definition: numpy.h:164
@ NPY_ARRAY_WRITEABLE_
Definition: numpy.h:146
@ NPY_ARRAY_C_CONTIGUOUS_
Definition: numpy.h:140
@ NPY_INT64_
Definition: numpy.h:180
@ NPY_LONGDOUBLE_
Definition: numpy.h:160
@ NPY_USHORT_
Definition: numpy.h:151
@ NPY_BYTE_
Definition: numpy.h:148
@ NPY_ARRAY_OWNDATA_
Definition: numpy.h:142
@ NPY_ARRAY_F_CONTIGUOUS_
Definition: numpy.h:141
@ NPY_UINT8_
Definition: numpy.h:170
@ NPY_BOOL_
Definition: numpy.h:147
@ NPY_FLOAT_
Definition: numpy.h:158
@ NPY_ARRAY_ALIGNED_
Definition: numpy.h:145
@ NPY_INT8_
Definition: numpy.h:169
@ NPY_ULONG_
Definition: numpy.h:155
@ NPY_INT_
Definition: numpy.h:152
@ NPY_UBYTE_
Definition: numpy.h:149
@ NPY_SHORT_
Definition: numpy.h:150
@ NPY_VOID_
Definition: numpy.h:167
@ NPY_ARRAY_FORCECAST_
Definition: numpy.h:143
@ NPY_LONGLONG_
Definition: numpy.h:156
functions
Definition: numpy.h:241
@ API_PyArray_SetBaseObject
Definition: numpy.h:260
@ API_PyVoidArrType_Type
Definition: numpy.h:245
@ API_PyArray_View
Definition: numpy.h:256
@ API_PyArray_NewFromDescr
Definition: numpy.h:252
@ API_PyArray_NewCopy
Definition: numpy.h:251
@ API_PyArray_EquivTypes
Definition: numpy.h:258
@ API_PyArray_DescrFromScalar
Definition: numpy.h:247
@ API_PyArray_FromAny
Definition: numpy.h:248
@ API_PyArray_DescrConverter
Definition: numpy.h:257
@ API_PyArray_DescrFromType
Definition: numpy.h:246
@ API_PyArray_Resize
Definition: numpy.h:249
@ API_PyArrayDescr_Type
Definition: numpy.h:244
@ API_PyArray_Type
Definition: numpy.h:243
@ API_PyArray_Squeeze
Definition: numpy.h:255
@ API_PyArray_GetNDArrayCFeatureVersion
Definition: numpy.h:242
@ API_PyArray_DescrNewFromType
Definition: numpy.h:253
@ API_PyArray_CopyInto
Definition: numpy.h:250
@ API_PyArray_Newshape
Definition: numpy.h:254
@ API_PyArray_GetArrayParamsFromObject
Definition: numpy.h:259
unsigned int(* PyArray_GetNDArrayCFeatureVersion_)()
Definition: numpy.h:204
static npy_api & get()
Definition: numpy.h:192
int(* PyArray_GetArrayParamsFromObject_)(PyObject *, PyObject *, unsigned char, PyObject **, int *, Py_intptr_t *, PyObject **, PyObject *)
Definition: numpy.h:225
bool(* PyArray_EquivTypes_)(PyObject *, PyObject *)
Definition: numpy.h:224
bool PyArrayDescr_Check_(PyObject *obj) const
Definition: numpy.h:200
static npy_api lookup()
Definition: numpy.h:263
int(* PyArray_CopyInto_)(PyObject *, PyObject *)
Definition: numpy.h:216
PyTypeObject * PyVoidArrType_Type_
Definition: numpy.h:219
bool PyArray_Check_(PyObject *obj) const
Definition: numpy.h:197
static PyObject * dtype_ptr()
Definition: numpy.h:1412
static pybind11::dtype dtype()
Definition: numpy.h:1397
static std::string format()
Definition: numpy.h:1399
static bool direct_converter(PyObject *obj, void *&value)
Definition: numpy.h:1417
static void register_dtype(any_container< field_descriptor > fields)
Definition: numpy.h:1404
numpy_type_info * get_type_info(bool throw_if_missing=true)
Definition: numpy.h:104
numpy_type_info * get_type_info(const std::type_info &tinfo, bool throw_if_missing=true)
Definition: numpy.h:92
std::unordered_map< std::type_index, numpy_type_info > registered_dtypes
Definition: numpy.h:90
PyObject * dtype_ptr
Definition: numpy.h:85
std::string format_str
Definition: numpy.h:86
PYBIND11_TYPE_CASTER(type, handle_type_name< type >::name)
static handle cast(const handle &src, return_value_policy, handle)
Definition: numpy.h:1188
bool load(handle src, bool convert)
Definition: numpy.h:1180
bool_constant< sizeof(T)==sizeof(U)> as
Definition: numpy.h:124
conditional_t< vectorize, array_t< remove_cv_t< call_type >, array::forcecast >, T > type
Definition: numpy.h:1722
remove_reference_t< T > call_type
Definition: numpy.h:1710
static constexpr bool vectorize
Definition: numpy.h:1713
object operator()(typename vectorize_arg< Args >::type... args)
Definition: numpy.h:1784
typename std::tuple_element< Index, arg_call_types >::type param_n_t
Definition: numpy.h:1798
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:1859
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:1810
static constexpr size_t NVectorized
Definition: numpy.h:1772
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:1885
vectorize_helper(T &&f)
Definition: numpy.h:1782
static constexpr size_t N
Definition: numpy.h:1771
remove_reference_t< Func > f
Definition: numpy.h:1792
std::tuple< typename vectorize_arg< Args >::call_type... > arg_call_types
Definition: numpy.h:1796
static detail::void_type call(Func &f, Args &...args)
Definition: numpy.h:1753
static Type create(broadcast_trivial, const std::vector< ssize_t > &)
Definition: numpy.h:1749
static void call(void *, size_t, Func &f, Args &...args)
Definition: numpy.h:1758
static Return call(Func &f, Args &...args)
Definition: numpy.h:1739
static void call(Return *out, size_t i, Func &f, Args &...args)
Definition: numpy.h:1741
static Return * mutable_data(Type &array)
Definition: numpy.h:1737
static Type create(broadcast_trivial trivial, const std::vector< ssize_t > &shape)
Definition: numpy.h:1730