Warning, file /jana2/src/python/externals/pybind11-2.10.3/include/pybind11/eigen/tensor.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "../numpy.h"
0011
0012 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
0013 static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");
0014 #endif
0015
0016
0017 PYBIND11_WARNING_PUSH
0018 PYBIND11_WARNING_DISABLE_MSVC(4554)
0019 PYBIND11_WARNING_DISABLE_MSVC(4127)
0020 PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
0021
0022 #include <unsupported/Eigen/CXX11/Tensor>
0023
0024 PYBIND11_WARNING_POP
0025
0026 static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
0027 "Eigen Tensor support in pybind11 requires Eigen >= 3.3.0");
0028
0029 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0030
0031 PYBIND11_WARNING_DISABLE_MSVC(4127)
0032
0033 PYBIND11_NAMESPACE_BEGIN(detail)
0034
0035 inline bool is_tensor_aligned(const void *data) {
0036 return (reinterpret_cast<std::size_t>(data) % EIGEN_DEFAULT_ALIGN_BYTES) == 0;
0037 }
0038
0039 template <typename T>
0040 constexpr int compute_array_flag_from_tensor() {
0041 static_assert((static_cast<int>(T::Layout) == static_cast<int>(Eigen::RowMajor))
0042 || (static_cast<int>(T::Layout) == static_cast<int>(Eigen::ColMajor)),
0043 "Layout must be row or column major");
0044 return (static_cast<int>(T::Layout) == static_cast<int>(Eigen::RowMajor)) ? array::c_style
0045 : array::f_style;
0046 }
0047
0048 template <typename T>
0049 struct eigen_tensor_helper {};
0050
0051 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType>
0052 struct eigen_tensor_helper<Eigen::Tensor<Scalar_, NumIndices_, Options_, IndexType>> {
0053 using Type = Eigen::Tensor<Scalar_, NumIndices_, Options_, IndexType>;
0054 using ValidType = void;
0055
0056 static Eigen::DSizes<typename Type::Index, Type::NumIndices> get_shape(const Type &f) {
0057 return f.dimensions();
0058 }
0059
0060 static constexpr bool
0061 is_correct_shape(const Eigen::DSizes<typename Type::Index, Type::NumIndices> & ) {
0062 return true;
0063 }
0064
0065 template <typename T>
0066 struct helper {};
0067
0068 template <size_t... Is>
0069 struct helper<index_sequence<Is...>> {
0070 static constexpr auto value = concat(const_name(((void) Is, "?"))...);
0071 };
0072
0073 static constexpr auto dimensions_descriptor
0074 = helper<decltype(make_index_sequence<Type::NumIndices>())>::value;
0075
0076 template <typename... Args>
0077 static Type *alloc(Args &&...args) {
0078 return new Type(std::forward<Args>(args)...);
0079 }
0080
0081 static void free(Type *tensor) { delete tensor; }
0082 };
0083
0084 template <typename Scalar_, typename std::ptrdiff_t... Indices, int Options_, typename IndexType>
0085 struct eigen_tensor_helper<
0086 Eigen::TensorFixedSize<Scalar_, Eigen::Sizes<Indices...>, Options_, IndexType>> {
0087 using Type = Eigen::TensorFixedSize<Scalar_, Eigen::Sizes<Indices...>, Options_, IndexType>;
0088 using ValidType = void;
0089
0090 static constexpr Eigen::DSizes<typename Type::Index, Type::NumIndices>
0091 get_shape(const Type & ) {
0092 return get_shape();
0093 }
0094
0095 static constexpr Eigen::DSizes<typename Type::Index, Type::NumIndices> get_shape() {
0096 return Eigen::DSizes<typename Type::Index, Type::NumIndices>(Indices...);
0097 }
0098
0099 static bool
0100 is_correct_shape(const Eigen::DSizes<typename Type::Index, Type::NumIndices> &shape) {
0101 return get_shape() == shape;
0102 }
0103
0104 static constexpr auto dimensions_descriptor = concat(const_name<Indices>()...);
0105
0106 template <typename... Args>
0107 static Type *alloc(Args &&...args) {
0108 Eigen::aligned_allocator<Type> allocator;
0109 return ::new (allocator.allocate(1)) Type(std::forward<Args>(args)...);
0110 }
0111
0112 static void free(Type *tensor) {
0113 Eigen::aligned_allocator<Type> allocator;
0114 tensor->~Type();
0115 allocator.deallocate(tensor, 1);
0116 }
0117 };
0118
0119 template <typename Type, bool ShowDetails, bool NeedsWriteable = false>
0120 struct get_tensor_descriptor {
0121 static constexpr auto details
0122 = const_name<NeedsWriteable>(", flags.writeable", "")
0123 + const_name<static_cast<int>(Type::Layout) == static_cast<int>(Eigen::RowMajor)>(
0124 ", flags.c_contiguous", ", flags.f_contiguous");
0125 static constexpr auto value
0126 = const_name("numpy.ndarray[") + npy_format_descriptor<typename Type::Scalar>::name
0127 + const_name("[") + eigen_tensor_helper<remove_cv_t<Type>>::dimensions_descriptor
0128 + const_name("]") + const_name<ShowDetails>(details, const_name("")) + const_name("]");
0129 };
0130
0131
0132
0133
0134
0135
0136 PYBIND11_WARNING_PUSH
0137 PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits")
0138
0139 template <typename T, int size>
0140 std::vector<T> convert_dsizes_to_vector(const Eigen::DSizes<T, size> &arr) {
0141 std::vector<T> result(size);
0142
0143 for (size_t i = 0; i < size; i++) {
0144 result[i] = arr[i];
0145 }
0146
0147 return result;
0148 }
0149
0150 template <typename T, int size>
0151 Eigen::DSizes<T, size> get_shape_for_array(const array &arr) {
0152 Eigen::DSizes<T, size> result;
0153 const T *shape = arr.shape();
0154 for (size_t i = 0; i < size; i++) {
0155 result[i] = shape[i];
0156 }
0157
0158 return result;
0159 }
0160
0161 PYBIND11_WARNING_POP
0162
0163 template <typename Type>
0164 struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
0165 using Helper = eigen_tensor_helper<Type>;
0166 static constexpr auto temp_name = get_tensor_descriptor<Type, false>::value;
0167 PYBIND11_TYPE_CASTER(Type, temp_name);
0168
0169 bool load(handle src, bool convert) {
0170 if (!convert) {
0171 if (!isinstance<array>(src)) {
0172 return false;
0173 }
0174 array temp = array::ensure(src);
0175 if (!temp) {
0176 return false;
0177 }
0178
0179 if (!temp.dtype().is(dtype::of<typename Type::Scalar>())) {
0180 return false;
0181 }
0182 }
0183
0184 array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()> arr(
0185 reinterpret_borrow<object>(src));
0186
0187 if (arr.ndim() != Type::NumIndices) {
0188 return false;
0189 }
0190 auto shape = get_shape_for_array<typename Type::Index, Type::NumIndices>(arr);
0191
0192 if (!Helper::is_correct_shape(shape)) {
0193 return false;
0194 }
0195
0196 #if EIGEN_VERSION_AT_LEAST(3, 4, 0)
0197 auto data_pointer = arr.data();
0198 #else
0199
0200 auto data_pointer = const_cast<typename Type::Scalar *>(arr.data());
0201 #endif
0202
0203 if (is_tensor_aligned(arr.data())) {
0204 value = Eigen::TensorMap<const Type, Eigen::Aligned>(data_pointer, shape);
0205 } else {
0206 value = Eigen::TensorMap<const Type>(data_pointer, shape);
0207 }
0208
0209 return true;
0210 }
0211
0212 static handle cast(Type &&src, return_value_policy policy, handle parent) {
0213 if (policy == return_value_policy::reference
0214 || policy == return_value_policy::reference_internal) {
0215 pybind11_fail("Cannot use a reference return value policy for an rvalue");
0216 }
0217 return cast_impl(&src, return_value_policy::move, parent);
0218 }
0219
0220 static handle cast(const Type &&src, return_value_policy policy, handle parent) {
0221 if (policy == return_value_policy::reference
0222 || policy == return_value_policy::reference_internal) {
0223 pybind11_fail("Cannot use a reference return value policy for an rvalue");
0224 }
0225 return cast_impl(&src, return_value_policy::move, parent);
0226 }
0227
0228 static handle cast(Type &src, return_value_policy policy, handle parent) {
0229 if (policy == return_value_policy::automatic
0230 || policy == return_value_policy::automatic_reference) {
0231 policy = return_value_policy::copy;
0232 }
0233 return cast_impl(&src, policy, parent);
0234 }
0235
0236 static handle cast(const Type &src, return_value_policy policy, handle parent) {
0237 if (policy == return_value_policy::automatic
0238 || policy == return_value_policy::automatic_reference) {
0239 policy = return_value_policy::copy;
0240 }
0241 return cast(&src, policy, parent);
0242 }
0243
0244 static handle cast(Type *src, return_value_policy policy, handle parent) {
0245 if (policy == return_value_policy::automatic) {
0246 policy = return_value_policy::take_ownership;
0247 } else if (policy == return_value_policy::automatic_reference) {
0248 policy = return_value_policy::reference;
0249 }
0250 return cast_impl(src, policy, parent);
0251 }
0252
0253 static handle cast(const Type *src, return_value_policy policy, handle parent) {
0254 if (policy == return_value_policy::automatic) {
0255 policy = return_value_policy::take_ownership;
0256 } else if (policy == return_value_policy::automatic_reference) {
0257 policy = return_value_policy::reference;
0258 }
0259 return cast_impl(src, policy, parent);
0260 }
0261
0262 template <typename C>
0263 static handle cast_impl(C *src, return_value_policy policy, handle parent) {
0264 object parent_object;
0265 bool writeable = false;
0266 switch (policy) {
0267 case return_value_policy::move:
0268 if (std::is_const<C>::value) {
0269 pybind11_fail("Cannot move from a constant reference");
0270 }
0271
0272 src = Helper::alloc(std::move(*src));
0273
0274 parent_object
0275 = capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
0276 writeable = true;
0277 break;
0278
0279 case return_value_policy::take_ownership:
0280 if (std::is_const<C>::value) {
0281
0282
0283 Helper::free(const_cast<Type *>(src));
0284 pybind11_fail("Cannot take ownership of a const reference");
0285 }
0286
0287 parent_object
0288 = capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
0289 writeable = true;
0290 break;
0291
0292 case return_value_policy::copy:
0293 writeable = true;
0294 break;
0295
0296 case return_value_policy::reference:
0297 parent_object = none();
0298 writeable = !std::is_const<C>::value;
0299 break;
0300
0301 case return_value_policy::reference_internal:
0302
0303 if (!parent) {
0304 pybind11_fail("Cannot use reference internal when there is no parent");
0305 }
0306 parent_object = reinterpret_borrow<object>(parent);
0307 writeable = !std::is_const<C>::value;
0308 break;
0309
0310 default:
0311 pybind11_fail("pybind11 bug in eigen.h, please file a bug report");
0312 }
0313
0314 auto result = array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()>(
0315 convert_dsizes_to_vector(Helper::get_shape(*src)), src->data(), parent_object);
0316
0317 if (!writeable) {
0318 array_proxy(result.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
0319 }
0320
0321 return result.release();
0322 }
0323 };
0324
0325 template <typename StoragePointerType,
0326 bool needs_writeable,
0327 enable_if_t<!needs_writeable, bool> = true>
0328 StoragePointerType get_array_data_for_type(array &arr) {
0329 #if EIGEN_VERSION_AT_LEAST(3, 4, 0)
0330 return reinterpret_cast<StoragePointerType>(arr.data());
0331 #else
0332
0333 return reinterpret_cast<StoragePointerType>(const_cast<void *>(arr.data()));
0334 #endif
0335 }
0336
0337 template <typename StoragePointerType,
0338 bool needs_writeable,
0339 enable_if_t<needs_writeable, bool> = true>
0340 StoragePointerType get_array_data_for_type(array &arr) {
0341 return reinterpret_cast<StoragePointerType>(arr.mutable_data());
0342 }
0343
0344 template <typename T, typename = void>
0345 struct get_storage_pointer_type;
0346
0347 template <typename MapType>
0348 struct get_storage_pointer_type<MapType, void_t<typename MapType::StoragePointerType>> {
0349 using SPT = typename MapType::StoragePointerType;
0350 };
0351
0352 template <typename MapType>
0353 struct get_storage_pointer_type<MapType, void_t<typename MapType::PointerArgType>> {
0354 using SPT = typename MapType::PointerArgType;
0355 };
0356
0357 template <typename Type, int Options>
0358 struct type_caster<Eigen::TensorMap<Type, Options>,
0359 typename eigen_tensor_helper<remove_cv_t<Type>>::ValidType> {
0360 using MapType = Eigen::TensorMap<Type, Options>;
0361 using Helper = eigen_tensor_helper<remove_cv_t<Type>>;
0362
0363 bool load(handle src, bool ) {
0364
0365 if (!isinstance<array>(src)) {
0366 return false;
0367 }
0368 auto arr = reinterpret_borrow<array>(src);
0369 if ((arr.flags() & compute_array_flag_from_tensor<Type>()) == 0) {
0370 return false;
0371 }
0372
0373 if (!arr.dtype().is(dtype::of<typename Type::Scalar>())) {
0374 return false;
0375 }
0376
0377 if (arr.ndim() != Type::NumIndices) {
0378 return false;
0379 }
0380
0381 constexpr bool is_aligned = (Options & Eigen::Aligned) != 0;
0382
0383 if (is_aligned && !is_tensor_aligned(arr.data())) {
0384 return false;
0385 }
0386
0387 auto shape = get_shape_for_array<typename Type::Index, Type::NumIndices>(arr);
0388
0389 if (!Helper::is_correct_shape(shape)) {
0390 return false;
0391 }
0392
0393 if (needs_writeable && !arr.writeable()) {
0394 return false;
0395 }
0396
0397 auto result = get_array_data_for_type<typename get_storage_pointer_type<MapType>::SPT,
0398 needs_writeable>(arr);
0399
0400 value.reset(new MapType(std::move(result), std::move(shape)));
0401
0402 return true;
0403 }
0404
0405 static handle cast(MapType &&src, return_value_policy policy, handle parent) {
0406 return cast_impl(&src, policy, parent);
0407 }
0408
0409 static handle cast(const MapType &&src, return_value_policy policy, handle parent) {
0410 return cast_impl(&src, policy, parent);
0411 }
0412
0413 static handle cast(MapType &src, return_value_policy policy, handle parent) {
0414 if (policy == return_value_policy::automatic
0415 || policy == return_value_policy::automatic_reference) {
0416 policy = return_value_policy::copy;
0417 }
0418 return cast_impl(&src, policy, parent);
0419 }
0420
0421 static handle cast(const MapType &src, return_value_policy policy, handle parent) {
0422 if (policy == return_value_policy::automatic
0423 || policy == return_value_policy::automatic_reference) {
0424 policy = return_value_policy::copy;
0425 }
0426 return cast(&src, policy, parent);
0427 }
0428
0429 static handle cast(MapType *src, return_value_policy policy, handle parent) {
0430 if (policy == return_value_policy::automatic) {
0431 policy = return_value_policy::take_ownership;
0432 } else if (policy == return_value_policy::automatic_reference) {
0433 policy = return_value_policy::reference;
0434 }
0435 return cast_impl(src, policy, parent);
0436 }
0437
0438 static handle cast(const MapType *src, return_value_policy policy, handle parent) {
0439 if (policy == return_value_policy::automatic) {
0440 policy = return_value_policy::take_ownership;
0441 } else if (policy == return_value_policy::automatic_reference) {
0442 policy = return_value_policy::reference;
0443 }
0444 return cast_impl(src, policy, parent);
0445 }
0446
0447 template <typename C>
0448 static handle cast_impl(C *src, return_value_policy policy, handle parent) {
0449 object parent_object;
0450 constexpr bool writeable = !std::is_const<C>::value;
0451 switch (policy) {
0452 case return_value_policy::reference:
0453 parent_object = none();
0454 break;
0455
0456 case return_value_policy::reference_internal:
0457
0458 if (!parent) {
0459 pybind11_fail("Cannot use reference internal when there is no parent");
0460 }
0461 parent_object = reinterpret_borrow<object>(parent);
0462 break;
0463
0464 case return_value_policy::take_ownership:
0465 delete src;
0466
0467 default:
0468
0469 pybind11_fail("Invalid return_value_policy for Eigen Map type, must be either "
0470 "reference or reference_internal");
0471 }
0472
0473 auto result = array_t<typename Type::Scalar, compute_array_flag_from_tensor<Type>()>(
0474 convert_dsizes_to_vector(Helper::get_shape(*src)),
0475 src->data(),
0476 std::move(parent_object));
0477
0478 if (!writeable) {
0479 array_proxy(result.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
0480 }
0481
0482 return result.release();
0483 }
0484
0485 #if EIGEN_VERSION_AT_LEAST(3, 4, 0)
0486
0487 static constexpr bool needs_writeable = !std::is_const<typename std::remove_pointer<
0488 typename get_storage_pointer_type<MapType>::SPT>::type>::value;
0489 #else
0490
0491 static constexpr bool needs_writeable = !std::is_const<Type>::value;
0492 #endif
0493
0494 protected:
0495
0496 std::unique_ptr<MapType> value;
0497
0498 public:
0499 static constexpr auto name = get_tensor_descriptor<Type, true, needs_writeable>::value;
0500 explicit operator MapType *() { return value.get(); }
0501 explicit operator MapType &() { return *value; }
0502 explicit operator MapType &&() && { return std::move(*value); }
0503
0504 template <typename T_>
0505 using cast_op_type = ::pybind11::detail::movable_cast_op_type<T_>;
0506 };
0507
0508 PYBIND11_NAMESPACE_END(detail)
0509 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)