μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
eigen.h
Go to the documentation of this file.
1/*
2 pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices
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/* HINT: To suppress warnings originating from the Eigen headers, use -isystem.
13 See also:
14 https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir
15 https://stackoverflow.com/questions/1741816/isystem-for-ms-visual-studio-c-compiler
16*/
17
18#include "numpy.h"
19
20// The C4127 suppression was introduced for Eigen 3.4.0. In theory we could
21// make it version specific, or even remove it later, but considering that
22// 1. C4127 is generally far more distracting than useful for modern template code, and
23// 2. we definitely want to ignore any MSVC warnings originating from Eigen code,
24// it is probably best to keep this around indefinitely.
25#if defined(_MSC_VER)
26# pragma warning(push)
27# pragma warning(disable : 4127) // C4127: conditional expression is constant
28#endif
29
30#include <Eigen/Core>
31#include <Eigen/SparseCore>
32
33#if defined(_MSC_VER)
34# pragma warning(pop)
35#endif
36
37// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
38// move constructors that break things. We could detect this an explicitly copy, but an extra copy
39// of matrices seems highly undesirable.
40static_assert(EIGEN_VERSION_AT_LEAST(3, 2, 7),
41 "Eigen support in pybind11 requires Eigen >= 3.2.7");
42
44
45// Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides:
46using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
47template <typename MatrixType>
48using EigenDRef = Eigen::Ref<MatrixType, 0, EigenDStride>;
49template <typename MatrixType>
50using EigenDMap = Eigen::Map<MatrixType, 0, EigenDStride>;
51
53
54#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
55using EigenIndex = Eigen::Index;
56template <typename Scalar, int Flags, typename StorageIndex>
57using EigenMapSparseMatrix = Eigen::Map<Eigen::SparseMatrix<Scalar, Flags, StorageIndex>>;
58#else
59using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
60template <typename Scalar, int Flags, typename StorageIndex>
61using EigenMapSparseMatrix = Eigen::MappedSparseMatrix<Scalar, Flags, StorageIndex>;
62#endif
63
64// Matches Eigen::Map, Eigen::Ref, blocks, etc:
65template <typename T>
67 std::is_base_of<Eigen::MapBase<T, Eigen::ReadOnlyAccessors>, T>>;
68template <typename T>
69using is_eigen_mutable_map = std::is_base_of<Eigen::MapBase<T, Eigen::WriteAccessors>, T>;
70template <typename T>
73template <typename T>
75// Test for objects inheriting from EigenBase<Derived> that aren't captured by the above. This
76// basically covers anything that can be assigned to a dense matrix but that don't have a typical
77// matrix data layout that can be copied from their .data(). For example, DiagonalMatrix and
78// SelfAdjointView fall into this category.
79template <typename T>
83
84// Captures numpy/eigen conformability status (returned by EigenProps::conformable()):
85template <bool EigenRowMajor>
87 bool conformable = false;
89 EigenDStride stride{0, 0}; // Only valid if negativestrides is false!
90 bool negativestrides = false; // If true, do not use stride!
91
92 // NOLINTNEXTLINE(google-explicit-constructor)
93 EigenConformable(bool fits = false) : conformable{fits} {}
94 // Matrix type:
96 : conformable{true}, rows{r}, cols{c},
97 // TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity.
98 // http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
99 stride{EigenRowMajor ? (rstride > 0 ? rstride : 0)
100 : (cstride > 0 ? cstride : 0) /* outer stride */,
101 EigenRowMajor ? (cstride > 0 ? cstride : 0)
102 : (rstride > 0 ? rstride : 0) /* inner stride */},
103 negativestrides{rstride < 0 || cstride < 0} {}
104 // Vector type:
106 : EigenConformable(r, c, r == 1 ? c * stride : stride, c == 1 ? r : r * stride) {}
107
108 template <typename props>
109 bool stride_compatible() const {
110 // To have compatible strides, we need (on both dimensions) one of fully dynamic strides,
111 // matching strides, or a dimension size of 1 (in which case the stride value is
112 // irrelevant)
113 return !negativestrides
114 && (props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner()
115 || (EigenRowMajor ? cols : rows) == 1)
116 && (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer()
117 || (EigenRowMajor ? rows : cols) == 1);
118 }
119 // NOLINTNEXTLINE(google-explicit-constructor)
120 operator bool() const { return conformable; }
121};
122
123template <typename Type>
125 using type = Type;
126};
127template <typename PlainObjectType, int MapOptions, typename StrideType>
128struct eigen_extract_stride<Eigen::Map<PlainObjectType, MapOptions, StrideType>> {
129 using type = StrideType;
130};
131template <typename PlainObjectType, int Options, typename StrideType>
132struct eigen_extract_stride<Eigen::Ref<PlainObjectType, Options, StrideType>> {
133 using type = StrideType;
134};
135
136// Helper struct for extracting information from an Eigen type
137template <typename Type_>
139 using Type = Type_;
140 using Scalar = typename Type::Scalar;
142 static constexpr EigenIndex rows = Type::RowsAtCompileTime, cols = Type::ColsAtCompileTime,
143 size = Type::SizeAtCompileTime;
144 static constexpr bool row_major = Type::IsRowMajor,
146 = Type::IsVectorAtCompileTime, // At least one dimension has fixed size 1
147 fixed_rows = rows != Eigen::Dynamic, fixed_cols = cols != Eigen::Dynamic,
148 fixed = size != Eigen::Dynamic, // Fully-fixed size
149 dynamic = !fixed_rows && !fixed_cols; // Fully-dynamic size
150
151 template <EigenIndex i, EigenIndex ifzero>
152 using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
153 static constexpr EigenIndex inner_stride
155 outer_stride = if_zero < StrideType::OuterStrideAtCompileTime,
156 vector ? size
157 : row_major ? cols
158 : rows > ::value;
159 static constexpr bool dynamic_stride
160 = inner_stride == Eigen::Dynamic && outer_stride == Eigen::Dynamic;
161 static constexpr bool requires_row_major
163 static constexpr bool requires_col_major
165
166 // Takes an input array and determines whether we can make it fit into the Eigen type. If
167 // the array is a vector, we attempt to fit it into either an Eigen 1xN or Nx1 vector
168 // (preferring the latter if it will fit in either, i.e. for a fully dynamic matrix type).
170 const auto dims = a.ndim();
171 if (dims < 1 || dims > 2) {
172 return false;
173 }
174
175 if (dims == 2) { // Matrix type: require exact match (or dynamic)
176
177 EigenIndex np_rows = a.shape(0), np_cols = a.shape(1),
178 np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
179 np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
180 if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows)
181 || (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
182 return false;
183 }
184
185 return {np_rows, np_cols, np_rstride, np_cstride};
186 }
187
188 // Otherwise we're storing an n-vector. Only one of the strides will be used, but
189 // whichever is used, we want the (single) numpy stride value.
190 const EigenIndex n = a.shape(0),
191 stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
192
193 if (vector) { // Eigen type is a compile-time vector
195 return false; // Vector size mismatch
196 }
197 return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
198 }
199 if (fixed) {
200 // The type has a fixed size, but is not a vector: abort
201 return false;
202 }
203 if (fixed_cols) {
204 // Since this isn't a vector, cols must be != 1. We allow this only if it exactly
205 // equals the number of elements (rows is Dynamic, and so 1 row is allowed).
206 if (cols != n) {
207 return false;
208 }
209 return {1, n, stride};
210 } // Otherwise it's either fully dynamic, or column dynamic; both become a column vector
212 return false;
213 }
214 return {n, 1, stride};
215 }
216
217 static constexpr bool show_writeable
221 static constexpr bool show_f_contiguous
223
224 static constexpr auto descriptor
226 + const_name<fixed_rows>(const_name<(size_t) rows>(), const_name("m")) + const_name(", ")
227 + const_name<fixed_cols>(const_name<(size_t) cols>(), const_name("n")) + const_name("]")
228 +
229 // For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to
230 // be satisfied: writeable=True (for a mutable reference), and, depending on the map's
231 // stride options, possibly f_contiguous or c_contiguous. We include them in the
232 // descriptor output to provide some hint as to why a TypeError is occurring (otherwise
233 // it can be confusing to see that a function accepts a 'numpy.ndarray[float64[3,2]]' and
234 // an error message that you *gave* a numpy.ndarray of the right type and dimensions.
235 const_name<show_writeable>(", flags.writeable", "")
236 + const_name<show_c_contiguous>(", flags.c_contiguous", "")
237 + const_name<show_f_contiguous>(", flags.f_contiguous", "") + const_name("]");
238};
239
240// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
241// otherwise it'll make a copy. writeable lets you turn off the writeable flag for the array.
242template <typename props>
243handle
244eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) {
245 constexpr ssize_t elem_size = sizeof(typename props::Scalar);
246 array a;
247 if (props::vector) {
248 a = array({src.size()}, {elem_size * src.innerStride()}, src.data(), base);
249 } else {
250 a = array({src.rows(), src.cols()},
251 {elem_size * src.rowStride(), elem_size * src.colStride()},
252 src.data(),
253 base);
254 }
255
256 if (!writeable) {
258 }
259
260 return a.release();
261}
262
263// Takes an lvalue ref to some Eigen type and a (python) base object, creating a numpy array that
264// reference the Eigen object's data with `base` as the python-registered base class (if omitted,
265// the base will be set to None, and lifetime management is up to the caller). The numpy array is
266// non-writeable if the given type is const.
267template <typename props, typename Type>
268handle eigen_ref_array(Type &src, handle parent = none()) {
269 // none here is to get past array's should-we-copy detection, which currently always
270 // copies when there is no base. Setting the base to None should be harmless.
271 return eigen_array_cast<props>(src, parent, !std::is_const<Type>::value);
272}
273
274// Takes a pointer to some dense, plain Eigen type, builds a capsule around it, then returns a
275// numpy array that references the encapsulated data with a python-side reference to the capsule to
276// tie its destruction to that of any dependent python objects. Const-ness is determined by
277// whether or not the Type of the pointer given is const.
278template <typename props, typename Type, typename = enable_if_t<is_eigen_dense_plain<Type>::value>>
280 capsule base(src, [](void *o) { delete static_cast<Type *>(o); });
281 return eigen_ref_array<props>(*src, base);
282}
283
284// Type caster for regular, dense matrix types (e.g. MatrixXd), but not maps/refs/etc. of dense
285// types.
286template <typename Type>
288 using Scalar = typename Type::Scalar;
290
291 bool load(handle src, bool convert) {
292 // If we're in no-convert mode, only load if given an array of the correct type
293 if (!convert && !isinstance<array_t<Scalar>>(src)) {
294 return false;
295 }
296
297 // Coerce into an array, but don't do type conversion yet; the copy below handles it.
298 auto buf = array::ensure(src);
299
300 if (!buf) {
301 return false;
302 }
303
304 auto dims = buf.ndim();
305 if (dims < 1 || dims > 2) {
306 return false;
307 }
308
309 auto fits = props::conformable(buf);
310 if (!fits) {
311 return false;
312 }
313
314 // Allocate the new type, then build a numpy reference into it
315 value = Type(fits.rows, fits.cols);
316 auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value));
317 if (dims == 1) {
318 ref = ref.squeeze();
319 } else if (ref.ndim() == 1) {
320 buf = buf.squeeze();
321 }
322
323 int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr());
324
325 if (result < 0) { // Copy failed!
326 PyErr_Clear();
327 return false;
328 }
329
330 return true;
331 }
332
333private:
334 // Cast implementation
335 template <typename CType>
336 static handle cast_impl(CType *src, return_value_policy policy, handle parent) {
337 switch (policy) {
338 case return_value_policy::take_ownership:
339 case return_value_policy::automatic:
340 return eigen_encapsulate<props>(src);
341 case return_value_policy::move:
342 return eigen_encapsulate<props>(new CType(std::move(*src)));
343 case return_value_policy::copy:
344 return eigen_array_cast<props>(*src);
345 case return_value_policy::reference:
346 case return_value_policy::automatic_reference:
347 return eigen_ref_array<props>(*src);
348 case return_value_policy::reference_internal:
349 return eigen_ref_array<props>(*src, parent);
350 default:
351 throw cast_error("unhandled return_value_policy: should not happen!");
352 };
353 }
354
355public:
356 // Normal returned non-reference, non-const value:
357 static handle cast(Type &&src, return_value_policy /* policy */, handle parent) {
358 return cast_impl(&src, return_value_policy::move, parent);
359 }
360 // If you return a non-reference const, we mark the numpy array readonly:
361 static handle cast(const Type &&src, return_value_policy /* policy */, handle parent) {
362 return cast_impl(&src, return_value_policy::move, parent);
363 }
364 // lvalue reference return; default (automatic) becomes copy
365 static handle cast(Type &src, return_value_policy policy, handle parent) {
366 if (policy == return_value_policy::automatic
367 || policy == return_value_policy::automatic_reference) {
368 policy = return_value_policy::copy;
369 }
370 return cast_impl(&src, policy, parent);
371 }
372 // const lvalue reference return; default (automatic) becomes copy
373 static handle cast(const Type &src, return_value_policy policy, handle parent) {
374 if (policy == return_value_policy::automatic
375 || policy == return_value_policy::automatic_reference) {
376 policy = return_value_policy::copy;
377 }
378 return cast(&src, policy, parent);
379 }
380 // non-const pointer return
381 static handle cast(Type *src, return_value_policy policy, handle parent) {
382 return cast_impl(src, policy, parent);
383 }
384 // const pointer return
385 static handle cast(const Type *src, return_value_policy policy, handle parent) {
386 return cast_impl(src, policy, parent);
387 }
388
389 static constexpr auto name = props::descriptor;
390
391 // NOLINTNEXTLINE(google-explicit-constructor)
392 operator Type *() { return &value; }
393 // NOLINTNEXTLINE(google-explicit-constructor)
394 operator Type &() { return value; }
395 // NOLINTNEXTLINE(google-explicit-constructor)
396 operator Type &&() && { return std::move(value); }
397 template <typename T>
399
400private:
401 Type value;
402};
403
404// Base class for casting reference/map/block/etc. objects back to python.
405template <typename MapType>
407private:
409
410public:
411 // Directly referencing a ref/map's data is a bit dangerous (whatever the map/ref points to has
412 // to stay around), but we'll allow it under the assumption that you know what you're doing
413 // (and have an appropriate keep_alive in place). We return a numpy array pointing directly at
414 // the ref's data (The numpy array ends up read-only if the ref was to a const matrix type.)
415 // Note that this means you need to ensure you don't destroy the object in some other way (e.g.
416 // with an appropriate keep_alive, or with a reference to a statically allocated matrix).
417 static handle cast(const MapType &src, return_value_policy policy, handle parent) {
418 switch (policy) {
419 case return_value_policy::copy:
420 return eigen_array_cast<props>(src);
421 case return_value_policy::reference_internal:
422 return eigen_array_cast<props>(src, parent, is_eigen_mutable_map<MapType>::value);
423 case return_value_policy::reference:
424 case return_value_policy::automatic:
425 case return_value_policy::automatic_reference:
426 return eigen_array_cast<props>(src, none(), is_eigen_mutable_map<MapType>::value);
427 default:
428 // move, take_ownership don't make any sense for a ref/map:
429 pybind11_fail("Invalid return_value_policy for Eigen Map/Ref/Block type");
430 }
431 }
432
433 static constexpr auto name = props::descriptor;
434
435 // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
436 // types but not bound arguments). We still provide them (with an explicitly delete) so that
437 // you end up here if you try anyway.
438 bool load(handle, bool) = delete;
439 operator MapType() = delete;
440 template <typename>
441 using cast_op_type = MapType;
442};
443
444// We can return any map-like object (but can only load Refs, specialized next):
445template <typename Type>
447
448// Loader for Ref<...> arguments. See the documentation for info on how to make this work without
449// copying (it requires some extra effort in many cases).
450template <typename PlainObjectType, typename StrideType>
452 Eigen::Ref<PlainObjectType, 0, StrideType>,
453 enable_if_t<is_eigen_dense_map<Eigen::Ref<PlainObjectType, 0, StrideType>>::value>>
454 : public eigen_map_caster<Eigen::Ref<PlainObjectType, 0, StrideType>> {
455private:
456 using Type = Eigen::Ref<PlainObjectType, 0, StrideType>;
458 using Scalar = typename props::Scalar;
459 using MapType = Eigen::Map<PlainObjectType, 0, StrideType>;
460 using Array
461 = array_t<Scalar,
463 | ((props::row_major ? props::inner_stride : props::outer_stride) == 1
465 : (props::row_major ? props::outer_stride : props::inner_stride) == 1
467 : 0)>;
468 static constexpr bool need_writeable = is_eigen_mutable_map<Type>::value;
469 // Delay construction (these have no default constructor)
470 std::unique_ptr<MapType> map;
471 std::unique_ptr<Type> ref;
472 // Our array. When possible, this is just a numpy array pointing to the source data, but
473 // sometimes we can't avoid copying (e.g. input is not a numpy array at all, has an
474 // incompatible layout, or is an array of a type that needs to be converted). Using a numpy
475 // temporary (rather than an Eigen temporary) saves an extra copy when we need both type
476 // conversion and storage order conversion. (Note that we refuse to use this temporary copy
477 // when loading an argument for a Ref<M> with M non-const, i.e. a read-write reference).
479
480public:
481 bool load(handle src, bool convert) {
482 // First check whether what we have is already an array of the right type. If not, we
483 // can't avoid a copy (because the copy is also going to do type conversion).
484 bool need_copy = !isinstance<Array>(src);
485
487 if (!need_copy) {
488 // We don't need a converting copy, but we also need to check whether the strides are
489 // compatible with the Ref's stride requirements
490 auto aref = reinterpret_borrow<Array>(src);
491
492 if (aref && (!need_writeable || aref.writeable())) {
493 fits = props::conformable(aref);
494 if (!fits) {
495 return false; // Incompatible dimensions
496 }
497 if (!fits.template stride_compatible<props>()) {
498 need_copy = true;
499 } else {
500 copy_or_ref = std::move(aref);
501 }
502 } else {
503 need_copy = true;
504 }
505 }
506
507 if (need_copy) {
508 // We need to copy: If we need a mutable reference, or we're not supposed to convert
509 // (either because we're in the no-convert overload pass, or because we're explicitly
510 // instructed not to copy (via `py::arg().noconvert()`) we have to fail loading.
511 if (!convert || need_writeable) {
512 return false;
513 }
514
515 Array copy = Array::ensure(src);
516 if (!copy) {
517 return false;
518 }
519 fits = props::conformable(copy);
520 if (!fits || !fits.template stride_compatible<props>()) {
521 return false;
522 }
523 copy_or_ref = std::move(copy);
525 }
526
527 ref.reset();
528 map.reset(new MapType(data(copy_or_ref),
529 fits.rows,
530 fits.cols,
531 make_stride(fits.stride.outer(), fits.stride.inner())));
532 ref.reset(new Type(*map));
533
534 return true;
535 }
536
537 // NOLINTNEXTLINE(google-explicit-constructor)
538 operator Type *() { return ref.get(); }
539 // NOLINTNEXTLINE(google-explicit-constructor)
540 operator Type &() { return *ref; }
541 template <typename _T>
542 using cast_op_type = pybind11::detail::cast_op_type<_T>;
543
544private:
545 template <typename T = Type, enable_if_t<is_eigen_mutable_map<T>::value, int> = 0>
547 return a.mutable_data();
548 }
549
550 template <typename T = Type, enable_if_t<!is_eigen_mutable_map<T>::value, int> = 0>
551 const Scalar *data(Array &a) {
552 return a.data();
553 }
554
555 // Attempt to figure out a constructor of `Stride` that will work.
556 // If both strides are fixed, use a default constructor:
557 template <typename S>
558 using stride_ctor_default = bool_constant<S::InnerStrideAtCompileTime != Eigen::Dynamic
559 && S::OuterStrideAtCompileTime != Eigen::Dynamic
560 && std::is_default_constructible<S>::value>;
561 // Otherwise, if there is a two-index constructor, assume it is (outer,inner) like
562 // Eigen::Stride, and use it:
563 template <typename S>
566 && std::is_constructible<S, EigenIndex, EigenIndex>::value>;
567 // Otherwise, if there is a one-index constructor, and just one of the strides is dynamic, use
568 // it (passing whichever stride is dynamic).
569 template <typename S>
572 && S::OuterStrideAtCompileTime == Eigen::Dynamic
573 && S::InnerStrideAtCompileTime != Eigen::Dynamic
574 && std::is_constructible<S, EigenIndex>::value>;
575 template <typename S>
578 && S::InnerStrideAtCompileTime == Eigen::Dynamic
579 && S::OuterStrideAtCompileTime != Eigen::Dynamic
580 && std::is_constructible<S, EigenIndex>::value>;
581
582 template <typename S = StrideType, enable_if_t<stride_ctor_default<S>::value, int> = 0>
584 return S();
585 }
586 template <typename S = StrideType, enable_if_t<stride_ctor_dual<S>::value, int> = 0>
587 static S make_stride(EigenIndex outer, EigenIndex inner) {
588 return S(outer, inner);
589 }
590 template <typename S = StrideType, enable_if_t<stride_ctor_outer<S>::value, int> = 0>
592 return S(outer);
593 }
594 template <typename S = StrideType, enable_if_t<stride_ctor_inner<S>::value, int> = 0>
596 return S(inner);
597 }
598};
599
600// type_caster for special matrix types (e.g. DiagonalMatrix), which are EigenBase, but not
601// EigenDense (i.e. they don't have a data(), at least not with the usual matrix layout).
602// load() is not supported, but we can cast them into the python domain by first copying to a
603// regular Eigen::Matrix, then casting that.
604template <typename Type>
606protected:
607 using Matrix
608 = Eigen::Matrix<typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime>;
610
611public:
612 static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
613 handle h = eigen_encapsulate<props>(new Matrix(src));
614 return h;
615 }
616 static handle cast(const Type *src, return_value_policy policy, handle parent) {
617 return cast(*src, policy, parent);
618 }
619
620 static constexpr auto name = props::descriptor;
621
622 // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return
623 // types but not bound arguments). We still provide them (with an explicitly delete) so that
624 // you end up here if you try anyway.
625 bool load(handle, bool) = delete;
626 operator Type() = delete;
627 template <typename>
628 using cast_op_type = Type;
629};
630
631template <typename Type>
633 using Scalar = typename Type::Scalar;
635 using Index = typename Type::Index;
636 static constexpr bool rowMajor = Type::IsRowMajor;
637
638 bool load(handle src, bool) {
639 if (!src) {
640 return false;
641 }
642
643 auto obj = reinterpret_borrow<object>(src);
644 object sparse_module = module_::import("scipy.sparse");
645 object matrix_type = sparse_module.attr(rowMajor ? "csr_matrix" : "csc_matrix");
646
647 if (!type::handle_of(obj).is(matrix_type)) {
648 try {
649 obj = matrix_type(obj);
650 } catch (const error_already_set &) {
651 return false;
652 }
653 }
654
655 auto values = array_t<Scalar>((object) obj.attr("data"));
656 auto innerIndices = array_t<StorageIndex>((object) obj.attr("indices"));
657 auto outerIndices = array_t<StorageIndex>((object) obj.attr("indptr"));
658 auto shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
659 auto nnz = obj.attr("nnz").cast<Index>();
660
661 if (!values || !innerIndices || !outerIndices) {
662 return false;
663 }
664
666 Type::Flags &(Eigen::RowMajor | Eigen::ColMajor),
667 StorageIndex>(shape[0].cast<Index>(),
668 shape[1].cast<Index>(),
669 nnz,
670 outerIndices.mutable_data(),
671 innerIndices.mutable_data(),
672 values.mutable_data());
673
674 return true;
675 }
676
677 static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
678 const_cast<Type &>(src).makeCompressed();
679
680 object matrix_type
681 = module_::import("scipy.sparse").attr(rowMajor ? "csr_matrix" : "csc_matrix");
682
683 array data(src.nonZeros(), src.valuePtr());
684 array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr());
685 array innerIndices(src.nonZeros(), src.innerIndexPtr());
686
687 return matrix_type(std::make_tuple(data, innerIndices, outerIndices),
688 std::make_pair(src.rows(), src.cols()))
689 .release();
690 }
691
693 const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[",
694 "scipy.sparse.csc_matrix[")
696};
697
Definition: numpy.h:991
const T * data(Ix... index) const
Definition: numpy.h:1055
T * mutable_data(Ix... index)
Definition: numpy.h:1060
Definition: numpy.h:655
ssize_t ndim() const
Number of dimensions.
Definition: numpy.h:770
const ssize_t * strides() const
Strides of the array.
Definition: numpy.h:787
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
@ forcecast
Definition: numpy.h:662
@ c_style
Definition: numpy.h:660
@ f_style
Definition: numpy.h:661
const ssize_t * shape() const
Dimensions of the array.
Definition: numpy.h:776
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 * ptr() const
Return the underlying PyObject * pointer.
Definition: pytypes.h:203
static PYBIND11_NOINLINE void add_patient(handle h)
This can only be used inside a pybind11-bound function, either by argument_loader at argument prepara...
static module_ import(const char *name)
Import and return a module or throws error_already_set.
Definition: pybind11.h:1200
Definition: pytypes.h:1422
handle release()
\rst Resets the internal pointer to nullptr without decreasing the object's reference count.
Definition: pytypes.h:283
Reference counting helper.
Definition: object.h:67
static handle cast(const itype &src, return_value_policy policy, handle parent)
Definition: pytypes.h:1167
static handle handle_of()
Convert C++ type to handle if previously registered.
Definition: cast.h:1643
bool isinstance(handle obj)
\rst Return true if obj is an instance of T.
Definition: pytypes.h:489
all_of< is_template_base_of< Eigen::DenseBase, T >, std::is_base_of< Eigen::MapBase< T, Eigen::ReadOnlyAccessors >, T > > is_eigen_dense_map
Definition: matrix.h:63
EIGEN_DEFAULT_DENSE_INDEX_TYPE EigenIndex
Definition: matrix.h:55
Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > EigenDStride
Definition: matrix.h:42
all_of< negation< is_eigen_dense_map< T > >, is_template_base_of< Eigen::PlainObjectBase, T > > is_eigen_dense_plain
Definition: matrix.h:68
std::is_base_of< Eigen::MapBase< T, Eigen::WriteAccessors >, T > is_eigen_mutable_map
Definition: matrix.h:65
Eigen::MappedSparseMatrix< Scalar, Flags, StorageIndex > EigenMapSparseMatrix
Definition: matrix.h:57
all_of< is_template_base_of< Eigen::EigenBase, T >, negation< any_of< is_eigen_dense_map< T >, is_eigen_dense_plain< T >, is_eigen_sparse< T > > > > is_eigen_other
Definition: matrix.h:78
is_template_base_of< Eigen::SparseMatrixBase, T > is_eigen_sparse
Definition: matrix.h:70
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
typename std::remove_reference< T >::type remove_reference_t
Definition: common.h:631
decltype(is_template_base_of_impl< Base >::check((intrinsic_t< T > *) nullptr)) is_template_base_of
Check if a template is the base of a type.
Definition: common.h:883
#define PYBIND11_NAMESPACE_END(name)
Definition: common.h:21
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: common.h:20
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
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
Definition: common.h:470
@ copy
Create a new copy of the returned object, which will be owned by Python.
#define PYBIND11_SILENCE_MSVC_C4127(...)
Definition: common.h:1206
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
conditional_t< std::is_pointer< typename std::remove_reference< T >::type >::value, typename std::add_pointer< intrinsic_t< T > >::type, conditional_t< std::is_rvalue_reference< T >::value, typename std::add_rvalue_reference< intrinsic_t< T > >::type, typename std::add_lvalue_reference< intrinsic_t< T > >::type > > movable_cast_op_type
Determine suitable casting operator for a type caster with a movable value.
handle eigen_array_cast(typename props::Type const &src, handle base=handle(), bool writeable=true)
Definition: eigen.h:244
all_of< is_template_base_of< Eigen::DenseBase, T >, std::is_base_of< Eigen::MapBase< T, Eigen::ReadOnlyAccessors >, T > > is_eigen_dense_map
Definition: eigen.h:67
Eigen::Map< MatrixType, 0, EigenDStride > EigenDMap
Definition: eigen.h:50
handle eigen_ref_array(Type &src, handle parent=none())
Definition: eigen.h:268
EIGEN_DEFAULT_DENSE_INDEX_TYPE EigenIndex
Definition: eigen.h:59
Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > EigenDStride
Definition: eigen.h:46
handle eigen_encapsulate(Type *src)
Definition: eigen.h:279
all_of< negation< is_eigen_dense_map< T > >, is_template_base_of< Eigen::PlainObjectBase, T > > is_eigen_dense_plain
Definition: eigen.h:72
std::is_base_of< Eigen::MapBase< T, Eigen::WriteAccessors >, T > is_eigen_mutable_map
Definition: eigen.h:69
Eigen::Ref< MatrixType, 0, EigenDStride > EigenDRef
Definition: eigen.h:48
Eigen::MappedSparseMatrix< Scalar, Flags, StorageIndex > EigenMapSparseMatrix
Definition: eigen.h:61
all_of< is_template_base_of< Eigen::EigenBase, T >, negation< any_of< is_eigen_dense_map< T >, is_eigen_dense_plain< T >, is_eigen_sparse< T > > > > is_eigen_other
Definition: eigen.h:82
is_template_base_of< Eigen::SparseMatrixBase, T > is_eigen_sparse
Definition: eigen.h:74
PyArray_Proxy * array_proxy(void *ptr)
Definition: numpy.h:301
arr data(const arr &a, Ix... index)
bool conformable
Definition: eigen.h:87
EigenConformable(bool fits=false)
Definition: eigen.h:93
EigenIndex rows
Definition: eigen.h:88
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex rstride, EigenIndex cstride)
Definition: eigen.h:95
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride)
Definition: eigen.h:105
bool stride_compatible() const
Definition: eigen.h:109
EigenIndex cols
Definition: eigen.h:88
EigenDStride stride
Definition: eigen.h:89
bool negativestrides
Definition: eigen.h:90
static constexpr bool fixed
Definition: eigen.h:148
static constexpr EigenIndex rows
Definition: eigen.h:142
static constexpr bool dynamic_stride
Definition: eigen.h:160
typename eigen_extract_stride< Type >::type StrideType
Definition: eigen.h:141
static constexpr bool show_writeable
Definition: eigen.h:218
static constexpr bool requires_row_major
Definition: eigen.h:162
static constexpr bool show_c_contiguous
Definition: eigen.h:220
static EigenConformable< row_major > conformable(const array &a)
Definition: eigen.h:169
static constexpr EigenIndex outer_stride
Definition: eigen.h:155
static constexpr bool row_major
Definition: eigen.h:144
static constexpr EigenIndex size
Definition: eigen.h:143
static constexpr bool vector
Definition: eigen.h:146
static constexpr bool fixed_rows
Definition: eigen.h:147
static constexpr bool show_order
Definition: eigen.h:219
static constexpr EigenIndex inner_stride
Definition: eigen.h:154
static constexpr auto descriptor
Definition: eigen.h:225
std::integral_constant< EigenIndex, i==0 ? ifzero :i > if_zero
Definition: eigen.h:152
static constexpr bool show_f_contiguous
Definition: eigen.h:222
Type_ Type
Definition: eigen.h:139
static constexpr bool fixed_cols
Definition: eigen.h:147
static constexpr bool dynamic
Definition: eigen.h:149
typename Type::Scalar Scalar
Definition: eigen.h:140
static constexpr EigenIndex cols
Definition: eigen.h:142
static constexpr bool requires_col_major
Definition: eigen.h:164
int flags
Definition: numpy.h:74
Annotation indicating that a class derives from another given type.
Definition: attr.h:60
MapType cast_op_type
Definition: eigen.h:441
bool load(handle, bool)=delete
static handle cast(const MapType &src, return_value_policy policy, handle parent)
Definition: eigen.h:417
Annotation for function names.
Definition: attr.h:47
@ NPY_ARRAY_WRITEABLE_
Definition: numpy.h:146
bool_constant<!any_of< stride_ctor_default< S >, stride_ctor_dual< S > >::value &&S::InnerStrideAtCompileTime==Eigen::Dynamic &&S::OuterStrideAtCompileTime !=Eigen::Dynamic &&std::is_constructible< S, EigenIndex >::value > stride_ctor_inner
Definition: eigen.h:580
bool_constant<!stride_ctor_default< S >::value &&std::is_constructible< S, EigenIndex, EigenIndex >::value > stride_ctor_dual
Definition: eigen.h:566
bool_constant<!any_of< stride_ctor_default< S >, stride_ctor_dual< S > >::value &&S::OuterStrideAtCompileTime==Eigen::Dynamic &&S::InnerStrideAtCompileTime !=Eigen::Dynamic &&std::is_constructible< S, EigenIndex >::value > stride_ctor_outer
Definition: eigen.h:574
bool_constant< S::InnerStrideAtCompileTime !=Eigen::Dynamic &&S::OuterStrideAtCompileTime !=Eigen::Dynamic &&std::is_default_constructible< S >::value > stride_ctor_default
Definition: eigen.h:560
static handle cast(Type &src, return_value_policy policy, handle parent)
Definition: eigen.h:365
static handle cast(Type *src, return_value_policy policy, handle parent)
Definition: eigen.h:381
static handle cast(const Type &src, return_value_policy policy, handle parent)
Definition: eigen.h:373
static handle cast(Type &&src, return_value_policy, handle parent)
Definition: eigen.h:357
static handle cast_impl(CType *src, return_value_policy policy, handle parent)
Definition: eigen.h:336
static handle cast(const Type *src, return_value_policy policy, handle parent)
Definition: eigen.h:385
static handle cast(const Type &&src, return_value_policy, handle parent)
Definition: eigen.h:361
Eigen::Matrix< typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime > Matrix
Definition: eigen.h:608
static handle cast(const Type *src, return_value_policy policy, handle parent)
Definition: eigen.h:616
static handle cast(const Type &src, return_value_policy, handle)
Definition: eigen.h:612
static handle cast(const Type &src, return_value_policy, handle)
Definition: eigen.h:677
remove_reference_t< decltype(*std::declval< Type >().outerIndexPtr())> StorageIndex
Definition: eigen.h:634
PYBIND11_TYPE_CASTER(Type, const_name<(Type::IsRowMajor) !=0 >("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")+npy_format_descriptor< Scalar >::name+const_name("]"))