Unverified Commit fc8c28c1 authored by Justin Carpentier's avatar Justin Carpentier Committed by GitHub
Browse files

Merge pull request #191 from jcarpent/devel

Sync submodule CMake + enforce testing
parents 6f29b9ec 5de17a9e
......@@ -47,3 +47,4 @@ jobs:
-DPYTHON_EXECUTABLE=%CONDA_PREFIX%\python.exe ^
..
cmake --build . --config Release --target install
ctest --output-on-failure
......@@ -150,6 +150,7 @@ SET(${PROJECT_NAME}_SOURCES
src/exception.cpp
src/eigenpy.cpp
src/numpy.cpp
src/numpy-type.cpp
src/matrix-float.cpp
src/matrix-complex-float.cpp
src/matrix-complex-double.cpp
......
Subproject commit caad0fd63c5824c5cc352cc856b666d8842df6d1
Subproject commit 9d6231d5743f6529bdd053b929a252ad95449162
......@@ -285,7 +285,7 @@ namespace eigenpy
template<typename MatType>
void* EigenFromPy<MatType>::convertible(PyArrayObject* pyArray)
{
if(!PyArray_Check(pyArray))
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
return 0;
if(!np_type_is_convertible_into_scalar<Scalar>(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
......@@ -476,7 +476,7 @@ namespace eigenpy
/// \brief Determine if pyObj can be converted into a MatType object
static void* convertible(PyArrayObject * pyArray)
{
if(!PyArray_Check(pyArray))
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
return 0;
if(!PyArray_ISWRITEABLE(pyArray))
return 0;
......
......@@ -8,7 +8,6 @@
#include "eigenpy/fwd.hpp"
#include "eigenpy/scalar-conversion.hpp"
#include <patchlevel.h> // For PY_MAJOR_VERSION
#include <stdexcept>
#include <typeinfo>
#include <sstream>
......@@ -73,121 +72,42 @@ namespace eigenpy
ARRAY_TYPE
};
struct NumpyType
struct EIGENPY_DLLEXPORT NumpyType
{
static NumpyType & getInstance()
{
static NumpyType instance;
return instance;
}
static NumpyType & getInstance();
operator bp::object () { return getInstance().CurrentNumpyType; }
static bp::object make(PyArrayObject* pyArray, bool copy = false)
{ return make((PyObject*)pyArray,copy); }
static bp::object make(PyArrayObject* pyArray, bool copy = false);
static bp::object make(PyObject* pyObj, bool copy = false)
{
bp::object m;
if(isMatrix())
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
else if(isArray())
m = bp::object(bp::handle<>(pyObj)); // nothing to do here
Py_INCREF(m.ptr());
return m;
}
static bp::object make(PyObject* pyObj, bool copy = false);
static void setNumpyType(bp::object & obj)
{
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
switchToNumpyMatrix();
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
switchToNumpyArray();
}
static void setNumpyType(bp::object & obj);
static void sharedMemory(const bool value)
{
getInstance().shared_memory = value;
}
static void sharedMemory(const bool value);
static bool sharedMemory()
{
return getInstance().shared_memory;
}
static bool sharedMemory();
static void switchToNumpyArray()
{
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
getInstance().getType() = ARRAY_TYPE;
}
static void switchToNumpyArray();
static void switchToNumpyMatrix()
{
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
getInstance().getType() = MATRIX_TYPE;
}
static void switchToNumpyMatrix();
static NP_TYPE & getType()
{
return getInstance().np_type;
}
static NP_TYPE & getType();
static bp::object getNumpyType()
{
return getInstance().CurrentNumpyType;
}
static bp::object getNumpyType();
static const PyTypeObject * getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}
static const PyTypeObject * getNumpyMatrixType();
static const PyTypeObject * getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}
static const PyTypeObject * getNumpyArrayType();
static bool isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}
static bool isMatrix();
static bool isArray()
{
if(getInstance().isMatrix()) return false;
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}
static bool isArray();
protected:
NumpyType()
{
pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
// TODO I don't know why this Py_INCREF is necessary.
// Without it, the destructor of NumpyType SEGV sometimes.
Py_INCREF(pyModule.ptr());
#endif
NumpyMatrixObject = pyModule.attr("matrix");
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
NumpyArrayObject = pyModule.attr("ndarray");
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
CurrentNumpyType = NumpyArrayObject; // default conversion
np_type = ARRAY_TYPE;
shared_memory = true;
}
NumpyType();
bp::object CurrentNumpyType;
bp::object pyModule;
......
......@@ -37,6 +37,8 @@ namespace eigenpy
#if defined _WIN32 || defined __CYGWIN__
namespace eigenpy
{
EIGENPY_DLLEXPORT bool call_PyArray_Check(PyObject *);
EIGENPY_DLLEXPORT PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type);
EIGENPY_DLLEXPORT PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options);
......@@ -52,6 +54,7 @@ namespace eigenpy
EIGENPY_DLLEXPORT int call_PyArray_RegisterDataType(PyArray_Descr * dtype);
}
#else
#define call_PyArray_Check(py_obj) PyArray_Check(py_obj)
#define call_PyArray_SimpleNew PyArray_SimpleNew
#define call_PyArray_New(py_type_ptr,nd,shape,np_type,data_ptr,options) \
PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL)
......
/*
* Copyright 2018-2020 INRIA
*/
#include "eigenpy/numpy-type.hpp"
#include <patchlevel.h> // For PY_MAJOR_VERSION
namespace eigenpy
{
namespace bp = boost::python;
NumpyType & NumpyType::getInstance()
{
static NumpyType instance;
return instance;
}
bp::object NumpyType::make(PyArrayObject* pyArray, bool copy)
{ return make((PyObject*)pyArray,copy); }
bp::object NumpyType::make(PyObject* pyObj, bool copy)
{
bp::object m;
if(isMatrix())
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
else if(isArray())
m = bp::object(bp::handle<>(pyObj)); // nothing to do here
Py_INCREF(m.ptr());
return m;
}
void NumpyType::setNumpyType(bp::object & obj)
{
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
switchToNumpyMatrix();
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
switchToNumpyArray();
}
void NumpyType::sharedMemory(const bool value)
{
getInstance().shared_memory = value;
}
bool NumpyType::sharedMemory()
{
return getInstance().shared_memory;
}
void NumpyType::switchToNumpyArray()
{
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
getInstance().getType() = ARRAY_TYPE;
}
void NumpyType::switchToNumpyMatrix()
{
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
getInstance().getType() = MATRIX_TYPE;
}
NP_TYPE & NumpyType::getType()
{
return getInstance().np_type;
}
bp::object NumpyType::getNumpyType()
{
return getInstance().CurrentNumpyType;
}
const PyTypeObject * NumpyType::getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}
const PyTypeObject * NumpyType::getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}
bool NumpyType::isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}
bool NumpyType::isArray()
{
if(getInstance().isMatrix()) return false;
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}
NumpyType::NumpyType()
{
pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
// TODO I don't know why this Py_INCREF is necessary.
// Without it, the destructor of NumpyType SEGV sometimes.
Py_INCREF(pyModule.ptr());
#endif
NumpyMatrixObject = pyModule.attr("matrix");
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
NumpyArrayObject = pyModule.attr("ndarray");
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
CurrentNumpyType = NumpyArrayObject; // default conversion
np_type = ARRAY_TYPE;
shared_memory = true;
}
}
......@@ -22,6 +22,11 @@ namespace eigenpy
#if defined _WIN32 || defined __CYGWIN__
bool call_PyArray_Check(PyObject * py_obj)
{
return PyArray_Check(py_obj);
}
PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type)
{
return PyArray_SimpleNew(nd,shape,np_type);
......
......@@ -81,12 +81,22 @@ MatrixDerived base(const Eigen::MatrixBase<MatrixDerived> & m)
return m.derived();
}
template<typename Scalar>
Eigen::Matrix<Scalar,6,6> matrix6(const Scalar & value)
{
typedef Eigen::Matrix<Scalar,6,6> ReturnType;
return ReturnType::Constant(value);
}
BOOST_PYTHON_MODULE(matrix)
{
using namespace Eigen;
namespace bp = boost::python;
eigenpy::enableEigenPy();
typedef Eigen::Matrix<double,6,6> Matrix6;
eigenpy::enableEigenPySpecific<Matrix6>();
Eigen::MatrixXd (*naturalsXX)(int,int,bool) = naturals;
Eigen::VectorXd (*naturalsX)(int,bool) = naturals;
Eigen::Matrix3d (*naturals33)(bool) = naturals;
......@@ -108,4 +118,6 @@ BOOST_PYTHON_MODULE(matrix)
bp::def("base", base<VectorXd>);
bp::def("base", base<MatrixXd>);
bp::def("matrix6", matrix6<double>);
}
......@@ -126,3 +126,7 @@ assert(mat1x1[0,0] == value)
vec1x1 = eigenpy.vector1x1(value)
assert(vec1x1.size == 1)
assert(vec1x1[0] == value)
# test registration of matrix6
mat6 = eigenpy.matrix6(0.)
assert(mat6.size == 36)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment