diff --git a/CMakeLists.txt b/CMakeLists.txt
index a5f0799e7bc9a4c724896bb1d8465dcd9ba00861..6925e0a8c9aacee8139da345c43023a9f09847b9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,6 +122,7 @@ SET(${PROJECT_NAME}_HEADERS
   include/eigenpy/quaternion.hpp
   include/eigenpy/user-type.hpp
   include/eigenpy/ufunc.hpp
+  include/eigenpy/register.hpp
   include/eigenpy/stride.hpp
   include/eigenpy/version.hpp
 )
@@ -152,7 +153,7 @@ SET(${PROJECT_NAME}_SOURCES
   src/matrix-float.cpp
   src/matrix-complex-float.cpp
   src/matrix-complex-double.cpp
-  src/user-type.cpp
+  src/register.cpp
   src/matrix-double.cpp
   src/matrix-long-double.cpp
   src/matrix-complex-long-double.cpp
diff --git a/include/eigenpy/eigen-allocator.hpp b/include/eigenpy/eigen-allocator.hpp
index 334ad536a7ae0426d48225d4dddb508dca678b42..dc6a84ce43a61a5afeaf3b55a08717e475ff448f 100644
--- a/include/eigenpy/eigen-allocator.hpp
+++ b/include/eigenpy/eigen-allocator.hpp
@@ -7,7 +7,7 @@
 
 #include "eigenpy/fwd.hpp"
 #include "eigenpy/numpy-map.hpp"
-#include "eigenpy/user-type.hpp"
+#include "eigenpy/register.hpp"
 #include "eigenpy/scalar-conversion.hpp"
 #include "eigenpy/utils/is-aligned.hpp"
 
diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp
index 760993f19741cec48503792e4f5f821d3de633cd..a627c8abbd66dc810d92109a30817552c6675008 100644
--- a/include/eigenpy/numpy-allocator.hpp
+++ b/include/eigenpy/numpy-allocator.hpp
@@ -9,7 +9,7 @@
 #include "eigenpy/numpy-type.hpp"
 #include "eigenpy/eigen-allocator.hpp"
 
-#include "eigenpy/user-type.hpp"
+#include "eigenpy/register.hpp"
 
 namespace eigenpy
 {
diff --git a/include/eigenpy/register.hpp b/include/eigenpy/register.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..42df36fc7eecf03e60d84f9e7558d6fa395fe181
--- /dev/null
+++ b/include/eigenpy/register.hpp
@@ -0,0 +1,184 @@
+//
+// Copyright (c) 2020 INRIA
+//
+
+#ifndef __eigenpy_register_hpp__
+#define __eigenpy_register_hpp__
+
+#include "eigenpy/fwd.hpp"
+#include "eigenpy/numpy-type.hpp"
+#include "eigenpy/exception.hpp"
+
+#include <algorithm>
+#include <map>
+#include <typeinfo>
+#include <string>
+
+namespace eigenpy
+{
+
+  /// \brief Structure collecting all the types registers in Numpy via EigenPy
+  struct EIGENPY_DLLEXPORT Register
+  {
+    
+    static PyArray_Descr * getPyArrayDescr(PyTypeObject * py_type_ptr)
+    {
+      MapDescr::iterator it = py_array_descr_bindings.find(py_type_ptr);
+      if(it != py_array_descr_bindings.end())
+        return it->second;
+      else
+        return NULL;
+    }
+    
+    template<typename Scalar>
+    static bool isRegistered()
+    {
+      return isRegistered(Register::getPyType<Scalar>());
+    }
+    
+    static bool isRegistered(PyTypeObject * py_type_ptr)
+    {
+      if(getPyArrayDescr(py_type_ptr) != NULL)
+        return true;
+      else
+        return false;
+    }
+    
+    static int getTypeCode(PyTypeObject * py_type_ptr)
+    {
+      MapCode::iterator it = py_array_code_bindings.find(py_type_ptr);
+      if(it != py_array_code_bindings.end())
+        return it->second;
+      else
+        return PyArray_TypeNum(py_type_ptr);
+    }
+  
+    template<typename Scalar>
+    static PyTypeObject * getPyType()
+    {
+      if(!isNumpyNativeType<Scalar>())
+      {
+        const PyTypeObject * const_py_type_ptr = bp::converter::registered_pytype<Scalar>::get_pytype();
+        if(const_py_type_ptr == NULL)
+        {
+          std::stringstream ss;
+          ss << "The type " << typeid(Scalar).name() << " does not have a registered converter inside Boot.Python." << std::endl;
+          throw std::invalid_argument(ss.str());
+        }
+        PyTypeObject * py_type_ptr = const_cast<PyTypeObject *>(const_py_type_ptr);
+        return py_type_ptr;
+      }
+      else
+      {
+        PyArray_Descr * new_descr = PyArray_DescrFromType(NumpyEquivalentType<Scalar>::type_code);
+        return new_descr->typeobj;
+      }
+    }
+
+    template<typename Scalar>
+    static int getTypeCode()
+    {
+      if(isNumpyNativeType<Scalar>())
+        return NumpyEquivalentType<Scalar>::type_code;
+      else
+      {
+        const std::type_info & info = typeid(Scalar);
+        if(type_to_py_type_bindings.find(&info) != type_to_py_type_bindings.end())
+        {
+          PyTypeObject * py_type = type_to_py_type_bindings[&info];
+          int code = py_array_code_bindings[py_type];
+  
+          return code;
+        }
+        else
+          return -1; // type not registered
+      }
+    }
+    
+    static int registerNewType(PyTypeObject * py_type_ptr,
+                               const std::type_info * type_info_ptr,
+                               const int type_size,
+                               PyArray_GetItemFunc * getitem,
+                               PyArray_SetItemFunc * setitem,
+                               PyArray_NonzeroFunc * nonzero,
+                               PyArray_CopySwapFunc * copyswap,
+                               PyArray_CopySwapNFunc * copyswapn,
+                               PyArray_DotFunc * dotfunc)
+    {
+      namespace bp = boost::python;
+  
+      PyArray_Descr * descr_ptr = new PyArray_Descr(*PyArray_DescrFromType(NPY_OBJECT));
+      PyArray_Descr & descr = *descr_ptr;
+      descr.typeobj = py_type_ptr;
+      descr.kind = 'V';
+      descr.byteorder = '=';
+      descr.elsize = type_size;
+      descr.flags = NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_USE_SETITEM | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI;
+//      descr->names = PyTuple_New(0);
+//      descr->fields = PyDict_New();
+      
+      PyArray_ArrFuncs * funcs_ptr = new PyArray_ArrFuncs;
+      PyArray_ArrFuncs & funcs = *funcs_ptr;
+      descr.f = funcs_ptr;
+      PyArray_InitArrFuncs(funcs_ptr);
+      funcs.getitem = getitem;
+      funcs.setitem = setitem;
+      funcs.nonzero = nonzero;
+      funcs.copyswap = copyswap;
+      funcs.copyswapn = copyswapn;
+      funcs.dotfunc = dotfunc;
+//      f->cast = cast;
+
+      const int code = PyArray_RegisterDataType(descr_ptr);
+      assert(code >= 0 && "The return code should be positive");
+      PyArray_Descr * new_descr = PyArray_DescrFromType(code);
+
+      type_to_py_type_bindings.insert(std::make_pair(type_info_ptr,py_type_ptr));
+      py_array_descr_bindings[py_type_ptr] = new_descr;
+      py_array_code_bindings[py_type_ptr] = code;
+      
+//      PyArray_RegisterCanCast(descr,NPY_OBJECT,NPY_NOSCALAR);
+      return code;
+    }
+    
+    static Register & instance()
+    {
+      return self;
+    }
+    
+  private:
+    
+    Register() {};
+    
+    struct Compare_PyTypeObject
+    {
+      bool operator()(const PyTypeObject * a, const PyTypeObject * b) const
+      {
+        return std::string(a->tp_name) < std::string(b->tp_name);
+      }
+    };
+  
+    struct Compare_TypeInfo
+    {
+      bool operator()(const std::type_info * a, const std::type_info * b) const
+      {
+        return std::string(a->name()) < std::string(b->name());
+      }
+    };
+  
+    typedef std::map<const std::type_info *,PyTypeObject *,Compare_TypeInfo> MapInfo;
+    static MapInfo type_to_py_type_bindings;
+    
+    typedef std::map<PyTypeObject *,PyArray_Descr *,Compare_PyTypeObject> MapDescr;
+    static MapDescr py_array_descr_bindings;
+    
+    typedef std::map<PyTypeObject *,int,Compare_PyTypeObject> MapCode;
+    static MapCode py_array_code_bindings;
+    
+    static Register self;
+    
+  };
+  
+} // namespace eigenpy
+
+#endif // __eigenpy_register_hpp__
diff --git a/include/eigenpy/ufunc.hpp b/include/eigenpy/ufunc.hpp
index 39504e72009418534fb4f2611844fe21b48ebd16..e9b074bf4dde3671ab395b8313ab3b6694c60ebf 100644
--- a/include/eigenpy/ufunc.hpp
+++ b/include/eigenpy/ufunc.hpp
@@ -5,7 +5,7 @@
 #ifndef __eigenpy_ufunc_hpp__
 #define __eigenpy_ufunc_hpp__
 
-#include "eigenpy/user-type.hpp"
+#include "eigenpy/register.hpp"
 
 namespace eigenpy
 {
diff --git a/include/eigenpy/user-type.hpp b/include/eigenpy/user-type.hpp
index 6d54301e9696bef261852c23e7a8a66028ac5a1d..212ef1dfd856c53cde99632550c847f7ca55f4d4 100644
--- a/include/eigenpy/user-type.hpp
+++ b/include/eigenpy/user-type.hpp
@@ -7,12 +7,7 @@
 
 #include "eigenpy/fwd.hpp"
 #include "eigenpy/numpy-type.hpp"
-#include "eigenpy/exception.hpp"
-
-#include <algorithm>
-#include <map>
-#include <typeinfo>
-#include <string>
+#include "eigenpy/register.hpp"
 
 namespace eigenpy
 {
@@ -171,168 +166,6 @@ namespace eigenpy
   
   } // namespace internal
 
-  /// \brief Structure collecting all the types registers in Numpy via EigenPy
-  struct EIGENPY_DLLEXPORT Register
-  {
-    
-    static PyArray_Descr * getPyArrayDescr(PyTypeObject * py_type_ptr)
-    {
-      MapDescr::iterator it = py_array_descr_bindings.find(py_type_ptr);
-      if(it != py_array_descr_bindings.end())
-        return it->second;
-      else
-        return NULL;
-    }
-    
-    template<typename Scalar>
-    static bool isRegistered()
-    {
-      return isRegistered(Register::getPyType<Scalar>());
-    }
-    
-    static bool isRegistered(PyTypeObject * py_type_ptr)
-    {
-      if(getPyArrayDescr(py_type_ptr) != NULL)
-        return true;
-      else
-        return false;
-    }
-    
-    static int getTypeCode(PyTypeObject * py_type_ptr)
-    {
-      MapCode::iterator it = py_array_code_bindings.find(py_type_ptr);
-      if(it != py_array_code_bindings.end())
-        return it->second;
-      else
-        return PyArray_TypeNum(py_type_ptr);
-    }
-  
-    template<typename Scalar>
-    static PyTypeObject * getPyType()
-    {
-      if(!isNumpyNativeType<Scalar>())
-      {
-        const PyTypeObject * const_py_type_ptr = bp::converter::registered_pytype<Scalar>::get_pytype();
-        if(const_py_type_ptr == NULL)
-        {
-          std::stringstream ss;
-          ss << "The type " << typeid(Scalar).name() << " does not have a registered converter inside Boot.Python." << std::endl;
-          throw std::invalid_argument(ss.str());
-        }
-        PyTypeObject * py_type_ptr = const_cast<PyTypeObject *>(const_py_type_ptr);
-        return py_type_ptr;
-      }
-      else
-      {
-        PyArray_Descr * new_descr = PyArray_DescrFromType(NumpyEquivalentType<Scalar>::type_code);
-        return new_descr->typeobj;
-      }
-    }
-
-    template<typename Scalar>
-    static int getTypeCode()
-    {
-      if(isNumpyNativeType<Scalar>())
-        return NumpyEquivalentType<Scalar>::type_code;
-      else
-      {
-        const std::type_info & info = typeid(Scalar);
-        if(type_to_py_type_bindings.find(&info) != type_to_py_type_bindings.end())
-        {
-          PyTypeObject * py_type = type_to_py_type_bindings[&info];
-          int code = py_array_code_bindings[py_type];
-  
-          return code;
-        }
-        else
-          return -1; // type not registered
-      }
-    }
-    
-    static int registerNewType(PyTypeObject * py_type_ptr,
-                               const std::type_info * type_info_ptr,
-                               const int type_size,
-                               PyArray_GetItemFunc * getitem,
-                               PyArray_SetItemFunc * setitem,
-                               PyArray_NonzeroFunc * nonzero,
-                               PyArray_CopySwapFunc * copyswap,
-                               PyArray_CopySwapNFunc * copyswapn,
-                               PyArray_DotFunc * dotfunc)
-    {
-      namespace bp = boost::python;
-  
-      PyArray_Descr * descr_ptr = new PyArray_Descr(*PyArray_DescrFromType(NPY_OBJECT));
-      PyArray_Descr & descr = *descr_ptr;
-      descr.typeobj = py_type_ptr;
-      descr.kind = 'V';
-      descr.byteorder = '=';
-      descr.elsize = type_size;
-      descr.flags = NPY_LIST_PICKLE | NPY_USE_GETITEM | NPY_USE_SETITEM | NPY_NEEDS_INIT | NPY_NEEDS_PYAPI;
-//      descr->names = PyTuple_New(0);
-//      descr->fields = PyDict_New();
-      
-      PyArray_ArrFuncs * funcs_ptr = new PyArray_ArrFuncs;
-      PyArray_ArrFuncs & funcs = *funcs_ptr;
-      descr.f = funcs_ptr;
-      PyArray_InitArrFuncs(funcs_ptr);
-      funcs.getitem = getitem;
-      funcs.setitem = setitem;
-      funcs.nonzero = nonzero;
-      funcs.copyswap = copyswap;
-      funcs.copyswapn = copyswapn;
-      funcs.dotfunc = dotfunc;
-//      f->cast = cast;
-
-      const int code = PyArray_RegisterDataType(descr_ptr);
-      assert(code >= 0 && "The return code should be positive");
-      PyArray_Descr * new_descr = PyArray_DescrFromType(code);
-
-      type_to_py_type_bindings.insert(std::make_pair(type_info_ptr,py_type_ptr));
-      py_array_descr_bindings[py_type_ptr] = new_descr;
-      py_array_code_bindings[py_type_ptr] = code;
-      
-//      PyArray_RegisterCanCast(descr,NPY_OBJECT,NPY_NOSCALAR);
-      return code;
-    }
-    
-    static Register & instance()
-    {
-      return self;
-    }
-    
-  private:
-    
-    Register() {};
-    
-    struct Compare_PyTypeObject
-    {
-      bool operator()(const PyTypeObject * a, const PyTypeObject * b) const
-      {
-        return std::string(a->tp_name) < std::string(b->tp_name);
-      }
-    };
-  
-    struct Compare_TypeInfo
-    {
-      bool operator()(const std::type_info * a, const std::type_info * b) const
-      {
-        return std::string(a->name()) < std::string(b->name());
-      }
-    };
-  
-    typedef std::map<const std::type_info *,PyTypeObject *,Compare_TypeInfo> MapInfo;
-    static MapInfo type_to_py_type_bindings;
-    
-    typedef std::map<PyTypeObject *,PyArray_Descr *,Compare_PyTypeObject> MapDescr;
-    static MapDescr py_array_descr_bindings;
-    
-    typedef std::map<PyTypeObject *,int,Compare_PyTypeObject> MapCode;
-    static MapCode py_array_code_bindings;
-    
-    static Register self;
-    
-  };
-
   template<typename Scalar>
   int registerNewType(PyTypeObject * py_type_ptr = NULL)
   {
diff --git a/src/user-type.cpp b/src/register.cpp
similarity index 88%
rename from src/user-type.cpp
rename to src/register.cpp
index bfdbbee7ba49206a46b0eaf5742589e642745ded..8e12ad752c0885ce4ab0a3e5e9ac5f25f8fb828c 100644
--- a/src/user-type.cpp
+++ b/src/register.cpp
@@ -2,7 +2,7 @@
  * Copyright 2020 INRIA
  */
 
-#include "eigenpy/user-type.hpp"
+#include "eigenpy/register.hpp"
 
 namespace eigenpy
 {