14 #if defined(__INTEL_COMPILER) 15 # pragma warning(disable: 1682) // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem) 16 #elif defined(__GNUG__) || defined(__clang__) 17 # pragma GCC diagnostic push 18 # pragma GCC diagnostic ignored "-Wconversion" 19 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 23 # pragma GCC diagnostic ignored "-Wdeprecated" 26 # pragma GCC diagnostic ignored "-Wint-in-bool-context" 31 # pragma warning(push) 32 # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant 33 # pragma warning(disable: 4996) // warning C4996: std::unary_negate is deprecated in C++17 37 #include <Eigen/SparseCore> 42 static_assert(EIGEN_VERSION_AT_LEAST(3,2,7),
"Eigen support in pybind11 requires Eigen >= 3.2.7");
47 using
EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
49 template <typename MatrixType> using
EigenDMap = Eigen::Map<MatrixType, 0, EigenDStride>;
53 #if EIGEN_VERSION_AT_LEAST(3,3,0) 61 template <
typename T>
using is_eigen_mutable_map = std::is_base_of<Eigen::MapBase<T, Eigen::WriteAccessors>, T>;
75 bool conformable =
false;
77 EigenDStride stride{0, 0};
78 bool negativestrides =
false;
84 conformable{
true}, rows{r}, cols{c} {
86 if (rstride < 0 || cstride < 0) {
87 negativestrides =
true;
89 stride = {EigenRowMajor ? rstride : cstride ,
90 EigenRowMajor ? cstride : rstride };
95 :
EigenConformable(r, c, r == 1 ? c*stride : stride, c == 1 ? r : r*stride) {}
102 (props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner() ||
103 (EigenRowMajor ? cols : rows) == 1) &&
104 (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer() ||
105 (EigenRowMajor ? rows : cols) == 1);
107 operator bool()
const {
return conformable; }
111 template <
typename PlainObjectType,
int MapOptions,
typename Str
ideType>
113 template <
typename PlainObjectType,
int Options,
typename Str
ideType>
122 rows = Type::RowsAtCompileTime,
123 cols = Type::ColsAtCompileTime,
124 size = Type::SizeAtCompileTime;
125 static constexpr
bool 126 row_major = Type::IsRowMajor,
127 vector = Type::IsVectorAtCompileTime,
128 fixed_rows = rows != Eigen::Dynamic,
129 fixed_cols = cols != Eigen::Dynamic,
130 fixed =
size != Eigen::Dynamic,
131 dynamic = !fixed_rows && !fixed_cols;
133 template <EigenIndex i, EigenIndex ifzero>
using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
135 outer_stride =
if_zero<StrideType::OuterStrideAtCompileTime,
137 static constexpr
bool dynamic_stride = inner_stride == Eigen::Dynamic && outer_stride == Eigen::Dynamic;
138 static constexpr
bool requires_row_major = !dynamic_stride && !vector && (row_major ? inner_stride : outer_stride) == 1;
139 static constexpr
bool requires_col_major = !dynamic_stride && !vector && (row_major ? outer_stride : inner_stride) == 1;
145 const auto dims = a.
ndim();
146 if (dims < 1 || dims > 2)
152 np_rows = a.
shape(0),
153 np_cols = a.
shape(1),
156 if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols))
159 return {np_rows, np_cols, np_rstride, np_cstride};
168 if (fixed &&
size != n)
170 return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
176 else if (fixed_cols) {
179 if (cols != n)
return false;
180 return {1, n, stride};
184 if (fixed_rows && rows != n)
return false;
185 return {n, 1, stride};
191 static constexpr
bool show_c_contiguous = show_order && requires_row_major;
192 static constexpr
bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
194 static constexpr
auto descriptor =
196 _(
"[") + _<fixed_rows>(_<(size_t) rows>(),
_(
"m")) +
197 _(
", ") + _<fixed_cols>(_<(size_t) cols>(),
_(
"n")) +
205 _<show_writeable>(
", flags.writeable",
"") +
206 _<show_c_contiguous>(
", flags.c_contiguous",
"") +
207 _<show_f_contiguous>(
", flags.f_contiguous",
"") +
214 constexpr
ssize_t elem_size =
sizeof(
typename props::Scalar);
217 a =
array({ src.size() }, { elem_size * src.innerStride() }, src.data(),
base);
219 a =
array({ src.rows(), src.cols() }, { elem_size * src.rowStride(), elem_size * src.colStride() },
223 array_proxy(a.
ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
232 template <
typename props,
typename Type>
245 capsule base(src, [](
void *o) {
delete static_cast<Type *
>(o); });
246 return eigen_ref_array<props>(*src,
base);
251 template<
typename Type>
262 auto buf = array::ensure(src);
267 auto dims = buf.ndim();
268 if (dims < 1 || dims > 2)
271 auto fits = props::conformable(buf);
276 value = Type(fits.rows, fits.cols);
277 auto ref = reinterpret_steal<array>(eigen_ref_array<props>(
value));
278 if (dims == 1)
ref =
ref.squeeze();
279 else if (
ref.ndim() == 1) buf = buf.squeeze();
281 int result = detail::npy_api::get().PyArray_CopyInto_(
ref.ptr(), buf.ptr());
294 template <
typename CType>
297 case return_value_policy::take_ownership:
298 case return_value_policy::automatic:
299 return eigen_encapsulate<props>(src);
301 return eigen_encapsulate<props>(
new CType(
std::move(*src)));
302 case return_value_policy::copy:
304 case return_value_policy::reference:
305 case return_value_policy::automatic_reference:
306 return eigen_ref_array<props>(*src);
307 case return_value_policy::reference_internal:
308 return eigen_ref_array<props>(*src, parent);
310 throw cast_error(
"unhandled return_value_policy: should not happen!");
326 if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
327 policy = return_value_policy::copy;
328 return cast_impl(&src, policy, parent);
332 if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
333 policy = return_value_policy::copy;
334 return cast(&src, policy, parent);
338 return cast_impl(src, policy, parent);
342 return cast_impl(src, policy, parent);
345 static constexpr
auto name = props::descriptor;
371 case return_value_policy::copy:
373 case return_value_policy::reference_internal:
375 case return_value_policy::reference:
376 case return_value_policy::automatic:
377 case return_value_policy::automatic_reference:
381 pybind11_fail(
"Invalid return_value_policy for Eigen Map/Ref/Block type");
385 static constexpr
auto name = props::descriptor;
390 bool load(
handle,
bool) =
delete;
391 operator MapType() =
delete;
401 template <
typename PlainObjectType,
typename Str
ideType>
403 Eigen::Ref<PlainObjectType, 0, StrideType>,
404 enable_if_t<is_eigen_dense_map<Eigen::Ref<PlainObjectType, 0, StrideType>>::value>
407 using Type = Eigen::Ref<PlainObjectType, 0, StrideType>;
410 using MapType = Eigen::Map<PlainObjectType, 0, StrideType>;
412 ((props::row_major ? props::inner_stride : props::outer_stride) == 1 ? array::c_style :
413 (props::row_major ? props::outer_stride : props::inner_stride) == 1 ? array::f_style : 0)>;
416 std::unique_ptr<MapType>
map;
417 std::unique_ptr<Type>
ref;
429 bool need_copy = !isinstance<Array>(src);
435 Array aref = reinterpret_borrow<Array>(src);
437 if (aref && (!need_writeable || aref.
writeable())) {
438 fits = props::conformable(aref);
439 if (!fits)
return false;
440 if (!fits.template stride_compatible<props>())
454 if (!convert || need_writeable)
return false;
457 if (!copy)
return false;
458 fits = props::conformable(copy);
459 if (!fits || !fits.template stride_compatible<props>())
466 map.reset(
new MapType(
data(copy_or_ref), fits.rows, fits.cols, make_stride(fits.stride.outer(), fits.stride.inner())));
467 ref.reset(
new Type(*map));
472 operator Type*() {
return ref.get(); }
473 operator Type&() {
return *
ref; }
486 S::InnerStrideAtCompileTime != Eigen::Dynamic && S::OuterStrideAtCompileTime != Eigen::Dynamic &&
496 S::OuterStrideAtCompileTime == Eigen::Dynamic && S::InnerStrideAtCompileTime != Eigen::Dynamic &&
500 S::InnerStrideAtCompileTime == Eigen::Dynamic && S::OuterStrideAtCompileTime != Eigen::Dynamic &&
518 template <
typename Type>
521 using Matrix = Eigen::Matrix<typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime>;
530 static constexpr
auto name = props::descriptor;
535 bool load(
handle,
bool) =
delete;
536 operator Type() =
delete;
540 template<
typename Type>
545 static constexpr
bool rowMajor = Type::IsRowMajor;
551 auto obj = reinterpret_borrow<object>(src);
552 object sparse_module = module::import(
"scipy.sparse");
553 object matrix_type = sparse_module.attr(
554 rowMajor ?
"csr_matrix" :
"csc_matrix");
556 if (!obj.get_type().is(matrix_type)) {
558 obj = matrix_type(obj);
568 auto nnz = obj.
attr(
"nnz").cast<Index>();
570 if (!values || !innerIndices || !outerIndices)
573 value = Eigen::MappedSparseMatrix<Scalar, Type::Flags, StorageIndex>(
574 shape[0].
cast<Index>(), shape[1].cast<Index>(), nnz,
581 const_cast<Type&
>(src).makeCompressed();
583 object matrix_type = module::import(
"scipy.sparse").attr(
584 rowMajor ?
"csr_matrix" :
"csc_matrix");
586 array data(src.nonZeros(), src.valuePtr());
587 array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr());
588 array innerIndices(src.nonZeros(), src.innerIndexPtr());
592 std::make_pair(src.rows(), src.cols())
596 PYBIND11_TYPE_CASTER(Type,
_<(Type::IsRowMajor) != 0>(
"scipy.sparse.csr_matrix[",
"scipy.sparse.csc_matrix[")
603 #if defined(__GNUG__) || defined(__clang__) 604 # pragma GCC diagnostic pop 605 #elif defined(_MSC_VER) 606 # pragma warning(pop) void * mutable_data(Ix... index)
static handle cast(const MapType &src, return_value_policy policy, handle parent)
Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > EigenDStride
const ssize_t * strides() const
Strides of the array.
#define PYBIND11_NAMESPACE
PyObject * ptr() const
Return the underlying PyObject * pointer.
static EigenConformable< row_major > conformable(const array &a)
const Scalar * data(Array &a)
PyArray_Proxy * array_proxy(void *ptr)
static handle cast(Type &&src, return_value_policy, handle parent)
void add_patient(PyObject *nurse, PyObject *patient)
bool load(handle src, bool convert)
std::integral_constant< EigenIndex, i==0 ? ifzero :i > if_zero
remove_reference_t< decltype(*std::declval< Type >).outerIndexPtr())> StorageIndex
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
bool load(handle src, bool convert)
bool_constant< !stride_ctor_default< S >::value &&std::is_constructible< S, EigenIndex, EigenIndex >::value > stride_ctor_dual
typename Type::Scalar Scalar
static handle cast(const Type &src, return_value_policy, handle)
static handle cast(const Type &&src, return_value_policy, handle parent)
constexpr descr< N - 1 > _(char const(&text)[N])
typename eigen_extract_stride< Type >::type StrideType
static S make_stride(EigenIndex, EigenIndex inner)
arr data(const arr &a, Ix... index)
handle eigen_encapsulate(Type *src)
conditional_t< std::is_pointer< remove_reference_t< T > >::value, typename std::add_pointer< intrinsic_t< T > >::type, typename std::add_lvalue_reference< intrinsic_t< T > >::type > cast_op_type
Eigen::Ref< MatrixType, 0, EigenDStride > EigenDRef
static handle cast(const Type *src, return_value_policy policy, handle parent)
obj_attr_accessor attr(handle key) const
const void * data(Ix... index) const
pybind11::detail::cast_op_type< _T > cast_op_type
#define NAMESPACE_END(name)
static handle cast(const Type &src, return_value_policy, handle)
return isinstance(obj, type)
static handle cast_impl(CType *src, return_value_policy policy, handle parent)
all_of< negation< is_eigen_dense_map< T > >, is_template_base_of< Eigen::PlainObjectBase, T > > is_eigen_dense_plain
static S make_stride(EigenIndex outer, EigenIndex)
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
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
Eigen::Matrix< typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime > Matrix
typename Type::Scalar Scalar
ssize_t ndim() const
Number of dimensions.
Reference counting helper.
typename std::remove_reference< T >::type remove_reference_t
handle eigen_array_cast(typename props::Type const &src, handle base=handle(), bool writeable=true)
typename props::Scalar Scalar
static S make_stride(EigenIndex, EigenIndex)
bool load(handle src, bool)
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
all_of< is_template_base_of< Eigen::DenseBase, T >, std::is_base_of< Eigen::MapBase< T, Eigen::ReadOnlyAccessors >, T > > is_eigen_dense_map
std::integral_constant< bool, B > bool_constant
Backports of std::bool_constant and std::negation to accommodate older compilers. ...
static handle cast(const Type &src, return_value_policy policy, handle parent)
Annotation indicating that a class derives from another given type.
EIGEN_DEFAULT_DENSE_INDEX_TYPE EigenIndex
Annotation for function names.
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
std::unique_ptr< Type > ref
Eigen::Map< PlainObjectType, 0, StrideType > MapType
decltype(is_template_base_of_impl< Base >::check((intrinsic_t< T > *) nullptr)) is_template_base_of
is_template_base_of< Eigen::SparseMatrixBase, T > is_eigen_sparse
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
static S make_stride(EigenIndex outer, EigenIndex inner)
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
bool writeable() const
If set, the array is writeable (otherwise the buffer is read-only)
#define NAMESPACE_BEGIN(name)
static handle cast(Type &src, return_value_policy policy, handle parent)
std::unique_ptr< MapType > map
T cast(const handle &handle)
const ssize_t * shape() const
Dimensions of the array.
bool_constant< S::InnerStrideAtCompileTime !=Eigen::Dynamic &&S::OuterStrideAtCompileTime !=Eigen::Dynamic &&std::is_default_constructible< S >::value > stride_ctor_default
handle eigen_ref_array(Type &src, handle parent=none())
static handle cast(Type *src, return_value_policy policy, handle parent)
std::is_base_of< Eigen::MapBase< T, Eigen::WriteAccessors >, T > is_eigen_mutable_map
#define PYBIND11_TYPE_CASTER(type, py_name)
Eigen::Map< MatrixType, 0, EigenDStride > EigenDMap
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
static handle cast(const Type *src, return_value_policy policy, handle parent)
movable_cast_op_type< T > cast_op_type