.. _program_listing_file__tmp_ws_src_eigenpy_include_eigenpy_eigen-from-python.hpp: Program Listing for File eigen-from-python.hpp ============================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/eigenpy/include/eigenpy/eigen-from-python.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // // Copyright (c) 2014-2023 CNRS INRIA // #ifndef __eigenpy_eigen_from_python_hpp__ #define __eigenpy_eigen_from_python_hpp__ #include "eigenpy/fwd.hpp" #include "eigenpy/eigen-allocator.hpp" #include "eigenpy/numpy-type.hpp" #include "eigenpy/scalar-conversion.hpp" namespace eigenpy { template ::type> struct expected_pytype_for_arg {}; template struct expected_pytype_for_arg > { static PyTypeObject const *get_pytype() { PyTypeObject const *py_type = eigenpy::getPyArrayType(); return py_type; } }; } // namespace eigenpy namespace boost { namespace python { namespace converter { template struct expected_pytype_for_arg< Eigen::Matrix > : eigenpy::expected_pytype_for_arg< Eigen::Matrix > {}; } // namespace converter } // namespace python } // namespace boost namespace eigenpy { namespace details { template ::value> struct copy_if_non_const { static void run(const Eigen::MatrixBase &input, PyArrayObject *pyArray) { EigenAllocator::copy(input, pyArray); } }; template struct copy_if_non_const { static void run(const Eigen::MatrixBase & /*input*/, PyArrayObject * /*pyArray*/) {} }; #if EIGEN_VERSION_AT_LEAST(3, 2, 0) template struct referent_storage_eigen_ref { typedef _RefType RefType; typedef typename get_eigen_plain_type::type PlainObjectType; typedef typename ::eigenpy::aligned_storage< ::boost::python::detail::referent_size::value>::type AlignedStorage; referent_storage_eigen_ref() : pyArray(NULL), plain_ptr(NULL), ref_ptr(reinterpret_cast(ref_storage.bytes)) {} referent_storage_eigen_ref(const RefType &ref, PyArrayObject *pyArray, PlainObjectType *plain_ptr = NULL) : pyArray(pyArray), plain_ptr(plain_ptr), ref_ptr(reinterpret_cast(ref_storage.bytes)) { Py_INCREF(pyArray); new (ref_storage.bytes) RefType(ref); } ~referent_storage_eigen_ref() { if (plain_ptr != NULL && PyArray_ISWRITEABLE(pyArray)) copy_if_non_const::run(*plain_ptr, pyArray); Py_DECREF(pyArray); if (plain_ptr != NULL) plain_ptr->~PlainObjectType(); ref_ptr->~RefType(); } AlignedStorage ref_storage; PyArrayObject *pyArray; PlainObjectType *plain_ptr; RefType *ref_ptr; }; #endif } // namespace details } // namespace eigenpy namespace boost { namespace python { namespace detail { #if EIGEN_VERSION_AT_LEAST(3, 2, 0) template struct referent_storage &> { typedef Eigen::Ref RefType; typedef ::eigenpy::details::referent_storage_eigen_ref StorageType; typedef typename ::eigenpy::aligned_storage< referent_size::value>::type type; }; template struct referent_storage &> { typedef Eigen::Ref RefType; typedef ::eigenpy::details::referent_storage_eigen_ref StorageType; typedef typename ::eigenpy::aligned_storage< referent_size::value>::type type; }; #endif } // namespace detail } // namespace python } // namespace boost namespace boost { namespace python { namespace converter { #define EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(type) \ typedef ::eigenpy::rvalue_from_python_data Base; \ \ rvalue_from_python_data(rvalue_from_python_stage1_data const &_stage1) \ : Base(_stage1) {} \ \ rvalue_from_python_data(void *convertible) : Base(convertible){}; template struct rvalue_from_python_data< Eigen::Matrix const &> : ::eigenpy::rvalue_from_python_data const &> { typedef Eigen::Matrix T; EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(T const &) }; template struct rvalue_from_python_data const &> : ::eigenpy::rvalue_from_python_data { EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(Derived const &) }; template struct rvalue_from_python_data const &> : ::eigenpy::rvalue_from_python_data { EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(Derived const &) }; template struct rvalue_from_python_data const &> : ::eigenpy::rvalue_from_python_data { EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(Derived const &) }; template struct rvalue_from_python_data &> : rvalue_from_python_storage &> { typedef Eigen::Ref RefType; #if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) && \ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) && \ (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) && \ !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing \ this */ // This must always be a POD struct with m_data its first member. BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage, stage1) == 0); #endif // The usual constructor rvalue_from_python_data(rvalue_from_python_stage1_data const &_stage1) { this->stage1 = _stage1; } // This constructor just sets m_convertible -- used by // implicitly_convertible<> to perform the final step of the // conversion, where the construct() function is already known. rvalue_from_python_data(void *convertible) { this->stage1.convertible = convertible; } // Destroys any object constructed in the storage. ~rvalue_from_python_data() { typedef ::eigenpy::details::referent_storage_eigen_ref StorageType; if (this->stage1.convertible == this->storage.bytes) static_cast((void *)this->storage.bytes)->~StorageType(); } }; template struct rvalue_from_python_data< const Eigen::Ref &> : rvalue_from_python_storage< const Eigen::Ref &> { typedef Eigen::Ref RefType; #if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) && \ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) && \ (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) && \ !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing \ this */ // This must always be a POD struct with m_data its first member. BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage, stage1) == 0); #endif // The usual constructor rvalue_from_python_data(rvalue_from_python_stage1_data const &_stage1) { this->stage1 = _stage1; } // This constructor just sets m_convertible -- used by // implicitly_convertible<> to perform the final step of the // conversion, where the construct() function is already known. rvalue_from_python_data(void *convertible) { this->stage1.convertible = convertible; } // Destroys any object constructed in the storage. ~rvalue_from_python_data() { typedef ::eigenpy::details::referent_storage_eigen_ref StorageType; if (this->stage1.convertible == this->storage.bytes) static_cast((void *)this->storage.bytes)->~StorageType(); } }; } // namespace converter } // namespace python } // namespace boost namespace eigenpy { template void eigen_from_py_construct( PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory) { PyArrayObject *pyArray = reinterpret_cast(pyObj); assert((PyArray_DIMS(pyArray)[0] < INT_MAX) && (PyArray_DIMS(pyArray)[1] < INT_MAX)); bp::converter::rvalue_from_python_storage *storage = reinterpret_cast< bp::converter::rvalue_from_python_storage *>( reinterpret_cast(memory)); EigenAllocator::allocate(pyArray, storage); memory->convertible = storage->storage.bytes; } template ::type> struct eigen_from_py_impl { typedef typename EigenType::Scalar Scalar; static void *convertible(PyObject *pyObj); static void construct(PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory); static void registration(); }; template struct eigen_from_py_impl > { typedef typename MatType::Scalar Scalar; static void *convertible(PyObject *pyObj); static void construct(PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory); static void registration(); }; #ifdef EIGENPY_MSVC_COMPILER template struct EigenFromPy::type::Scalar> #else template struct EigenFromPy #endif : eigen_from_py_impl { }; template void *eigen_from_py_impl >::convertible( PyObject *pyObj) { if (!call_PyArray_Check(reinterpret_cast(pyObj))) return 0; PyArrayObject *pyArray = reinterpret_cast(pyObj); if (!np_type_is_convertible_into_scalar( EIGENPY_GET_PY_ARRAY_TYPE(pyArray))) return 0; if (MatType::IsVectorAtCompileTime) { const Eigen::DenseIndex size_at_compile_time = MatType::IsRowMajor ? MatType::ColsAtCompileTime : MatType::RowsAtCompileTime; switch (PyArray_NDIM(pyArray)) { case 0: return 0; case 1: { if (size_at_compile_time != Eigen::Dynamic) { // check that the sizes at compile time matche if (PyArray_DIMS(pyArray)[0] == size_at_compile_time) return pyArray; else return 0; } else // This is a dynamic MatType return pyArray; } case 2: { // Special care of scalar matrix of dimension 1x1. if (PyArray_DIMS(pyArray)[0] == 1 && PyArray_DIMS(pyArray)[1] == 1) { if (size_at_compile_time != Eigen::Dynamic) { if (size_at_compile_time == 1) return pyArray; else return 0; } else // This is a dynamic MatType return pyArray; } if (PyArray_DIMS(pyArray)[0] > 1 && PyArray_DIMS(pyArray)[1] > 1) { return 0; } if (((PyArray_DIMS(pyArray)[0] == 1) && (MatType::ColsAtCompileTime == 1)) || ((PyArray_DIMS(pyArray)[1] == 1) && (MatType::RowsAtCompileTime == 1))) { return 0; } if (size_at_compile_time != Eigen::Dynamic) { // This is a fixe size vector const Eigen::DenseIndex pyArray_size = PyArray_DIMS(pyArray)[0] > PyArray_DIMS(pyArray)[1] ? PyArray_DIMS(pyArray)[0] : PyArray_DIMS(pyArray)[1]; if (size_at_compile_time != pyArray_size) return 0; } break; } default: return 0; } } else // this is a matrix { if (PyArray_NDIM(pyArray) == 1) // We can always convert a vector into a matrix { return pyArray; } if (PyArray_NDIM(pyArray) != 2) { return 0; } if (PyArray_NDIM(pyArray) == 2) { const int R = (int)PyArray_DIMS(pyArray)[0]; const int C = (int)PyArray_DIMS(pyArray)[1]; if ((MatType::RowsAtCompileTime != R) && (MatType::RowsAtCompileTime != Eigen::Dynamic)) return 0; if ((MatType::ColsAtCompileTime != C) && (MatType::ColsAtCompileTime != Eigen::Dynamic)) return 0; } } #ifdef NPY_1_8_API_VERSION if (!(PyArray_FLAGS(pyArray))) #else if (!(PyArray_FLAGS(pyArray) & NPY_ALIGNED)) #endif { return 0; } return pyArray; } template void eigen_from_py_impl >::construct( PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory) { eigen_from_py_construct(pyObj, memory); } template void eigen_from_py_impl >::registration() { bp::converter::registry::push_back( reinterpret_cast(&eigen_from_py_impl::convertible), &eigen_from_py_impl::construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } template ::type> struct eigen_from_py_converter_impl; template struct EigenFromPyConverter : eigen_from_py_converter_impl {}; template struct eigen_from_py_converter_impl > { static void registration() { EigenFromPy::registration(); // Add conversion to Eigen::MatrixBase typedef Eigen::MatrixBase MatrixBase; EigenFromPy::registration(); // Add conversion to Eigen::EigenBase typedef Eigen::EigenBase EigenBase; EigenFromPy::registration(); // Add conversion to Eigen::PlainObjectBase typedef Eigen::PlainObjectBase PlainObjectBase; EigenFromPy::registration(); #if EIGEN_VERSION_AT_LEAST(3, 2, 0) // Add conversion to Eigen::Ref typedef Eigen::Ref RefType; EigenFromPy::registration(); // Add conversion to Eigen::Ref typedef const Eigen::Ref ConstRefType; EigenFromPy::registration(); #endif } }; template struct EigenFromPy > : EigenFromPy { typedef EigenFromPy EigenFromPyDerived; typedef Eigen::MatrixBase Base; static void registration() { bp::converter::registry::push_back( reinterpret_cast(&EigenFromPy::convertible), &EigenFromPy::construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } }; template struct EigenFromPy, typename MatType::Scalar> : EigenFromPy { typedef EigenFromPy EigenFromPyDerived; typedef Eigen::EigenBase Base; static void registration() { bp::converter::registry::push_back( reinterpret_cast(&EigenFromPy::convertible), &EigenFromPy::construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } }; template struct EigenFromPy > : EigenFromPy { typedef EigenFromPy EigenFromPyDerived; typedef Eigen::PlainObjectBase Base; static void registration() { bp::converter::registry::push_back( reinterpret_cast(&EigenFromPy::convertible), &EigenFromPy::construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } }; #if EIGEN_VERSION_AT_LEAST(3, 2, 0) template struct EigenFromPy > { typedef Eigen::Ref RefType; typedef typename MatType::Scalar Scalar; static void *convertible(PyObject *pyObj) { if (!call_PyArray_Check(pyObj)) return 0; PyArrayObject *pyArray = reinterpret_cast(pyObj); if (!PyArray_ISWRITEABLE(pyArray)) return 0; return EigenFromPy::convertible(pyObj); } static void registration() { bp::converter::registry::push_back( reinterpret_cast(&EigenFromPy::convertible), &eigen_from_py_construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } }; template struct EigenFromPy > { typedef const Eigen::Ref ConstRefType; typedef typename MatType::Scalar Scalar; static void *convertible(PyObject *pyObj) { return EigenFromPy::convertible(pyObj); } static void registration() { bp::converter::registry::push_back( reinterpret_cast(&EigenFromPy::convertible), &eigen_from_py_construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &eigenpy::expected_pytype_for_arg::get_pytype #endif ); } }; #endif } // namespace eigenpy #ifdef EIGENPY_WITH_TENSOR_SUPPORT #include "eigenpy/tensor/eigen-from-python.hpp" #endif #include "eigenpy/sparse/eigen-from-python.hpp" #endif // __eigenpy_eigen_from_python_hpp__