From fe2240dabb7d11c667eaefb2a8b7e5325488f3d1 Mon Sep 17 00:00:00 2001 From: Justin Carpentier <justin.carpentier@inria.fr> Date: Tue, 5 May 2020 15:40:20 +0200 Subject: [PATCH] core: add register file --- CMakeLists.txt | 3 +- include/eigenpy/eigen-allocator.hpp | 2 +- include/eigenpy/numpy-allocator.hpp | 2 +- include/eigenpy/register.hpp | 184 ++++++++++++++++++++++++++++ include/eigenpy/ufunc.hpp | 2 +- include/eigenpy/user-type.hpp | 169 +------------------------ src/{user-type.cpp => register.cpp} | 2 +- 7 files changed, 191 insertions(+), 173 deletions(-) create mode 100644 include/eigenpy/register.hpp rename src/{user-type.cpp => register.cpp} (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5f0799e..6925e0a8 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 334ad536..dc6a84ce 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 760993f1..a627c8ab 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 00000000..42df36fc --- /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 39504e72..e9b074bf 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 6d54301e..212ef1df 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 bfdbbee7..8e12ad75 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 { -- GitLab