Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • jcarpent/eigenpy
  • gsaurel/eigenpy
  • stack-of-tasks/eigenpy
3 results
Show changes
Showing
with 10038 additions and 113 deletions
//
// Copyright (c) 2020-2022 INRIA
//
#ifndef __eigenpy_user_type_hpp__
#define __eigenpy_user_type_hpp__
#include <iostream>
#include "eigenpy/fwd.hpp"
#include "eigenpy/numpy-type.hpp"
#include "eigenpy/register.hpp"
namespace eigenpy {
/// \brief Default cast algo to cast a From to To. Can be specialized for any
/// types.
template <typename From, typename To>
struct cast {
static To run(const From& from) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wfloat-conversion"
return static_cast<To>(from);
#pragma GCC diagnostic pop
}
};
namespace internal {
template <typename From, typename To>
static void cast(void* from_, void* to_, npy_intp n, void* /*fromarr*/,
void* /*toarr*/) {
// std::cout << "cast::run" << std::endl;
const From* from = static_cast<From*>(from_);
To* to = static_cast<To*>(to_);
for (npy_intp i = 0; i < n; i++) {
to[i] = eigenpy::cast<From, To>::run(from[i]);
}
}
template <typename T>
struct getitem {
///
/// \brief Get a python object from an array
/// It returns a standard Python object from
/// a single element of the array object arr pointed to by data.
/// \param[in] data Pointer to the first element of the C++ data stream
/// \param[in] arr Pointer to the first element of the Python object data
/// stream
///
/// \returns PyObject corresponding to the python datastream.
///
static PyObject* run(void* data, void* /* arr */) {
// std::cout << "getitem" << std::endl;
T* elt_ptr = static_cast<T*>(data);
bp::object m(boost::ref(*elt_ptr));
Py_INCREF(m.ptr());
return m.ptr();
}
};
template <typename T, int type_code = NumpyEquivalentType<T>::type_code>
struct SpecialMethods {
inline static void copyswap(void* /*dst*/, void* /*src*/, int /*swap*/,
void* /*arr*/) /*{}*/;
inline static PyObject* getitem(void* /*ip*/,
void* /*ap*/) /*{ return NULL; }*/;
inline static int setitem(PyObject* /*op*/, void* /*ov*/,
void* /*ap*/) /*{ return -1; }*/;
inline static void copyswapn(void* /*dest*/, long /*dstride*/, void* /*src*/,
long /*sstride*/, long /*n*/, int /*swap*/,
void* /*arr*/) /*{}*/;
inline static npy_bool nonzero(
void* /*ip*/, void* /*array*/) /*{ return (npy_bool)false; }*/;
inline static void dotfunc(void* /*ip0_*/, npy_intp /*is0*/, void* /*ip1_*/,
npy_intp /*is1*/, void* /*op*/, npy_intp /*n*/,
void* /*arr*/);
inline static int fill(void* data_, npy_intp length, void* arr);
inline static int fillwithscalar(void* buffer_, npy_intp length, void* value,
void* arr);
};
template <typename T>
struct OffsetOf {
struct Data {
char c;
T v;
};
enum { value = offsetof(Data, v) };
};
template <typename T>
struct SpecialMethods<T, NPY_USERDEF> {
static void copyswap(void* dst, void* src, int swap, void* /*arr*/) {
// std::cout << "copyswap" << std::endl;
if (src != NULL) {
T& t1 = *static_cast<T*>(dst);
T& t2 = *static_cast<T*>(src);
t1 = t2;
}
if (swap) {
T& t1 = *static_cast<T*>(dst);
T& t2 = *static_cast<T*>(src);
std::swap(t1, t2);
}
}
static PyObject* getitem(void* ip, void* ap) {
return eigenpy::internal::getitem<T>::run(ip, ap);
}
///
/// \brief Set a python object in an array.
/// It sets the Python object "item" into the array, arr, at the
/// position pointed to by data. This function deals with “misbehaved”
/// arrays. If successful, a zero is returned, otherwise, a negative
/// one is returned (and a Python error set).
/// \param[in] src_obj Pointer to the location of the python object
/// \param[in] dest_ptr Pointer to the location in the array where the source
/// object should be saved. \param[in] array Pointer to the location of the
/// array
///
/// \returns int Success(0) or Failure(-1)
///
inline static int setitem(PyObject* src_obj, void* dest_ptr, void* array) {
// std::cout << "setitem" << std::endl;
if (array == NULL) {
eigenpy::Exception("Cannot retrieve the type stored in the array.");
return -1;
}
PyArrayObject* py_array = static_cast<PyArrayObject*>(array);
PyArray_Descr* descr = PyArray_DTYPE(py_array);
PyTypeObject* array_scalar_type = descr->typeobj;
PyTypeObject* src_obj_type = Py_TYPE(src_obj);
T& dest = *static_cast<T*>(dest_ptr);
if (array_scalar_type != src_obj_type) {
long long src_value = PyLong_AsLongLong(src_obj);
if (src_value == -1 && PyErr_Occurred()) {
std::stringstream ss;
ss << "The input type is of wrong type. ";
ss << "The expected type is " << bp::type_info(typeid(T)).name()
<< std::endl;
eigenpy::Exception(ss.str());
return -1;
}
dest = T(src_value);
} else {
bp::extract<T&> extract_src_obj(src_obj);
if (!extract_src_obj.check()) {
std::cout << "if (!extract_src_obj.check())" << std::endl;
std::stringstream ss;
ss << "The input type is of wrong type. ";
ss << "The expected type is " << bp::type_info(typeid(T)).name()
<< std::endl;
eigenpy::Exception(ss.str());
return -1;
}
const T& src = extract_src_obj();
T& dest = *static_cast<T*>(dest_ptr);
dest = src;
}
return 0;
}
inline static void copyswapn(void* dst, long dstride, void* src, long sstride,
long n, int swap, void* array) {
// std::cout << "copyswapn" << std::endl;
char* dstptr = static_cast<char*>(dst);
char* srcptr = static_cast<char*>(src);
PyArrayObject* py_array = static_cast<PyArrayObject*>(array);
PyArray_CopySwapFunc* copyswap =
PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap;
for (npy_intp i = 0; i < n; i++) {
copyswap(dstptr, srcptr, swap, array);
dstptr += dstride;
srcptr += sstride;
}
}
inline static npy_bool nonzero(void* ip, void* array) {
// std::cout << "nonzero" << std::endl;
static const T ZeroValue = T(0);
PyArrayObject* py_array = static_cast<PyArrayObject*>(array);
if (py_array == NULL || PyArray_ISBEHAVED_RO(py_array)) {
const T& value = *static_cast<T*>(ip);
return (npy_bool)(value != ZeroValue);
} else {
T tmp_value;
PyDataType_GetArrFuncs(PyArray_DESCR(py_array))
->copyswap(&tmp_value, ip, PyArray_ISBYTESWAPPED(py_array), array);
return (npy_bool)(tmp_value != ZeroValue);
}
}
inline static void dotfunc(void* ip0_, npy_intp is0, void* ip1_, npy_intp is1,
void* op, npy_intp n, void* /*arr*/) {
// std::cout << "dotfunc" << std::endl;
typedef Eigen::Matrix<T, Eigen::Dynamic, 1> VectorT;
typedef Eigen::InnerStride<Eigen::Dynamic> InputStride;
typedef const Eigen::Map<const VectorT, 0, InputStride> ConstMapType;
ConstMapType v0(static_cast<T*>(ip0_), n,
InputStride(is0 / (Eigen::DenseIndex)sizeof(T))),
v1(static_cast<T*>(ip1_), n,
InputStride(is1 / (Eigen::DenseIndex)sizeof(T)));
*static_cast<T*>(op) = v0.dot(v1);
}
inline static int fillwithscalar(void* buffer_, npy_intp length, void* value,
void* /*arr*/) {
// std::cout << "fillwithscalar" << std::endl;
T r = *static_cast<T*>(value);
T* buffer = static_cast<T*>(buffer_);
npy_intp i;
for (i = 0; i < length; i++) {
buffer[i] = r;
}
return 0;
}
static int fill(void* data_, npy_intp length, void* /*arr*/) {
// std::cout << "fill" << std::endl;
T* data = static_cast<T*>(data_);
const T delta = data[1] - data[0];
T r = data[1];
npy_intp i;
for (i = 2; i < length; i++) {
r = r + delta;
data[i] = r;
}
return 0;
}
}; // struct SpecialMethods<T,NPY_USERDEF>
} // namespace internal
template <typename From, typename To>
bool registerCast(const bool safe) {
PyArray_Descr* from_array_descr = Register::getPyArrayDescr<From>();
// int from_typenum = Register::getTypeCode<From>();
// PyTypeObject * to_py_type = Register::getPyType<To>();
int to_typenum = Register::getTypeCode<To>();
assert(to_typenum >= 0 && "to_typenum is not valid");
assert(from_array_descr != NULL && "from_array_descr is not valid");
// std::cout << "From: " << bp::type_info(typeid(From)).name() << " " <<
// Register::getTypeCode<From>()
// << " to: " << bp::type_info(typeid(To)).name() << " " <<
// Register::getTypeCode<To>()
// << "\n to_typenum: " << to_typenum
// << std::endl;
if (call_PyArray_RegisterCastFunc(from_array_descr, to_typenum,
static_cast<PyArray_VectorUnaryFunc*>(
&eigenpy::internal::cast<From, To>)) <
0) {
std::stringstream ss;
ss << "PyArray_RegisterCastFunc of the cast from "
<< bp::type_info(typeid(From)).name() << " to "
<< bp::type_info(typeid(To)).name() << " has failed.";
eigenpy::Exception(ss.str());
return false;
}
if (safe && call_PyArray_RegisterCanCast(from_array_descr, to_typenum,
NPY_NOSCALAR) < 0) {
std::stringstream ss;
ss << "PyArray_RegisterCanCast of the cast from "
<< bp::type_info(typeid(From)).name() << " to "
<< bp::type_info(typeid(To)).name() << " has failed.";
eigenpy::Exception(ss.str());
return false;
}
return true;
}
/// \brief Get the class object for a wrapped type that has been exposed
/// through Boost.Python.
template <typename T>
boost::python::object getInstanceClass() {
// Query into the registry for type T.
bp::type_info type = bp::type_id<T>();
const bp::converter::registration* registration =
bp::converter::registry::query(type);
// If the class is not registered, return None.
if (!registration) {
// std::cerr<<"Class Not Registered. Returning Empty."<<std::endl;
return bp::object();
}
bp::handle<PyTypeObject> handle(
bp::borrowed(registration->get_class_object()));
return bp::object(handle);
}
template <typename Scalar>
int registerNewType(PyTypeObject* py_type_ptr = NULL) {
// Check whether the type is a Numpy native type.
// In this case, the registration is not required.
if (isNumpyNativeType<Scalar>())
return NumpyEquivalentType<Scalar>::type_code;
// Retrieve the registered type for the current Scalar
if (py_type_ptr == NULL) { // retrive the type from Boost.Python
py_type_ptr = Register::getPyType<Scalar>();
}
if (Register::isRegistered(py_type_ptr))
return Register::getTypeCode(
py_type_ptr); // the type is already registered
PyArray_GetItemFunc* getitem = &internal::SpecialMethods<Scalar>::getitem;
PyArray_SetItemFunc* setitem = &internal::SpecialMethods<Scalar>::setitem;
PyArray_NonzeroFunc* nonzero = &internal::SpecialMethods<Scalar>::nonzero;
PyArray_CopySwapFunc* copyswap = &internal::SpecialMethods<Scalar>::copyswap;
PyArray_CopySwapNFunc* copyswapn = reinterpret_cast<PyArray_CopySwapNFunc*>(
&internal::SpecialMethods<Scalar>::copyswapn);
PyArray_DotFunc* dotfunc = &internal::SpecialMethods<Scalar>::dotfunc;
PyArray_FillFunc* fill = &internal::SpecialMethods<Scalar>::fill;
PyArray_FillWithScalarFunc* fillwithscalar =
&internal::SpecialMethods<Scalar>::fillwithscalar;
int code = Register::registerNewType(
py_type_ptr, &typeid(Scalar), sizeof(Scalar),
internal::OffsetOf<Scalar>::value, getitem, setitem, nonzero, copyswap,
copyswapn, dotfunc, fill, fillwithscalar);
call_PyArray_RegisterCanCast(call_PyArray_DescrFromType(NPY_OBJECT), code,
NPY_NOSCALAR);
return code;
}
} // namespace eigenpy
#endif // __eigenpy_user_type_hpp__
#ifndef __eigenpy_utils_empty_visitor_hpp__
#define __eigenpy_utils_empty_visitor_hpp__
#include <boost/python.hpp>
namespace eigenpy {
struct EmptyPythonVisitor
: public ::boost::python::def_visitor<EmptyPythonVisitor> {
template <class classT>
void visit(classT &) const {}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_utils_empty_visitor_hpp__
//
// Copyright (c) 2020-2023 INRIA
//
#ifndef __eigenpy_utils_is_aligned_hpp__
#define __eigenpy_utils_is_aligned_hpp__
namespace eigenpy {
inline bool is_aligned(const void* ptr, std::size_t alignment) {
return (reinterpret_cast<std::size_t>(ptr) & (alignment - 1)) == 0;
}
} // namespace eigenpy
#endif
/*
* Copyright 2020-2024 INRIA
*/
#ifndef __eigenpy_utils_is_approx_hpp__
#define __eigenpy_utils_is_approx_hpp__
#include <Eigen/Core>
#include <Eigen/SparseCore>
namespace eigenpy {
template <typename MatrixType1, typename MatrixType2>
EIGEN_DONT_INLINE bool is_approx(const Eigen::MatrixBase<MatrixType1>& mat1,
const Eigen::MatrixBase<MatrixType2>& mat2,
const typename MatrixType1::RealScalar& prec) {
return mat1.isApprox(mat2, prec);
}
template <typename MatrixType1, typename MatrixType2>
EIGEN_DONT_INLINE bool is_approx(const Eigen::MatrixBase<MatrixType1>& mat1,
const Eigen::MatrixBase<MatrixType2>& mat2) {
return is_approx(
mat1, mat2,
Eigen::NumTraits<typename MatrixType1::RealScalar>::dummy_precision());
}
template <typename MatrixType1, typename MatrixType2>
EIGEN_DONT_INLINE bool is_approx(
const Eigen::SparseMatrixBase<MatrixType1>& mat1,
const Eigen::SparseMatrixBase<MatrixType2>& mat2,
const typename MatrixType1::RealScalar& prec) {
return mat1.isApprox(mat2, prec);
}
template <typename MatrixType1, typename MatrixType2>
EIGEN_DONT_INLINE bool is_approx(
const Eigen::SparseMatrixBase<MatrixType1>& mat1,
const Eigen::SparseMatrixBase<MatrixType2>& mat2) {
return is_approx(
mat1, mat2,
Eigen::NumTraits<typename MatrixType1::RealScalar>::dummy_precision());
}
} // namespace eigenpy
#endif // ifndef __eigenpy_utils_is_approx_hpp__
//
// Copyright (c) 2024 INRIA
//
//
#ifndef __eigenpy_utils_python_compat_hpp__
#define __eigenpy_utils_python_compat_hpp__
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyStr_Check PyUnicode_Check
#define PyStr_FromString PyUnicode_FromString
#else
#define PyStr_Check PyString_Check
#define PyStr_FromString PyString_FromString
#endif
#endif // ifndef __eigenpy_utils_python_compat_hpp__
/*
* Copyright 2020 INRIA
*/
#ifndef __eigenpy_utils_scalar_name_hpp__
#define __eigenpy_utils_scalar_name_hpp__
#include <complex>
#include <string>
namespace eigenpy {
template <typename Scalar>
struct scalar_name {
static std::string shortname();
};
template <>
struct scalar_name<float> {
static std::string shortname() { return "f"; };
};
template <>
struct scalar_name<double> {
static std::string shortname() { return "d"; };
};
template <>
struct scalar_name<long double> {
static std::string shortname() { return "ld"; };
};
template <typename Scalar>
struct scalar_name<std::complex<Scalar> > {
static std::string shortname() { return "c" + scalar_name<Scalar>(); };
};
} // namespace eigenpy
#endif // ifndef __eigenpy_utils_scalar_name_hpp__
//
// Copyright (c) 2024 INRIA
//
//
#ifndef __eigenpy_utils_traits_hpp__
#define __eigenpy_utils_traits_hpp__
#include <type_traits>
#include <string>
#include <complex>
namespace eigenpy {
namespace details {
/// Trait to remove const&
template <typename T>
struct remove_cvref : std::remove_cv<typename std::remove_reference<T>::type> {
};
/// Trait to detect if T is a class or an union
template <typename T>
struct is_class_or_union
: std::integral_constant<bool, std::is_class<T>::value ||
std::is_union<T>::value> {};
/// trait to detect if T is a std::complex managed by Boost Python
template <typename T>
struct is_python_complex : std::false_type {};
/// From boost/python/converter/builtin_converters
template <>
struct is_python_complex<std::complex<float> > : std::true_type {};
template <>
struct is_python_complex<std::complex<double> > : std::true_type {};
template <>
struct is_python_complex<std::complex<long double> > : std::true_type {};
template <typename T>
struct is_python_primitive_type_helper
: std::integral_constant<bool, !is_class_or_union<T>::value ||
std::is_same<T, std::string>::value ||
std::is_same<T, std::wstring>::value ||
is_python_complex<T>::value> {};
/// Trait to detect if T is a Python primitive type
template <typename T>
struct is_python_primitive_type
: is_python_primitive_type_helper<typename remove_cvref<T>::type> {};
} // namespace details
} // namespace eigenpy
#endif // ifndef __eigenpy_utils_traits_hpp__
//
// Copyright (c) 2024 INRIA
//
#ifndef __eigenpy_utils_variant_hpp__
#define __eigenpy_utils_variant_hpp__
#include "eigenpy/fwd.hpp"
#include "eigenpy/utils/traits.hpp"
#include "eigenpy/utils/python-compat.hpp"
#include <boost/python.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <type_traits>
#ifdef EIGENPY_WITH_CXX17_SUPPORT
#include <variant>
#endif
namespace eigenpy {
namespace details {
/// Allow to use std::variant and boost::variant with the same API
template <typename ResultType, typename Variant>
struct VariantVisitorType {};
/// Allow to get all alternatives in a boost::mpl vector
template <typename Variant>
struct VariantAlternatives {};
template <typename Variant>
struct empty_variant {};
template <typename T>
struct is_empty_variant : std::false_type {};
#ifdef EIGENPY_WITH_CXX17_SUPPORT
/// std::variant implementation
template <typename ResultType, typename... Alternatives>
struct VariantVisitorType<ResultType, std::variant<Alternatives...> > {
typedef std::variant<Alternatives...> variant_type;
typedef ResultType result_type;
template <typename Visitor, typename Visitable>
static result_type visit(Visitor&& visitor, Visitable&& v) {
return std::visit(std::forward<Visitor>(visitor),
std::forward<Visitable>(v));
}
result_type operator()(std::monostate) const {
return bp::incref(bp::object().ptr()); // None
}
};
template <typename... Alternatives>
struct VariantAlternatives<std::variant<Alternatives...> > {
typedef boost::mpl::vector<Alternatives...> types;
};
template <typename... Alternatives>
struct empty_variant<std::variant<Alternatives...> > {
typedef std::monostate type;
};
template <>
struct is_empty_variant<std::monostate> : std::true_type {};
#endif
/// boost::variant implementation
template <typename ResultType, typename... Alternatives>
struct VariantVisitorType<ResultType, boost::variant<Alternatives...> >
: boost::static_visitor<ResultType> {
typedef boost::variant<Alternatives...> variant_type;
typedef ResultType result_type;
template <typename Visitor, typename Visitable>
static result_type visit(Visitor&& visitor, Visitable&& visitable) {
return std::forward<Visitable>(visitable).apply_visitor(visitor);
}
result_type operator()(boost::blank) const {
return bp::incref(bp::object().ptr()); // None
}
};
template <typename... Alternatives>
struct VariantAlternatives<boost::variant<Alternatives...> > {
typedef typename boost::variant<Alternatives...>::types types;
};
template <typename... Alternatives>
struct empty_variant<boost::variant<Alternatives...> > {
typedef boost::blank type;
};
template <>
struct is_empty_variant<boost::blank> : std::true_type {};
/// Convert None to a {boost,std}::variant with boost::blank or std::monostate
/// value
template <typename Variant>
struct EmptyConvertible {
static void registration() {
bp::converter::registry::push_back(convertible, construct,
bp::type_id<Variant>());
}
// convertible only for None
static void* convertible(PyObject* obj) {
return (obj == Py_None) ? obj : nullptr;
};
// construct in place
static void construct(PyObject*,
bp::converter::rvalue_from_python_stage1_data* data) {
void* storage =
reinterpret_cast<bp::converter::rvalue_from_python_storage<Variant>*>(
data)
->storage.bytes;
new (storage) Variant(typename empty_variant<Variant>::type());
data->convertible = storage;
};
};
/// Implement convertible and expected_pytype for bool, integer and float
template <typename T, class Enable = void>
struct NumericConvertibleImpl {};
template <typename T>
struct NumericConvertibleImpl<
T, typename std::enable_if<std::is_same<T, bool>::value>::type> {
static void* convertible(PyObject* obj) {
return PyBool_Check(obj) ? obj : nullptr;
}
static PyTypeObject const* expected_pytype() { return &PyBool_Type; }
};
template <typename T>
struct NumericConvertibleImpl<
T, typename std::enable_if<!std::is_same<T, bool>::value &&
std::is_integral<T>::value>::type> {
static void* convertible(PyObject* obj) {
// PyLong return true for bool type
return (PyInt_Check(obj) && !PyBool_Check(obj)) ? obj : nullptr;
}
static PyTypeObject const* expected_pytype() { return &PyLong_Type; }
};
template <typename T>
struct NumericConvertibleImpl<
T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
static void* convertible(PyObject* obj) {
return PyFloat_Check(obj) ? obj : nullptr;
}
static PyTypeObject const* expected_pytype() { return &PyFloat_Type; }
};
/// Convert numeric type to Variant without ambiguity
template <typename T, typename Variant>
struct NumericConvertible {
static void registration() {
bp::converter::registry::push_back(
&convertible, &bp::converter::implicit<T, Variant>::construct,
bp::type_id<Variant>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
,
&expected_pytype
#endif
);
}
static void* convertible(PyObject* obj) {
return NumericConvertibleImpl<T>::convertible(obj);
}
static PyTypeObject const* expected_pytype() {
return NumericConvertibleImpl<T>::expected_pytype();
}
};
/// Convert {boost,std}::variant<class...> alternative to a Python object.
/// This converter copy the alternative.
template <typename Variant>
struct VariantValueToObject : VariantVisitorType<PyObject*, Variant> {
typedef VariantVisitorType<PyObject*, Variant> Base;
typedef typename Base::result_type result_type;
typedef typename Base::variant_type variant_type;
static result_type convert(const variant_type& v) {
return Base::visit(VariantValueToObject(), v);
}
template <typename T>
result_type operator()(T& t) const {
return bp::incref(bp::object(t).ptr());
}
using Base::operator();
};
/// Convert {boost,std}::variant<class...> alternative reference to a Python
/// object. This converter return the alternative reference. The code that
/// create the reference holder is taken from \see
/// bp::to_python_indirect.
template <typename Variant>
struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
typedef VariantVisitorType<PyObject*, Variant> Base;
typedef typename Base::result_type result_type;
typedef typename Base::variant_type variant_type;
static result_type convert(const variant_type& v) {
return Base::visit(VariantRefToObject(), v);
}
template <typename T,
typename std::enable_if<is_python_primitive_type<T>::value,
bool>::type = true>
result_type operator()(T t) const {
return bp::incref(bp::object(t).ptr());
}
template <typename T,
typename std::enable_if<!is_python_primitive_type<T>::value,
bool>::type = true>
result_type operator()(T& t) const {
return bp::detail::make_reference_holder::execute(&t);
}
/// Copy the object when it's None
using Base::operator();
};
/// Converter used in \see ReturnInternalVariant.
/// This is inspired by \see bp::reference_existing_object.
/// It will call \see VariantRefToObject to extract the alternative
/// reference.
template <typename Variant>
struct VariantConverter {
typedef Variant variant_type;
template <class T>
struct apply {
struct type {
PyObject* operator()(const variant_type& v) const {
return VariantRefToObject<variant_type>::convert(v);
}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
PyTypeObject const* get_pytype() const {
return bp::converter::registered_pytype<variant_type>::get_pytype();
}
#endif
};
};
};
/// Convert an Alternative type to a Variant
template <typename Variant>
struct VariantConvertible {
typedef Variant variant_type;
template <class T, typename std::enable_if<is_empty_variant<T>::value,
bool>::type = true>
void operator()(T) {
EmptyConvertible<variant_type>::registration();
}
template <class T, typename std::enable_if<!is_empty_variant<T>::value &&
std::is_arithmetic<T>::value,
bool>::type = true>
void operator()(T) {
NumericConvertible<T, variant_type>::registration();
}
template <class T, typename std::enable_if<!is_empty_variant<T>::value &&
!std::is_arithmetic<T>::value,
bool>::type = true>
void operator()(T) {
bp::implicitly_convertible<T, variant_type>();
}
};
} // namespace details
/// Variant of \see bp::return_internal_reference that
/// extract {boost,std}::variant<class...> alternative reference before
/// converting it into a PyObject
template <typename Variant>
struct ReturnInternalVariant : bp::return_internal_reference<> {
typedef Variant variant_type;
typedef details::VariantConverter<variant_type> result_converter;
template <class ArgumentPackage>
static PyObject* postcall(ArgumentPackage const& args_, PyObject* result) {
// Don't run return_internal_reference postcall on primitive type
if (PyInt_Check(result) || PyBool_Check(result) || PyFloat_Check(result) ||
PyStr_Check(result) || PyComplex_Check(result)) {
return result;
}
return bp::return_internal_reference<>::postcall(args_, result);
}
};
/// Define a defaults converter to convert a {boost,std}::variant alternative to
/// a Python object by copy and to convert implicitly an alternative to a
/// {boost,std}::variant.
///
/// Example:
///
/// typedef boost::variant<Struct1, Struct2> MyVariant;
/// struct VariantHolder {
/// MyVariant variant;
/// };
/// ...
/// void expose() {
/// bp::class_<Struct1>("Struct1", bp::init<>());
/// bp::class_<Struct2>("Struct1", bp::init<>())
/// typedef eigenpy::VariantConverter<MyVariant> Converter;
/// Converter::registration();
///
/// bp::class_<VariantHolder>("VariantHolder", bp::init<>())
/// .add_property("variant",
/// bp::make_getter(&VariantHolder::variant,
/// Converter::return_internal_reference()),
/// bp::make_setter(&VariantHolder::variant));
/// }
template <typename Variant>
struct VariantConverter {
typedef Variant variant_type;
typedef ReturnInternalVariant<variant_type> return_internal_reference;
static void registration() {
typedef details::VariantValueToObject<variant_type> variant_to_value;
typedef typename details::VariantAlternatives<variant_type>::types types;
bp::to_python_converter<variant_type, variant_to_value>();
boost::mpl::for_each<types>(details::VariantConvertible<variant_type>());
}
};
} // namespace eigenpy
#endif // ifndef __eigenpy_utils_variant_hpp__
//
// Copyright (c) 2019-2020 INRIA
//
#ifndef __eigenpy_version_hpp__
#define __eigenpy_version_hpp__
#include <string>
#include "eigenpy/config.hpp"
namespace eigenpy {
///
/// \brief Returns the current version of EigenPy as a string using
/// the following standard:
/// EIGENPY_MINOR_VERSION.EIGENPY_MINOR_VERSION.EIGENPY_PATCH_VERSION
///
std::string EIGENPY_DLLAPI printVersion(const std::string& delimiter = ".");
///
/// \brief Returns the current version of Eigen3 as a string using
/// the following standard:
/// EIGEN_MINOR_VERSION.EIGEN_MINOR_VERSION.EIGEN_PATCH_VERSION
///
std::string EIGENPY_DLLAPI
printEigenVersion(const std::string& delimiter = ".");
///
/// \brief Checks if the current version of EigenPy is at least the version
/// provided
/// by the input arguments.
///
/// \param[in] major_version Major version to check.
/// \param[in] minor_version Minor version to check.
/// \param[in] patch_version Patch version to check.
///
/// \returns true if the current version of EigenPy is greater than the version
/// provided
/// by the input arguments.
///
bool EIGENPY_DLLAPI checkVersionAtLeast(unsigned int major_version,
unsigned int minor_version,
unsigned int patch_version);
} // namespace eigenpy
#endif // __eigenpy_version_hpp__
<?xml version="1.0"?>
<package format="2">
<package format="3">
<name>eigenpy</name>
<version>1.6.2</version>
<version>3.10.3</version>
<description>Bindings between Numpy and Eigen using Boost.Python</description>
<maintainer email="justin.carpentier@inria.fr">Justin Carpentier</maintainer>
<maintainer email="wolfgang.merkt@ed.ac.uk">Wolfgang Merkt</maintainer>
<maintainer email="opensource@wolfgangmerkt.com">Wolfgang Merkt</maintainer>
<author>Justin Carpentier</author>
<author>Nicolas Mansard</author>
<license>BSD</license>
......@@ -13,8 +13,16 @@
<build_depend>git</build_depend>
<build_depend>doxygen</build_depend>
<depend>python</depend>
<depend>python-numpy</depend>
<!-- The following tag is recommended by REP-136 -->
<exec_depend condition="$ROS_VERSION == 1">catkin</exec_depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3</depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python-numpy</depend>
<depend condition="$ROS_PYTHON_VERSION == 2">python-scipy</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3-numpy</depend>
<depend condition="$ROS_PYTHON_VERSION == 3">python3-scipy</depend>
<depend>eigen</depend>
<depend>boost</depend>
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
[project]
name = "eigenpy"
version = "3.10.3"
description = "Bindings between Numpy and Eigen using Boost.Python"
platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"]
channels = ["conda-forge"]
license = "BSD-2-Clause"
license-file = "LICENSE"
[build-dependencies]
ccache = ">=4.9.1"
cmake = ">=3.10"
cxx-compiler = ">=1.7.0"
ninja = ">=1.11"
pkg-config = ">=0.29.2"
git = ">=2.47.0"
[dependencies]
libboost-devel = ">=1.80.0"
libboost-python-devel = ">=1.80.0"
eigen = ">=3.4.0"
numpy = ">=1.22.0"
python = ">=3.9.0"
scipy = ">=1.10.0"
[activation]
scripts = ["development/scripts//pixi/activation.sh"]
[target.win-64.activation]
scripts = ["development/scripts//pixi/activation.bat"]
[tasks]
# We must avoid to set CMAKE_CXX_FLAGS because of WIN32
# https://discourse.cmake.org/t/strictly-appending-to-cmake-lang-flags/6478
configure = { cmd = [
"CXXFLAGS=$EIGENPY_CXX_FLAGS",
"cmake",
"-G",
"Ninja",
"-B",
"build",
"-S",
".",
"-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX",
"-DCMAKE_BUILD_TYPE=$EIGENPY_BUILD_TYPE",
"-DGENERATE_PYTHON_STUBS=$EIGENPY_PYTHON_STUBS",
"-DBUILD_WITH_CHOLMOD_SUPPORT=$EIGENPY_CHOLMOD_SUPPORT",
"-DBUILD_WITH_ACCELERATE_SUPPORT=$EIGENPY_ACCELERATE_SUPPORT",
] }
build = { cmd = "cmake --build build --target all", depends-on = ["configure"] }
clean = { cmd = "rm -rf build" }
test = { cmd = "ctest --test-dir build --output-on-failure", depends-on = [
"build",
] }
[feature.lint]
dependencies = { pre-commit = ">=3.6.2" }
tasks = { lint = { cmd = "pre-commit run --all" } }
# Increment the version number with EIGENPY_VERSION variable
[feature.new-version.dependencies]
tomlkit = ">=0.13.2"
[feature.new-version.tasks]
configure_new_version = { cmd = [
"CXXFLAGS=$EIGENPY_CXX_FLAGS",
"cmake",
"-G",
"Ninja",
"-B",
"build_new_version",
"-S",
".",
"-DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX",
"-DCMAKE_BUILD_TYPE=$EIGENPY_BUILD_TYPE",
"-DGENERATE_PYTHON_STUBS=ON",
"-DBUILD_WITH_CHOLMOD_SUPPORT=ON",
"-DBUILD_WITH_ACCELERATE_SUPPORT=OFF",
] }
release_new_version = { cmd = "VERSION=$EIGENPY_VERSION cmake --build build_new_version --target release", depends-on = [
"configure_new_version",
] }
# Cholmod support
[feature.cholmod]
dependencies = { suitesparse = ">=5" }
activation = { env = { EIGENPY_CHOLMOD_SUPPORT = "ON" } }
# Accelerate only work on Apple ARM platform
[feature.accelerate]
[feature.accelerate.target.osx-arm64]
activation = { env = { EIGENPY_ACCELERATE_SUPPORT = "ON" } }
[feature.py312.dependencies]
python = "3.12.*"
[feature.py39.dependencies]
python = "3.9.*"
# Use clang-cl on Windows.
# We must use scripts instead of env to setup CC and CXX
# to avoid cxx-compiler to overwrite them.
[feature.clang-cl]
platforms = ["win-64"]
activation = { scripts = ["development/scripts//pixi/activation_clang_cl.bat"] }
# Use clang on GNU/Linux.
# We must use scripts instead of env to setup CC and CXX
# to avoid cxx-compiler to overwrite them.
[feature.clang]
platforms = ["linux-64"]
activation = { scripts = ["development/scripts//pixi/activation_clang.sh"] }
dependencies = { clangxx = "*" }
[environments]
default = { features = ["py312"], solve-group = "py312" }
clang = { features = ["clang", "py312"] }
lint = { features = ["lint"], solve-group = "py312" }
cholmod = { features = ["cholmod", "py312"], solve-group = "py312" }
accelerate = { features = ["accelerate", "py312"], solve-group = "py312" }
py39 = { features = ["py39"], solve-group = "py39" }
# Accelerate will only work in Eigen next release
all = { features = ["cholmod", "py312"], solve-group = "py312" }
all-py39 = { features = ["cholmod", "py39"], solve-group = "py39" }
all-clang-cl = { features = [
"cholmod",
"clang-cl",
"py312",
], solve-group = "py312" }
# Release a new software version
new-version = { features = [
"new-version",
"cholmod",
"py312",
], solve-group = "py312" }
[tool.ruff]
extend-exclude = ["cmake"]
[tool.ruff.lint]
extend-select = ["I", "NPY", "RUF", "UP", "W"]
[tool.ruff.lint.isort]
known-first-party = ["eigenpy"]
[tool.tomlsort]
all = true
#
# Copyright (c) 2014-2019 CNRS
# Copyright (c) 2018-2019 INRIA
# Copyright (c) 2014-2023 CNRS INRIA
#
MACRO(SYMLINK_AND_INSTALL_HEADERS HEADERS SUBPATH)
FOREACH(header ${HEADERS})
GET_FILENAME_COMPONENT(headerName ${header} NAME)
GET_FILENAME_COMPONENT(headerPath ${header} PATH)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK}
${CMAKE_CURRENT_SOURCE_DIR}/${header}
${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/${SUBPATH}/${header})
# --- LIBRARY --- #
set(PYWRAP ${PROJECT_NAME}_pywrap)
set(PYWRAP
${PYWRAP}
PARENT_SCOPE)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${header}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/${SUBPATH}/${headerPath}
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE)
ENDFOREACH(header)
ENDMACRO(SYMLINK_AND_INSTALL_HEADERS HEADERS SUBPATH)
make_directory("${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}")
include(${JRL_CMAKE_MODULES}/python-helpers.cmake)
include("${JRL_CMAKE_MODULES}/stubs.cmake")
# --- LIBRARY --- #
SET(PYWRAP ${PROJECT_NAME}_pywrap)
SET(PYWRAP ${PYWRAP} PARENT_SCOPE)
add_custom_target(${PROJECT_NAME}_python)
set_target_properties(${PROJECT_NAME}_python
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True)
MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}")
add_library(${PYWRAP} MODULE main.cpp)
add_dependencies(${PROJECT_NAME}_python ${PYWRAP})
target_link_libraries(${PYWRAP} PUBLIC ${PROJECT_NAME})
ADD_LIBRARY(${PYWRAP} SHARED main.cpp)
TARGET_LINK_LIBRARIES(${PYWRAP} ${PROJECT_NAME})
TARGET_LINK_BOOST_PYTHON(${PYWRAP})
#IF(BUILD_WITH_COMMIT_VERSION)
# TAG_LIBRARY_VERSION(${PYWRAP})
#ENDIF(BUILD_WITH_COMMIT_VERSION)
SET(${PYWRAP}_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB})
python_build_get_target(python_build_target)
add_dependencies(${PYWRAP} ${python_build_target})
SET_PROPERTY(TARGET ${PYWRAP} PROPERTY LINKER_LANGUAGE CXX)
IF(APPLE)
# We need to change the extension for python bindings
SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES SUFFIX ".so")
ELSEIF(WIN32)
SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES SUFFIX ".pyd")
ENDIF(APPLE)
# BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS spews conversion warnings from int to
# long unsigned int. Unfortunately, using literals does not work in a macro. As
# such, this turns them off for the entire wrapper:
if(NOT WIN32)
target_compile_options(${PYWRAP} PRIVATE "-Wno-conversion")
endif()
if(IS_ABSOLUTE ${PYTHON_SITELIB})
set(ABSOLUTE_PYTHON_SITELIB ${PYTHON_SITELIB})
else()
set(ABSOLUTE_PYTHON_SITELIB ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB})
endif()
set(${PYWRAP}_INSTALL_DIR ${ABSOLUTE_PYTHON_SITELIB}/${PROJECT_NAME})
SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}")
set_target_properties(
${PYWRAP}
PROPERTIES PREFIX ""
SUFFIX ${PYTHON_EXT_SUFFIX}
LIBRARY_OUTPUT_DIRECTORY
"${PROJECT_BINARY_DIR}/python/${PROJECT_NAME}"
LIBRARY_OUTPUT_DIRECTORY_<CONFIG>
"${PROJECT_BINARY_DIR}/python/${PROJECT_NAME}"
RUNTIME_OUTPUT_DIRECTORY
"${PROJECT_BINARY_DIR}/python/${PROJECT_NAME}"
RUNTIME_OUTPUT_DIRECTORY_<CONFIG>
"${PROJECT_BINARY_DIR}/python/${PROJECT_NAME}")
SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
if(UNIX)
get_relative_rpath(${${PYWRAP}_INSTALL_DIR} ${PYWRAP}_INSTALL_RPATH)
set_target_properties(${PYWRAP} PROPERTIES INSTALL_RPATH
"${${PYWRAP}_INSTALL_RPATH}")
endif()
INSTALL(TARGETS ${PYWRAP} DESTINATION ${${PYWRAP}_INSTALL_DIR})
install(TARGETS ${PYWRAP} DESTINATION ${${PYWRAP}_INSTALL_DIR})
## --- INSTALL SCRIPTS
#SET(PYTHON_FILES
# __init__.py
# )
#
#FOREACH(python ${PYTHON_FILES})
# GET_FILENAME_COMPONENT(pythonFile ${python} NAME)
# EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK}
# ${${PROJECT_NAME}_SOURCE_DIR}/python/scripts/${python}
# ${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile})
#
# # Generate pyc file
# EXECUTE_PROCESS(COMMAND
# ${PYTHON_EXECUTABLE} -m py_compile
# ${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile})
# # Tag pyc file as generated.
# SET_SOURCE_FILES_PROPERTIES(
# "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c"
# PROPERTIES GENERATED TRUE)
#
# # Clean generated files.
# SET_PROPERTY(
# DIRECTORY APPEND PROPERTY
# ADDITIONAL_MAKE_CLEAN_FILES
# "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c")
#
# INSTALL(FILES
# "${${PROJECT_NAME}_SOURCE_DIR}/python/scripts/${python}"
# "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c"
# DESTINATION ${${PYWRAP}_INSTALL_DIR})
#ENDFOREACH(python)
# --- GENERATE STUBS
if(GENERATE_PYTHON_STUBS)
load_stubgen()
# Set PYWRAP and PROJECT_NAME as stubs dependencies PROJECT_NAME is mandatory
# (even if it's a PYWRAP dependency) to find PROJECT_NAME name DLL on windows
generate_stubs(${CMAKE_CURRENT_BINARY_DIR} ${PROJECT_NAME}
${ABSOLUTE_PYTHON_SITELIB} ${PYWRAP} ${PROJECT_NAME})
endif(GENERATE_PYTHON_STUBS)
# --- INSTALL SCRIPTS
set(PYTHON_FILES __init__.py windows_dll_manager.py)
foreach(python ${PYTHON_FILES})
python_build(${PROJECT_NAME} ${python})
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/eigenpy/${python}"
DESTINATION ${${PYWRAP}_INSTALL_DIR})
endforeach(python)
#
# Copyright (c) 2017-2021 CNRS INRIA
#
# On Windows, if eigenpy.dll is not in the same directory than
# the .pyd, it will not be loaded.
# We first try to load eigenpy, then, if it fail and we are on Windows:
# 1. We add all paths inside eigenpy_WINDOWS_DLL_PATH to DllDirectory
# 2. If EIGENPY_WINDOWS_DLL_PATH we add the relative path from the
# package directory to the bin directory to DllDirectory
# This solution is inspired from:
# - https://github.com/PixarAnimationStudios/OpenUSD/pull/1511/files
# - https://stackoverflow.com/questions/65334494/python-c-extension-packaging-dll-along-with-pyd
# More resources on https://github.com/diffpy/pyobjcryst/issues/33
try:
from .eigenpy_pywrap import * # noqa
from .eigenpy_pywrap import __raw_version__, __version__
except ImportError:
import platform
if platform.system() == "Windows":
from .windows_dll_manager import build_directory_manager, get_dll_paths
with build_directory_manager() as dll_dir_manager:
for p in get_dll_paths():
dll_dir_manager.add_dll_directory(p)
from .eigenpy_pywrap import * # noqa
from .eigenpy_pywrap import __raw_version__, __version__ # noqa
else:
raise
import contextlib
import os
def get_dll_paths():
eigenpy_paths = os.getenv("EIGENPY_WINDOWS_DLL_PATH")
if eigenpy_paths is None:
# From https://peps.python.org/pep-0250/#implementation
# lib/python-version/site-packages/package
RELATIVE_DLL_PATH1 = "..\\..\\..\\..\\bin"
# lib/site-packages/package
RELATIVE_DLL_PATH2 = "..\\..\\..\\bin"
# For unit test
RELATIVE_DLL_PATH3 = "..\\..\\bin"
return [
os.path.join(os.path.dirname(__file__), RELATIVE_DLL_PATH1),
os.path.join(os.path.dirname(__file__), RELATIVE_DLL_PATH2),
os.path.join(os.path.dirname(__file__), RELATIVE_DLL_PATH3),
]
else:
return eigenpy_paths.split(os.pathsep)
class DllDirectoryManager(contextlib.AbstractContextManager):
"""Restore DllDirectory state after importing Python module"""
def add_dll_directory(self, dll_dir: str):
# add_dll_directory can fail on relative path and non
# existing path.
# Since we don't know all the fail criterion we just ignore
# thrown exception
try:
self.dll_dirs.append(os.add_dll_directory(dll_dir))
except OSError:
pass
def __enter__(self):
self.dll_dirs = []
return self
def __exit__(self, *exc_details):
for d in self.dll_dirs:
d.close()
def build_directory_manager():
return DllDirectoryManager()
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2018-2024, INRIA
*/
#include <boost/python/scope.hpp>
#include "eigenpy/computation-info.hpp"
#include "eigenpy/decompositions/decompositions.hpp"
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/geometry.hpp"
#include "eigenpy/solvers/solvers.hpp"
#include "eigenpy/solvers/preconditioners.hpp"
#include <iostream>
#include <boost/python/scope.hpp>
#include "eigenpy/solvers/solvers.hpp"
#include "eigenpy/std-vector.hpp"
#include "eigenpy/utils/is-approx.hpp"
#include "eigenpy/version.hpp"
using namespace eigenpy;
BOOST_PYTHON_MODULE(eigenpy)
{
template <typename Scalar>
void exposeIsApprox() {
enum { Options = 0 };
EIGENPY_MAKE_TYPEDEFS(Scalar, Options, s, Eigen::Dynamic, X);
EIGENPY_UNUSED_TYPE(VectorXs);
EIGENPY_UNUSED_TYPE(RowVectorXs);
// typedef Eigen::SparseMatrix<Scalar, Options> SparseMatrixXs;
typedef typename MatrixXs::RealScalar RealScalar;
using namespace Eigen;
const RealScalar dummy_precision =
Eigen::NumTraits<RealScalar>::dummy_precision();
bp::def("is_approx",
(bool (*)(const Eigen::MatrixBase<MatrixXs> &,
const Eigen::MatrixBase<MatrixXs> &,
const RealScalar &))&is_approx,
(bp::arg("A"), bp::arg("B"), bp::arg("prec") = dummy_precision),
"Returns True if A is approximately equal to B, within the "
"precision determined by prec.");
// bp::def("is_approx",
// (bool (*)(const Eigen::SparseMatrixBase<SparseMatrixXs> &,
// const Eigen::SparseMatrixBase<SparseMatrixXs> &,
// const RealScalar &)) &
// is_approx,
// (bp::arg("A"), bp::arg("B"), bp::arg("prec") = dummy_precision),
// "Returns True if A is approximately equal to B, within the "
// "precision determined by prec.");
}
BOOST_PYTHON_MODULE(eigenpy_pywrap) {
enableEigenPy();
bp::scope().attr("__version__") = eigenpy::printVersion();
bp::scope().attr("__eigen_version__") = eigenpy::printEigenVersion();
bp::scope().attr("__raw_version__") = bp::str(EIGENPY_VERSION);
bp::def("checkVersionAtLeast", &eigenpy::checkVersionAtLeast,
bp::args("major_version", "minor_version", "patch_version"),
"Checks if the current version of EigenPy is at least the version "
"provided by the input arguments.");
bp::def("SimdInstructionSetsInUse", &Eigen::SimdInstructionSetsInUse,
"Get the set of SIMD instructions in use with Eigen.");
exposeAngleAxis();
exposeQuaternion();
exposeGeometryConversion();
exposeStdVector();
exposeComputationInfo();
{
boost::python::scope solvers = boost::python::class_<SolversScope>("solvers");
bp::scope solvers = boost::python::class_<SolversScope>("solvers");
exposeSolvers();
exposePreconditioners();
register_symbolic_link_to_registered_type<Eigen::ComputationInfo>();
}
exposeIsApprox<double>();
exposeIsApprox<std::complex<double> >();
exposeDecompositions();
}
#
# Copyright (c) 2017 CNRS
#
# This file is part of eigenpy
# eigenpy is free software: you can redistribute it
# and/or modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either version
# 3 of the License, or (at your option) any later version.
# Pinocchio is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Lesser Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with
# eigenpy If not, see
# <http://www.gnu.org/licenses/>.
import numpy as np
from eigenpy import *
[flake8]
extend-ignore = E203
max-line-length = 88
exclude = cmake/.docs/cmake.py
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2019, INRIA
* Copyright 2018-2023, INRIA
*/
#include "eigenpy/memory.hpp"
#include "eigenpy/geometry.hpp"
#include "eigenpy/angle-axis.hpp"
#include "eigenpy/geometry.hpp"
EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(Eigen::AngleAxisd)
namespace eigenpy
{
void exposeAngleAxis()
{
expose<Eigen::AngleAxisd>();
}
} // namespace eigenpy
namespace eigenpy {
void exposeAngleAxis() { expose<Eigen::AngleAxisd>(); }
} // namespace eigenpy