diff --git a/cmake b/cmake index 3a52692a40839b10f38352c1b06ccfebc0b53f36..094834088ad9de32f1abdc2d56d29bca2190772c 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 3a52692a40839b10f38352c1b06ccfebc0b53f36 +Subproject commit 094834088ad9de32f1abdc2d56d29bca2190772c diff --git a/include/eigenpy/numpy-type.hpp b/include/eigenpy/numpy-type.hpp index c9bccd774380df3364016b57ecbd3660af7d5100..bef0f187bd6c1dec63818675d7c84e9f08c1e2c9 100644 --- a/include/eigenpy/numpy-type.hpp +++ b/include/eigenpy/numpy-type.hpp @@ -7,6 +7,7 @@ #include "eigenpy/fwd.hpp" #include "eigenpy/scalar-conversion.hpp" +#include "eigenpy/register.hpp" #include <stdexcept> #include <typeinfo> @@ -16,33 +17,15 @@ namespace eigenpy { namespace bp = boost::python; - // By default, the Scalar is considered as a Python object - template <typename Scalar> struct NumpyEquivalentType { enum { type_code = NPY_USERDEF };}; - - template <> struct NumpyEquivalentType<float> { enum { type_code = NPY_FLOAT };}; - template <> struct NumpyEquivalentType< std::complex<float> > { enum { type_code = NPY_CFLOAT };}; - template <> struct NumpyEquivalentType<double> { enum { type_code = NPY_DOUBLE };}; - template <> struct NumpyEquivalentType< std::complex<double> > { enum { type_code = NPY_CDOUBLE };}; - template <> struct NumpyEquivalentType<long double> { enum { type_code = NPY_LONGDOUBLE };}; - template <> struct NumpyEquivalentType< std::complex<long double> > { enum { type_code = NPY_CLONGDOUBLE };}; - template <> struct NumpyEquivalentType<bool> { enum { type_code = NPY_BOOL };}; - template <> struct NumpyEquivalentType<int> { enum { type_code = NPY_INT };}; - template <> struct NumpyEquivalentType<long> { enum { type_code = NPY_LONG };}; - - template<typename Scalar> - bool isNumpyNativeType() - { - if((int)NumpyEquivalentType<Scalar>::type_code == NPY_USERDEF) - return false; - return true; - } - template<typename Scalar> bool np_type_is_convertible_into_scalar(const int np_type) { + if(NumpyEquivalentType<Scalar>::type_code >= NPY_USERDEF) + return np_type == Register::getTypeCode<Scalar>(); + if(NumpyEquivalentType<Scalar>::type_code == np_type) return true; - + switch(np_type) { case NPY_INT: diff --git a/include/eigenpy/numpy.hpp b/include/eigenpy/numpy.hpp index 1631a79752cf1153589f0886fb3e4b25cf0fac38..bd68b7c04fded250a0a71075810a55d632517e45 100644 --- a/include/eigenpy/numpy.hpp +++ b/include/eigenpy/numpy.hpp @@ -31,6 +31,28 @@ namespace eigenpy { void EIGENPY_DLLAPI import_numpy(); int EIGENPY_DLLAPI PyArray_TypeNum(PyTypeObject * type); + + // By default, the Scalar is considered as a Python object + template <typename Scalar> struct NumpyEquivalentType { enum { type_code = NPY_USERDEF };}; + + template <> struct NumpyEquivalentType<float> { enum { type_code = NPY_FLOAT };}; + template <> struct NumpyEquivalentType< std::complex<float> > { enum { type_code = NPY_CFLOAT };}; + template <> struct NumpyEquivalentType<double> { enum { type_code = NPY_DOUBLE };}; + template <> struct NumpyEquivalentType< std::complex<double> > { enum { type_code = NPY_CDOUBLE };}; + template <> struct NumpyEquivalentType<long double> { enum { type_code = NPY_LONGDOUBLE };}; + template <> struct NumpyEquivalentType< std::complex<long double> > { enum { type_code = NPY_CLONGDOUBLE };}; + template <> struct NumpyEquivalentType<bool> { enum { type_code = NPY_BOOL };}; + template <> struct NumpyEquivalentType<int> { enum { type_code = NPY_INT };}; + template <> struct NumpyEquivalentType<long> { enum { type_code = NPY_LONG };}; + + template<typename Scalar> + bool isNumpyNativeType() + { + if((int)NumpyEquivalentType<Scalar>::type_code == NPY_USERDEF) + return false; + return true; + } + } #if defined _WIN32 || defined __CYGWIN__ diff --git a/include/eigenpy/register.hpp b/include/eigenpy/register.hpp index 58bb770a835e32fe732f83a2231c444e9241926b..2164449357dfff90a177066fe6ce7e746bbbd284 100644 --- a/include/eigenpy/register.hpp +++ b/include/eigenpy/register.hpp @@ -6,7 +6,7 @@ #define __eigenpy_register_hpp__ #include "eigenpy/fwd.hpp" -#include "eigenpy/numpy-type.hpp" +#include "eigenpy/numpy.hpp" #include "eigenpy/exception.hpp" #include <algorithm> @@ -36,6 +36,7 @@ namespace eigenpy template<typename Scalar> static PyTypeObject * getPyType() { + namespace bp = boost::python; if(!isNumpyNativeType<Scalar>()) { const PyTypeObject * const_py_type_ptr = bp::converter::registered_pytype<Scalar>::get_pytype(); diff --git a/package.xml b/package.xml index ca1c22b04569e59d7b4aa5660305f76e0c1a2d10..5338f850559a1327af5ce1a1ad68d0f9aec8700a 100644 --- a/package.xml +++ b/package.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <package format="3"> <name>eigenpy</name> - <version>2.6.3</version> + <version>2.6.4</version> <description>Bindings between Numpy and Eigen using Boost.Python</description> <maintainer email="justin.carpentier@inria.fr">Justin Carpentier</maintainer> <maintainer email="opensource@wolfgangmerkt.com">Wolfgang Merkt</maintainer> diff --git a/unittest/user_type.cpp b/unittest/user_type.cpp index a6fdeee89031774403abbd52537aa1bf2ab80b30..250f7a15759504c178d242ab9902037bd35e14e5 100644 --- a/unittest/user_type.cpp +++ b/unittest/user_type.cpp @@ -9,6 +9,63 @@ #include <iostream> #include <sstream> +template<typename Scalar> struct CustomType; + +namespace Eigen +{ + /// @brief Eigen::NumTraits<> specialization for casadi::SX + /// + template<typename Scalar> + struct NumTraits< CustomType<Scalar> > + { + typedef CustomType<Scalar> Real; + typedef CustomType<Scalar> NonInteger; + typedef CustomType<Scalar> Literal; + typedef CustomType<Scalar> Nested; + + enum { + // does not support complex Base types + IsComplex = 0 , + // does not support integer Base types + IsInteger = 0 , + // only support signed Base types + IsSigned = 1 , + // must initialize an AD<Base> object + RequireInitialization = 1 , + // computational cost of the corresponding operations + ReadCost = 1 , + AddCost = 2 , + MulCost = 2 + }; + + static Scalar epsilon() + { + return CustomType<Scalar>(std::numeric_limits<Scalar>::epsilon()); + } + + static CustomType<Scalar> dummy_precision() + { + return CustomType<Scalar>(NumTraits<Scalar>::dummy_precision()); + } + + static CustomType<Scalar> highest() + { + return CustomType<Scalar>(std::numeric_limits<Scalar>::max()); + } + + static CustomType<Scalar> lowest() + { + return CustomType<Scalar>(std::numeric_limits<Scalar>::min()); + } + + static int digits10() + { + return std::numeric_limits<Scalar>::digits10; + } + }; +} // namespace Eigen + + template<typename Scalar> struct CustomType { @@ -46,6 +103,12 @@ struct CustomType ss << "value: " << m_value << std::endl; return ss.str(); } + + friend std::ostream & operator <<(std::ostream & os, const CustomType & X) + { + os << X.m_value; + return os; + } protected: @@ -59,6 +122,12 @@ Eigen::Matrix<CustomType<Scalar>,Eigen::Dynamic,Eigen::Dynamic> create(int rows, return Matrix(rows,cols); } +template<typename Scalar> +void print(const Eigen::Matrix<CustomType<Scalar>,Eigen::Dynamic,Eigen::Dynamic> & mat) +{ + std::cout << mat << std::endl; +} + template<typename Scalar> Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> build_matrix(int rows, int cols) { @@ -104,13 +173,17 @@ BOOST_PYTHON_MODULE(user_type) typedef CustomType<double> DoubleType; typedef Eigen::Matrix<DoubleType,Eigen::Dynamic,Eigen::Dynamic> DoubleMatrix; eigenpy::EigenToPyConverter<DoubleMatrix>::registration(); + eigenpy::EigenFromPyConverter<DoubleMatrix>::registration(); bp::def("create_double",create<double>); expose_custom_type<float>("CustomFloat"); typedef CustomType<float> FloatType; typedef Eigen::Matrix<FloatType,Eigen::Dynamic,Eigen::Dynamic> FloatMatrix; eigenpy::EigenToPyConverter<FloatMatrix>::registration(); + eigenpy::EigenFromPyConverter<FloatMatrix>::registration(); bp::def("create_float",create<float>); bp::def("build_matrix",build_matrix<double>); + bp::def("print",print<double>); + bp::def("print",print<float>); }