eigenpy 3.12.0
Bindings between Numpy and Eigen using Boost.Python
Loading...
Searching...
No Matches
alignment.hpp
1/*
2 * Copyright 2023 INRIA
3 */
4
5#ifndef __eigenpy_alignment_hpp__
6#define __eigenpy_alignment_hpp__
7
8#include <boost/python/detail/referent_storage.hpp>
9#include <boost/python/converter/arg_from_python.hpp>
10#include <boost/python/converter/rvalue_from_python_data.hpp>
11#include <boost/type_traits/aligned_storage.hpp>
12#include <eigenpy/utils/is-aligned.hpp>
13
14namespace eigenpy {
15
16template <std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES>
18 union type {
19 typename ::boost::aligned_storage<size, alignment>::type data;
20 char bytes[size];
21 };
22};
23
24template <class Data>
26 PyObject_VAR_HEAD PyObject *dict;
27 PyObject *weakrefs;
28 boost::python::instance_holder *objects;
29
30 typename aligned_storage<sizeof(Data)>::type storage;
31};
32
33inline void *aligned_malloc(
34 std::size_t size, std::size_t alignment = EIGENPY_DEFAULT_ALIGN_BYTES) {
35 void *original = std::malloc(size + alignment);
36 if (original == 0) return 0;
37 if (is_aligned(original, alignment)) return original;
38 void *aligned =
39 reinterpret_cast<void *>((reinterpret_cast<std::size_t>(original) &
40 ~(std::size_t(alignment - 1))) +
41 alignment);
42 *(reinterpret_cast<void **>(aligned) - 1) = original;
43 return aligned;
44}
45
46} // namespace eigenpy
47
48namespace boost {
49namespace python {
50namespace detail {
51
52template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
53 int MaxCols>
54struct referent_storage<
55 Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
56 typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
57 typedef
59};
60
61template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
62 int MaxCols>
63struct referent_storage<
64 const Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &> {
65 typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> T;
66 typedef
68};
69
70#ifdef EIGENPY_WITH_TENSOR_SUPPORT
71template <typename Scalar, int Rank, int Options, typename IndexType>
72struct referent_storage<Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
73 typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
74 typedef
76};
77
78template <typename Scalar, int Rank, int Options, typename IndexType>
79struct referent_storage<
80 const Eigen::Tensor<Scalar, Rank, Options, IndexType> &> {
81 typedef Eigen::Tensor<Scalar, Rank, Options, IndexType> T;
82 typedef
84};
85#endif
86
87template <typename Scalar, int Options>
88struct referent_storage<Eigen::Quaternion<Scalar, Options> &> {
89 typedef Eigen::Quaternion<Scalar, Options> T;
90 typedef
92};
93
94template <typename Scalar, int Options>
95struct referent_storage<const Eigen::Quaternion<Scalar, Options> &> {
96 typedef Eigen::Quaternion<Scalar, Options> T;
97 typedef
99};
100
101} // namespace detail
102} // namespace python
103} // namespace boost
104
105namespace boost {
106namespace python {
107namespace objects {
108
109// Force alignment of instance with value_holder
110template <typename Derived>
111struct instance<value_holder<Derived>>
112 : ::eigenpy::aligned_instance<value_holder<Derived>> {};
113
114} // namespace objects
115} // namespace python
116} // namespace boost
117
118namespace eigenpy {
119
120template <class T>
122 static void run(void *bytes) {
123 typedef typename boost::remove_const<
124 typename boost::remove_reference<T>::type>::type T_;
125 static_cast<T_ *>((void *)bytes)->~T_();
126 }
127};
128
129template <class T>
130struct rvalue_from_python_data
131 : ::boost::python::converter::rvalue_from_python_storage<T> {
132#if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) && \
133 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) && \
134 (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) && \
135 !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing \
136 this */
137 // This must always be a POD struct with m_data its first member.
138 BOOST_STATIC_ASSERT(
139 BOOST_PYTHON_OFFSETOF(
140 ::boost::python::converter::rvalue_from_python_storage<T>, stage1) ==
141 0);
142#endif
143
144 // The usual constructor
145 rvalue_from_python_data(
146 ::boost::python::converter::rvalue_from_python_stage1_data const
147 &_stage1) {
148 this->stage1 = _stage1;
149 }
150
151 // This constructor just sets m_convertible -- used by
152 // implicitly_convertible<> to perform the final step of the
153 // conversion, where the construct() function is already known.
154 rvalue_from_python_data(void *convertible) {
155 this->stage1.convertible = convertible;
156 }
157
158 // Destroys any object constructed in the storage.
159 ~rvalue_from_python_data() {
160 if (this->stage1.convertible == this->storage.bytes) {
161 void *storage = reinterpret_cast<void *>(this->storage.bytes);
162 call_destructor<T>::run(storage);
163 }
164 }
165};
166
167} // namespace eigenpy
168
169#endif // __eigenpy_alignment_hpp__