Program Listing for File alignment.hpp
↰ Return to documentation for file (include/eigenpy/alignment.hpp
)
/*
* Copyright 2023 INRIA
*/
#ifndef __eigenpy_alignment_hpp__
#define __eigenpy_alignment_hpp__
#include <boost/python/detail/referent_storage.hpp>
#include <boost/python/converter/arg_from_python.hpp>
#include <boost/python/converter/rvalue_from_python_data.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <eigenpy/utils/is-aligned.hpp>
namespace eigenpy {
template <std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES>
struct aligned_storage {
union type {
typename ::boost::aligned_storage<size, alignment>::type data;
char bytes[size];
};
};
template <class Data>
struct aligned_instance {
PyObject_VAR_HEAD PyObject *dict;
PyObject *weakrefs;
boost::python::instance_holder *objects;
typename aligned_storage<sizeof(Data)>::type storage;
};
inline void *aligned_malloc(
std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES) {
void *original = std::malloc(size + alignment);
if (original == 0) return 0;
if (is_aligned(original, alignment)) return original;
void *aligned =
reinterpret_cast<void *>((reinterpret_cast<std::size_t>(original) &
~(std::size_t(alignment - 1))) +
alignment);
*(reinterpret_cast<void **>(aligned) - 1) = original;
return aligned;
}
} // namespace eigenpy
namespace boost {
namespace python {
namespace detail {
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
int MaxCols>
struct referent_storage<
Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
int MaxCols>
struct referent_storage<
const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
#ifdef EIGENPY_WITH_TENSOR_SUPPORT
template <typename Scalar, int Rank, int Options, typename IndexType>
struct referent_storage<Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Rank, int Options, typename IndexType>
struct referent_storage<
const Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
#endif
template <typename Scalar, int Options>
struct referent_storage<Eigen::Quaternion<Scalar, Options> &> {
typedef Eigen::Quaternion<Scalar, Options> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
template <typename Scalar, int Options>
struct referent_storage<const Eigen::Quaternion<Scalar, Options> &> {
typedef Eigen::Quaternion<Scalar, Options> T;
typedef
typename eigenpy::aligned_storage<referent_size<T &>::value>::type type;
};
} // namespace detail
} // namespace python
} // namespace boost
namespace boost {
namespace python {
namespace objects {
// Force alignment of instance with value_holder
template <typename Derived>
struct instance<value_holder<Derived> >
: ::eigenpy::aligned_instance<value_holder<Derived> > {};
} // namespace objects
} // namespace python
} // namespace boost
namespace eigenpy {
template <class T>
struct call_destructor {
static void run(void *bytes) {
typedef typename boost::remove_const<
typename boost::remove_reference<T>::type>::type T_;
static_cast<T_ *>((void *)bytes)->~T_();
}
};
template <class T>
struct rvalue_from_python_data
: ::boost::python::converter::rvalue_from_python_storage<T> {
#if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) && \
(!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) && \
(!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) && \
!defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing \
this */
// This must always be a POD struct with m_data its first member.
BOOST_STATIC_ASSERT(
BOOST_PYTHON_OFFSETOF(
::boost::python::converter::rvalue_from_python_storage<T>, stage1) ==
0);
#endif
// The usual constructor
rvalue_from_python_data(
::boost::python::converter::rvalue_from_python_stage1_data const
&_stage1) {
this->stage1 = _stage1;
}
// This constructor just sets m_convertible -- used by
// implicitly_convertible<> to perform the final step of the
// conversion, where the construct() function is already known.
rvalue_from_python_data(void *convertible) {
this->stage1.convertible = convertible;
}
// Destroys any object constructed in the storage.
~rvalue_from_python_data() {
if (this->stage1.convertible == this->storage.bytes) {
void *storage = reinterpret_cast<void *>(this->storage.bytes);
call_destructor<T>::run(storage);
}
}
};
} // namespace eigenpy
#endif // __eigenpy_alignment_hpp__