From b66155d535c621bb44adac293e43e9241f9e99c8 Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Thu, 18 May 2023 15:29:02 -0500 Subject: [PATCH 01/10] source and header for example project --- .../custom_numeric_type/include/header.hpp | 229 ++++++++++++++++++ examples/custom_numeric_type/src/src.cpp | 62 +++++ 2 files changed, 291 insertions(+) create mode 100644 examples/custom_numeric_type/include/header.hpp create mode 100644 examples/custom_numeric_type/src/src.cpp diff --git a/examples/custom_numeric_type/include/header.hpp b/examples/custom_numeric_type/include/header.hpp new file mode 100644 index 000000000..97536d972 --- /dev/null +++ b/examples/custom_numeric_type/include/header.hpp @@ -0,0 +1,229 @@ + + +#pragma once + +#ifndef EXAMPLE_CUSTOM_NUMERIC_TYPE +#define EXAMPLE_CUSTOM_NUMERIC_TYPE + +#include +#include +#include + +#include + + +namespace bmp = boost::multiprecision; +using bmp::backends::mpc_complex_backend; +using mpfr_complex = bmp::number, bmp::et_on >; // T is a variable-precision complex number with expression templates turned on. + + + +void Expose(); + + + + + + +// this code derived from +// https://github.com/stack-of-tasks/eigenpy/issues/365 +// where I asked about using custom types, and @jcarpent responded with a discussion +// of an application of this in Pinnochio, a library for rigid body dynamics. +namespace eigenpy +{ + namespace internal + { + + + +// a template specialization for complex numbers + // derived directly from the example for Pinnochio +template <> +struct getitem +{ + static PyObject* run(void* data, void* /* arr */) { + mpfr_complex & mpfr_scalar = *static_cast(data); + auto & backend = mpfr_scalar.backend(); + + if(backend.data()[0].re->_mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. + { + mpfr_scalar = mpfr_complex(0); + } + boost::python::object m(boost::ref(mpfr_scalar)); + Py_INCREF(m.ptr()); + return m.ptr(); + } +}; + + +} // namespace internal + + + + + + +// i lifted this from EigenPy and adapted it, basically removing the calls for the comparitors. +template +void registerUfunct_without_comparitors(){ + const int type_code = Register::getTypeCode(); + + PyObject *numpy_str; + #if PY_MAJOR_VERSION >= 3 + numpy_str = PyUnicode_FromString("numpy"); + #else + numpy_str = PyString_FromString("numpy"); + #endif + PyObject *numpy; + numpy = PyImport_Import(numpy_str); + Py_DECREF(numpy_str); + + import_ufunc(); + + // Matrix multiply + { + int types[3] = {type_code, type_code, type_code}; + + std::stringstream ss; + ss << "return result of multiplying two matrices of "; + ss << bp::type_info(typeid(Scalar)).name(); + PyUFuncObject *ufunc = + (PyUFuncObject *)PyObject_GetAttrString(numpy, "matmul"); + if (!ufunc) { + std::stringstream ss; + ss << "Impossible to define matrix_multiply for given type " + << bp::type_info(typeid(Scalar)).name() << std::endl; + eigenpy::Exception(ss.str()); + } + if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, type_code, + &internal::gufunc_matrix_multiply, + types, 0) < 0) { + std::stringstream ss; + ss << "Impossible to register matrix_multiply for given type " + << bp::type_info(typeid(Scalar)).name() << std::endl; + eigenpy::Exception(ss.str()); + } + + Py_DECREF(ufunc); + } + + // Binary operators + EIGENPY_REGISTER_BINARY_UFUNC(add, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(subtract, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(multiply, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(divide, type_code, Scalar, Scalar, Scalar); + + // Comparison operators + EIGENPY_REGISTER_BINARY_UFUNC(equal, type_code, Scalar, Scalar, bool); + EIGENPY_REGISTER_BINARY_UFUNC(not_equal, type_code, Scalar, Scalar, bool); + + //these are commented out because the comparisons are NOT defined for complex types!! + // EIGENPY_REGISTER_BINARY_UFUNC(greater, type_code, Scalar, Scalar, bool); + // EIGENPY_REGISTER_BINARY_UFUNC(less, type_code, Scalar, Scalar, bool); + // EIGENPY_REGISTER_BINARY_UFUNC(greater_equal, type_code, Scalar, Scalar, bool); + // EIGENPY_REGISTER_BINARY_UFUNC(less_equal, type_code, Scalar, Scalar, bool); + + // Unary operators + EIGENPY_REGISTER_UNARY_UFUNC(negative, type_code, Scalar, Scalar); + + Py_DECREF(numpy); +} + +} // namespace eigenpy + + + +namespace bp = boost::python; + +// this derived directly from the code at https://github.com/stack-of-tasks/eigenpy/issues/365, in which this example was requested +template +struct BoostNumberPythonVisitor +: public boost::python::def_visitor< BoostNumberPythonVisitor > +{ + +public: + + template + void visit(PyClass& cl) const + { + cl + .def(bp::init<>("Default constructor.",bp::arg("self"))) + .def(bp::init("Copy constructor.",bp::args("self","value"))) + .def(bp::init("Constructor from a string.",bp::args("self","str_value"))) + .def(bp::init("Constructor from a pair of strings.",bp::args("self","real","imag"))) + + + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self * bp::self) + .def(bp::self *= bp::self) + .def(bp::self / bp::self) + .def(bp::self /= bp::self) + + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def(bp::self_ns::pow(bp::self_ns::self,long())) + + + + .def("str",&BoostNumber::str,bp::args("self","precision","scientific")) + + .def("default_precision", + static_cast(BoostNumber::default_precision), + "Get the default precision of the class.") + .def("default_precision", + static_cast(BoostNumber::default_precision),bp::arg("digits10"), + "Set the default precision of the class.") + .staticmethod("default_precision") + + .def("precision", + static_cast(&BoostNumber::precision), + bp::arg("self"), + "Get the precision of this.") + .def("precision", + static_cast(&BoostNumber::precision), + bp::args("self","digits10"), + "Set the precision of this.") + + + .def("__str__",&print,bp::arg("self")) + .def("__repr__",&print,bp::arg("self")) + + .def("set_display_precision",&set_display_precision,bp::arg("digit"), + "Set the precision when printing values.") + .staticmethod("set_display_precision") + + .def("get_display_precision",&get_display_precision, + "Get the precision when printing values.", + bp::return_value_policy()) + .staticmethod("get_display_precision") + + ; + + } + + static std::string print(const BoostNumber & self) + { + return self.str(get_display_precision(), std::ios_base::dec); + } + + static void set_display_precision(const int digit) + { + get_display_precision() = digit; + } + + static int & get_display_precision() + { + static int precision = BoostNumber::default_precision(); + return precision; + } +}; + + + + +#endif + + diff --git a/examples/custom_numeric_type/src/src.cpp b/examples/custom_numeric_type/src/src.cpp new file mode 100644 index 000000000..a47aaf810 --- /dev/null +++ b/examples/custom_numeric_type/src/src.cpp @@ -0,0 +1,62 @@ +#include "header.hpp" + + + +BOOST_PYTHON_MODULE(eigenpy_example_custom_numeric_type) // this name must match the name of the generated .so file. +{ + // see https://stackoverflow.com/questions/6114462/how-to-override-the-automatically-created-docstring-data-for-boostpython + // docstring_options d(true, true, false); // local_ + boost::python::docstring_options docopt; + docopt.enable_all(); + docopt.disable_cpp_signatures(); + + boost::python::object package = boost::python::scope(); + package.attr("__path__") = "eigenpy_example_custom_numeric_type"; + + + Expose(); +} + + + +#define IMPLICITLY_CONVERTIBLE(T1,T2) \ + boost::python::implicitly_convertible(); + +void Expose(){ + + eigenpy::enableEigenPy(); + + boost::python::class_("MpfrComplex", + "",bp::no_init) + .def(BoostNumberPythonVisitor()) + ; + + + + eigenpy::registerNewType(); + eigenpy::registerUfunct_without_comparitors(); + + + eigenpy::registerCast(true); + eigenpy::registerCast(true); + eigenpy::registerCast(true); + + + + IMPLICITLY_CONVERTIBLE(int,mpfr_complex); + IMPLICITLY_CONVERTIBLE(long,mpfr_complex); + IMPLICITLY_CONVERTIBLE(int64_t,mpfr_complex); + + using VecX = Eigen::Matrix; + using MatXX = Eigen::Matrix; + + + + + eigenpy::enableEigenPySpecific(); + eigenpy::enableEigenPySpecific(); +} + + + +#undef IMPLICITLY_CONVERTIBLE From 26151126944b3d279008588154c51fdb8d9583df Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Thu, 18 May 2023 15:30:33 -0500 Subject: [PATCH 02/10] build system directly derived from other files inside eigenpy --- examples/custom_numeric_type/CMakeLists.txt | 226 ++++++++++++++++++++ examples/custom_numeric_type/package.xml | 32 +++ 2 files changed, 258 insertions(+) create mode 100644 examples/custom_numeric_type/CMakeLists.txt create mode 100644 examples/custom_numeric_type/package.xml diff --git a/examples/custom_numeric_type/CMakeLists.txt b/examples/custom_numeric_type/CMakeLists.txt new file mode 100644 index 000000000..6fade50b0 --- /dev/null +++ b/examples/custom_numeric_type/CMakeLists.txt @@ -0,0 +1,226 @@ +# derived from eigenpy/CMakeLists.txt for this example + +cmake_minimum_required(VERSION 3.1) + +set(PROJECT_NAME eigenpy_example_custom_numeric_type) +set(PROJECT_DESCRIPTION "An example of using eigenpy with a custom numeric type: Boost.Multiprecision complex numbers") +set(PROJECT_URL "http://github.com/stack-of-tasks/eigenpy/examples/custom_numeric_type") +set(PROJECT_USE_CMAKE_EXPORT TRUE) +set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) +set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") +set(PROJECT_COMPATIBILITY_VERSION AnyNewerVersion) + + + +# Check if the submodule cmake have been initialized +set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake") +if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/base.cmake") + if(${CMAKE_VERSION} VERSION_LESS "3.14.0") + message( + FATAL_ERROR + "\nPlease run the following command first:\ngit submodule update --init\n" + ) + else() + message(STATUS "JRL cmakemodules not found. Let's fetch it.") + include(FetchContent) + FetchContent_Declare( + "jrl-cmakemodules" + GIT_REPOSITORY "https://github.com/jrl-umi3218/jrl-cmakemodules.git") + FetchContent_MakeAvailable("jrl-cmakemodules") + FetchContent_GetProperties("jrl-cmakemodules" SOURCE_DIR JRL_CMAKE_MODULES) + endif() +endif() + + +# Disable -Werror on Unix for now. +set(CXX_DISABLE_WERROR True) +set(CMAKE_VERBOSE_MAKEFILE True) + +option(INSTALL_DOCUMENTATION "Generate and install the documentation" OFF) +option(SUFFIX_SO_VERSION "Suffix library name with its version" OFF) + +if(DEFINED BUILD_UNIT_TESTS) + message( + AUTHOR_WARNING + "BUILD_UNIT_TESTS is deprecated. Use BUILD_TESTING instead.") + set(BUILD_TESTING ${BUILD_UNIT_TESTS}) +endif(DEFINED BUILD_UNIT_TESTS) + + +include("${JRL_CMAKE_MODULES}/base.cmake") +compute_project_args(PROJECT_ARGS LANGUAGES CXX) +project(${PROJECT_NAME} ${PROJECT_ARGS}) + + +include("${JRL_CMAKE_MODULES}/boost.cmake") +include("${JRL_CMAKE_MODULES}/python.cmake") +include("${JRL_CMAKE_MODULES}/ide.cmake") +include("${JRL_CMAKE_MODULES}/apple.cmake") + + +option(GENERATE_PYTHON_STUBS + "Generate the Python stubs associated to the Python library" OFF) + +string(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + + +# If needed, fix CMake policy for APPLE systems +apply_default_apple_configuration() +check_minimal_cxx_standard(11 ENFORCE) + +if(WIN32) + set(LINK copy_if_different) +else(WIN32) + set(LINK create_symlink) +endif(WIN32) + +if(CMAKE_CROSSCOMPILING) + set(PYTHON_COMPONENTS Interpreter NumPy) +else() + set(PYTHON_COMPONENTS Interpreter Development.Module NumPy) +endif() +set(PYTHON_EXPORT_DEPENDENCY ON) +findpython(REQUIRED) + + +if(${NUMPY_VERSION} VERSION_LESS "1.16.0") + set(NUMPY_WITH_BROKEN_UFUNC_SUPPORT TRUE) +endif() + + +if(WIN32) + link_directories(${PYTHON_LIBRARY_DIRS}) + # # Set default Windows build paths SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY + # ${PROJECT_BINARY_DIR}/Bin CACHE PATH "Single directory for all libraries") + # SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Bin CACHE PATH + # "Single directory for all executables") SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY + # ${PROJECT_BINARY_DIR}/Bin CACHE PATH "Sing$le directory for all archives") +endif(WIN32) + + + +# ---------------------------------------------------- +# --- DEPENDENCIES ----------------------------------- +# ---------------------------------------------------- +add_project_dependency(Eigen3 REQUIRED PKG_CONFIG_REQUIRES "eigen3 >= 3.0.5") +add_project_dependency(eigenpy REQUIRED PKG_CONFIG_REQUIRES "eigenpy >= 3.0.0") + +set_boost_default_options() +export_boost_default_options() +find_package(Boost REQUIRED) +search_for_boost_python(REQUIRED) + + +# ---------------------------------------------------- +# --- INCLUDE ---------------------------------------- +# ---------------------------------------------------- +set(${PROJECT_NAME}_HEADERS + include/header.hpp) + + +set(${PROJECT_NAME}_SOURCES src/src.cpp) + + + +add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} + ${${PROJECT_NAME}_HEADERS}) + + +target_include_directories( + ${PROJECT_NAME} SYSTEM + PUBLIC $ + $) + + +modernize_target_link_libraries( + ${PROJECT_NAME} + SCOPE + PUBLIC + TARGETS + Eigen3::Eigen + INCLUDE_DIRS + ${EIGEN3_INCLUDE_DIR}) + + +modernize_target_link_libraries( + ${PROJECT_NAME} + SCOPE + PUBLIC + TARGETS + Python${PYTHON_VERSION_MAJOR}::NumPy + INCLUDE_DIRS + ${NUMPY_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIR}) + + + +if(SUFFIX_SO_VERSION) + set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION}) +endif(SUFFIX_SO_VERSION) + + + + +if(NOT WIN32) + target_compile_options( + ${PROJECT_NAME} PRIVATE $<$:-bigobj> + "-Wno-conversion") +else() + target_compile_options(${PROJECT_NAME} + PRIVATE $<$:-bigobj>) + target_compile_definitions(${PROJECT_NAME} PUBLIC "HAVE_SNPRINTF") +endif() + +target_link_boost_python(${PROJECT_NAME} PUBLIC) +install( + TARGETS ${PROJECT_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_header_group(${PROJECT_NAME}_HEADERS) +add_source_group(${PROJECT_NAME}_SOURCES) + +# Install package for ROS +install(FILES package.xml DESTINATION share/example_) +# Allows Colcon to find non-Ament packages when using workspace underlays +file( + WRITE + ${CMAKE_CURRENT_BINARY_DIR}/share/ament_index/resource_index/packages/${PROJECT_NAME} + "") +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/share/ament_index/resource_index/packages/${PROJECT_NAME} + DESTINATION share/ament_index/resource_index/packages) +file( + WRITE + ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/ament_prefix_path.dsv + "prepend-non-duplicate;AMENT_PREFIX_PATH;") +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/ament_prefix_path.dsv + DESTINATION share/${PROJECT_NAME}/hook) +file(WRITE + ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/python_path.dsv + "prepend-non-duplicate;PYTHONPATH;${PYTHON_SITELIB}") +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/share/${PROJECT_NAME}/hook/python_path.dsv + DESTINATION share/${PROJECT_NAME}/hook) + +# ---------------------------------------------------- +# --- PYTHON LIBRARY --------------------------------- +# ---------------------------------------------------- +#add_subdirectory(python) + +pkg_config_append_libs(${PROJECT_NAME}) +pkg_config_append_cflags("-I${PYTHON_INCLUDE_DIRS}") +pkg_config_append_cflags("-I${NUMPY_INCLUDE_DIRS}") +pkg_config_append_boost_libs(${BOOST_COMPONENTS}) + + + + diff --git a/examples/custom_numeric_type/package.xml b/examples/custom_numeric_type/package.xml new file mode 100644 index 000000000..ea4f32fb4 --- /dev/null +++ b/examples/custom_numeric_type/package.xml @@ -0,0 +1,32 @@ + + + eigenpy_example_custom_numeric_type + 3.0.0 + Example of using EigenPy to enable custom numeric types with Eigen + Justin Carpentier + Wolfgang Merkt + Justin Carpentier + Nicolas Mansard + BSD + + https://github.com/stack-of-tasks/eigenpy/examples/custom_numeric_type + + git + doxygen + + + catkin + + python + python3 + python-numpy + python3-numpy + eigen + boost + eigenpy + + cmake + + cmake + + From 7d9048b6134e387affe576908ebec91977c1288f Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Thu, 18 May 2023 15:30:43 -0500 Subject: [PATCH 03/10] ignoring generated files --- examples/custom_numeric_type/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/custom_numeric_type/.gitignore diff --git a/examples/custom_numeric_type/.gitignore b/examples/custom_numeric_type/.gitignore new file mode 100644 index 000000000..68e319c8b --- /dev/null +++ b/examples/custom_numeric_type/.gitignore @@ -0,0 +1,3 @@ +include/eigenpy/example/custom/numeric/type/config.hpp +include/eigenpy/example/custom/numeric/type/deprecated.hpp +include/eigenpy/example/custom/numeric/type/warning.hpp \ No newline at end of file From c98aafbcebf3d49aab3351170c8e222e39497a2a Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Thu, 18 May 2023 15:30:59 -0500 Subject: [PATCH 04/10] made a readme --- examples/custom_numeric_type/readme.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 examples/custom_numeric_type/readme.md diff --git a/examples/custom_numeric_type/readme.md b/examples/custom_numeric_type/readme.md new file mode 100644 index 000000000..dd933cb61 --- /dev/null +++ b/examples/custom_numeric_type/readme.md @@ -0,0 +1,10 @@ +# An example of using eigenpy to extend Python using Eigen linear algebra package with custom numeric types + +## Building + +1. Make a build directory. Move into it +2. `cmake ../` +3. `make` +4. `make install` +5. Move back up a directory +6. `python3 examplescript.py` \ No newline at end of file From d13f4fabc3b400177d3974e24ddeec2d7193e02a Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Thu, 18 May 2023 15:31:06 -0500 Subject: [PATCH 05/10] an example script --- examples/custom_numeric_type/examplescript.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/custom_numeric_type/examplescript.py diff --git a/examples/custom_numeric_type/examplescript.py b/examples/custom_numeric_type/examplescript.py new file mode 100644 index 000000000..d3c947d63 --- /dev/null +++ b/examples/custom_numeric_type/examplescript.py @@ -0,0 +1,3 @@ +import eigenpy_example_custom_numeric_type as example + +example.MpfrComplex(2) # the number 2, in variable precision as a complex number \ No newline at end of file From 6566e878370da14d437b171234bbc879d32bc09b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 May 2023 20:33:45 +0000 Subject: [PATCH 06/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/custom_numeric_type/CMakeLists.txt | 42 +-- examples/custom_numeric_type/examplescript.py | 2 +- .../custom_numeric_type/include/header.hpp | 316 ++++++++---------- examples/custom_numeric_type/src/src.cpp | 81 ++--- 4 files changed, 188 insertions(+), 253 deletions(-) diff --git a/examples/custom_numeric_type/CMakeLists.txt b/examples/custom_numeric_type/CMakeLists.txt index 6fade50b0..fe4300a74 100644 --- a/examples/custom_numeric_type/CMakeLists.txt +++ b/examples/custom_numeric_type/CMakeLists.txt @@ -3,15 +3,16 @@ cmake_minimum_required(VERSION 3.1) set(PROJECT_NAME eigenpy_example_custom_numeric_type) -set(PROJECT_DESCRIPTION "An example of using eigenpy with a custom numeric type: Boost.Multiprecision complex numbers") -set(PROJECT_URL "http://github.com/stack-of-tasks/eigenpy/examples/custom_numeric_type") +set(PROJECT_DESCRIPTION + "An example of using eigenpy with a custom numeric type: Boost.Multiprecision complex numbers" +) +set(PROJECT_URL + "http://github.com/stack-of-tasks/eigenpy/examples/custom_numeric_type") set(PROJECT_USE_CMAKE_EXPORT TRUE) set(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE) set(PROJECT_CUSTOM_HEADER_EXTENSION "hpp") set(PROJECT_COMPATIBILITY_VERSION AnyNewerVersion) - - # Check if the submodule cmake have been initialized set(JRL_CMAKE_MODULES "${CMAKE_CURRENT_LIST_DIR}/cmake") if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/base.cmake") @@ -31,7 +32,6 @@ if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/base.cmake") endif() endif() - # Disable -Werror on Unix for now. set(CXX_DISABLE_WERROR True) set(CMAKE_VERBOSE_MAKEFILE True) @@ -41,29 +41,24 @@ option(SUFFIX_SO_VERSION "Suffix library name with its version" OFF) if(DEFINED BUILD_UNIT_TESTS) message( - AUTHOR_WARNING - "BUILD_UNIT_TESTS is deprecated. Use BUILD_TESTING instead.") + AUTHOR_WARNING "BUILD_UNIT_TESTS is deprecated. Use BUILD_TESTING instead.") set(BUILD_TESTING ${BUILD_UNIT_TESTS}) endif(DEFINED BUILD_UNIT_TESTS) - include("${JRL_CMAKE_MODULES}/base.cmake") compute_project_args(PROJECT_ARGS LANGUAGES CXX) project(${PROJECT_NAME} ${PROJECT_ARGS}) - include("${JRL_CMAKE_MODULES}/boost.cmake") include("${JRL_CMAKE_MODULES}/python.cmake") include("${JRL_CMAKE_MODULES}/ide.cmake") include("${JRL_CMAKE_MODULES}/apple.cmake") - option(GENERATE_PYTHON_STUBS "Generate the Python stubs associated to the Python library" OFF) string(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - # If needed, fix CMake policy for APPLE systems apply_default_apple_configuration() check_minimal_cxx_standard(11 ENFORCE) @@ -82,12 +77,10 @@ endif() set(PYTHON_EXPORT_DEPENDENCY ON) findpython(REQUIRED) - if(${NUMPY_VERSION} VERSION_LESS "1.16.0") set(NUMPY_WITH_BROKEN_UFUNC_SUPPORT TRUE) endif() - if(WIN32) link_directories(${PYTHON_LIBRARY_DIRS}) # # Set default Windows build paths SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY @@ -97,8 +90,6 @@ if(WIN32) # ${PROJECT_BINARY_DIR}/Bin CACHE PATH "Sing$le directory for all archives") endif(WIN32) - - # ---------------------------------------------------- # --- DEPENDENCIES ----------------------------------- # ---------------------------------------------------- @@ -110,28 +101,21 @@ export_boost_default_options() find_package(Boost REQUIRED) search_for_boost_python(REQUIRED) - # ---------------------------------------------------- # --- INCLUDE ---------------------------------------- # ---------------------------------------------------- -set(${PROJECT_NAME}_HEADERS - include/header.hpp) - +set(${PROJECT_NAME}_HEADERS include/header.hpp) set(${PROJECT_NAME}_SOURCES src/src.cpp) - - add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS}) - target_include_directories( ${PROJECT_NAME} SYSTEM PUBLIC $ $) - modernize_target_link_libraries( ${PROJECT_NAME} SCOPE @@ -141,7 +125,6 @@ modernize_target_link_libraries( INCLUDE_DIRS ${EIGEN3_INCLUDE_DIR}) - modernize_target_link_libraries( ${PROJECT_NAME} SCOPE @@ -152,15 +135,10 @@ modernize_target_link_libraries( ${NUMPY_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIR}) - - if(SUFFIX_SO_VERSION) set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION}) endif(SUFFIX_SO_VERSION) - - - if(NOT WIN32) target_compile_options( ${PROJECT_NAME} PRIVATE $<$:-bigobj> @@ -214,13 +192,9 @@ install( # ---------------------------------------------------- # --- PYTHON LIBRARY --------------------------------- # ---------------------------------------------------- -#add_subdirectory(python) +# add_subdirectory(python) pkg_config_append_libs(${PROJECT_NAME}) pkg_config_append_cflags("-I${PYTHON_INCLUDE_DIRS}") pkg_config_append_cflags("-I${NUMPY_INCLUDE_DIRS}") pkg_config_append_boost_libs(${BOOST_COMPONENTS}) - - - - diff --git a/examples/custom_numeric_type/examplescript.py b/examples/custom_numeric_type/examplescript.py index d3c947d63..e566d36be 100644 --- a/examples/custom_numeric_type/examplescript.py +++ b/examples/custom_numeric_type/examplescript.py @@ -1,3 +1,3 @@ import eigenpy_example_custom_numeric_type as example -example.MpfrComplex(2) # the number 2, in variable precision as a complex number \ No newline at end of file +example.MpfrComplex(2) # the number 2, in variable precision as a complex number diff --git a/examples/custom_numeric_type/include/header.hpp b/examples/custom_numeric_type/include/header.hpp index 97536d972..659cfdae6 100644 --- a/examples/custom_numeric_type/include/header.hpp +++ b/examples/custom_numeric_type/include/header.hpp @@ -11,41 +11,33 @@ #include - namespace bmp = boost::multiprecision; using bmp::backends::mpc_complex_backend; -using mpfr_complex = bmp::number, bmp::et_on >; // T is a variable-precision complex number with expression templates turned on. - - +using mpfr_complex = + bmp::number, + bmp::et_on>; // T is a variable-precision complex number with + // expression templates turned on. void Expose(); - - - - - -// this code derived from +// this code derived from // https://github.com/stack-of-tasks/eigenpy/issues/365 -// where I asked about using custom types, and @jcarpent responded with a discussion -// of an application of this in Pinnochio, a library for rigid body dynamics. -namespace eigenpy -{ - namespace internal - { - - +// where I asked about using custom types, and @jcarpent responded with a +// discussion of an application of this in Pinnochio, a library for rigid body +// dynamics. +namespace eigenpy { +namespace internal { // a template specialization for complex numbers - // derived directly from the example for Pinnochio +// derived directly from the example for Pinnochio template <> -struct getitem -{ - static PyObject* run(void* data, void* /* arr */) { - mpfr_complex & mpfr_scalar = *static_cast(data); - auto & backend = mpfr_scalar.backend(); - - if(backend.data()[0].re->_mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. +struct getitem { + static PyObject *run(void *data, void * /* arr */) { + mpfr_complex &mpfr_scalar = *static_cast(data); + auto &backend = mpfr_scalar.backend(); + + if (backend.data()[0].re->_mpfr_d == + 0) // If the mpfr_scalar is not initialized, we have to init it. { mpfr_scalar = mpfr_complex(0); } @@ -55,175 +47,159 @@ struct getitem } }; +} // namespace internal -} // namespace internal - - - - - - -// i lifted this from EigenPy and adapted it, basically removing the calls for the comparitors. +// i lifted this from EigenPy and adapted it, basically removing the calls for +// the comparitors. template -void registerUfunct_without_comparitors(){ - const int type_code = Register::getTypeCode(); - - PyObject *numpy_str; - #if PY_MAJOR_VERSION >= 3 - numpy_str = PyUnicode_FromString("numpy"); - #else - numpy_str = PyString_FromString("numpy"); - #endif - PyObject *numpy; - numpy = PyImport_Import(numpy_str); - Py_DECREF(numpy_str); - - import_ufunc(); - - // Matrix multiply - { - int types[3] = {type_code, type_code, type_code}; +void registerUfunct_without_comparitors() { + const int type_code = Register::getTypeCode(); + + PyObject *numpy_str; +#if PY_MAJOR_VERSION >= 3 + numpy_str = PyUnicode_FromString("numpy"); +#else + numpy_str = PyString_FromString("numpy"); +#endif + PyObject *numpy; + numpy = PyImport_Import(numpy_str); + Py_DECREF(numpy_str); + import_ufunc(); + + // Matrix multiply + { + int types[3] = {type_code, type_code, type_code}; + + std::stringstream ss; + ss << "return result of multiplying two matrices of "; + ss << bp::type_info(typeid(Scalar)).name(); + PyUFuncObject *ufunc = + (PyUFuncObject *)PyObject_GetAttrString(numpy, "matmul"); + if (!ufunc) { std::stringstream ss; - ss << "return result of multiplying two matrices of "; - ss << bp::type_info(typeid(Scalar)).name(); - PyUFuncObject *ufunc = - (PyUFuncObject *)PyObject_GetAttrString(numpy, "matmul"); - if (!ufunc) { - std::stringstream ss; - ss << "Impossible to define matrix_multiply for given type " - << bp::type_info(typeid(Scalar)).name() << std::endl; - eigenpy::Exception(ss.str()); - } - if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, type_code, - &internal::gufunc_matrix_multiply, - types, 0) < 0) { - std::stringstream ss; - ss << "Impossible to register matrix_multiply for given type " - << bp::type_info(typeid(Scalar)).name() << std::endl; - eigenpy::Exception(ss.str()); - } - - Py_DECREF(ufunc); + ss << "Impossible to define matrix_multiply for given type " + << bp::type_info(typeid(Scalar)).name() << std::endl; + eigenpy::Exception(ss.str()); + } + if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, type_code, + &internal::gufunc_matrix_multiply, + types, 0) < 0) { + std::stringstream ss; + ss << "Impossible to register matrix_multiply for given type " + << bp::type_info(typeid(Scalar)).name() << std::endl; + eigenpy::Exception(ss.str()); } - // Binary operators - EIGENPY_REGISTER_BINARY_UFUNC(add, type_code, Scalar, Scalar, Scalar); - EIGENPY_REGISTER_BINARY_UFUNC(subtract, type_code, Scalar, Scalar, Scalar); - EIGENPY_REGISTER_BINARY_UFUNC(multiply, type_code, Scalar, Scalar, Scalar); - EIGENPY_REGISTER_BINARY_UFUNC(divide, type_code, Scalar, Scalar, Scalar); - - // Comparison operators - EIGENPY_REGISTER_BINARY_UFUNC(equal, type_code, Scalar, Scalar, bool); - EIGENPY_REGISTER_BINARY_UFUNC(not_equal, type_code, Scalar, Scalar, bool); + Py_DECREF(ufunc); + } - //these are commented out because the comparisons are NOT defined for complex types!! - // EIGENPY_REGISTER_BINARY_UFUNC(greater, type_code, Scalar, Scalar, bool); - // EIGENPY_REGISTER_BINARY_UFUNC(less, type_code, Scalar, Scalar, bool); - // EIGENPY_REGISTER_BINARY_UFUNC(greater_equal, type_code, Scalar, Scalar, bool); - // EIGENPY_REGISTER_BINARY_UFUNC(less_equal, type_code, Scalar, Scalar, bool); + // Binary operators + EIGENPY_REGISTER_BINARY_UFUNC(add, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(subtract, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(multiply, type_code, Scalar, Scalar, Scalar); + EIGENPY_REGISTER_BINARY_UFUNC(divide, type_code, Scalar, Scalar, Scalar); - // Unary operators - EIGENPY_REGISTER_UNARY_UFUNC(negative, type_code, Scalar, Scalar); + // Comparison operators + EIGENPY_REGISTER_BINARY_UFUNC(equal, type_code, Scalar, Scalar, bool); + EIGENPY_REGISTER_BINARY_UFUNC(not_equal, type_code, Scalar, Scalar, bool); - Py_DECREF(numpy); -} + // these are commented out because the comparisons are NOT defined for complex + // types!! + // EIGENPY_REGISTER_BINARY_UFUNC(greater, type_code, Scalar, Scalar, bool); + // EIGENPY_REGISTER_BINARY_UFUNC(less, type_code, Scalar, Scalar, bool); + // EIGENPY_REGISTER_BINARY_UFUNC(greater_equal, type_code, Scalar, Scalar, + // bool); EIGENPY_REGISTER_BINARY_UFUNC(less_equal, type_code, Scalar, + // Scalar, bool); -} // namespace eigenpy + // Unary operators + EIGENPY_REGISTER_UNARY_UFUNC(negative, type_code, Scalar, Scalar); + Py_DECREF(numpy); +} +} // namespace eigenpy namespace bp = boost::python; -// this derived directly from the code at https://github.com/stack-of-tasks/eigenpy/issues/365, in which this example was requested -template -struct BoostNumberPythonVisitor -: public boost::python::def_visitor< BoostNumberPythonVisitor > -{ - -public: - - template - void visit(PyClass& cl) const - { - cl - .def(bp::init<>("Default constructor.",bp::arg("self"))) - .def(bp::init("Copy constructor.",bp::args("self","value"))) - .def(bp::init("Constructor from a string.",bp::args("self","str_value"))) - .def(bp::init("Constructor from a pair of strings.",bp::args("self","real","imag"))) - - - .def(bp::self + bp::self) - .def(bp::self += bp::self) - .def(bp::self - bp::self) - .def(bp::self -= bp::self) - .def(bp::self * bp::self) - .def(bp::self *= bp::self) - .def(bp::self / bp::self) - .def(bp::self /= bp::self) - - .def(bp::self == bp::self) - .def(bp::self != bp::self) - .def(bp::self_ns::pow(bp::self_ns::self,long())) - - - - .def("str",&BoostNumber::str,bp::args("self","precision","scientific")) - - .def("default_precision", - static_cast(BoostNumber::default_precision), - "Get the default precision of the class.") - .def("default_precision", - static_cast(BoostNumber::default_precision),bp::arg("digits10"), - "Set the default precision of the class.") - .staticmethod("default_precision") - - .def("precision", - static_cast(&BoostNumber::precision), - bp::arg("self"), - "Get the precision of this.") - .def("precision", - static_cast(&BoostNumber::precision), - bp::args("self","digits10"), - "Set the precision of this.") - - - .def("__str__",&print,bp::arg("self")) - .def("__repr__",&print,bp::arg("self")) - - .def("set_display_precision",&set_display_precision,bp::arg("digit"), - "Set the precision when printing values.") - .staticmethod("set_display_precision") - - .def("get_display_precision",&get_display_precision, - "Get the precision when printing values.", - bp::return_value_policy()) - .staticmethod("get_display_precision") - - ; - +// this derived directly from the code at +// https://github.com/stack-of-tasks/eigenpy/issues/365, in which this example +// was requested +template +struct BoostNumberPythonVisitor : public boost::python::def_visitor< + BoostNumberPythonVisitor > { + public: + template + void visit(PyClass &cl) const { + cl.def(bp::init<>("Default constructor.", bp::arg("self"))) + .def(bp::init("Copy constructor.", + bp::args("self", "value"))) + .def(bp::init("Constructor from a string.", + bp::args("self", "str_value"))) + .def(bp::init( + "Constructor from a pair of strings.", + bp::args("self", "real", "imag"))) + + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self * bp::self) + .def(bp::self *= bp::self) + .def(bp::self / bp::self) + .def(bp::self /= bp::self) + + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def(bp::self_ns::pow(bp::self_ns::self, long())) + + .def("str", &BoostNumber::str, + bp::args("self", "precision", "scientific")) + + .def("default_precision", + static_cast(BoostNumber::default_precision), + "Get the default precision of the class.") + .def("default_precision", + static_cast(BoostNumber::default_precision), + bp::arg("digits10"), "Set the default precision of the class.") + .staticmethod("default_precision") + + .def("precision", + static_cast( + &BoostNumber::precision), + bp::arg("self"), "Get the precision of this.") + .def("precision", + static_cast( + &BoostNumber::precision), + bp::args("self", "digits10"), "Set the precision of this.") + + .def("__str__", &print, bp::arg("self")) + .def("__repr__", &print, bp::arg("self")) + + .def("set_display_precision", &set_display_precision, bp::arg("digit"), + "Set the precision when printing values.") + .staticmethod("set_display_precision") + + .def("get_display_precision", &get_display_precision, + "Get the precision when printing values.", + bp::return_value_policy()) + .staticmethod("get_display_precision") + + ; } - static std::string print(const BoostNumber & self) - { + static std::string print(const BoostNumber &self) { return self.str(get_display_precision(), std::ios_base::dec); } - static void set_display_precision(const int digit) - { + static void set_display_precision(const int digit) { get_display_precision() = digit; } - - static int & get_display_precision() - { + + static int &get_display_precision() { static int precision = BoostNumber::default_precision(); return precision; } }; - - - #endif - - diff --git a/examples/custom_numeric_type/src/src.cpp b/examples/custom_numeric_type/src/src.cpp index a47aaf810..79b88b85c 100644 --- a/examples/custom_numeric_type/src/src.cpp +++ b/examples/custom_numeric_type/src/src.cpp @@ -1,62 +1,47 @@ #include "header.hpp" - - -BOOST_PYTHON_MODULE(eigenpy_example_custom_numeric_type) // this name must match the name of the generated .so file. -{ - // see https://stackoverflow.com/questions/6114462/how-to-override-the-automatically-created-docstring-data-for-boostpython - // docstring_options d(true, true, false); // local_ - boost::python::docstring_options docopt; - docopt.enable_all(); - docopt.disable_cpp_signatures(); - - boost::python::object package = boost::python::scope(); - package.attr("__path__") = "eigenpy_example_custom_numeric_type"; - - - Expose(); +BOOST_PYTHON_MODULE( + eigenpy_example_custom_numeric_type) // this name must match the name of + // the generated .so file. +{ + // see + // https://stackoverflow.com/questions/6114462/how-to-override-the-automatically-created-docstring-data-for-boostpython + // docstring_options d(true, true, false); // local_ + boost::python::docstring_options docopt; + docopt.enable_all(); + docopt.disable_cpp_signatures(); + + boost::python::object package = boost::python::scope(); + package.attr("__path__") = "eigenpy_example_custom_numeric_type"; + + Expose(); } +#define IMPLICITLY_CONVERTIBLE(T1, T2) \ + boost::python::implicitly_convertible(); +void Expose() { + eigenpy::enableEigenPy(); -#define IMPLICITLY_CONVERTIBLE(T1,T2) \ - boost::python::implicitly_convertible(); - -void Expose(){ - - eigenpy::enableEigenPy(); - - boost::python::class_("MpfrComplex", - "",bp::no_init) - .def(BoostNumberPythonVisitor()) - ; - + boost::python::class_("MpfrComplex", "", bp::no_init) + .def(BoostNumberPythonVisitor()); + eigenpy::registerNewType(); + eigenpy::registerUfunct_without_comparitors(); - eigenpy::registerNewType(); - eigenpy::registerUfunct_without_comparitors(); + eigenpy::registerCast(true); + eigenpy::registerCast(true); + eigenpy::registerCast(true); + IMPLICITLY_CONVERTIBLE(int, mpfr_complex); + IMPLICITLY_CONVERTIBLE(long, mpfr_complex); + IMPLICITLY_CONVERTIBLE(int64_t, mpfr_complex); - eigenpy::registerCast(true); - eigenpy::registerCast(true); - eigenpy::registerCast(true); + using VecX = Eigen::Matrix; + using MatXX = Eigen::Matrix; - - - IMPLICITLY_CONVERTIBLE(int,mpfr_complex); - IMPLICITLY_CONVERTIBLE(long,mpfr_complex); - IMPLICITLY_CONVERTIBLE(int64_t,mpfr_complex); - - using VecX = Eigen::Matrix; - using MatXX = Eigen::Matrix; - - - - - eigenpy::enableEigenPySpecific(); - eigenpy::enableEigenPySpecific(); + eigenpy::enableEigenPySpecific(); + eigenpy::enableEigenPySpecific(); } - - #undef IMPLICITLY_CONVERTIBLE From 5645b0a7b160d056cebf56d1d3c9bf7fbd757444 Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:29:54 -0600 Subject: [PATCH 07/10] finding libraries, making .so without lib now makes a library without `lib` at front, and with `.so` at the end. I was able to get this to compile and import using libraries installed via `conda`. --- examples/custom_numeric_type/CMakeLists.txt | 28 ++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/examples/custom_numeric_type/CMakeLists.txt b/examples/custom_numeric_type/CMakeLists.txt index fe4300a74..d332efbed 100644 --- a/examples/custom_numeric_type/CMakeLists.txt +++ b/examples/custom_numeric_type/CMakeLists.txt @@ -1,6 +1,6 @@ # derived from eigenpy/CMakeLists.txt for this example -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.10) set(PROJECT_NAME eigenpy_example_custom_numeric_type) set(PROJECT_DESCRIPTION @@ -93,6 +93,7 @@ endif(WIN32) # ---------------------------------------------------- # --- DEPENDENCIES ----------------------------------- # ---------------------------------------------------- + add_project_dependency(Eigen3 REQUIRED PKG_CONFIG_REQUIRES "eigen3 >= 3.0.5") add_project_dependency(eigenpy REQUIRED PKG_CONFIG_REQUIRES "eigenpy >= 3.0.0") @@ -116,14 +117,8 @@ target_include_directories( PUBLIC $ $) -modernize_target_link_libraries( - ${PROJECT_NAME} - SCOPE - PUBLIC - TARGETS - Eigen3::Eigen - INCLUDE_DIRS - ${EIGEN3_INCLUDE_DIR}) +target_link_directories(${PROJECT_NAME} + PUBLIC ${EIGENPY_LIB_DIR}) modernize_target_link_libraries( ${PROJECT_NAME} @@ -131,14 +126,26 @@ modernize_target_link_libraries( PUBLIC TARGETS Python${PYTHON_VERSION_MAJOR}::NumPy + Eigen3::Eigen + eigenpy INCLUDE_DIRS + ${EIGEN3_INCLUDE_DIR} + ${EIGENPY_INCLUDE_DIR} ${NUMPY_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIR}) + +target_link_libraries(${PROJECT_NAME} PUBLIC eigenpy::eigenpy mpc mpfr) + if(SUFFIX_SO_VERSION) set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION}) endif(SUFFIX_SO_VERSION) + +#silviana did this +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") +set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".so") + if(NOT WIN32) target_compile_options( ${PROJECT_NAME} PRIVATE $<$:-bigobj> @@ -150,6 +157,9 @@ else() endif() target_link_boost_python(${PROJECT_NAME} PUBLIC) + + + install( TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} From bc20416be95dcfc29de2c351826e683b26f313ed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:30:17 +0000 Subject: [PATCH 08/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/custom_numeric_type/CMakeLists.txt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/custom_numeric_type/CMakeLists.txt b/examples/custom_numeric_type/CMakeLists.txt index d332efbed..be6dba62e 100644 --- a/examples/custom_numeric_type/CMakeLists.txt +++ b/examples/custom_numeric_type/CMakeLists.txt @@ -117,8 +117,7 @@ target_include_directories( PUBLIC $ $) -target_link_directories(${PROJECT_NAME} - PUBLIC ${EIGENPY_LIB_DIR}) +target_link_directories(${PROJECT_NAME} PUBLIC ${EIGENPY_LIB_DIR}) modernize_target_link_libraries( ${PROJECT_NAME} @@ -134,15 +133,13 @@ modernize_target_link_libraries( ${NUMPY_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIR}) - target_link_libraries(${PROJECT_NAME} PUBLIC eigenpy::eigenpy mpc mpfr) if(SUFFIX_SO_VERSION) set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION}) endif(SUFFIX_SO_VERSION) - -#silviana did this +# silviana did this set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".so") @@ -158,8 +155,6 @@ endif() target_link_boost_python(${PROJECT_NAME} PUBLIC) - - install( TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} From de32d977608e25cd08fe3917c944a304aeed63b4 Mon Sep 17 00:00:00 2001 From: silviana amethyst <1388063+ofloveandhate@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:43:38 -0600 Subject: [PATCH 09/10] now can actually make complexes and interact without crashes * brought in the real visitor from https://github.com/stack-of-tasks/eigenpy/issues/365 (from which I had previously derived the complex visitor). * provided the `real` and `imag` properties the code could be cleaner, but now I can actually import the built library, make a complex, get its real/imag parts, do arithmetic, and use dot-tab completion in ipython without crashes. (motivation: i'm working towards a MWE for the alignment issues I get in Bertini 2. either I can replicate it using this code, in which case we can find the bug / whatever in eigenpy, or I fail, and I reveal the bug in MY code.) --- .../custom_numeric_type/include/header.hpp | 209 +++++++++++++++++- examples/custom_numeric_type/src/src.cpp | 27 ++- 2 files changed, 227 insertions(+), 9 deletions(-) diff --git a/examples/custom_numeric_type/include/header.hpp b/examples/custom_numeric_type/include/header.hpp index 659cfdae6..658718b6b 100644 --- a/examples/custom_numeric_type/include/header.hpp +++ b/examples/custom_numeric_type/include/header.hpp @@ -11,14 +11,24 @@ #include +#include + namespace bmp = boost::multiprecision; + + + +using mpfr_float = boost::multiprecision::number, boost::multiprecision::et_off>; + + using bmp::backends::mpc_complex_backend; using mpfr_complex = bmp::number, - bmp::et_on>; // T is a variable-precision complex number with + bmp::et_off>; // T is a variable-precision complex number with // expression templates turned on. -void Expose(); +void ExposeAll(); +void ExposeReal(); +void ExposeComplex(); // this code derived from // https://github.com/stack-of-tasks/eigenpy/issues/365 @@ -28,6 +38,24 @@ void Expose(); namespace eigenpy { namespace internal { +// a template specialization for complex numbers +// derived directly from the example for Pinnochio +template <> +struct getitem { + static PyObject *run(void *data, void * /* arr */) { + mpfr_float &mpfr_scalar = *static_cast(data); + auto &backend = mpfr_scalar.backend(); + + if (backend.data()[0]._mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. + { + mpfr_scalar = mpfr_float(0); + } + boost::python::object m(boost::ref(mpfr_scalar)); + Py_INCREF(m.ptr()); + return m.ptr(); + } +}; + // a template specialization for complex numbers // derived directly from the example for Pinnochio template <> @@ -36,8 +64,7 @@ struct getitem { mpfr_complex &mpfr_scalar = *static_cast(data); auto &backend = mpfr_scalar.backend(); - if (backend.data()[0].re->_mpfr_d == - 0) // If the mpfr_scalar is not initialized, we have to init it. + if (backend.data()[0].re->_mpfr_d == 0 || backend.data()[0].im->_mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. { mpfr_scalar = mpfr_complex(0); } @@ -120,14 +147,169 @@ void registerUfunct_without_comparitors() { } // namespace eigenpy + namespace bp = boost::python; + + + + +template +struct BoostNumberPythonVisitor +: public boost::python::def_visitor< BoostNumberPythonVisitor > +{ + +public: + + template + void visit(PyClass& cl) const + { + cl + .def(bp::init<>("Default constructor.",bp::arg("self"))) + .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) +// .def(bp::init("Copy constructor.",bp::args("self","value"))) + .def(bp::init("Constructor from a string.",bp::args("self","str_value"))) + + + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self * bp::self) + .def(bp::self *= bp::self) + .def(bp::self / bp::self) + .def(bp::self /= bp::self) + + .def(bp::self < bp::self) + .def(bp::self <= bp::self) + .def(bp::self > bp::self) + .def(bp::self >= bp::self) + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def(bp::self_ns::pow(bp::self_ns::self,long())) + + + .def("str",&BoostNumber::str,bp::args("self","precision","scientific")) + + .def("default_precision", + static_cast(BoostNumber::default_precision), + "Get the default precision of the class.") + .def("default_precision", + static_cast(BoostNumber::default_precision),bp::arg("digits10"), + "Set the default precision of the class.") + .staticmethod("default_precision") + + .def("precision", + static_cast(&BoostNumber::precision), + bp::arg("self"), + "Get the precision of this.") + .def("precision", + static_cast(&BoostNumber::precision), + bp::args("self","digits10"), + "Set the precision of this.") + + .def("__float__",&cast,bp::arg("self"),"Cast to float.") + .def("__int__",&cast,bp::arg("self"),"Cast to int.") + + .def("__str__",&print,bp::arg("self")) + .def("__repr__",&print,bp::arg("self")) + + .def("set_display_precision",&set_display_precision,bp::arg("digit"), + "Set the precision when printing values.") + .staticmethod("set_display_precision") + + .def("get_display_precision",&get_display_precision, + "Get the precision when printing values.", + bp::return_value_policy()) + .staticmethod("get_display_precision") + +//#ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION +// .def_pickle(Pickle()) +//#endif + ; + + } + + + static void expose(const std::string & type_name) + { + bp::class_(type_name.c_str(), + "",bp::no_init) + .def(BoostNumberPythonVisitor()) + ; + + eigenpy::registerNewType(); + eigenpy::registerCommonUfunc(); + +#define IMPLICITLY_CONVERTIBLE(T1,T2) \ + bp::implicitly_convertible(); +// bp::implicitly_convertible(); + + IMPLICITLY_CONVERTIBLE(double,BoostNumber); + IMPLICITLY_CONVERTIBLE(float,BoostNumber); + IMPLICITLY_CONVERTIBLE(long int,BoostNumber); + IMPLICITLY_CONVERTIBLE(int,BoostNumber); + IMPLICITLY_CONVERTIBLE(long,BoostNumber); + IMPLICITLY_CONVERTIBLE(unsigned int,BoostNumber); + IMPLICITLY_CONVERTIBLE(unsigned long int,BoostNumber); + IMPLICITLY_CONVERTIBLE(bool,BoostNumber); + +#undef IMPLICITLY_CONVERTIBLE + + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true);; + eigenpy::registerCast(false); + eigenpy::registerCast(true); + } + + private: + + template + static T cast(const BoostNumber & self) + { + return static_cast(self); + } + + static std::string print(const BoostNumber & self) + { + return self.str(get_display_precision(), std::ios_base::dec); + } + + static void set_display_precision(const int digit) + { + get_display_precision() = digit; + } + + static int & get_display_precision() + { + static int precision = BoostNumber::default_precision(); + return precision; + } + + }; + + + + // this derived directly from the code at // https://github.com/stack-of-tasks/eigenpy/issues/365, in which this example // was requested + template -struct BoostNumberPythonVisitor : public boost::python::def_visitor< - BoostNumberPythonVisitor > { +struct BoostComplexPythonVisitor : public boost::python::def_visitor< + BoostComplexPythonVisitor > { public: template void visit(PyClass &cl) const { @@ -140,6 +322,10 @@ struct BoostNumberPythonVisitor : public boost::python::def_visitor< "Constructor from a pair of strings.", bp::args("self", "real", "imag"))) + .def(bp::init( + "Constructor from a pair of integers.", + bp::args("self", "real", "imag"))) + .def(bp::self + bp::self) .def(bp::self += bp::self) .def(bp::self - bp::self) @@ -164,6 +350,10 @@ struct BoostNumberPythonVisitor : public boost::python::def_visitor< bp::arg("digits10"), "Set the default precision of the class.") .staticmethod("default_precision") + + .add_property("real", &get_real, &set_real) + .add_property("imag", &get_imag, &set_imag) + .def("precision", static_cast( &BoostNumber::precision), @@ -188,6 +378,13 @@ struct BoostNumberPythonVisitor : public boost::python::def_visitor< ; } + static void set_real(BoostNumber &c, mpfr_float const& r) { c.real(r);} + static mpfr_float get_real(BoostNumber const&c) { return c.real();} + + static void set_imag(BoostNumber &c, mpfr_float const& r) { c.imag(r);} + static mpfr_float get_imag(BoostNumber const&c) { return c.imag();} + + static std::string print(const BoostNumber &self) { return self.str(get_display_precision(), std::ios_base::dec); } diff --git a/examples/custom_numeric_type/src/src.cpp b/examples/custom_numeric_type/src/src.cpp index 79b88b85c..423103972 100644 --- a/examples/custom_numeric_type/src/src.cpp +++ b/examples/custom_numeric_type/src/src.cpp @@ -14,17 +14,38 @@ BOOST_PYTHON_MODULE( boost::python::object package = boost::python::scope(); package.attr("__path__") = "eigenpy_example_custom_numeric_type"; - Expose(); + ExposeAll(); } #define IMPLICITLY_CONVERTIBLE(T1, T2) \ boost::python::implicitly_convertible(); -void Expose() { + + +void ExposeAll(){ eigenpy::enableEigenPy(); + ExposeReal(); + ExposeComplex(); +} + +void ExposeReal() { + + BoostNumberPythonVisitor::expose("MpfrFloat"); + + + using VecX = Eigen::Matrix; + using MatXX = Eigen::Matrix; + + eigenpy::enableEigenPySpecific(); + eigenpy::enableEigenPySpecific(); +} + + +void ExposeComplex() { + boost::python::class_("MpfrComplex", "", bp::no_init) - .def(BoostNumberPythonVisitor()); + .def(BoostComplexPythonVisitor()); eigenpy::registerNewType(); eigenpy::registerUfunct_without_comparitors(); From 4c40a1940bb3fe28733f12c4a38d5bdfa1d4f7b5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:44:16 +0000 Subject: [PATCH 10/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../custom_numeric_type/include/header.hpp | 297 +++++++++--------- examples/custom_numeric_type/src/src.cpp | 8 +- 2 files changed, 141 insertions(+), 164 deletions(-) diff --git a/examples/custom_numeric_type/include/header.hpp b/examples/custom_numeric_type/include/header.hpp index 658718b6b..d8289aaef 100644 --- a/examples/custom_numeric_type/include/header.hpp +++ b/examples/custom_numeric_type/include/header.hpp @@ -15,16 +15,15 @@ namespace bmp = boost::multiprecision; - - -using mpfr_float = boost::multiprecision::number, boost::multiprecision::et_off>; - +using mpfr_float = + boost::multiprecision::number, + boost::multiprecision::et_off>; using bmp::backends::mpc_complex_backend; using mpfr_complex = bmp::number, bmp::et_off>; // T is a variable-precision complex number with - // expression templates turned on. + // expression templates turned on. void ExposeAll(); void ExposeReal(); @@ -46,7 +45,8 @@ struct getitem { mpfr_float &mpfr_scalar = *static_cast(data); auto &backend = mpfr_scalar.backend(); - if (backend.data()[0]._mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. + if (backend.data()[0]._mpfr_d == + 0) // If the mpfr_scalar is not initialized, we have to init it. { mpfr_scalar = mpfr_float(0); } @@ -64,7 +64,9 @@ struct getitem { mpfr_complex &mpfr_scalar = *static_cast(data); auto &backend = mpfr_scalar.backend(); - if (backend.data()[0].re->_mpfr_d == 0 || backend.data()[0].im->_mpfr_d == 0) // If the mpfr_scalar is not initialized, we have to init it. + if (backend.data()[0].re->_mpfr_d == 0 || + backend.data()[0].im->_mpfr_d == + 0) // If the mpfr_scalar is not initialized, we have to init it. { mpfr_scalar = mpfr_complex(0); } @@ -147,169 +149,153 @@ void registerUfunct_without_comparitors() { } // namespace eigenpy - namespace bp = boost::python; +template +struct BoostNumberPythonVisitor : public boost::python::def_visitor< + BoostNumberPythonVisitor > { + public: + template + void visit(PyClass &cl) const { + cl.def(bp::init<>("Default constructor.", bp::arg("self"))) + .def(bp::init("Copy constructor.", + bp::args("self", "value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) .def(bp::init("Copy constructor.",bp::args("self","value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) + // .def(bp::init("Copy + // constructor.",bp::args("self","value"))) + .def(bp::init("Constructor from a string.", + bp::args("self", "str_value"))) + .def(bp::self + bp::self) + .def(bp::self += bp::self) + .def(bp::self - bp::self) + .def(bp::self -= bp::self) + .def(bp::self * bp::self) + .def(bp::self *= bp::self) + .def(bp::self / bp::self) + .def(bp::self /= bp::self) + + .def(bp::self < bp::self) + .def(bp::self <= bp::self) + .def(bp::self > bp::self) + .def(bp::self >= bp::self) + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def(bp::self_ns::pow(bp::self_ns::self, long())) + + .def("str", &BoostNumber::str, + bp::args("self", "precision", "scientific")) + + .def("default_precision", + static_cast(BoostNumber::default_precision), + "Get the default precision of the class.") + .def("default_precision", + static_cast(BoostNumber::default_precision), + bp::arg("digits10"), "Set the default precision of the class.") + .staticmethod("default_precision") + + .def("precision", + static_cast( + &BoostNumber::precision), + bp::arg("self"), "Get the precision of this.") + .def("precision", + static_cast( + &BoostNumber::precision), + bp::args("self", "digits10"), "Set the precision of this.") + .def("__float__", &cast, bp::arg("self"), "Cast to float.") + .def("__int__", &cast, bp::arg("self"), "Cast to int.") + .def("__str__", &print, bp::arg("self")) + .def("__repr__", &print, bp::arg("self")) -template -struct BoostNumberPythonVisitor -: public boost::python::def_visitor< BoostNumberPythonVisitor > -{ + .def("set_display_precision", &set_display_precision, bp::arg("digit"), + "Set the precision when printing values.") + .staticmethod("set_display_precision") -public: + .def("get_display_precision", &get_display_precision, + "Get the precision when printing values.", + bp::return_value_policy()) + .staticmethod("get_display_precision") - template - void visit(PyClass& cl) const - { - cl - .def(bp::init<>("Default constructor.",bp::arg("self"))) - .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) -// .def(bp::init("Copy constructor.",bp::args("self","value"))) - .def(bp::init("Constructor from a string.",bp::args("self","str_value"))) - - - .def(bp::self + bp::self) - .def(bp::self += bp::self) - .def(bp::self - bp::self) - .def(bp::self -= bp::self) - .def(bp::self * bp::self) - .def(bp::self *= bp::self) - .def(bp::self / bp::self) - .def(bp::self /= bp::self) - - .def(bp::self < bp::self) - .def(bp::self <= bp::self) - .def(bp::self > bp::self) - .def(bp::self >= bp::self) - .def(bp::self == bp::self) - .def(bp::self != bp::self) - .def(bp::self_ns::pow(bp::self_ns::self,long())) - - - .def("str",&BoostNumber::str,bp::args("self","precision","scientific")) - - .def("default_precision", - static_cast(BoostNumber::default_precision), - "Get the default precision of the class.") - .def("default_precision", - static_cast(BoostNumber::default_precision),bp::arg("digits10"), - "Set the default precision of the class.") - .staticmethod("default_precision") - - .def("precision", - static_cast(&BoostNumber::precision), - bp::arg("self"), - "Get the precision of this.") - .def("precision", - static_cast(&BoostNumber::precision), - bp::args("self","digits10"), - "Set the precision of this.") - - .def("__float__",&cast,bp::arg("self"),"Cast to float.") - .def("__int__",&cast,bp::arg("self"),"Cast to int.") - - .def("__str__",&print,bp::arg("self")) - .def("__repr__",&print,bp::arg("self")) - - .def("set_display_precision",&set_display_precision,bp::arg("digit"), - "Set the precision when printing values.") - .staticmethod("set_display_precision") - - .def("get_display_precision",&get_display_precision, - "Get the precision when printing values.", - bp::return_value_policy()) - .staticmethod("get_display_precision") - -//#ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION -// .def_pickle(Pickle()) -//#endif - ; - + // #ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION + // .def_pickle(Pickle()) + // #endif + ; } + static void expose(const std::string &type_name) { + bp::class_(type_name.c_str(), "", bp::no_init) + .def(BoostNumberPythonVisitor()); + + eigenpy::registerNewType(); + eigenpy::registerCommonUfunc(); + +#define IMPLICITLY_CONVERTIBLE(T1, T2) bp::implicitly_convertible(); + // bp::implicitly_convertible(); + + IMPLICITLY_CONVERTIBLE(double, BoostNumber); + IMPLICITLY_CONVERTIBLE(float, BoostNumber); + IMPLICITLY_CONVERTIBLE(long int, BoostNumber); + IMPLICITLY_CONVERTIBLE(int, BoostNumber); + IMPLICITLY_CONVERTIBLE(long, BoostNumber); + IMPLICITLY_CONVERTIBLE(unsigned int, BoostNumber); + IMPLICITLY_CONVERTIBLE(unsigned long int, BoostNumber); + IMPLICITLY_CONVERTIBLE(bool, BoostNumber); - static void expose(const std::string & type_name) - { - bp::class_(type_name.c_str(), - "",bp::no_init) - .def(BoostNumberPythonVisitor()) - ; - - eigenpy::registerNewType(); - eigenpy::registerCommonUfunc(); - -#define IMPLICITLY_CONVERTIBLE(T1,T2) \ - bp::implicitly_convertible(); -// bp::implicitly_convertible(); - - IMPLICITLY_CONVERTIBLE(double,BoostNumber); - IMPLICITLY_CONVERTIBLE(float,BoostNumber); - IMPLICITLY_CONVERTIBLE(long int,BoostNumber); - IMPLICITLY_CONVERTIBLE(int,BoostNumber); - IMPLICITLY_CONVERTIBLE(long,BoostNumber); - IMPLICITLY_CONVERTIBLE(unsigned int,BoostNumber); - IMPLICITLY_CONVERTIBLE(unsigned long int,BoostNumber); - IMPLICITLY_CONVERTIBLE(bool,BoostNumber); - #undef IMPLICITLY_CONVERTIBLE - eigenpy::registerCast(false); - eigenpy::registerCast(true); - eigenpy::registerCast(false); - eigenpy::registerCast(true); - eigenpy::registerCast(false); - eigenpy::registerCast(true); - eigenpy::registerCast(false); - eigenpy::registerCast(true);; - eigenpy::registerCast(false); - eigenpy::registerCast(true); - } - - private: - - template - static T cast(const BoostNumber & self) - { - return static_cast(self); - } - - static std::string print(const BoostNumber & self) - { - return self.str(get_display_precision(), std::ios_base::dec); - } - - static void set_display_precision(const int digit) - { - get_display_precision() = digit; - } - - static int & get_display_precision() - { - static int precision = BoostNumber::default_precision(); - return precision; - } - - }; + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true); + eigenpy::registerCast(false); + eigenpy::registerCast(true); + ; + eigenpy::registerCast(false); + eigenpy::registerCast(true); + } + private: + template + static T cast(const BoostNumber &self) { + return static_cast(self); + } + static std::string print(const BoostNumber &self) { + return self.str(get_display_precision(), std::ios_base::dec); + } + static void set_display_precision(const int digit) { + get_display_precision() = digit; + } + + static int &get_display_precision() { + static int precision = BoostNumber::default_precision(); + return precision; + } +}; // this derived directly from the code at // https://github.com/stack-of-tasks/eigenpy/issues/365, in which this example // was requested template -struct BoostComplexPythonVisitor : public boost::python::def_visitor< - BoostComplexPythonVisitor > { +struct BoostComplexPythonVisitor + : public boost::python::def_visitor< + BoostComplexPythonVisitor > { public: template void visit(PyClass &cl) const { @@ -322,9 +308,8 @@ struct BoostComplexPythonVisitor : public boost::python::def_visitor< "Constructor from a pair of strings.", bp::args("self", "real", "imag"))) - .def(bp::init( - "Constructor from a pair of integers.", - bp::args("self", "real", "imag"))) + .def(bp::init("Constructor from a pair of integers.", + bp::args("self", "real", "imag"))) .def(bp::self + bp::self) .def(bp::self += bp::self) @@ -350,7 +335,6 @@ struct BoostComplexPythonVisitor : public boost::python::def_visitor< bp::arg("digits10"), "Set the default precision of the class.") .staticmethod("default_precision") - .add_property("real", &get_real, &set_real) .add_property("imag", &get_imag, &set_imag) @@ -378,12 +362,11 @@ struct BoostComplexPythonVisitor : public boost::python::def_visitor< ; } - static void set_real(BoostNumber &c, mpfr_float const& r) { c.real(r);} - static mpfr_float get_real(BoostNumber const&c) { return c.real();} - - static void set_imag(BoostNumber &c, mpfr_float const& r) { c.imag(r);} - static mpfr_float get_imag(BoostNumber const&c) { return c.imag();} + static void set_real(BoostNumber &c, mpfr_float const &r) { c.real(r); } + static mpfr_float get_real(BoostNumber const &c) { return c.real(); } + static void set_imag(BoostNumber &c, mpfr_float const &r) { c.imag(r); } + static mpfr_float get_imag(BoostNumber const &c) { return c.imag(); } static std::string print(const BoostNumber &self) { return self.str(get_display_precision(), std::ios_base::dec); diff --git a/examples/custom_numeric_type/src/src.cpp b/examples/custom_numeric_type/src/src.cpp index 423103972..14b055cb2 100644 --- a/examples/custom_numeric_type/src/src.cpp +++ b/examples/custom_numeric_type/src/src.cpp @@ -20,9 +20,7 @@ BOOST_PYTHON_MODULE( #define IMPLICITLY_CONVERTIBLE(T1, T2) \ boost::python::implicitly_convertible(); - - -void ExposeAll(){ +void ExposeAll() { eigenpy::enableEigenPy(); ExposeReal(); @@ -30,10 +28,8 @@ void ExposeAll(){ } void ExposeReal() { - BoostNumberPythonVisitor::expose("MpfrFloat"); - using VecX = Eigen::Matrix; using MatXX = Eigen::Matrix; @@ -41,9 +37,7 @@ void ExposeReal() { eigenpy::enableEigenPySpecific(); } - void ExposeComplex() { - boost::python::class_("MpfrComplex", "", bp::no_init) .def(BoostComplexPythonVisitor());