11#include <pybind11/stl.h>
18#include <Eigen/Cholesky>
20using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
26 for (
int i = 0; i < x.rows(); i++) {
27 for (
int j = 0; j < x.cols(); j++) {
28 x(i, j) = 11 + 10 * i + j;
35 static Eigen::MatrixXd *x;
37 x =
new Eigen::MatrixXd(3, 3);
58double get_elem(
const Eigen::Ref<const Eigen::MatrixXd> &m) {
return m(2, 1); };
62template <
typename MatrixArgType>
64 Eigen::MatrixXd ret(m);
65 for (
int c = 0; c < m.cols(); c++) {
66 for (
int r = 0; r < m.rows(); r++) {
67 ret(r, c) += 10 * r + 100 * c;
76 Eigen::Matrix4d
a = Eigen::Matrix4d::Zero();
77 Eigen::Matrix4d
b = Eigen::Matrix4d::Identity();
83 using FixedMatrixR = Eigen::Matrix<float, 5, 6, Eigen::RowMajor>;
84 using FixedMatrixC = Eigen::Matrix<float, 5, 6>;
85 using DenseMatrixR = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
86 using DenseMatrixC = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
87 using FourRowMatrixC = Eigen::Matrix<float, 4, Eigen::Dynamic>;
88 using FourColMatrixC = Eigen::Matrix<float, Eigen::Dynamic, 4>;
89 using FourRowMatrixR = Eigen::Matrix<float, 4, Eigen::Dynamic>;
90 using FourColMatrixR = Eigen::Matrix<float, Eigen::Dynamic, 4>;
91 using SparseMatrixR = Eigen::SparseMatrix<float, Eigen::RowMajor>;
92 using SparseMatrixC = Eigen::SparseMatrix<float>;
95 m.def(
"double_col", [](
const Eigen::VectorXf &x) -> Eigen::VectorXf {
return 2.0f * x; });
97 [](
const Eigen::RowVectorXf &x) -> Eigen::RowVectorXf {
return 2.0f * x; });
98 m.def(
"double_complex",
99 [](
const Eigen::VectorXcf &x) -> Eigen::VectorXcf {
return 2.0f * x; });
100 m.def(
"double_threec", [](py::EigenDRef<Eigen::Vector3f> x) { x *= 2; });
101 m.def(
"double_threer", [](py::EigenDRef<Eigen::RowVector3f> x) { x *= 2; });
102 m.def(
"double_mat_cm", [](
const Eigen::MatrixXf &x) -> Eigen::MatrixXf {
return 2.0f * x; });
103 m.def(
"double_mat_rm", [](
const DenseMatrixR &x) -> DenseMatrixR {
return 2.0f * x; });
108 [](
const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd {
return x.llt().matrixL(); });
109 m.def(
"cholesky2", [](
const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
110 return x.llt().matrixL();
113 [](
const Eigen::Ref<MatrixXdR> &x) -> Eigen::MatrixXd {
return x.llt().matrixL(); });
114 m.def(
"cholesky4", [](
const Eigen::Ref<const MatrixXdR> &x) -> Eigen::MatrixXd {
115 return x.llt().matrixL();
123 auto add_rm = [](Eigen::Ref<MatrixXdR> x,
int r,
int c,
double v) { x(r, c) += v; };
124 auto add_cm = [](Eigen::Ref<Eigen::MatrixXd> x,
int r,
int c,
double v) { x(r, c) += v; };
127 m.def(
"add_rm", add_rm);
128 m.def(
"add_cm", add_cm);
130 m.def(
"add1", add_rm);
131 m.def(
"add1", add_cm);
132 m.def(
"add2", add_cm);
133 m.def(
"add2", add_rm);
136 [](py::EigenDRef<Eigen::MatrixXd> x,
int r,
int c,
double v) { x(r, c) += v; });
139 m.def(
"get_cm_ref", []() {
return Eigen::Ref<Eigen::MatrixXd>(
get_cm()); });
140 m.def(
"get_rm_ref", []() {
return Eigen::Ref<MatrixXdR>(
get_rm()); });
142 m.def(
"get_cm_const_ref", []() {
return Eigen::Ref<const Eigen::MatrixXd>(
get_cm()); });
143 m.def(
"get_rm_const_ref", []() {
return Eigen::Ref<const MatrixXdR>(
get_rm()); });
150 [](Eigen::Ref<Eigen::MatrixXd> m,
double v) {
151 m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
154 py::return_value_policy::reference);
159 [](py::EigenDRef<Eigen::MatrixXd> m,
double v) {
160 m += Eigen::MatrixXd::Constant(m.rows(), m.cols(), v);
163 py::return_value_policy::reference);
168 [](py::EigenDRef<Eigen::MatrixXd> m) {
169 return py::EigenDMap<Eigen::MatrixXd>(
173 py::EigenDStride(m.outerStride(), 2 * m.innerStride()));
175 py::return_value_policy::reference);
180 [](py::EigenDRef<Eigen::MatrixXd> m) {
181 return py::EigenDMap<Eigen::MatrixXd>(
185 py::EigenDStride(2 * m.outerStride(), m.innerStride()));
187 py::return_value_policy::reference);
190 m.def(
"diagonal", [](
const Eigen::Ref<const Eigen::MatrixXd> &x) {
return x.diagonal(); });
192 [](
const Eigen::Ref<const Eigen::MatrixXd> &x) {
return x.diagonal<1>(); });
194 [](
const Eigen::Ref<const Eigen::MatrixXd> &x,
int index) {
return x.diagonal(index); });
198 [m](
const py::object &x_obj,
203 return m.attr(
"_block")(x_obj, x_obj, start_row, start_col, block_rows, block_cols);
208 [](
const py::object &x_obj,
209 const Eigen::Ref<const Eigen::MatrixXd> &x,
216 auto i0 = py::make_tuple(0, 0);
217 auto x0_orig = x_obj[*i0].cast<
double>();
218 if (x(0, 0) != x0_orig) {
219 throw std::runtime_error(
220 "Something in the type_caster for Eigen::Ref is terribly wrong.");
222 double x0_mod = x0_orig + 1;
224 auto copy_detected = (x(0, 0) != x0_mod);
225 x_obj[*i0] = x0_orig;
227 throw std::runtime_error(
"type_caster for Eigen::Ref made a copy.");
229 return x.block(start_row, start_col, block_rows, block_cols);
231 py::keep_alive<0, 1>());
236 Eigen::MatrixXd mat = create();
241 static Eigen::MatrixXd create() {
return Eigen::MatrixXd::Ones(10, 10); }
243 static const Eigen::MatrixXd createConst() {
return Eigen::MatrixXd::Ones(10, 10); }
244 Eigen::MatrixXd &get() {
return mat; }
245 Eigen::MatrixXd *getPtr() {
return &mat; }
246 const Eigen::MatrixXd &view() {
return mat; }
247 const Eigen::MatrixXd *viewPtr() {
return &mat; }
248 Eigen::Ref<Eigen::MatrixXd>
ref() {
return mat; }
249 Eigen::Ref<const Eigen::MatrixXd> refConst() {
return mat; }
250 Eigen::Block<Eigen::MatrixXd> block(
int r,
int c,
int nrow,
int ncol) {
251 return mat.block(r, c, nrow, ncol);
253 Eigen::Block<const Eigen::MatrixXd> blockConst(
int r,
int c,
int nrow,
int ncol)
const {
254 return mat.block(r, c, nrow, ncol);
256 py::EigenDMap<Eigen::Matrix2d> corners() {
257 return py::EigenDMap<Eigen::Matrix2d>(
259 py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
260 mat.innerStride() * (mat.innerSize() - 1)));
262 py::EigenDMap<const Eigen::Matrix2d> cornersConst()
const {
263 return py::EigenDMap<const Eigen::Matrix2d>(
265 py::EigenDStride(mat.outerStride() * (mat.outerSize() - 1),
266 mat.innerStride() * (mat.innerSize() - 1)));
269 using rvp = py::return_value_policy;
270 py::class_<ReturnTester>(m,
"ReturnTester")
272 .def_static(
"create", &ReturnTester::create)
273 .def_static(
"create_const", &ReturnTester::createConst)
274 .def(
"get", &ReturnTester::get, rvp::reference_internal)
275 .def(
"get_ptr", &ReturnTester::getPtr, rvp::reference_internal)
276 .def(
"view", &ReturnTester::view, rvp::reference_internal)
277 .def(
"view_ptr", &ReturnTester::view, rvp::reference_internal)
278 .def(
"copy_get", &ReturnTester::get)
279 .def(
"copy_view", &ReturnTester::view)
280 .def(
"ref", &ReturnTester::ref)
281 .def(
"ref_const", &ReturnTester::refConst)
282 .def(
"ref_safe", &ReturnTester::ref, rvp::reference_internal)
283 .def(
"ref_const_safe", &ReturnTester::refConst, rvp::reference_internal)
284 .def(
"copy_ref", &ReturnTester::ref, rvp::copy)
285 .def(
"copy_ref_const", &ReturnTester::refConst, rvp::copy)
286 .def(
"block", &ReturnTester::block)
287 .def(
"block_safe", &ReturnTester::block, rvp::reference_internal)
288 .def(
"block_const", &ReturnTester::blockConst, rvp::reference_internal)
289 .def(
"copy_block", &ReturnTester::block, rvp::copy)
290 .def(
"corners", &ReturnTester::corners, rvp::reference_internal)
291 .def(
"corners_const", &ReturnTester::cornersConst, rvp::reference_internal);
295 m.def(
"incr_diag", [](
int k) {
296 Eigen::DiagonalMatrix<int, Eigen::Dynamic> m(k);
297 for (
int i = 0; i < k; i++) {
298 m.diagonal()[i] = i + 1;
304 m.def(
"symmetric_lower",
305 [](
const Eigen::MatrixXi &m) {
return m.selfadjointView<Eigen::Lower>(); });
307 m.def(
"symmetric_upper",
308 [](
const Eigen::MatrixXi &m) {
return m.selfadjointView<Eigen::Upper>(); });
311 Eigen::MatrixXf mat(5, 6);
312 mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 14,
316 m.def(
"fixed_r", [mat]() -> FixedMatrixR {
return FixedMatrixR(mat); });
320 m.def(
"fixed_r_const", [mat]() ->
const FixedMatrixR {
return FixedMatrixR(mat); });
321 m.def(
"fixed_c", [mat]() -> FixedMatrixC {
return FixedMatrixC(mat); });
322 m.def(
"fixed_copy_r", [](
const FixedMatrixR &m) -> FixedMatrixR {
return m; });
323 m.def(
"fixed_copy_c", [](
const FixedMatrixC &m) -> FixedMatrixC {
return m; });
325 m.def(
"fixed_mutator_r", [](
const Eigen::Ref<FixedMatrixR> &) {});
326 m.def(
"fixed_mutator_c", [](
const Eigen::Ref<FixedMatrixC> &) {});
327 m.def(
"fixed_mutator_a", [](
const py::EigenDRef<FixedMatrixC> &) {});
329 m.def(
"dense_r", [mat]() -> DenseMatrixR {
return DenseMatrixR(mat); });
330 m.def(
"dense_c", [mat]() -> DenseMatrixC {
return DenseMatrixC(mat); });
331 m.def(
"dense_copy_r", [](
const DenseMatrixR &m) -> DenseMatrixR {
return m; });
332 m.def(
"dense_copy_c", [](
const DenseMatrixC &m) -> DenseMatrixC {
return m; });
334 m.def(
"sparse_r", [mat]() -> SparseMatrixR {
336 return Eigen::SparseView<Eigen::MatrixXf>(mat);
339 [mat]() -> SparseMatrixC {
return Eigen::SparseView<Eigen::MatrixXf>(mat); });
340 m.def(
"sparse_copy_r", [](
const SparseMatrixR &m) -> SparseMatrixR {
return m; });
341 m.def(
"sparse_copy_c", [](
const SparseMatrixC &m) -> SparseMatrixC {
return m; });
343 m.def(
"partial_copy_four_rm_r", [](
const FourRowMatrixR &m) -> FourRowMatrixR {
return m; });
344 m.def(
"partial_copy_four_rm_c", [](
const FourColMatrixR &m) -> FourColMatrixR {
return m; });
345 m.def(
"partial_copy_four_cm_r", [](
const FourRowMatrixC &m) -> FourRowMatrixC {
return m; });
346 m.def(
"partial_copy_four_cm_c", [](
const FourColMatrixC &m) -> FourColMatrixC {
return m; });
350 m.def(
"cpp_copy", [](py::handle m) {
return m.cast<Eigen::MatrixXd>()(1, 0); });
351 m.def(
"cpp_ref_c", [](py::handle m) {
return m.cast<Eigen::Ref<Eigen::MatrixXd>>()(1, 0); });
352 m.def(
"cpp_ref_r", [](py::handle m) {
return m.cast<Eigen::Ref<MatrixXdR>>()(1, 0); });
354 [](py::handle m) {
return m.cast<py::EigenDRef<Eigen::MatrixXd>>()(1, 0); });
365 [](
const Eigen::Ref<const Eigen::MatrixXd> &m) ->
double {
return get_elem(m); },
366 py::arg{}.noconvert());
369 "get_elem_rm_nocopy",
370 [](Eigen::Ref<
const Eigen::Matrix<long, -1, -1, Eigen::RowMajor>> &m) ->
long {
373 py::arg{}.noconvert());
384 py::arg{}.noconvert());
386 &
adjust_matrix<
const Eigen::Ref<
const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>,
387 py::arg{}.noconvert());
393 m.def(
"iss1105_col", [](
const Eigen::VectorXd &) {
return true; });
394 m.def(
"iss1105_row", [](
const Eigen::RowVectorXd &) {
return true; });
400 [](
const py::EigenDRef<const Eigen::MatrixXd> &
A,
401 const py::EigenDRef<const Eigen::MatrixXd> &
B) -> Eigen::MatrixXd {
402 if (
A.cols() !=
B.rows()) {
403 throw std::domain_error(
"Nonconformable matrices!");
411 py::class_<CustomOperatorNew>(m,
"CustomOperatorNew")
420 m.def(
"get_elem_direct", [](
const Eigen::Ref<const Eigen::VectorXd> &v) {
421 py::module_::import(
"numpy").attr(
"ones")(10);
424 m.def(
"get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
425 py::module_::import(
"numpy").attr(
"ones")(10);
Reference counting helper.
void print_created(T *inst, Values &&...values)
void print_destroyed(T *inst, Values &&...values)
#define TEST_SUBMODULE(name, variable)
#define PYBIND11_WARNING_DISABLE_MSVC(name)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
CustomOperatorNew()=default
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > MatrixXdR
Eigen::MatrixXd adjust_matrix(MatrixArgType m)
double get_elem(const Eigen::Ref< const Eigen::MatrixXd > &m)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > MatrixXdR
Eigen::MatrixXd & get_cm()