diff --git a/.github/workflows/windows-conda.yml b/.github/workflows/windows-conda.yml index b3f8ad815..6315c0f4a 100644 --- a/.github/workflows/windows-conda.yml +++ b/.github/workflows/windows-conda.yml @@ -58,7 +58,7 @@ jobs: if errorlevel 1 exit 1 :: Build and Install - cmake --build . --config Release --target install + cmake --build . -j3 --config Release --target install if errorlevel 1 exit 1 :: Testing diff --git a/CHANGELOG.md b/CHANGELOG.md index 18791046b..12eeb5369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Allow use of installed JRL-cmakemodule ([#446](https://github.com/stack-of-tasks/eigenpy/pull/446) - Support of Numpy 2.0.0b1 ([#448](https://github.com/stack-of-tasks/eigenpy/pull/448)) +- Support new primitive type (char, int8_t, uint8_t, int16_t, uint16_t, uint32_t, uint64_t) ([#455]()https://github.com/stack-of-tasks/eigenpy/pull/455) +- Support conversion between signed <-> unsigned integers ([#455](https://github.com/stack-of-tasks/eigenpy/pull/455)) +- Support conversion between complex numbers ([#455](https://github.com/stack-of-tasks/eigenpy/pull/455)) ### Fixed - Fix unit test build in C++11 ([#442](https://github.com/stack-of-tasks/eigenpy/pull/442)) - Fix unit test function signature [#443](https://github.com/stack-of-tasks/eigenpy/pull/443)) - Fix CMake export ([#446](https://github.com/stack-of-tasks/eigenpy/pull/446) +- Fix `int` management on Windows ([#455](https://github.com/stack-of-tasks/eigenpy/pull/455)) +- Fix `long long` management on Mac ([#455](https://github.com/stack-of-tasks/eigenpy/pull/455)) + +### Removed +- Remove casting when converting from Eigen scalar to Numpy scalar. + This should not remove any functionality since Numpy array are created from the Eigen scalar type + ([#455](https://github.com/stack-of-tasks/eigenpy/pull/455)) ## [3.4.0] - 2024-02-26 diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fc16e5d5..47502c232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ 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) option(BUILD_TESTING_SCIPY - "Build the SciPy tests (scipy should be installed on the machine)" OFF) + "Build the SciPy tests (scipy should be installed on the machine)" ON) include("${JRL_CMAKE_MODULES}/base.cmake") compute_project_args(PROJECT_ARGS LANGUAGES CXX) @@ -267,7 +267,16 @@ set(${PROJECT_NAME}_SOLVERS_SOURCES src/solvers/preconditioners.cpp src/solvers/solvers.cpp) set(${PROJECT_NAME}_DECOMPOSITIONS_SOURCES - src/decompositions/decompositions.cpp) + src/decompositions/decompositions.cpp + src/decompositions/eigen-solver.cpp + src/decompositions/llt-solver.cpp + src/decompositions/ldlt-solver.cpp + src/decompositions/minres-solver.cpp + src/decompositions/eigen-solver.cpp + src/decompositions/self-adjoint-eigen-solver.cpp + src/decompositions/permutation-matrix.cpp + src/decompositions/simplicial-llt-solver.cpp + src/decompositions/simplicial-ldlt-solver.cpp) if(BUILD_WITH_CHOLMOD_SUPPORT) list(APPEND ${PROJECT_NAME}_DECOMPOSITIONS_SOURCES @@ -294,8 +303,21 @@ set(${PROJECT_NAME}_SOURCES src/matrix-long-double.cpp src/matrix-complex-long-double.cpp src/matrix-bool.cpp - src/matrix-int.cpp - src/matrix-long.cpp + src/matrix-char.cpp + src/matrix-int8.cpp + src/matrix-uint8.cpp + src/matrix-int16.cpp + src/matrix-uint16.cpp + src/matrix-int32.cpp + src/matrix-uint32.cpp + src/matrix-windows-long.cpp + src/matrix-windows-ulong.cpp + src/matrix-mac-long.cpp + src/matrix-mac-ulong.cpp + src/matrix-int64.cpp + src/matrix-uint64.cpp + src/matrix-linux-long-long.cpp + src/matrix-linux-ulong-long.cpp src/angle-axis.cpp src/quaternion.cpp src/geometry-conversion.cpp diff --git a/include/eigenpy/eigen-allocator.hpp b/include/eigenpy/eigen-allocator.hpp index 7c31c56f4..3b47a9a19 100644 --- a/include/eigenpy/eigen-allocator.hpp +++ b/include/eigenpy/eigen-allocator.hpp @@ -198,6 +198,91 @@ struct cast { mat, NumpyMap::map( \ pyArray, details::check_swap(pyArray, mat))) +// Define specific cast for Windows and Mac +#if defined _WIN32 || defined __CYGWIN__ +// Manage NPY_INT on Windows (NPY_INT32 is NPY_LONG). +// See https://github.com/stack-of-tasks/eigenpy/pull/455 +#define EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH_OS_SPECIFIC( \ + MatType, Scalar, pyArray, mat, CAST_MACRO) \ + case NPY_INT: \ + CAST_MACRO(MatType, int32_t, Scalar, pyArray, mat); \ + break; \ + case NPY_UINT: \ + CAST_MACRO(MatType, uint32_t, Scalar, pyArray, mat); \ + break; +#elif defined __APPLE__ +// Manage NPY_LONGLONG on Mac (NPY_INT64 is NPY_LONG). +// long long and long are both the same type +// but NPY_LONGLONG and NPY_LONGĀ are different dtype. +// See https://github.com/stack-of-tasks/eigenpy/pull/455 +#define EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH_OS_SPECIFIC( \ + MatType, Scalar, pyArray, mat, CAST_MACRO) \ + case NPY_LONGLONG: \ + CAST_MACRO(MatType, int64_t, Scalar, pyArray, mat); \ + break; \ + case NPY_ULONGLONG: \ + CAST_MACRO(MatType, uint64_t, Scalar, pyArray, mat); \ + break; +#else +#define EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH_OS_SPECIFIC( \ + MatType, Scalar, pyArray, mat, CAST_MACRO) +#endif + +/// Define casting between Numpy matrix type to Eigen type. +#define EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH( \ + pyArray_type_code, MatType, Scalar, pyArray, mat, CAST_MACRO) \ + switch (pyArray_type_code) { \ + case NPY_BOOL: \ + CAST_MACRO(MatType, bool, Scalar, pyArray, mat); \ + break; \ + case NPY_INT8: \ + CAST_MACRO(MatType, int8_t, Scalar, pyArray, mat); \ + break; \ + case NPY_INT16: \ + CAST_MACRO(MatType, int16_t, Scalar, pyArray, mat); \ + break; \ + case NPY_INT32: \ + CAST_MACRO(MatType, int32_t, Scalar, pyArray, mat); \ + break; \ + case NPY_INT64: \ + CAST_MACRO(MatType, int64_t, Scalar, pyArray, mat); \ + break; \ + case NPY_UINT8: \ + CAST_MACRO(MatType, uint8_t, Scalar, pyArray, mat); \ + break; \ + case NPY_UINT16: \ + CAST_MACRO(MatType, uint16_t, Scalar, pyArray, mat); \ + break; \ + case NPY_UINT32: \ + CAST_MACRO(MatType, uint32_t, Scalar, pyArray, mat); \ + break; \ + case NPY_UINT64: \ + CAST_MACRO(MatType, uint64_t, Scalar, pyArray, mat); \ + break; \ + case NPY_FLOAT: \ + CAST_MACRO(MatType, float, Scalar, pyArray, mat); \ + break; \ + case NPY_CFLOAT: \ + CAST_MACRO(MatType, std::complex, Scalar, pyArray, mat); \ + break; \ + case NPY_DOUBLE: \ + CAST_MACRO(MatType, double, Scalar, pyArray, mat); \ + break; \ + case NPY_CDOUBLE: \ + CAST_MACRO(MatType, std::complex, Scalar, pyArray, mat); \ + break; \ + case NPY_LONGDOUBLE: \ + CAST_MACRO(MatType, long double, Scalar, pyArray, mat); \ + break; \ + case NPY_CLONGDOUBLE: \ + CAST_MACRO(MatType, std::complex, Scalar, pyArray, mat); \ + break; \ + EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH_OS_SPECIFIC( \ + MatType, Scalar, pyArray, mat, CAST_MACRO) \ + default: \ + throw Exception("You asked for a conversion which is not implemented."); \ + } + template struct EigenAllocator; @@ -247,43 +332,9 @@ struct eigen_allocator_impl_matrix { pyArray, details::check_swap(pyArray, mat)); // avoid useless cast return; } - - switch (pyArray_type_code) { - case NPY_INT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, int, Scalar, pyArray, - mat); - break; - case NPY_LONG: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, long, Scalar, - pyArray, mat); - break; - case NPY_FLOAT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, float, Scalar, - pyArray, mat); - break; - case NPY_CFLOAT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, std::complex, - Scalar, pyArray, mat); - break; - case NPY_DOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, double, Scalar, - pyArray, mat); - break; - case NPY_CDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, std::complex, - Scalar, pyArray, mat); - break; - case NPY_LONGDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType, long double, Scalar, - pyArray, mat); - break; - case NPY_CLONGDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX( - MatType, std::complex, Scalar, pyArray, mat); - break; - default: - throw Exception("You asked for a conversion which is not implemented."); - } + EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH( + pyArray_type_code, MatType, Scalar, pyArray, mat, + EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX); } /// \brief Copy mat into the Python array using Eigen::Map @@ -301,43 +352,8 @@ struct eigen_allocator_impl_matrix { details::check_swap(pyArray, mat)) = mat; return; } - - switch (pyArray_type_code) { - case NPY_INT: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType, Scalar, int, mat, - pyArray); - break; - case NPY_LONG: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType, Scalar, long, mat, - pyArray); - break; - case NPY_FLOAT: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType, Scalar, float, mat, - pyArray); - break; - case NPY_CFLOAT: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY( - MatType, Scalar, std::complex, mat, pyArray); - break; - case NPY_DOUBLE: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType, Scalar, double, mat, - pyArray); - break; - case NPY_CDOUBLE: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY( - MatType, Scalar, std::complex, mat, pyArray); - break; - case NPY_LONGDOUBLE: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType, Scalar, long double, - mat, pyArray); - break; - case NPY_CLONGDOUBLE: - EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY( - MatType, Scalar, std::complex, mat, pyArray); - break; - default: - throw Exception("You asked for a conversion which is not implemented."); - } + throw Exception( + "Scalar conversion from Eigen to Numpy is not implemented."); } }; @@ -394,42 +410,9 @@ struct eigen_allocator_impl_tensor { return; } - switch (pyArray_type_code) { - case NPY_INT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR(TensorType, int, Scalar, - pyArray, tensor); - break; - case NPY_LONG: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR(TensorType, long, Scalar, - pyArray, tensor); - break; - case NPY_FLOAT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR(TensorType, float, Scalar, - pyArray, tensor); - break; - case NPY_CFLOAT: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR( - TensorType, std::complex, Scalar, pyArray, tensor); - break; - case NPY_DOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR(TensorType, double, Scalar, - pyArray, tensor); - break; - case NPY_CDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR( - TensorType, std::complex, Scalar, pyArray, tensor); - break; - case NPY_LONGDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR(TensorType, long double, - Scalar, pyArray, tensor); - break; - case NPY_CLONGDOUBLE: - EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR( - TensorType, std::complex, Scalar, pyArray, tensor); - break; - default: - throw Exception("You asked for a conversion which is not implemented."); - } + EIGENPY_CAST_FROM_NUMPY_TO_EIGEN_SWITCH( + pyArray_type_code, TensorType, Scalar, pyArray, tensor, + EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_TENSOR); } #define EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, \ @@ -454,42 +437,8 @@ struct eigen_allocator_impl_tensor { return; } - switch (pyArray_type_code) { - case NPY_INT: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, int, - tensor, pyArray); - break; - case NPY_LONG: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, long, - tensor, pyArray); - break; - case NPY_FLOAT: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, float, - tensor, pyArray); - break; - case NPY_CFLOAT: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY( - TensorType, Scalar, std::complex, tensor, pyArray); - break; - case NPY_DOUBLE: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, double, - tensor, pyArray); - break; - case NPY_CDOUBLE: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY( - TensorType, Scalar, std::complex, tensor, pyArray); - break; - case NPY_LONGDOUBLE: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY(TensorType, Scalar, - long double, tensor, pyArray); - break; - case NPY_CLONGDOUBLE: - EIGENPY_CAST_FROM_EIGEN_TENSOR_TO_PYARRAY( - TensorType, Scalar, std::complex, tensor, pyArray); - break; - default: - throw Exception("You asked for a conversion which is not implemented."); - } + throw Exception( + "Scalar conversion from Eigen to Numpy is not implemented."); } }; #endif diff --git a/include/eigenpy/numpy-type.hpp b/include/eigenpy/numpy-type.hpp index 25dee99f2..c57a914db 100644 --- a/include/eigenpy/numpy-type.hpp +++ b/include/eigenpy/numpy-type.hpp @@ -17,26 +17,54 @@ namespace eigenpy { template bool np_type_is_convertible_into_scalar(const int np_type) { - if (static_cast(NumpyEquivalentType::type_code) >= - NPY_USERDEF) + const auto scalar_np_code = + static_cast(NumpyEquivalentType::type_code); + + if (scalar_np_code >= NPY_USERDEF) return np_type == Register::getTypeCode(); - if (NumpyEquivalentType::type_code == np_type) return true; + if (scalar_np_code == np_type) return true; + // Manage type promotion switch (np_type) { -#ifdef WIN32 - case NPY_INT: - case NPY_LONG: - return FromTypeToType::value; - case NPY_LONGLONG: - return FromTypeToType<__int64, Scalar>::value; -#else + case NPY_BOOL: + return FromTypeToType::value; + case NPY_INT8: + return FromTypeToType::value; + case NPY_INT16: + return FromTypeToType::value; + case NPY_INT32: + return FromTypeToType::value; + case NPY_INT64: + return FromTypeToType::value; + case NPY_UINT8: + return FromTypeToType::value; + case NPY_UINT16: + return FromTypeToType::value; + case NPY_UINT32: + return FromTypeToType::value; + case NPY_UINT64: + return FromTypeToType::value; + +#if defined _WIN32 || defined __CYGWIN__ + // Manage NPY_INT on Windows (NPY_INT32 is NPY_LONG). + // See https://github.com/stack-of-tasks/eigenpy/pull/455 case NPY_INT: - return FromTypeToType::value; - case NPY_LONG: + return FromTypeToType::value; + case NPY_UINT: + return FromTypeToType::value; +#endif // WIN32 + +#if defined __APPLE__ + // Manage NPY_LONGLONG on Mac (NPY_INT64 is NPY_LONG).. + // long long and long are both the same type + // but NPY_LONGLONG and NPY_LONGĀ are different dtype. + // See https://github.com/stack-of-tasks/eigenpy/pull/455 case NPY_LONGLONG: - return FromTypeToType::value; -#endif + return FromTypeToType::value; + case NPY_ULONGLONG: + return FromTypeToType::value; +#endif // MAC case NPY_FLOAT: return FromTypeToType::value; case NPY_CFLOAT: diff --git a/include/eigenpy/numpy.hpp b/include/eigenpy/numpy.hpp index 3529ec257..3786b091b 100644 --- a/include/eigenpy/numpy.hpp +++ b/include/eigenpy/numpy.hpp @@ -61,57 +61,119 @@ struct NumpyEquivalentType { }; template <> -struct NumpyEquivalentType { - enum { type_code = NPY_FLOAT }; +struct NumpyEquivalentType { + enum { type_code = NPY_BOOL }; }; + template <> -struct NumpyEquivalentType > { - enum { type_code = NPY_CFLOAT }; +struct NumpyEquivalentType { + enum { type_code = NPY_INT8 }; }; template <> -struct NumpyEquivalentType { - enum { type_code = NPY_DOUBLE }; +struct NumpyEquivalentType { + enum { type_code = NPY_UINT8 }; }; template <> -struct NumpyEquivalentType > { - enum { type_code = NPY_CDOUBLE }; +struct NumpyEquivalentType { + enum { type_code = NPY_INT8 }; }; + template <> -struct NumpyEquivalentType { - enum { type_code = NPY_LONGDOUBLE }; +struct NumpyEquivalentType { + enum { type_code = NPY_INT16 }; }; template <> -struct NumpyEquivalentType > { - enum { type_code = NPY_CLONGDOUBLE }; +struct NumpyEquivalentType { + enum { type_code = NPY_UINT16 }; +}; + +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_INT32 }; }; template <> -struct NumpyEquivalentType { - enum { type_code = NPY_BOOL }; +struct NumpyEquivalentType { + enum { type_code = NPY_UINT32 }; }; + +// On Windows, long is a 32 bytes type but it's a different type than int +// See https://github.com/stack-of-tasks/eigenpy/pull/455 +#if defined _WIN32 || defined __CYGWIN__ + template <> -struct NumpyEquivalentType { - enum { type_code = NPY_INT }; +struct NumpyEquivalentType { + enum { type_code = NPY_INT32 }; }; template <> -struct NumpyEquivalentType { - enum { type_code = NPY_UINT }; +struct NumpyEquivalentType { + enum { type_code = NPY_UINT32 }; }; + +#endif // WIN32 + +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_INT64 }; +}; +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_UINT64 }; +}; + +// On Mac, long is a 64 bytes type but it's a different type than int64_t +// See https://github.com/stack-of-tasks/eigenpy/pull/455 +#if defined __APPLE__ + template <> struct NumpyEquivalentType { - enum { type_code = NPY_LONG }; + enum { type_code = NPY_INT64 }; }; -// #if defined _WIN32 || defined __CYGWIN__ +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_UINT64 }; +}; + +#endif // MAC + +// On Linux, long long is a 64 bytes type but it's a different type than int64_t +// See https://github.com/stack-of-tasks/eigenpy/pull/455 +#if defined __linux__ + template <> struct NumpyEquivalentType { enum { type_code = NPY_LONGLONG }; }; -// #else -// template <> struct NumpyEquivalentType { enum { type_code = -// NPY_LONGLONG };}; -// #endif template <> -struct NumpyEquivalentType { - enum { type_code = NPY_ULONG }; +struct NumpyEquivalentType { + enum { type_code = NPY_ULONGLONG }; +}; + +#endif // Linux + +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_FLOAT }; +}; +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_DOUBLE }; +}; +template <> +struct NumpyEquivalentType { + enum { type_code = NPY_LONGDOUBLE }; +}; + +template <> +struct NumpyEquivalentType > { + enum { type_code = NPY_CFLOAT }; +}; +template <> +struct NumpyEquivalentType > { + enum { type_code = NPY_CDOUBLE }; +}; +template <> +struct NumpyEquivalentType > { + enum { type_code = NPY_CLONGDOUBLE }; }; template diff --git a/include/eigenpy/scalar-conversion.hpp b/include/eigenpy/scalar-conversion.hpp index 8a8532d9a..18a50a215 100644 --- a/include/eigenpy/scalar-conversion.hpp +++ b/include/eigenpy/scalar-conversion.hpp @@ -7,11 +7,24 @@ #include "eigenpy/config.hpp" #include +#include namespace eigenpy { + template struct FromTypeToType - : public boost::numeric::conversion_traits::subranged {}; + : public boost::mpl::if_c::value, + std::true_type, + typename boost::numeric::conversion_traits< + Source, Target>::subranged>::type {}; + +/// FromTypeToType specialization to manage std::complex +template +struct FromTypeToType, std::complex > + : public boost::mpl::if_c< + std::is_same::value, std::true_type, + typename boost::numeric::conversion_traits< + ScalarSource, ScalarTarget>::subranged>::type {}; } // namespace eigenpy diff --git a/src/decompositions/decompositions.cpp b/src/decompositions/decompositions.cpp index 2b58c03d0..a497db1e8 100644 --- a/src/decompositions/decompositions.cpp +++ b/src/decompositions/decompositions.cpp @@ -4,29 +4,27 @@ #include "eigenpy/decompositions/decompositions.hpp" -#include "eigenpy/decompositions/EigenSolver.hpp" -#include "eigenpy/decompositions/LDLT.hpp" -#include "eigenpy/decompositions/LLT.hpp" -#include "eigenpy/decompositions/PermutationMatrix.hpp" -#include "eigenpy/decompositions/sparse/LLT.hpp" -#include "eigenpy/decompositions/sparse/LDLT.hpp" -#include "eigenpy/decompositions/SelfAdjointEigenSolver.hpp" -#include "eigenpy/decompositions/minres.hpp" #include "eigenpy/fwd.hpp" namespace eigenpy { -void exposeDecompositions() { - using namespace Eigen; - typedef Eigen::SparseMatrix ColMajorSparseMatrix; - // typedef Eigen::SparseMatrix RowMajorSparseMatrix; +void exposeEigenSolver(); +void exposeSelfAdjointEigenSolver(); +void exposeLLTSolver(); +void exposeLDLTSolver(); +void exposeMINRESSolver(); +void exposeSimplicialLLTSolver(); +void exposeSimplicialLDLTSolver(); +void exposePermutationMatrix(); - EigenSolverVisitor::expose("EigenSolver"); - SelfAdjointEigenSolverVisitor::expose("SelfAdjointEigenSolver"); - LLTSolverVisitor::expose("LLT"); - LDLTSolverVisitor::expose("LDLT"); +void exposeDecompositions() { + using namespace Eigen; - MINRESSolverVisitor::expose("MINRES"); + exposeEigenSolver(); + exposeSelfAdjointEigenSolver(); + exposeLLTSolver(); + exposeLDLTSolver(); + exposeMINRESSolver(); { bp::enum_("DecompositionOptions") @@ -42,12 +40,10 @@ void exposeDecompositions() { } // Expose sparse decompositions - { - SimplicialLLTVisitor::expose("SimplicialLLT"); - SimplicialLDLTVisitor::expose("SimplicialLDLT"); - } + exposeSimplicialLLTSolver(); + exposeSimplicialLDLTSolver(); - PermutationMatrixVisitor::expose("PermutationMatrix"); + exposePermutationMatrix(); #ifdef EIGENPY_WITH_CHOLMOD_SUPPORT exposeCholmod(); diff --git a/src/decompositions/eigen-solver.cpp b/src/decompositions/eigen-solver.cpp new file mode 100644 index 000000000..8fdfbf4af --- /dev/null +++ b/src/decompositions/eigen-solver.cpp @@ -0,0 +1,13 @@ + +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/EigenSolver.hpp" + +namespace eigenpy { +void exposeEigenSolver() { + using namespace Eigen; + EigenSolverVisitor::expose("EigenSolver"); +} +} // namespace eigenpy diff --git a/src/decompositions/ldlt-solver.cpp b/src/decompositions/ldlt-solver.cpp new file mode 100644 index 000000000..6f3a2a605 --- /dev/null +++ b/src/decompositions/ldlt-solver.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/LDLT.hpp" + +namespace eigenpy { +void exposeLDLTSolver() { + using namespace Eigen; + LDLTSolverVisitor::expose("LDLT"); +} +} // namespace eigenpy diff --git a/src/decompositions/llt-solver.cpp b/src/decompositions/llt-solver.cpp new file mode 100644 index 000000000..a58db9b45 --- /dev/null +++ b/src/decompositions/llt-solver.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/LLT.hpp" + +namespace eigenpy { +void exposeLLTSolver() { + using namespace Eigen; + LLTSolverVisitor::expose("LLT"); +} +} // namespace eigenpy diff --git a/src/decompositions/minres-solver.cpp b/src/decompositions/minres-solver.cpp new file mode 100644 index 000000000..44a12cea1 --- /dev/null +++ b/src/decompositions/minres-solver.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/minres.hpp" + +namespace eigenpy { +void exposeMINRESSolver() { + using namespace Eigen; + MINRESSolverVisitor::expose("MINRES"); +} +} // namespace eigenpy diff --git a/src/decompositions/permutation-matrix.cpp b/src/decompositions/permutation-matrix.cpp new file mode 100644 index 000000000..082ac8092 --- /dev/null +++ b/src/decompositions/permutation-matrix.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/PermutationMatrix.hpp" + +namespace eigenpy { +void exposePermutationMatrix() { + using namespace Eigen; + PermutationMatrixVisitor::expose("PermutationMatrix"); +} +} // namespace eigenpy diff --git a/src/decompositions/seigen-solver.cpp b/src/decompositions/seigen-solver.cpp new file mode 100644 index 000000000..8fdfbf4af --- /dev/null +++ b/src/decompositions/seigen-solver.cpp @@ -0,0 +1,13 @@ + +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/EigenSolver.hpp" + +namespace eigenpy { +void exposeEigenSolver() { + using namespace Eigen; + EigenSolverVisitor::expose("EigenSolver"); +} +} // namespace eigenpy diff --git a/src/decompositions/self-adjoint-eigen-solver.cpp b/src/decompositions/self-adjoint-eigen-solver.cpp new file mode 100644 index 000000000..1497f3bed --- /dev/null +++ b/src/decompositions/self-adjoint-eigen-solver.cpp @@ -0,0 +1,13 @@ + +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/SelfAdjointEigenSolver.hpp" + +namespace eigenpy { +void exposeSelfAdjointEigenSolver() { + using namespace Eigen; + SelfAdjointEigenSolverVisitor::expose("SelfAdjointEigenSolver"); +} +} // namespace eigenpy diff --git a/src/decompositions/simplicial-ldlt-solver.cpp b/src/decompositions/simplicial-ldlt-solver.cpp new file mode 100644 index 000000000..c9a3e7b98 --- /dev/null +++ b/src/decompositions/simplicial-ldlt-solver.cpp @@ -0,0 +1,13 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/sparse/LDLT.hpp" + +namespace eigenpy { +void exposeSimplicialLDLTSolver() { + using namespace Eigen; + typedef SparseMatrix ColMajorSparseMatrix; + SimplicialLDLTVisitor::expose("SimplicialLDLT"); +} +} // namespace eigenpy diff --git a/src/decompositions/simplicial-llt-solver.cpp b/src/decompositions/simplicial-llt-solver.cpp new file mode 100644 index 000000000..f46e36f25 --- /dev/null +++ b/src/decompositions/simplicial-llt-solver.cpp @@ -0,0 +1,13 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/decompositions/sparse/LLT.hpp" + +namespace eigenpy { +void exposeSimplicialLLTSolver() { + using namespace Eigen; + typedef SparseMatrix ColMajorSparseMatrix; + SimplicialLLTVisitor::expose("SimplicialLLT"); +} +} // namespace eigenpy diff --git a/src/eigenpy.cpp b/src/eigenpy.cpp index 6a74bc6a9..cc2dcefbc 100644 --- a/src/eigenpy.cpp +++ b/src/eigenpy.cpp @@ -12,8 +12,21 @@ namespace eigenpy { void seed(unsigned int seed_value) { srand(seed_value); } void exposeMatrixBool(); -void exposeMatrixInt(); -void exposeMatrixLong(); +void exposeMatrixInt8(); +void exposeMatrixChar(); +void exposeMatrixUInt8(); +void exposeMatrixInt16(); +void exposeMatrixUInt16(); +void exposeMatrixInt32(); +void exposeMatrixUInt32(); +void exposeMatrixWindowsLong(); +void exposeMatrixWindowsULong(); +void exposeMatrixMacLong(); +void exposeMatrixMacULong(); +void exposeMatrixInt64(); +void exposeMatrixUInt64(); +void exposeMatrixLinuxLongLong(); +void exposeMatrixLinuxULongLong(); void exposeMatrixFloat(); void exposeMatrixDouble(); void exposeMatrixLongDouble(); @@ -47,8 +60,21 @@ void enableEigenPy() { "seed_value."); exposeMatrixBool(); - exposeMatrixInt(); - exposeMatrixLong(); + exposeMatrixInt8(); + exposeMatrixChar(); + exposeMatrixUInt8(); + exposeMatrixInt16(); + exposeMatrixUInt16(); + exposeMatrixInt32(); + exposeMatrixUInt32(); + exposeMatrixWindowsLong(); + exposeMatrixWindowsULong(); + exposeMatrixMacLong(); + exposeMatrixMacULong(); + exposeMatrixInt64(); + exposeMatrixUInt64(); + exposeMatrixLinuxLongLong(); + exposeMatrixLinuxULongLong(); exposeMatrixFloat(); exposeMatrixDouble(); exposeMatrixLongDouble(); diff --git a/src/matrix-char.cpp b/src/matrix-char.cpp new file mode 100644 index 000000000..3c1a3a1c0 --- /dev/null +++ b/src/matrix-char.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixChar() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-int.cpp b/src/matrix-int.cpp deleted file mode 100644 index 26dbe3ca9..000000000 --- a/src/matrix-int.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020 INRIA - */ - -#include "eigenpy/eigenpy.hpp" - -namespace eigenpy { -void exposeMatrixInt() { - exposeType(); - exposeType(); -} -} // namespace eigenpy diff --git a/src/matrix-int16.cpp b/src/matrix-int16.cpp new file mode 100644 index 000000000..8e75cfdfc --- /dev/null +++ b/src/matrix-int16.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixInt16() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-int32.cpp b/src/matrix-int32.cpp new file mode 100644 index 000000000..f6f1bdcb5 --- /dev/null +++ b/src/matrix-int32.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixInt32() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-int64.cpp b/src/matrix-int64.cpp new file mode 100644 index 000000000..9bbe6899a --- /dev/null +++ b/src/matrix-int64.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixInt64() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-int8.cpp b/src/matrix-int8.cpp new file mode 100644 index 000000000..7d4ca642f --- /dev/null +++ b/src/matrix-int8.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixInt8() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-linux-long-long.cpp b/src/matrix-linux-long-long.cpp new file mode 100644 index 000000000..7084ea4e6 --- /dev/null +++ b/src/matrix-linux-long-long.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace eigenpy { +void exposeMatrixLinuxLongLong() { +// On Linux, long long is a 64 bytes type but it's a different type than int64_t +#ifdef __linux__ + exposeType(); + exposeType(); +#endif // linux +} +} // namespace eigenpy diff --git a/src/matrix-linux-ulong-long.cpp b/src/matrix-linux-ulong-long.cpp new file mode 100644 index 000000000..bac418ee0 --- /dev/null +++ b/src/matrix-linux-ulong-long.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace eigenpy { +void exposeMatrixLinuxULongLong() { +// On Linux, long long is a 64 bytes type but it's a different type than int64_t +#ifdef __linux__ + exposeType(); + exposeType(); +#endif // linux +} +} // namespace eigenpy diff --git a/src/matrix-mac-long.cpp b/src/matrix-mac-long.cpp new file mode 100644 index 000000000..f2956f36b --- /dev/null +++ b/src/matrix-mac-long.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace eigenpy { +void exposeMatrixMacLong() { +// On Mac, long is a 64 bytes type but it's a different type than int64_t +#ifdef __APPLE__ + exposeType(); + exposeType(); +#endif // Mac +} +} // namespace eigenpy diff --git a/src/matrix-mac-ulong.cpp b/src/matrix-mac-ulong.cpp new file mode 100644 index 000000000..993740116 --- /dev/null +++ b/src/matrix-mac-ulong.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace eigenpy { +void exposeMatrixMacULong() { +// On Mac, long is a 64 bytes type but it's a different type than int64_t +#ifdef __APPLE__ + exposeType(); + exposeType(); +#endif // Mac +} +} // namespace eigenpy diff --git a/src/matrix-uint16.cpp b/src/matrix-uint16.cpp new file mode 100644 index 000000000..fd89e8681 --- /dev/null +++ b/src/matrix-uint16.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixUInt16() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-uint32.cpp b/src/matrix-uint32.cpp new file mode 100644 index 000000000..c8c227d87 --- /dev/null +++ b/src/matrix-uint32.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixUInt32() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-uint64.cpp b/src/matrix-uint64.cpp new file mode 100644 index 000000000..26a6df996 --- /dev/null +++ b/src/matrix-uint64.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixUInt64() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-uint8.cpp b/src/matrix-uint8.cpp new file mode 100644 index 000000000..a2cf34499 --- /dev/null +++ b/src/matrix-uint8.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +#include + +namespace eigenpy { +void exposeMatrixUInt8() { + exposeType(); + exposeType(); +} +} // namespace eigenpy diff --git a/src/matrix-long.cpp b/src/matrix-windows-long.cpp similarity index 51% rename from src/matrix-long.cpp rename to src/matrix-windows-long.cpp index f52e89f1a..448710477 100644 --- a/src/matrix-long.cpp +++ b/src/matrix-windows-long.cpp @@ -1,17 +1,15 @@ /* - * Copyright 2020 INRIA + * Copyright 2024 INRIA */ #include "eigenpy/eigenpy.hpp" namespace eigenpy { -void exposeMatrixLong() { +void exposeMatrixWindowsLong() { +// On Windows, long is a 32 bytes type but it's a different type than int #ifdef WIN32 - exposeType<__int64>(); - exposeType<__int64, Eigen::RowMajor>(); -#else exposeType(); exposeType(); -#endif +#endif // WIN32 } } // namespace eigenpy diff --git a/src/matrix-windows-ulong.cpp b/src/matrix-windows-ulong.cpp new file mode 100644 index 000000000..a657ece17 --- /dev/null +++ b/src/matrix-windows-ulong.cpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace eigenpy { +void exposeMatrixWindowsULong() { +// On Windows, long is a 32 bytes type but it's a different type than int +#ifdef WIN32 + exposeType(); + exposeType(); +#endif // WIN32 +} +} // namespace eigenpy diff --git a/unittest/matrix.cpp b/unittest/matrix.cpp index e202c572b..e9fcf1947 100644 --- a/unittest/matrix.cpp +++ b/unittest/matrix.cpp @@ -132,6 +132,11 @@ ReturnMatrix copy(const Eigen::MatrixBase& mat) { return mat; } +template +Matrix copy_same(const Eigen::MatrixBase& mat) { + return mat; +} + BOOST_PYTHON_MODULE(matrix) { using namespace Eigen; namespace bp = boost::python; @@ -190,4 +195,39 @@ BOOST_PYTHON_MODULE(matrix) { copy); bp::def("asRowMajorFromRowMajorVector", copy); + + bp::def("copyBoolToBool", copy_same >); + + bp::def("copyInt8ToInt8", copy_same >); + bp::def("copyCharToChar", copy_same >); + bp::def("copyUCharToUChar", copy_same >); + + bp::def("copyInt16ToInt16", copy_same >); + bp::def("copyUInt16ToUInt16", copy_same >); + + bp::def("copyInt32ToInt32", copy_same >); + bp::def("copyUInt32ToUInt32", copy_same >); + + bp::def("copyInt64ToInt64", copy_same >); + bp::def("copyUInt64ToUInt64", copy_same >); + + bp::def("copyLongToLong", copy_same >); + bp::def("copyULongToULong", copy_same >); + + bp::def("copyLongLongToLongLong", + copy_same >); + bp::def("copyULongLongToULongLong", + copy_same >); + + bp::def("copyFloatToFloat", copy_same >); + bp::def("copyDoubleToDouble", copy_same >); + bp::def("copyLongDoubleToLongDouble", + copy_same >); + + bp::def("copyCFloatToCFloat", + copy_same, -1, -1> >); + bp::def("copyCDoubleToCDouble", + copy_same, -1, -1> >); + bp::def("copyCLongDoubleToCLongDouble", + copy_same, -1, -1> >); } diff --git a/unittest/python/test_matrix.py b/unittest/python/test_matrix.py index 87b3fd10b..9c14ad93c 100644 --- a/unittest/python/test_matrix.py +++ b/unittest/python/test_matrix.py @@ -1,3 +1,5 @@ +import platform + import matrix as eigenpy import numpy as np @@ -180,3 +182,167 @@ assert (eigenpy.asRowMajorFromColMajorVector(vec) == vec).all() assert (eigenpy.asRowMajorFromRowMajorMatrix(vec) == vec).all() assert (eigenpy.asRowMajorFromRowMajorVector(vec) == vec).all() + +# Test numpy -> Eigen -> numpy for all same type + + +def test_conversion(function, dtype): + input_array = np.array([1, 0], dtype=dtype) + assert input_array.dtype == dtype + output_array = function(input_array) + assert output_array.dtype == dtype + assert (output_array == input_array).all() + + +bool_t = np.dtype(np.bool_) +int8_t = np.dtype(np.int8) +uint8_t = np.dtype(np.uint8) +int16_t = np.dtype(np.int16) +uint16_t = np.dtype(np.uint16) +int32_t = np.dtype(np.int32) +uint32_t = np.dtype(np.uint32) +int64_t = np.dtype(np.int64) +uint64_t = np.dtype(np.uint64) +# On Windows long is a 32 bits integer but is a different type than int32. +long_t = np.dtype(np.int32 if platform.system() == "Windows" else np.int64) +ulong_t = np.dtype(np.uint32 if platform.system() == "Windows" else np.uint64) +longlong_t = np.dtype(np.longlong) +ulonglong_t = np.dtype(np.ulonglong) + +float32_t = np.dtype(np.float32) +float64_t = np.dtype(np.float64) + +complex64_t = np.dtype(np.complex64) +complex128_t = np.dtype(np.complex128) +complex256_t = np.dtype(np.clongdouble) + + +test_conversion(eigenpy.copyBoolToBool, bool_t) + +test_conversion(eigenpy.copyInt8ToInt8, int8_t) +test_conversion(eigenpy.copyCharToChar, int8_t) +test_conversion(eigenpy.copyUCharToUChar, uint8_t) + +test_conversion(eigenpy.copyInt16ToInt16, int16_t) +test_conversion(eigenpy.copyUInt16ToUInt16, uint16_t) + +test_conversion(eigenpy.copyInt32ToInt32, int32_t) +test_conversion(eigenpy.copyUInt32ToUInt32, uint32_t) + +test_conversion(eigenpy.copyInt64ToInt64, int64_t) +test_conversion(eigenpy.copyUInt64ToUInt64, uint64_t) + +test_conversion(eigenpy.copyLongToLong, long_t) +test_conversion(eigenpy.copyULongToULong, ulong_t) + +# On Windows long long is an int64_t alias. +# The numpy dtype match between longlong and int64. + +# On Linux long long is a 64 bits integer but is a different type than int64_t. +# The numpy dtype doesn't match and it's not an issue since C++ type are different. + +# On Mac long long is an int64_t and long alias. +# This is an issue because longlong numpy dtype is different than long numpy dtype +# but long and long long are the same type in C++. +# The test should pass thanks to the promotion code. +test_conversion(eigenpy.copyLongLongToLongLong, longlong_t) +test_conversion(eigenpy.copyULongLongToULongLong, ulonglong_t) + +test_conversion(eigenpy.copyFloatToFloat, float32_t) +test_conversion(eigenpy.copyDoubleToDouble, float64_t) +# On Windows and Mac longdouble is 64 bits +test_conversion(eigenpy.copyLongDoubleToLongDouble, np.dtype(np.longdouble)) + +test_conversion(eigenpy.copyCFloatToCFloat, complex64_t) +test_conversion(eigenpy.copyCDoubleToCDouble, complex128_t) +# On Windows and Mac clongdouble is 128 bits +test_conversion(eigenpy.copyCLongDoubleToCLongDouble, complex256_t) + + +# Test numpy -> Eigen -> numpy promotion + + +def test_conversion_promotion(function, input_dtype, output_dtype): + input_array = np.array([1, 0], dtype=input_dtype) + assert input_array.dtype == input_dtype + output_array = function(input_array) + assert output_array.dtype == output_dtype + assert (output_array == input_array).all() + + +# Test bool to other type +test_conversion_promotion(eigenpy.copyInt8ToInt8, bool_t, int8_t) +test_conversion_promotion(eigenpy.copyUCharToUChar, bool_t, uint8_t) +test_conversion_promotion(eigenpy.copyInt16ToInt16, bool_t, int16_t) +test_conversion_promotion(eigenpy.copyUInt16ToUInt16, bool_t, uint16_t) +test_conversion_promotion(eigenpy.copyInt32ToInt32, bool_t, int32_t) +test_conversion_promotion(eigenpy.copyUInt32ToUInt32, bool_t, uint32_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, bool_t, int64_t) +test_conversion_promotion(eigenpy.copyUInt64ToUInt64, bool_t, uint64_t) +test_conversion_promotion(eigenpy.copyLongToLong, bool_t, long_t) +test_conversion_promotion(eigenpy.copyULongToULong, bool_t, ulong_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, bool_t, int64_t) +test_conversion_promotion(eigenpy.copyULongLongToULongLong, bool_t, uint64_t) + +# Test int8 to other type +test_conversion_promotion(eigenpy.copyInt16ToInt16, int8_t, int16_t) +test_conversion_promotion(eigenpy.copyInt16ToInt16, uint8_t, int16_t) +test_conversion_promotion(eigenpy.copyUInt16ToUInt16, uint8_t, uint16_t) +test_conversion_promotion(eigenpy.copyInt32ToInt32, int8_t, int32_t) +test_conversion_promotion(eigenpy.copyInt32ToInt32, uint8_t, int32_t) +test_conversion_promotion(eigenpy.copyUInt32ToUInt32, uint8_t, uint32_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, int8_t, int64_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, uint8_t, int64_t) +test_conversion_promotion(eigenpy.copyUInt64ToUInt64, uint8_t, uint64_t) +test_conversion_promotion(eigenpy.copyLongToLong, int8_t, long_t) +test_conversion_promotion(eigenpy.copyLongToLong, uint8_t, long_t) +test_conversion_promotion(eigenpy.copyULongToULong, uint8_t, ulong_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, int8_t, int64_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, uint8_t, int64_t) +test_conversion_promotion(eigenpy.copyULongLongToULongLong, uint8_t, uint64_t) + +# Test int16 to other type +test_conversion_promotion(eigenpy.copyInt32ToInt32, int16_t, int32_t) +test_conversion_promotion(eigenpy.copyInt32ToInt32, uint16_t, int32_t) +test_conversion_promotion(eigenpy.copyUInt32ToUInt32, uint16_t, uint32_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, int16_t, int64_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, uint16_t, int64_t) +test_conversion_promotion(eigenpy.copyUInt64ToUInt64, uint16_t, uint64_t) +test_conversion_promotion(eigenpy.copyLongToLong, int16_t, long_t) +test_conversion_promotion(eigenpy.copyLongToLong, uint16_t, long_t) +test_conversion_promotion(eigenpy.copyULongToULong, uint16_t, ulong_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, int16_t, int64_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, uint16_t, int64_t) +test_conversion_promotion(eigenpy.copyULongLongToULongLong, uint16_t, uint64_t) + +# Test int32 to other type +test_conversion_promotion(eigenpy.copyInt64ToInt64, int32_t, int64_t) +test_conversion_promotion(eigenpy.copyInt64ToInt64, uint32_t, int64_t) +test_conversion_promotion(eigenpy.copyUInt64ToUInt64, uint32_t, uint64_t) +test_conversion_promotion(eigenpy.copyLongToLong, int32_t, long_t) +test_conversion_promotion(eigenpy.copyLongToLong, uint32_t, long_t) +test_conversion_promotion(eigenpy.copyULongToULong, uint32_t, ulong_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, int32_t, int64_t) +test_conversion_promotion(eigenpy.copyLongLongToLongLong, uint32_t, int64_t) +test_conversion_promotion(eigenpy.copyULongLongToULongLong, uint32_t, uint64_t) + +# Test float to double +test_conversion_promotion(eigenpy.copyDoubleToDouble, float32_t, float64_t) + +# Test complex to other type +test_conversion_promotion(eigenpy.copyCDoubleToCDouble, complex64_t, complex128_t) + +test_conversion_promotion( + eigenpy.copyCLongDoubleToCLongDouble, + complex64_t, + complex256_t, +) + +# Only Linux store complex double into 258 bits. +# Then, 128 bits complex can be promoted. +if platform.system() == "Linux": + test_conversion_promotion( + eigenpy.copyCLongDoubleToCLongDouble, + complex128_t, + complex256_t, + ) diff --git a/unittest/python/test_user_type.py b/unittest/python/test_user_type.py index e22b534cd..76f8591f8 100644 --- a/unittest/python/test_user_type.py +++ b/unittest/python/test_user_type.py @@ -9,7 +9,7 @@ def test(dtype): rng = np.random.default_rng() - mat = np.array(np.ones((rows, cols)).astype(np.intc), dtype=dtype) + mat = np.array(np.ones((rows, cols)).astype(np.int32), dtype=dtype) mat = rng.random((rows, cols)).astype(dtype) mat_copy = mat.copy() assert (mat == mat_copy).all()