github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/pybind11/docs/advanced/cast/eigen.rst (about) 1 Eigen 2 ##### 3 4 `Eigen <http://eigen.tuxfamily.org>`_ is C++ header-based library for dense and 5 sparse linear algebra. Due to its popularity and widespread adoption, pybind11 6 provides transparent conversion and limited mapping support between Eigen and 7 Scientific Python linear algebra data types. 8 9 To enable the built-in Eigen support you must include the optional header file 10 :file:`pybind11/eigen.h`. 11 12 Pass-by-value 13 ============= 14 15 When binding a function with ordinary Eigen dense object arguments (for 16 example, ``Eigen::MatrixXd``), pybind11 will accept any input value that is 17 already (or convertible to) a ``numpy.ndarray`` with dimensions compatible with 18 the Eigen type, copy its values into a temporary Eigen variable of the 19 appropriate type, then call the function with this temporary variable. 20 21 Sparse matrices are similarly copied to or from 22 ``scipy.sparse.csr_matrix``/``scipy.sparse.csc_matrix`` objects. 23 24 Pass-by-reference 25 ================= 26 27 One major limitation of the above is that every data conversion implicitly 28 involves a copy, which can be both expensive (for large matrices) and disallows 29 binding functions that change their (Matrix) arguments. Pybind11 allows you to 30 work around this by using Eigen's ``Eigen::Ref<MatrixType>`` class much as you 31 would when writing a function taking a generic type in Eigen itself (subject to 32 some limitations discussed below). 33 34 When calling a bound function accepting a ``Eigen::Ref<const MatrixType>`` 35 type, pybind11 will attempt to avoid copying by using an ``Eigen::Map`` object 36 that maps into the source ``numpy.ndarray`` data: this requires both that the 37 data types are the same (e.g. ``dtype='float64'`` and ``MatrixType::Scalar`` is 38 ``double``); and that the storage is layout compatible. The latter limitation 39 is discussed in detail in the section below, and requires careful 40 consideration: by default, numpy matrices and Eigen matrices are *not* storage 41 compatible. 42 43 If the numpy matrix cannot be used as is (either because its types differ, e.g. 44 passing an array of integers to an Eigen parameter requiring doubles, or 45 because the storage is incompatible), pybind11 makes a temporary copy and 46 passes the copy instead. 47 48 When a bound function parameter is instead ``Eigen::Ref<MatrixType>`` (note the 49 lack of ``const``), pybind11 will only allow the function to be called if it 50 can be mapped *and* if the numpy array is writeable (that is 51 ``a.flags.writeable`` is true). Any access (including modification) made to 52 the passed variable will be transparently carried out directly on the 53 ``numpy.ndarray``. 54 55 This means you can write code such as the following and have it work as 56 expected: 57 58 .. code-block:: cpp 59 60 void scale_by_2(Eigen::Ref<Eigen::VectorXd> v) { 61 v *= 2; 62 } 63 64 Note, however, that you will likely run into limitations due to numpy and 65 Eigen's difference default storage order for data; see the below section on 66 :ref:`storage_orders` for details on how to bind code that won't run into such 67 limitations. 68 69 .. note:: 70 71 Passing by reference is not supported for sparse types. 72 73 Returning values to Python 74 ========================== 75 76 When returning an ordinary dense Eigen matrix type to numpy (e.g. 77 ``Eigen::MatrixXd`` or ``Eigen::RowVectorXf``) pybind11 keeps the matrix and 78 returns a numpy array that directly references the Eigen matrix: no copy of the 79 data is performed. The numpy array will have ``array.flags.owndata`` set to 80 ``False`` to indicate that it does not own the data, and the lifetime of the 81 stored Eigen matrix will be tied to the returned ``array``. 82 83 If you bind a function with a non-reference, ``const`` return type (e.g. 84 ``const Eigen::MatrixXd``), the same thing happens except that pybind11 also 85 sets the numpy array's ``writeable`` flag to false. 86 87 If you return an lvalue reference or pointer, the usual pybind11 rules apply, 88 as dictated by the binding function's return value policy (see the 89 documentation on :ref:`return_value_policies` for full details). That means, 90 without an explicit return value policy, lvalue references will be copied and 91 pointers will be managed by pybind11. In order to avoid copying, you should 92 explicitly specify an appropriate return value policy, as in the following 93 example: 94 95 .. code-block:: cpp 96 97 class MyClass { 98 Eigen::MatrixXd big_mat = Eigen::MatrixXd::Zero(10000, 10000); 99 public: 100 Eigen::MatrixXd &getMatrix() { return big_mat; } 101 const Eigen::MatrixXd &viewMatrix() { return big_mat; } 102 }; 103 104 // Later, in binding code: 105 py::class_<MyClass>(m, "MyClass") 106 .def(py::init<>()) 107 .def("copy_matrix", &MyClass::getMatrix) // Makes a copy! 108 .def("get_matrix", &MyClass::getMatrix, py::return_value_policy::reference_internal) 109 .def("view_matrix", &MyClass::viewMatrix, py::return_value_policy::reference_internal) 110 ; 111 112 .. code-block:: python 113 114 a = MyClass() 115 m = a.get_matrix() # flags.writeable = True, flags.owndata = False 116 v = a.view_matrix() # flags.writeable = False, flags.owndata = False 117 c = a.copy_matrix() # flags.writeable = True, flags.owndata = True 118 # m[5,6] and v[5,6] refer to the same element, c[5,6] does not. 119 120 Note in this example that ``py::return_value_policy::reference_internal`` is 121 used to tie the life of the MyClass object to the life of the returned arrays. 122 123 You may also return an ``Eigen::Ref``, ``Eigen::Map`` or other map-like Eigen 124 object (for example, the return value of ``matrix.block()`` and related 125 methods) that map into a dense Eigen type. When doing so, the default 126 behaviour of pybind11 is to simply reference the returned data: you must take 127 care to ensure that this data remains valid! You may ask pybind11 to 128 explicitly *copy* such a return value by using the 129 ``py::return_value_policy::copy`` policy when binding the function. You may 130 also use ``py::return_value_policy::reference_internal`` or a 131 ``py::keep_alive`` to ensure the data stays valid as long as the returned numpy 132 array does. 133 134 When returning such a reference of map, pybind11 additionally respects the 135 readonly-status of the returned value, marking the numpy array as non-writeable 136 if the reference or map was itself read-only. 137 138 .. note:: 139 140 Sparse types are always copied when returned. 141 142 .. _storage_orders: 143 144 Storage orders 145 ============== 146 147 Passing arguments via ``Eigen::Ref`` has some limitations that you must be 148 aware of in order to effectively pass matrices by reference. First and 149 foremost is that the default ``Eigen::Ref<MatrixType>`` class requires 150 contiguous storage along columns (for column-major types, the default in Eigen) 151 or rows if ``MatrixType`` is specifically an ``Eigen::RowMajor`` storage type. 152 The former, Eigen's default, is incompatible with ``numpy``'s default row-major 153 storage, and so you will not be able to pass numpy arrays to Eigen by reference 154 without making one of two changes. 155 156 (Note that this does not apply to vectors (or column or row matrices): for such 157 types the "row-major" and "column-major" distinction is meaningless). 158 159 The first approach is to change the use of ``Eigen::Ref<MatrixType>`` to the 160 more general ``Eigen::Ref<MatrixType, 0, Eigen::Stride<Eigen::Dynamic, 161 Eigen::Dynamic>>`` (or similar type with a fully dynamic stride type in the 162 third template argument). Since this is a rather cumbersome type, pybind11 163 provides a ``py::EigenDRef<MatrixType>`` type alias for your convenience (along 164 with EigenDMap for the equivalent Map, and EigenDStride for just the stride 165 type). 166 167 This type allows Eigen to map into any arbitrary storage order. This is not 168 the default in Eigen for performance reasons: contiguous storage allows 169 vectorization that cannot be done when storage is not known to be contiguous at 170 compile time. The default ``Eigen::Ref`` stride type allows non-contiguous 171 storage along the outer dimension (that is, the rows of a column-major matrix 172 or columns of a row-major matrix), but not along the inner dimension. 173 174 This type, however, has the added benefit of also being able to map numpy array 175 slices. For example, the following (contrived) example uses Eigen with a numpy 176 slice to multiply by 2 all coefficients that are both on even rows (0, 2, 4, 177 ...) and in columns 2, 5, or 8: 178 179 .. code-block:: cpp 180 181 m.def("scale", [](py::EigenDRef<Eigen::MatrixXd> m, double c) { m *= c; }); 182 183 .. code-block:: python 184 185 # a = np.array(...) 186 scale_by_2(myarray[0::2, 2:9:3]) 187 188 The second approach to avoid copying is more intrusive: rearranging the 189 underlying data types to not run into the non-contiguous storage problem in the 190 first place. In particular, that means using matrices with ``Eigen::RowMajor`` 191 storage, where appropriate, such as: 192 193 .. code-block:: cpp 194 195 using RowMatrixXd = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>; 196 // Use RowMatrixXd instead of MatrixXd 197 198 Now bound functions accepting ``Eigen::Ref<RowMatrixXd>`` arguments will be 199 callable with numpy's (default) arrays without involving a copying. 200 201 You can, alternatively, change the storage order that numpy arrays use by 202 adding the ``order='F'`` option when creating an array: 203 204 .. code-block:: python 205 206 myarray = np.array(source, order="F") 207 208 Such an object will be passable to a bound function accepting an 209 ``Eigen::Ref<MatrixXd>`` (or similar column-major Eigen type). 210 211 One major caveat with this approach, however, is that it is not entirely as 212 easy as simply flipping all Eigen or numpy usage from one to the other: some 213 operations may alter the storage order of a numpy array. For example, ``a2 = 214 array.transpose()`` results in ``a2`` being a view of ``array`` that references 215 the same data, but in the opposite storage order! 216 217 While this approach allows fully optimized vectorized calculations in Eigen, it 218 cannot be used with array slices, unlike the first approach. 219 220 When *returning* a matrix to Python (either a regular matrix, a reference via 221 ``Eigen::Ref<>``, or a map/block into a matrix), no special storage 222 consideration is required: the created numpy array will have the required 223 stride that allows numpy to properly interpret the array, whatever its storage 224 order. 225 226 Failing rather than copying 227 =========================== 228 229 The default behaviour when binding ``Eigen::Ref<const MatrixType>`` Eigen 230 references is to copy matrix values when passed a numpy array that does not 231 conform to the element type of ``MatrixType`` or does not have a compatible 232 stride layout. If you want to explicitly avoid copying in such a case, you 233 should bind arguments using the ``py::arg().noconvert()`` annotation (as 234 described in the :ref:`nonconverting_arguments` documentation). 235 236 The following example shows an example of arguments that don't allow data 237 copying to take place: 238 239 .. code-block:: cpp 240 241 // The method and function to be bound: 242 class MyClass { 243 // ... 244 double some_method(const Eigen::Ref<const MatrixXd> &matrix) { /* ... */ } 245 }; 246 float some_function(const Eigen::Ref<const MatrixXf> &big, 247 const Eigen::Ref<const MatrixXf> &small) { 248 // ... 249 } 250 251 // The associated binding code: 252 using namespace pybind11::literals; // for "arg"_a 253 py::class_<MyClass>(m, "MyClass") 254 // ... other class definitions 255 .def("some_method", &MyClass::some_method, py::arg().noconvert()); 256 257 m.def("some_function", &some_function, 258 "big"_a.noconvert(), // <- Don't allow copying for this arg 259 "small"_a // <- This one can be copied if needed 260 ); 261 262 With the above binding code, attempting to call the the ``some_method(m)`` 263 method on a ``MyClass`` object, or attempting to call ``some_function(m, m2)`` 264 will raise a ``RuntimeError`` rather than making a temporary copy of the array. 265 It will, however, allow the ``m2`` argument to be copied into a temporary if 266 necessary. 267 268 Note that explicitly specifying ``.noconvert()`` is not required for *mutable* 269 Eigen references (e.g. ``Eigen::Ref<MatrixXd>`` without ``const`` on the 270 ``MatrixXd``): mutable references will never be called with a temporary copy. 271 272 Vectors versus column/row matrices 273 ================================== 274 275 Eigen and numpy have fundamentally different notions of a vector. In Eigen, a 276 vector is simply a matrix with the number of columns or rows set to 1 at 277 compile time (for a column vector or row vector, respectively). NumPy, in 278 contrast, has comparable 2-dimensional 1xN and Nx1 arrays, but *also* has 279 1-dimensional arrays of size N. 280 281 When passing a 2-dimensional 1xN or Nx1 array to Eigen, the Eigen type must 282 have matching dimensions: That is, you cannot pass a 2-dimensional Nx1 numpy 283 array to an Eigen value expecting a row vector, or a 1xN numpy array as a 284 column vector argument. 285 286 On the other hand, pybind11 allows you to pass 1-dimensional arrays of length N 287 as Eigen parameters. If the Eigen type can hold a column vector of length N it 288 will be passed as such a column vector. If not, but the Eigen type constraints 289 will accept a row vector, it will be passed as a row vector. (The column 290 vector takes precedence when both are supported, for example, when passing a 291 1D numpy array to a MatrixXd argument). Note that the type need not be 292 explicitly a vector: it is permitted to pass a 1D numpy array of size 5 to an 293 Eigen ``Matrix<double, Dynamic, 5>``: you would end up with a 1x5 Eigen matrix. 294 Passing the same to an ``Eigen::MatrixXd`` would result in a 5x1 Eigen matrix. 295 296 When returning an Eigen vector to numpy, the conversion is ambiguous: a row 297 vector of length 4 could be returned as either a 1D array of length 4, or as a 298 2D array of size 1x4. When encountering such a situation, pybind11 compromises 299 by considering the returned Eigen type: if it is a compile-time vector--that 300 is, the type has either the number of rows or columns set to 1 at compile 301 time--pybind11 converts to a 1D numpy array when returning the value. For 302 instances that are a vector only at run-time (e.g. ``MatrixXd``, 303 ``Matrix<float, Dynamic, 4>``), pybind11 returns the vector as a 2D array to 304 numpy. If this isn't want you want, you can use ``array.reshape(...)`` to get 305 a view of the same data in the desired dimensions. 306 307 .. seealso:: 308 309 The file :file:`tests/test_eigen.cpp` contains a complete example that 310 shows how to pass Eigen sparse and dense data types in more detail.