28 # pragma warning(push) 29 # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant 36 static_assert(
sizeof(
ssize_t) ==
sizeof(Py_intptr_t),
"ssize_t != Py_intptr_t");
88 auto it = registered_dtypes.find(std::type_index(tinfo));
89 if (it != registered_dtypes.end())
92 pybind11_fail(std::string(
"NumPy type info missing for ") + tinfo.name());
102 ptr = &get_or_create_shared_data<numpy_internals>(
"_numpy_internals");
108 load_numpy_internals(ptr);
117 template <
typename Concrete,
typename... Check,
typename... Int>
119 using code_index = std::integral_constant<int, constexpr_first<same_size<Concrete>::template as, Check...>()>;
120 static_assert(
code_index::value !=
sizeof...(Check),
"Unable to match type on this platform");
126 NPY_ARRAY_C_CONTIGUOUS_ = 0x0001,
127 NPY_ARRAY_F_CONTIGUOUS_ = 0x0002,
128 NPY_ARRAY_OWNDATA_ = 0x0004,
129 NPY_ARRAY_FORCECAST_ = 0x0010,
130 NPY_ARRAY_ENSUREARRAY_ = 0x0040,
131 NPY_ARRAY_ALIGNED_ = 0x0100,
132 NPY_ARRAY_WRITEABLE_ = 0x0400,
144 NPY_INT8_ = NPY_BYTE_,
145 NPY_UINT8_ = NPY_UBYTE_,
146 NPY_INT16_ = NPY_SHORT_,
147 NPY_UINT16_ = NPY_USHORT_,
151 NPY_INT32_ = platform_lookup<std::int32_t, long, int, short>(
152 NPY_LONG_, NPY_INT_, NPY_SHORT_),
153 NPY_UINT32_ = platform_lookup<std::uint32_t, unsigned long, unsigned int, unsigned short>(
154 NPY_ULONG_, NPY_UINT_, NPY_USHORT_),
155 NPY_INT64_ = platform_lookup<std::int64_t, long, long long, int>(
156 NPY_LONG_, NPY_LONGLONG_, NPY_INT_),
157 NPY_UINT64_ = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
158 NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
172 return (
bool) PyObject_TypeCheck(obj, PyArray_Type_);
175 return (
bool) PyObject_TypeCheck(obj, PyArrayDescr_Type_);
178 unsigned int (*PyArray_GetNDArrayCFeatureVersion_)();
179 PyObject *(*PyArray_DescrFromType_)(int);
180 PyObject *(*PyArray_NewFromDescr_)
181 (PyTypeObject *, PyObject *, int, Py_intptr_t *,
182 Py_intptr_t *,
void *, int, PyObject *);
183 PyObject *(*PyArray_DescrNewFromType_)(int);
184 int (*PyArray_CopyInto_)(PyObject *, PyObject *);
185 PyObject *(*PyArray_NewCopy_)(PyObject *, int);
189 PyObject *(*PyArray_DescrFromScalar_)(PyObject *);
190 PyObject *(*PyArray_FromAny_) (PyObject *, PyObject *, int, int, int, PyObject *);
191 int (*PyArray_DescrConverter_) (PyObject *, PyObject **);
192 bool (*PyArray_EquivTypes_) (PyObject *, PyObject *);
193 int (*PyArray_GetArrayParamsFromObject_)(PyObject *, PyObject *, char, PyObject **,
int *,
194 Py_ssize_t *, PyObject **, PyObject *);
195 PyObject *(*PyArray_Squeeze_)(PyObject *);
196 int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
200 API_PyArray_GetNDArrayCFeatureVersion = 211,
201 API_PyArray_Type = 2,
202 API_PyArrayDescr_Type = 3,
203 API_PyVoidArrType_Type = 39,
204 API_PyArray_DescrFromType = 45,
205 API_PyArray_DescrFromScalar = 57,
206 API_PyArray_FromAny = 69,
207 API_PyArray_Resize = 80,
208 API_PyArray_CopyInto = 82,
209 API_PyArray_NewCopy = 85,
210 API_PyArray_NewFromDescr = 94,
211 API_PyArray_DescrNewFromType = 9,
212 API_PyArray_DescrConverter = 174,
213 API_PyArray_EquivTypes = 182,
214 API_PyArray_GetArrayParamsFromObject = 278,
215 API_PyArray_Squeeze = 136,
216 API_PyArray_SetBaseObject = 282
220 module m = module::import(
"numpy.core.multiarray");
221 auto c = m.
attr(
"_ARRAY_API");
222 #if PY_MAJOR_VERSION >= 3 223 void **api_ptr = (
void **) PyCapsule_GetPointer(c.ptr(), NULL);
225 void **api_ptr = (
void **) PyCObject_AsVoidPtr(c.ptr());
228 #define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func]; 231 pybind11_fail(
"pybind11 numpy support requires numpy >= 1.7.0");
275 template <
typename T>
struct is_complex : std::false_type { };
276 template <
typename T>
struct is_complex<std::complex<T>> : std::true_type { };
280 static constexpr
bool is_array =
false;
281 static constexpr
bool is_empty =
false;
282 static constexpr
auto extents =
_(
"");
291 static constexpr
bool is_array =
true;
293 static constexpr
size_t extent = N;
301 static constexpr
auto extents = _<array_info<T>::is_array>(
313 std::is_standard_layout<T>,
314 #if !defined(__GNUG__) || defined(_LIBCPP_VERSION) || defined(_GLIBCXX_USE_CXX11_ABI) 317 std::is_trivially_copyable<T>,
320 std::is_trivially_destructible<T>,
327 template <
ssize_t Dim = 0,
typename Strides,
typename... Ix>
329 return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
337 template <
typename T, s
size_t Dims>
340 static constexpr
bool Dynamic = Dims < 0;
350 template <
bool Dyn = Dynamic>
352 : data_{
reinterpret_cast<const unsigned char *
>(
data)}, dims_{Dims} {
353 for (
size_t i = 0;
i < (
size_t) dims_;
i++) {
359 template <
bool Dyn = Dynamic>
361 : data_{
reinterpret_cast<const unsigned char *
>(
data)}, shape_{
shape}, strides_{
strides}, dims_{dims} {}
369 template <
typename... Ix>
const T &
operator()(Ix... index)
const {
370 static_assert(
ssize_t{
sizeof...(Ix)} == Dims || Dynamic,
371 "Invalid number of indices for unchecked array reference");
378 template <s
size_t D = Dims,
typename = enable_if_t<D == 1 || Dynamic>>
394 template <
bool Dyn = Dynamic>
396 return std::accumulate(shape_.begin(), shape_.end(), (
ssize_t) 1, std::multiplies<ssize_t>());
398 template <
bool Dyn = Dynamic>
400 return std::accumulate(shape_, shape_ +
ndim(), (
ssize_t) 1, std::multiplies<ssize_t>());
410 template <
typename T, s
size_t Dims>
414 using ConstBase::ConstBase;
415 using ConstBase::Dynamic;
419 static_assert(
ssize_t{
sizeof...(Ix)} == Dims || Dynamic,
420 "Invalid number of indices for unchecked array reference");
421 return const_cast<T &
>(ConstBase::operator()(index...));
428 template <s
size_t D = Dims,
typename = enable_if_t<D == 1 || Dynamic>>
435 template <
typename T, s
size_t Dim>
437 static_assert(Dim == 0 && Dim > 0 ,
"unchecked array proxy object is not castable");
439 template <
typename T, s
size_t Dim>
462 args[
"names"] = names;
463 args[
"formats"] = formats;
464 args[
"offsets"] = offsets;
466 m_ptr = from_args(args).release().ptr();
471 PyObject *ptr =
nullptr;
472 if (!detail::npy_api::get().PyArray_DescrConverter_(args.
ptr(), &ptr) || !ptr)
474 return reinterpret_steal<dtype>(ptr);
499 static PyObject *obj = module::import(
"numpy.core._internal")
500 .
attr(
"_dtype_from_pep3118").cast<
object>().
release().ptr();
501 return reinterpret_borrow<object>(obj);
511 std::vector<field_descr> field_descriptors;
513 for (
auto field : attr(
"fields").attr(
"items")()) {
516 auto format = spec[1].cast<
tuple>()[0].cast<dtype>();
517 auto offset = spec[1].cast<
tuple>()[1].cast<pybind11::int_>();
518 if (!
len(name) && format.kind() ==
'V')
520 field_descriptors.push_back({(
PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset});
523 std::sort(field_descriptors.begin(), field_descriptors.end(),
524 [](
const field_descr& a,
const field_descr& b) {
525 return a.offset.cast<
int>() < b.offset.cast<
int>();
528 list names, formats, offsets;
529 for (
auto& descr : field_descriptors) {
530 names.append(descr.name);
531 formats.append(descr.format);
532 offsets.append(descr.offset);
534 return dtype(names, formats, offsets, itemsize);
543 c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
544 f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
545 forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
548 array() :
array({{0}},
static_cast<const double *
>(
nullptr)) {}
557 if (strides->empty())
558 *strides = c_strides(*shape, dt.
itemsize());
560 auto ndim = shape->size();
561 if (ndim != strides->size())
562 pybind11_fail(
"NumPy: shape ndim doesn't match strides ndim");
567 if (isinstance<array>(
base))
569 flags = reinterpret_borrow<array>(
base).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
572 flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
575 auto &api = detail::npy_api::get();
576 auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
577 api.PyArray_Type_, descr.release().ptr(), (int) ndim, shape->data(), strides->data(),
578 const_cast<void *
>(ptr), flags,
nullptr));
583 api.PyArray_SetBaseObject_(tmp.ptr(),
base.inc_ref().ptr());
585 tmp = reinterpret_steal<object>(api.PyArray_NewCopy_(tmp.ptr(), -1 ));
588 m_ptr = tmp.release().ptr();
598 template <
typename T>
602 template <
typename T>
606 template <
typename T>
619 return std::accumulate(shape(), shape() + ndim(), (
ssize_t) 1, std::multiplies<ssize_t>());
650 fail_dim_check(dim,
"invalid axis");
662 fail_dim_check(dim,
"invalid axis");
663 return strides()[dim];
683 template<
typename... Ix>
const void*
data(Ix... index)
const {
698 if ((
ssize_t)
sizeof...(index) > ndim())
699 fail_dim_check(
sizeof...(index),
"too many indices for an array");
700 return byte_offset(
ssize_t(index)...);
718 if (Dims >= 0 && ndim() != Dims)
719 throw std::domain_error(
"array has incorrect number of dimensions: " +
std::to_string(ndim()) +
732 if (Dims >= 0 && ndim() != Dims)
733 throw std::domain_error(
"array has incorrect number of dimensions: " +
std::to_string(ndim()) +
740 auto& api = detail::npy_api::get();
741 return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
749 new_shape->data(), int(new_shape->size())
752 object new_array = reinterpret_steal<object>(
753 detail::npy_api::get().PyArray_Resize_(m_ptr, &d,
int(refcheck), -1)
756 if (isinstance<array>(new_array)) { *
this =
std::move(new_array); }
762 auto result = reinterpret_steal<array>(raw_array(h.
ptr(), ExtraFlags));
777 check_dimensions(index...);
783 throw std::domain_error(
"array is not writeable");
788 auto ndim = shape.size();
789 std::vector<ssize_t> strides(ndim, itemsize);
791 for (
size_t i = ndim - 1;
i > 0; --
i)
792 strides[
i - 1] = strides[
i] * shape[
i];
798 auto ndim = shape.size();
799 std::vector<ssize_t> strides(ndim, itemsize);
800 for (
size_t i = 1;
i < ndim; ++
i)
801 strides[
i] = strides[
i - 1] * shape[
i - 1];
817 check_dimensions_impl(axis + 1, shape + 1, index...);
821 static PyObject *
raw_array(PyObject *ptr,
int ExtraFlags = 0) {
822 if (ptr ==
nullptr) {
823 PyErr_SetString(PyExc_ValueError,
"cannot create a pybind11::array from a nullptr");
826 return detail::npy_api::get().PyArray_FromAny_(
827 ptr,
nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags,
nullptr);
831 template <
typename T,
int ExtraFlags = array::forcecast>
class array_t :
public array {
848 if (!m_ptr) PyErr_Clear();
849 if (!is_borrowed) Py_XDECREF(h.ptr());
862 : array_t(private_ctor{},
std::move(shape),
863 ExtraFlags & f_style ? f_strides(*shape,
itemsize()) : c_strides(*shape,
itemsize()),
866 explicit array_t(
size_t count,
const T *ptr =
nullptr,
handle base =
handle())
877 template<
typename... Ix>
const T*
data(Ix... index)
const {
878 return static_cast<const T*
>(
array::data(index...));
881 template<
typename... Ix> T* mutable_data(Ix... index) {
882 return static_cast<T*
>(array::mutable_data(index...));
886 template<
typename... Ix>
const T&
at(Ix... index)
const {
887 if ((
ssize_t)
sizeof...(index) != ndim())
888 fail_dim_check(
sizeof...(index),
"index dimension mismatch");
893 template<
typename... Ix> T& mutable_at(Ix... index) {
894 if ((
ssize_t)
sizeof...(index) != ndim())
895 fail_dim_check(
sizeof...(index),
"index dimension mismatch");
896 return *(
static_cast<T*
>(array::mutable_data()) + byte_offset(
ssize_t(index)...) /
itemsize());
906 return array::mutable_unchecked<T, Dims>();
917 return array::unchecked<T, Dims>();
923 auto result = reinterpret_steal<array_t>(raw_array_t(h.
ptr()));
930 const auto &api = detail::npy_api::get();
931 return api.PyArray_Check_(h.
ptr())
938 if (ptr ==
nullptr) {
939 PyErr_SetString(PyExc_ValueError,
"cannot create a pybind11::array_t from a nullptr");
942 return detail::npy_api::get().PyArray_FromAny_(
943 ptr, dtype::of<T>().
release().ptr(), 0, 0,
944 detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags,
nullptr);
948 template <
typename T>
962 template <
typename T>
970 template <
typename T>
973 using namespace detail;
974 static constexpr
auto extents =
_(
"(") + array_info<T>::extents +
_(
")");
980 template <
typename T,
int ExtraFlags>
985 if (!convert && !type::check_(src))
987 value = type::ensure(src);
988 return static_cast<bool>(
value);
997 template <
typename T>
1000 return npy_api::get().PyArray_EquivTypes_(dtype::of<T>().ptr(),
dtype(b).ptr());
1004 template <
typename T,
typename =
void>
1007 template <
typename T>
1014 template <
typename T>
1017 _(
"float") + _<sizeof(T)*8>(),
_(
"longdouble")
1021 template <
typename T>
1025 _(
"complex") + _<sizeof(typename T::value_type)*16>(),
_(
"longcomplex")
1029 template <
typename T>
1034 constexpr
static const int values[15] = {
1036 npy_api::NPY_BYTE_, npy_api::NPY_UBYTE_, npy_api::NPY_INT16_, npy_api::NPY_UINT16_,
1037 npy_api::NPY_INT32_, npy_api::NPY_UINT32_, npy_api::NPY_INT64_, npy_api::NPY_UINT64_,
1038 npy_api::NPY_FLOAT_, npy_api::NPY_DOUBLE_, npy_api::NPY_LONGDOUBLE_,
1039 npy_api::NPY_CFLOAT_, npy_api::NPY_CDOUBLE_, npy_api::NPY_CLONGDOUBLE_
1046 if (
auto ptr = npy_api::get().PyArray_DescrFromType_(value))
1047 return reinterpret_steal<pybind11::dtype>(ptr);
1048 pybind11_fail(
"Unsupported buffer format!");
1052 #define PYBIND11_DECL_CHAR_FMT \ 1053 static constexpr auto name = _("S") + _<N>(); \ 1054 static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); } 1057 #undef PYBIND11_DECL_CHAR_FMT 1077 static constexpr
auto name = base_descr::name;
1096 pybind11_fail(
"NumPy: dtype is already registered");
1100 std::vector<field_descriptor> ordered_fields(
std::move(fields));
1101 std::sort(ordered_fields.begin(), ordered_fields.end(),
1104 list names, formats, offsets;
1105 for (
auto& field : ordered_fields) {
1107 pybind11_fail(std::string(
"NumPy: unsupported field dtype: `") +
1108 field.name +
"` @ " + tinfo.name());
1110 formats.append(field.descr);
1123 std::ostringstream oss;
1130 for (
auto& field : ordered_fields) {
1131 if (field.offset > offset)
1132 oss << (field.offset - offset) <<
'x';
1133 oss << field.format <<
':' << field.name <<
':';
1134 offset = field.offset + field.size;
1136 if (itemsize > offset)
1137 oss << (itemsize - offset) <<
'x';
1139 auto format_str = oss.str();
1142 auto& api = npy_api::get();
1144 if (!api.PyArray_EquivTypes_(dtype_ptr,
arr.
dtype().
ptr()))
1145 pybind11_fail(
"NumPy: invalid buffer descriptor!");
1147 auto tindex = std::type_index(tinfo);
1153 static_assert(
is_pod_struct<T>::value,
"Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1158 return reinterpret_borrow<pybind11::dtype>(dtype_ptr());
1178 auto& api = npy_api::get();
1179 if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_))
1181 if (
auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1182 if (api.PyArray_EquivTypes_(dtype_ptr(),
descr.ptr())) {
1191 #ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code) 1192 # define PYBIND11_NUMPY_DTYPE(Type, ...) ((void)0) 1193 # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void)0) 1196 #define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \ 1197 ::pybind11::detail::field_descriptor { \ 1198 Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \ 1199 ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \ 1200 ::pybind11::detail::npy_format_descriptor<decltype(std::declval<T>().Field)>::dtype() \ 1204 #define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, #Field) 1208 #define PYBIND11_EVAL0(...) __VA_ARGS__ 1209 #define PYBIND11_EVAL1(...) PYBIND11_EVAL0 (PYBIND11_EVAL0 (PYBIND11_EVAL0 (__VA_ARGS__))) 1210 #define PYBIND11_EVAL2(...) PYBIND11_EVAL1 (PYBIND11_EVAL1 (PYBIND11_EVAL1 (__VA_ARGS__))) 1211 #define PYBIND11_EVAL3(...) PYBIND11_EVAL2 (PYBIND11_EVAL2 (PYBIND11_EVAL2 (__VA_ARGS__))) 1212 #define PYBIND11_EVAL4(...) PYBIND11_EVAL3 (PYBIND11_EVAL3 (PYBIND11_EVAL3 (__VA_ARGS__))) 1213 #define PYBIND11_EVAL(...) PYBIND11_EVAL4 (PYBIND11_EVAL4 (PYBIND11_EVAL4 (__VA_ARGS__))) 1214 #define PYBIND11_MAP_END(...) 1215 #define PYBIND11_MAP_OUT 1216 #define PYBIND11_MAP_COMMA , 1217 #define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END 1218 #define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT 1219 #define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0 (test, next, 0) 1220 #define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1 (PYBIND11_MAP_GET_END test, next) 1221 #ifdef _MSC_VER // MSVC is not as eager to expand macros, hence this workaround 1222 #define PYBIND11_MAP_LIST_NEXT1(test, next) \ 1223 PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)) 1225 #define PYBIND11_MAP_LIST_NEXT1(test, next) \ 1226 PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0) 1228 #define PYBIND11_MAP_LIST_NEXT(test, next) \ 1229 PYBIND11_MAP_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next) 1230 #define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \ 1231 f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST1) (f, t, peek, __VA_ARGS__) 1232 #define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \ 1233 f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST0) (f, t, peek, __VA_ARGS__) 1235 #define PYBIND11_MAP_LIST(f, t, ...) \ 1236 PYBIND11_EVAL (PYBIND11_MAP_LIST1 (f, t, __VA_ARGS__, (), 0)) 1238 #define PYBIND11_NUMPY_DTYPE(Type, ...) \ 1239 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \ 1240 (::std::vector<::pybind11::detail::field_descriptor> \ 1241 {PYBIND11_MAP_LIST (PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)}) 1244 #define PYBIND11_MAP2_LIST_NEXT1(test, next) \ 1245 PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)) 1247 #define PYBIND11_MAP2_LIST_NEXT1(test, next) \ 1248 PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0) 1250 #define PYBIND11_MAP2_LIST_NEXT(test, next) \ 1251 PYBIND11_MAP2_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next) 1252 #define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \ 1253 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST1) (f, t, peek, __VA_ARGS__) 1254 #define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \ 1255 f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST0) (f, t, peek, __VA_ARGS__) 1257 #define PYBIND11_MAP2_LIST(f, t, ...) \ 1258 PYBIND11_EVAL (PYBIND11_MAP2_LIST1 (f, t, __VA_ARGS__, (), 0)) 1260 #define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \ 1261 ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \ 1262 (::std::vector<::pybind11::detail::field_descriptor> \ 1263 {PYBIND11_MAP2_LIST (PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)}) 1265 #endif // __CLION_IDE__ 1289 : p_ptr(reinterpret_cast<char*>(ptr)), m_strides(strides.
size()) {
1290 m_strides.back() =
static_cast<value_type>(strides.back());
1291 for (
size_type i = m_strides.size() - 1;
i != 0; --
i) {
1294 m_strides[j] = strides[j] + m_strides[
i] - strides[
i] * s;
1299 p_ptr += m_strides[dim];
1317 : m_shape(shape.
size()), m_index(shape.
size(), 0),
1318 m_common_iterator() {
1321 for (
size_t i = 0;
i < shape.size(); ++
i)
1322 m_shape[
i] = shape[
i];
1325 for (
size_t i = 0;
i < N; ++
i)
1326 init_common_iterator(buffers[
i], shape, m_common_iterator[i], strides);
1330 for (
size_t j = m_index.size(); j != 0; --j) {
1332 if (++m_index[i] != m_shape[i]) {
1333 increment_common_iterator(i);
1342 template <
size_t K,
class T =
void> T*
data()
const {
1343 return reinterpret_cast<T*
>(m_common_iterator[K].data());
1354 auto buffer_shape_iter = buffer.
shape.rbegin();
1355 auto buffer_strides_iter = buffer.
strides.rbegin();
1356 auto shape_iter = shape.rbegin();
1357 auto strides_iter = strides.rbegin();
1359 while (buffer_shape_iter != buffer.
shape.rend()) {
1360 if (*shape_iter == *buffer_shape_iter)
1361 *strides_iter = *buffer_strides_iter;
1365 ++buffer_shape_iter;
1366 ++buffer_strides_iter;
1371 std::fill(strides_iter, strides.rend(), 0);
1376 for (
auto &
iter : m_common_iterator)
1377 iter.increment(dim);
1394 return std::max(res, buf.ndim);
1398 shape.resize((
size_t) ndim, 1);
1402 for (
size_t i = 0;
i < N; ++
i) {
1403 auto res_iter = shape.rbegin();
1404 auto end = buffers[
i].shape.rend();
1405 for (
auto shape_iter = buffers[
i].shape.rbegin(); shape_iter !=
end; ++shape_iter, ++res_iter) {
1406 const auto &dim_size_in = *shape_iter;
1407 auto &dim_size_out = *res_iter;
1410 if (dim_size_out == 1)
1411 dim_size_out = dim_size_in;
1412 else if (dim_size_in != 1 && dim_size_in != dim_size_out)
1413 pybind11_fail(
"pybind11::vectorize: incompatible size/dimension of inputs!");
1417 bool trivial_broadcast_c =
true;
1418 bool trivial_broadcast_f =
true;
1419 for (
size_t i = 0;
i < N && (trivial_broadcast_c || trivial_broadcast_f); ++
i) {
1420 if (buffers[
i].
size == 1)
1424 if (buffers[
i].ndim != ndim)
1425 return broadcast_trivial::non_trivial;
1428 if (!std::equal(buffers[
i].shape.cbegin(), buffers[
i].shape.cend(), shape.cbegin()))
1429 return broadcast_trivial::non_trivial;
1432 if (trivial_broadcast_c) {
1433 ssize_t expect_stride = buffers[
i].itemsize;
1434 auto end = buffers[
i].shape.crend();
1435 for (
auto shape_iter = buffers[
i].shape.crbegin(), stride_iter = buffers[
i].strides.crbegin();
1436 trivial_broadcast_c && shape_iter !=
end; ++shape_iter, ++stride_iter) {
1437 if (expect_stride == *stride_iter)
1438 expect_stride *= *shape_iter;
1440 trivial_broadcast_c =
false;
1445 if (trivial_broadcast_f) {
1446 ssize_t expect_stride = buffers[
i].itemsize;
1447 auto end = buffers[
i].shape.cend();
1448 for (
auto shape_iter = buffers[
i].shape.cbegin(), stride_iter = buffers[
i].strides.cbegin();
1449 trivial_broadcast_f && shape_iter !=
end; ++shape_iter, ++stride_iter) {
1450 if (expect_stride == *stride_iter)
1451 expect_stride *= *shape_iter;
1453 trivial_broadcast_f =
false;
1459 trivial_broadcast_c ? broadcast_trivial::c_trivial :
1460 trivial_broadcast_f ? broadcast_trivial::f_trivial :
1461 broadcast_trivial::non_trivial;
1464 template <
typename T>
1479 template <
typename Func,
typename Return,
typename... Args>
1482 static constexpr
size_t N =
sizeof...(Args);
1484 static_assert(NVectorized >= 1,
1485 "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1488 template <
typename T>
1513 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
object run(
1520 std::array<void *, N> params{{ &args... }};
1523 std::array<buffer_info, NVectorized>
buffers{{
reinterpret_cast<array *
>(params[VIndex])->request()... }};
1527 std::vector<ssize_t> shape(0);
1529 size_t ndim = (
size_t) nd;
1531 size_t size = std::accumulate(shape.begin(), shape.end(), (
size_t) 1, std::multiplies<size_t>());
1535 if (size == 1 && ndim == 0) {
1544 if (size == 0)
return std::move(result);
1547 if (trivial == broadcast_trivial::non_trivial)
1548 apply_broadcast(
buffers, params, result, i_seq, vi_seq, bi_seq);
1555 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
1557 std::array<void *, N> ¶ms,
1565 std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{{
1566 std::pair<unsigned char *&, const size_t>(
1567 reinterpret_cast<unsigned char *&
>(params[VIndex] = buffers[BIndex].ptr),
1572 for (
size_t i = 0;
i <
size; ++
i) {
1574 for (
auto &
x : vecparams)
x.first +=
x.second;
1578 template <
size_t... Index,
size_t... VIndex,
size_t... BIndex>
1580 std::array<void *, N> ¶ms,
1589 ++
iter, ++input_iter) {
1591 params[VIndex] = input_iter.template data<BIndex>()
1598 template <
typename Func,
typename Return,
typename... Args>
1611 template <
typename Return,
typename... Args>
1625 template <
typename Return,
typename Class,
typename... Args,
1626 typename Helper =
detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())), Return, Class *, Args...>>
1628 return Helper(std::mem_fn(f));
1632 template <
typename Return,
typename Class,
typename... Args,
1633 typename Helper =
detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)
const>())), Return,
const Class *, Args...>>
1634 Helper
vectorize(Return (Class::*f)(Args...)
const) {
1635 return Helper(std::mem_fn(f));
1640 #if defined(_MSC_VER) 1641 #pragma warning(pop) enable_if_t< Dyn, ssize_t > size() const
void * mutable_data(Ix... index)
static dtype of()
Return dtype associated with a C++ type.
void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const
array_t(handle h, stolen_t)
ssize_t index_at(Ix... index) const
object operator()(typename vectorize_arg< Args >::type... args)
void increment_common_iterator(size_t dim)
PyArrayDescr_Proxy * descr
typename std::add_pointer< T >::type array_iterator
const ssize_t * strides() const
Strides of the array.
#define PYBIND11_NAMESPACE
std::tuple< typename vectorize_arg< Args >::call_type... > arg_call_types
dtype(const std::string &format)
PyObject * ptr() const
Return the underlying PyObject * pointer.
ssize_t shape(ssize_t dim) const
Dimension along a given axis.
typename select_indices_impl< index_sequence<>, 0, Bs... >::type select_indices
object run(typename vectorize_arg< Args >::type &...args, index_sequence< Index... > i_seq, index_sequence< VIndex... > vi_seq, index_sequence< BIndex... > bi_seq)
T * mutable_data(Ix... ix)
Mutable pointer access to the data at the given indices.
array(const buffer_info &info)
array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base)
glibc defines I as a macro which breaks things, e.g., boost template names
static std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
static bool check_(handle h)
#define DECL_NPY_API(Func)
char kind() const
Single-character type code.
object operator()(Args &&...args) const
std::vector< ssize_t > container_type
const std::type_info ssize_t bool(* direct_converter)(PyObject *, void *&))
T & operator[](ssize_t index)
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
static dtype from_args(object args)
This is essentially the same as calling numpy.dtype(args) in Python.
static object _dtype_from_pep3118()
PyObject_HEAD char * data
detail::unchecked_mutable_reference< T, Dims > mutable_unchecked() &
array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, const void *ptr=nullptr, handle base=handle())
void increment(size_type dim)
array(ssize_t count, const T *ptr, handle base=handle())
const PyArrayDescr_Proxy * array_descriptor_proxy(const PyObject *ptr)
ssize_t itemsize() const
Byte size of a single element.
void fail_dim_check(ssize_t dim, const std::string &msg) const
ssize_t offset_at(const arr &a, Ix... idx)
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > &>(), fmt, tp), std::basic_string< CharT >
std::vector< ssize_t > strides
pybind11::dtype dtype() const
Array descriptor (dtype)
constexpr descr< N - 1 > _(char const(&text)[N])
arr data(const arr &a, Ix... index)
detail::unchecked_reference< T, Dims > unchecked() const &
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun)
PyTypeObject * PyArrayDescr_Type_
ssize_t offset_at(Ix... index) const
Information record describing a Python buffer object.
typename std::tuple_element< Index, arg_call_types >::type param_n_t
Wrapper for Python extension modules.
std::vector< ssize_t > shape
#define PYBIND11_NOINLINE
typename std::enable_if< B, T >::type enable_if_t
ssize_t strides(ssize_t dim) const
Stride along a given axis.
bool Dims mutable_unchecked() &
enable_if_t<!Dyn, ssize_t > size() const
Returns the total number of elements in the referenced array, i.e. the product of the shapes...
obj_attr_accessor attr(handle key) const
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
dtype(const char *format)
PyTypeObject * PyArray_Type_
bool has_fields() const
Returns true for structured data types.
ssize_t nbytes() const
Total number of bytes.
conditional_t< Dynamic, const ssize_t *, std::array< ssize_t,(size_t) Dims > > strides_
const void * data(Ix... index) const
ssize_t byte_offset(Ix... index) const
op_< op_int, op_u, self_t, undefined_t > int_(const self_t &)
ssize_t itemsize() const
Size of the data type in bytes.
conditional_t< vectorize, array_t< remove_cv_t< call_type >, array::forcecast >, T > type
const T * data(Ix... ix) const
Pointer access to the data at the given indices.
#define NAMESPACE_END(name)
dtype strip_padding(ssize_t itemsize)
const T & operator()(Ix... index) const
Helper vectorize(Return(Class::*f)(Args...))
void resize(ShapeContainer new_shape, bool refcheck=true)
std::unordered_map< std::type_index, numpy_type_info > registered_dtypes
void apply_trivial(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > ¶ms, Return *out, size_t size, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
object base() const
Base object.
static PyObject * raw_array_t(PyObject *ptr)
Create array from any object – always returns a new reference.
unsigned int(* PyArray_GetNDArrayCFeatureVersion_)()
array(ShapeContainer shape, const T *ptr, handle base=handle())
dtype(list names, list formats, list offsets, ssize_t itemsize)
remove_reference_t< T > call_type
ssize_t offset_at() const
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun)
const unsigned char * data_
numpy_type_info * get_type_info(bool throw_if_missing=true)
#define PYBIND11_DECL_CHAR_FMT
const std::type_info ssize_t itemsize
remove_reference_t< Func > f
#define PYBIND11_STR_TYPE
void check_writeable() const
common_iterator(void *ptr, const container_type &strides, const container_type &shape)
ssize_t ndim() const
Number of dimensions.
vectorize_helper< Func, Return, Args... > vectorize_extractor(const Func &f, Return(*)(Args ...))
ssize_t shape(ssize_t dim) const
Returns the shape (i.e. size) of dimension dim
typename make_index_sequence_impl< N >::type make_index_sequence
container_type::value_type value_type
#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN)
constexpr size_t constexpr_sum()
Compile-time integer sum.
dtype(const buffer_info &info)
PyObject_VAR_HEAD char * obval
const x_value & at(const std::map< x_key, x_value > &a_map, const x_key &a_key, const x_value &a_default)
std::vector< ssize_t > container_type
void init_common_iterator(const buffer_info &buffer, const container_type &shape, common_iter &iterator, container_type &strides)
typename std::remove_reference< T >::type remove_reference_t
ssize_t index_at(const arr &a, Ix... idx)
array(const pybind11::dtype &dt, T count, const void *ptr=nullptr, handle base=handle())
PyTypeObject * PyVoidArrType_Type_
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t >)
void apply_broadcast(std::array< buffer_info, NVectorized > &buffers, std::array< void *, N > ¶ms, array_t< Return > &output_array, index_sequence< Index... >, index_sequence< VIndex... >, index_sequence< BIndex... >)
array_iterator< T > array_end(const buffer_info &buffer)
typename std::conditional< B, T, F >::type conditional_t
static PyObject * raw_array(PyObject *ptr, int ExtraFlags=0)
Create array from any object – always returns a new reference.
void check_dimensions_impl(ssize_t, const ssize_t *) const
bool PyArray_Check_(PyObject *obj) const
container_type::size_type size_type
const T & operator[](ssize_t index) const
array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr=nullptr, handle base=handle())
bool_constant< sizeof(T)==sizeof(U)> as
std::array< common_iter, N > m_common_iterator
ssize_t ndim() const
Returns the number of dimensions of the array.
array_iterator< T > array_begin(const buffer_info &buffer)
test_initializer buffers("buffers", test_submodule_buffers)
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers. ...
multi_array_iterator(const std::array< buffer_info, N > &buffers, const container_type &shape)
Annotation indicating that a class derives from another given type.
static array_t ensure(handle h)
const detail::type_info * type
Annotation for function names.
unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t< Dyn, ssize_t > dims)
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
int flags() const
Return the NumPy array flags.
bool check_flags(const void *ptr, int flag)
array squeeze()
Return a new view with all of the dimensions of length 1 removed.
#define PYBIND11_DEPRECATED(reason)
detail::unchecked_reference< T, Dims > unchecked() const &
ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index)
static std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
static void append_extents(list &)
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
array_t(handle h, borrowed_t)
#define NAMESPACE_BEGIN(name)
iterator iter(handle obj)
T & operator()(Ix... index)
Mutable, unchecked access to data at the given indices.
T cast(const handle &handle)
static bool compare(const buffer_info &b)
static void append_extents(list &shape)
numpy_internals & get_numpy_internals()
const ssize_t * shape() const
Dimensions of the array.
broadcast_trivial broadcast(const std::array< buffer_info, N > &buffers, ssize_t &ndim, std::vector< ssize_t > &shape)
constexpr int platform_lookup(Int... codes)
conditional_t< std::is_function< F >::value, F, typename conditional_t< std::is_pointer< F >::value||std::is_member_pointer< F >::value, std::remove_pointer< F >, strip_function_object< F > >::type > function_signature_t
ssize_t size() const
Total number of elements.
PyObject_HEAD PyObject * typeobj
const PyArray_Proxy * array_proxy(const void *ptr)
array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base=handle())
const std::type_info & tinfo
#define PYBIND11_TYPE_CASTER(type, py_name)
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
bool PyArrayDescr_Check_(PyObject *obj) const
const handle & inc_ref() const &
typename array_info< T >::type remove_all_extents_t
auto to_string(T &&value) -> decltype(std::forward< T >(value))
Convert an object to a string (directly forward if this can become a string)
static constexpr ssize_t itemsize()
Returns the item size, i.e. sizeof(T)
void check_dimensions(Ix... index) const
typename array_info< T >::type type
constexpr descr< 0 > concat()
numpy_type_info * get_type_info(const std::type_info &tinfo, bool throw_if_missing=true)
bool owndata() const
If set, the array owns the data (will be freed when the array is deleted)
static array ensure(handle h, int ExtraFlags=0)
multi_array_iterator & operator++()