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>;
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>;
86 if (rstride < 0 || cstride < 0) {
89 stride = {EigenRowMajor ? rstride : cstride ,
90 EigenRowMajor ? cstride : rstride };
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);
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
133 template <EigenIndex i, EigenIndex ifzero>
using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
145 const auto dims = a.
ndim();
146 if (dims < 1 || dims > 2)
152 np_rows = a.
shape(0),
153 np_cols = a.
shape(1),
159 return {np_rows, np_cols, np_rstride, np_cstride};
170 return {
rows == 1 ? 1 : n,
cols == 1 ? 1 : n, stride};
179 if (
cols != n)
return false;
180 return {1, n, stride};
185 return {n, 1, stride};
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() },
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>
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:
303 return eigen_array_cast<props>(*src);
305 case return_value_policy::automatic_reference:
306 return eigen_ref_array<props>(*src);
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;
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:
372 return eigen_array_cast<props>(src);
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");
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 auto 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;
456 Array copy = Array::ensure(src);
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; }
474 template <
typename _T>
using cast_op_type = pybind11::detail::cast_op_type<_T>;
481 const Scalar *
data(Array &a) {
return a.data(); }
485 template <
typename S>
using stride_ctor_default =
bool_constant<
486 S::InnerStrideAtCompileTime != Eigen::Dynamic && S::OuterStrideAtCompileTime != Eigen::Dynamic &&
490 template <
typename S>
using stride_ctor_dual =
bool_constant<
494 template <
typename S>
using stride_ctor_outer =
bool_constant<
496 S::OuterStrideAtCompileTime == Eigen::Dynamic && S::InnerStrideAtCompileTime != Eigen::Dynamic &&
498 template <
typename S>
using stride_ctor_inner =
bool_constant<
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;
536 operator Type() =
delete;
540 template<
typename Type>
545 static constexpr
bool rowMajor = Type::IsRowMajor;
551 auto obj = reinterpret_borrow<object>(src);
553 object matrix_type = sparse_module.attr(
554 rowMajor ?
"csr_matrix" :
"csc_matrix");
558 obj = matrix_type(obj);
567 auto shape = pybind11::tuple((pybind11::object) obj.attr(
"shape"));
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,
575 outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
581 const_cast<Type&
>(src).makeCompressed();
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)