diff --git a/include/eigenpy/eigen-from-python.hpp b/include/eigenpy/eigen-from-python.hpp
index b5717e330dde421ae9785eaee674aeff7a807413..c923079153e02cedf8eedd479955674927628e58 100644
--- a/include/eigenpy/eigen-from-python.hpp
+++ b/include/eigenpy/eigen-from-python.hpp
@@ -14,12 +14,11 @@
 
 namespace boost { namespace python { namespace converter {
 
-  /// \brief Template specialization of rvalue_from_python_data
-  template<typename Derived>
-  struct rvalue_from_python_data<Eigen::MatrixBase<Derived> const & >
-  : rvalue_from_python_storage<Derived const & >
+  template<typename MatrixReference>
+  struct rvalue_from_python_data_eigen
+  : rvalue_from_python_storage<MatrixReference>
   {
-    typedef Eigen::MatrixBase<Derived> const & T;
+    typedef MatrixReference T;
     
 # if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
@@ -30,7 +29,7 @@ namespace boost { namespace python { namespace converter {
 # endif
     
     // The usual constructor
-    rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)
+    rvalue_from_python_data_eigen(rvalue_from_python_stage1_data const & _stage1)
     {
       this->stage1 = _stage1;
     }
@@ -38,56 +37,48 @@ namespace boost { namespace python { namespace converter {
     // 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)
+    rvalue_from_python_data_eigen(void* convertible)
     {
       this->stage1.convertible = convertible;
     }
     
     // Destroys any object constructed in the storage.
-    ~rvalue_from_python_data()
+    ~rvalue_from_python_data_eigen()
     {
+      typedef typename boost::remove_const<typename boost::remove_reference<MatrixReference>::type>::type MatrixType;
       if (this->stage1.convertible == this->storage.bytes)
-        static_cast<Derived *>((void *)this->storage.bytes)->~Derived();
+        static_cast<MatrixType *>((void *)this->storage.bytes)->~MatrixType();
     }
   };
 
+
+#define RVALUE_FROM_PYTHON_DATA_INIT(type)                                 \
+  typedef rvalue_from_python_data_eigen<type> Base;                        \
+                                                                           \
+  rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)  \
+  : Base(_stage1)                                                          \
+  {}                                                                       \
+                                                                           \
+  rvalue_from_python_data(void* convertible) : Base(convertible) {};
+
   /// \brief Template specialization of rvalue_from_python_data
   template<typename Derived>
-  struct rvalue_from_python_data<Eigen::EigenBase<Derived> const & >
-  : rvalue_from_python_storage<Derived const & >
+  struct rvalue_from_python_data<Eigen::MatrixBase<Derived> const &>
+  : rvalue_from_python_data_eigen<Derived const &>
   {
-    typedef Eigen::EigenBase<Derived> const & T;
-    
-# 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<T>,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()
-    {
-      if (this->stage1.convertible == this->storage.bytes)
-        static_cast<Derived *>((void *)this->storage.bytes)->~Derived();
-    }
+    RVALUE_FROM_PYTHON_DATA_INIT(Derived const &)
+  };
+
+  /// \brief Template specialization of rvalue_from_python_data
+  template<typename Derived>
+  struct rvalue_from_python_data<Eigen::EigenBase<Derived> const &>
+  : rvalue_from_python_data_eigen<Derived const &>
+  {
+    RVALUE_FROM_PYTHON_DATA_INIT(Derived const &)
   };
 
+#undef RVALUE_FROM_PYTHON_DATA_INIT
+
 } } }
 
 namespace eigenpy
@@ -95,61 +86,59 @@ namespace eigenpy
   template<typename MatType>
   struct EigenFromPy
   {
-    
-    static bool isScalarConvertible(const int np_type)
-    {
-      if(NumpyEquivalentType<typename MatType::Scalar>::type_code == np_type)
-        return true;
-      
-      switch(np_type)
-      {
-        case NPY_INT:
-          return FromTypeToType<int,typename MatType::Scalar>::value;
-        case NPY_LONG:
-          return FromTypeToType<long,typename MatType::Scalar>::value;
-        case NPY_FLOAT:
-          return FromTypeToType<float,typename MatType::Scalar>::value;
-        case NPY_CFLOAT:
-          return FromTypeToType<std::complex<float>,typename MatType::Scalar>::value;
-        case NPY_DOUBLE:
-          return FromTypeToType<double,typename MatType::Scalar>::value;
-        case NPY_CDOUBLE:
-          return FromTypeToType<std::complex<double>,typename MatType::Scalar>::value;
-        case NPY_LONGDOUBLE:
-          return FromTypeToType<long double,typename MatType::Scalar>::value;
-        case NPY_CLONGDOUBLE:
-          return FromTypeToType<std::complex<long double>,typename MatType::Scalar>::value;
-        default:
-          return false;
-      }
-    }
+    typedef typename MatType::Scalar Scalar;
     
     /// \brief Determine if pyObj can be converted into a MatType object
-    static void* convertible(PyArrayObject* pyArray)
+    static void* convertible(PyArrayObject* pyArray);
+ 
+    /// \brief Allocate memory and copy pyObj in the new storage
+    static void construct(PyObject* pyObj,
+                          bp::converter::rvalue_from_python_stage1_data* memory);
+    
+    static void registration();
+  };
+
+  template<typename MatType>
+  void* EigenFromPy<MatType>::convertible(PyArrayObject* pyArray)
+  {
+    if(!PyArray_Check(pyArray))
+      return 0;
+    
+    if(!np_type_is_convertible_into_scalar<Scalar>(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
+      return 0;
+    
+    if(MatType::IsVectorAtCompileTime)
     {
-      if(!PyArray_Check(pyArray))
-        return 0;
+      const Eigen::DenseIndex size_at_compile_time
+      = MatType::IsRowMajor
+      ? MatType::ColsAtCompileTime
+      : MatType::RowsAtCompileTime;
       
-      if(!isScalarConvertible(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
-        return 0;
-
-      if(MatType::IsVectorAtCompileTime)
+      switch(PyArray_NDIM(pyArray))
       {
-        const Eigen::DenseIndex size_at_compile_time
-        = MatType::IsRowMajor
-        ? MatType::ColsAtCompileTime
-        : MatType::RowsAtCompileTime;
-        
-        switch(PyArray_NDIM(pyArray))
+        case 0:
+          return 0;
+        case 1:
         {
-          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)
             {
-              // check that the sizes at compile time matche
-              if(PyArray_DIMS(pyArray)[0] == size_at_compile_time)
+              if(size_at_compile_time == 1)
                 return pyArray;
               else
                 return 0;
@@ -157,108 +146,93 @@ namespace eigenpy
             else // This is a dynamic MatType
               return pyArray;
           }
-          case 2:
+          
+          if(PyArray_DIMS(pyArray)[0] > 1 && PyArray_DIMS(pyArray)[1] > 1)
           {
-            // 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;
+            return 0;
           }
-          default:
+          
+          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
+    }
+    else // this is a matrix
+    {
+      if(PyArray_NDIM(pyArray) == 1) // We can always convert a vector into 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;
-        }
+        return pyArray;
       }
-        
-#ifdef NPY_1_8_API_VERSION
-      if(!(PyArray_FLAGS(pyArray)))
-#else
-      if(!(PyArray_FLAGS(pyArray) & NPY_ALIGNED))
-#endif
+      
+      if(PyArray_NDIM(pyArray) != 2)
       {
         return 0;
       }
       
-      return pyArray;
-    }
- 
-    /// \brief Allocate memory and copy pyObj in the new storage
-    static void construct(PyObject* pyObj,
-                          bp::converter::rvalue_from_python_stage1_data* memory)
-    {
-      PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
-      assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));
-      
-      void* storage = reinterpret_cast<bp::converter::rvalue_from_python_storage<MatType>*>
-                     (reinterpret_cast<void*>(memory))->storage.bytes;
-      
-      EigenAllocator<MatType>::allocate(pyArray,storage);
-
-      memory->convertible = storage;
+      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;
+      }
     }
     
-    static void registration()
+#ifdef NPY_1_8_API_VERSION
+    if(!(PyArray_FLAGS(pyArray)))
+#else
+    if(!(PyArray_FLAGS(pyArray) & NPY_ALIGNED))
+#endif
     {
-      bp::converter::registry::push_back
-      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
-       &EigenFromPy::construct,bp::type_id<MatType>());
+      return 0;
     }
-  };
+    
+    return pyArray;
+  }
+
+  template<typename MatType>
+  void EigenFromPy<MatType>::construct(PyObject* pyObj,
+                                       bp::converter::rvalue_from_python_stage1_data* memory)
+  {
+    PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
+    assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));
+    
+    void* storage = reinterpret_cast<bp::converter::rvalue_from_python_storage<MatType>*>
+                   (reinterpret_cast<void*>(memory))->storage.bytes;
+    
+    EigenAllocator<MatType>::allocate(pyArray,storage);
+
+    memory->convertible = storage;
+  }
+
+  template<typename MatType>
+  void EigenFromPy<MatType>::registration()
+  {
+    bp::converter::registry::push_back
+    (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
+     &EigenFromPy::construct,bp::type_id<MatType>());
+  }
   
   template<typename MatType>
   struct EigenFromPyConverter
@@ -317,8 +291,8 @@ namespace eigenpy
        &EigenFromPy<MatType>::construct,bp::type_id<MatType>());
     }
   };
-
 #endif
+
 }
 
 #endif // __eigenpy_eigen_from_python_hpp__
diff --git a/include/eigenpy/numpy-type.hpp b/include/eigenpy/numpy-type.hpp
index 2bf7d03b9737563d873bbaea8600d90fb6eff4c0..3085b55e8ffe1dd33f4752900a97b934fad1a4c9 100644
--- a/include/eigenpy/numpy-type.hpp
+++ b/include/eigenpy/numpy-type.hpp
@@ -6,6 +6,7 @@
 #define __eigenpy_numpy_type_hpp__
 
 #include "eigenpy/fwd.hpp"
+#include "eigenpy/scalar-conversion.hpp"
 
 #include <patchlevel.h> // For PY_MAJOR_VERSION
 
@@ -23,6 +24,35 @@ namespace eigenpy
   template <> struct NumpyEquivalentType< std::complex<long double> >  { enum { type_code = NPY_CLONGDOUBLE };};
   template <> struct NumpyEquivalentType<int>     { enum { type_code = NPY_INT    };};
   template <> struct NumpyEquivalentType<long>    { enum { type_code = NPY_LONG    };};
+
+  template<typename Scalar>
+  bool np_type_is_convertible_into_scalar(const int np_type)
+  {
+    if(NumpyEquivalentType<Scalar>::type_code == np_type)
+      return true;
+    
+    switch(np_type)
+    {
+      case NPY_INT:
+        return FromTypeToType<int,Scalar>::value;
+      case NPY_LONG:
+        return FromTypeToType<long,Scalar>::value;
+      case NPY_FLOAT:
+        return FromTypeToType<float,Scalar>::value;
+      case NPY_CFLOAT:
+        return FromTypeToType<std::complex<float>,Scalar>::value;
+      case NPY_DOUBLE:
+        return FromTypeToType<double,Scalar>::value;
+      case NPY_CDOUBLE:
+        return FromTypeToType<std::complex<double>,Scalar>::value;
+      case NPY_LONGDOUBLE:
+        return FromTypeToType<long double,Scalar>::value;
+      case NPY_CLONGDOUBLE:
+        return FromTypeToType<std::complex<long double>,Scalar>::value;
+      default:
+        return false;
+    }
+  }
    
   enum NP_TYPE
   {