user-type.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 INRIA
3 //
4 
5 #ifndef __eigenpy_user_type_hpp__
6 #define __eigenpy_user_type_hpp__
7 
8 #include "eigenpy/fwd.hpp"
9 #include "eigenpy/numpy-type.hpp"
10 #include "eigenpy/register.hpp"
11 
12 namespace eigenpy
13 {
14  namespace internal
15  {
16  template<typename T, int type_code = NumpyEquivalentType<T>::type_code>
18  {
19  inline static void copyswap(void * /*dst*/, void * /*src*/, int /*swap*/, void * /*arr*/) /*{}*/;
20  inline static PyObject * getitem(void * /*ip*/, void * /*ap*/) /*{ return NULL; }*/;
21  inline static int setitem(PyObject * /*op*/, void * /*ov*/, void * /*ap*/) /*{ return -1; }*/;
22  inline static void copyswapn(void * /*dest*/, long /*dstride*/, void * /*src*/,
23  long /*sstride*/, long /*n*/, int /*swap*/, void * /*arr*/) /*{}*/;
24  inline static npy_bool nonzero(void * /*ip*/, void * /*array*/) /*{ return (npy_bool)false; }*/;
25  inline static void dotfunc(void * /*ip0_*/, npy_intp /*is0*/, void * /*ip1_*/, npy_intp /*is1*/,
26  void * /*op*/, npy_intp /*n*/, void * /*arr*/);
27 // static void cast(void * /*from*/, void * /*to*/, npy_intp /*n*/, void * /*fromarr*/, void * /*toarr*/) {};
28  };
29 
30  template<typename T>
31  struct SpecialMethods<T,NPY_USERDEF>
32  {
33  inline static void copyswap(void * dst, void * src, int swap, void * /*arr*/)
34  {
35 // std::cout << "copyswap" << std::endl;
36  if (src != NULL)
37  {
38  T & t1 = *static_cast<T*>(dst);
39  T & t2 = *static_cast<T*>(src);
40  t1 = t2;
41  }
42 
43  if(swap)
44  {
45  T & t1 = *static_cast<T*>(dst);
46  T & t2 = *static_cast<T*>(src);
47  std::swap(t1,t2);
48  }
49  }
50 
51  inline static PyObject * getitem(void * ip, void * ap)
52  {
53 // std::cout << "getitem" << std::endl;
54  PyArrayObject * py_array = static_cast<PyArrayObject *>(ap);
55  if((py_array==NULL) || PyArray_ISBEHAVED_RO(py_array))
56  {
57  T * elt_ptr = static_cast<T*>(ip);
58  bp::object m(boost::ref(*elt_ptr));
59  Py_INCREF(m.ptr());
60  return m.ptr();
61  }
62  else
63  {
64  T * elt_ptr = static_cast<T*>(ip);
65  bp::object m(boost::ref(*elt_ptr));
66  Py_INCREF(m.ptr());
67  return m.ptr();
68  }
69  }
70 
71  inline static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
72  {
73 // std::cout << "setitem" << std::endl;
74  if(array == NULL)
75  {
76  eigenpy::Exception("Cannot retrieve the type stored in the array.");
77  return -1;
78  }
79  PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
80  PyArray_Descr * descr = PyArray_DTYPE(py_array);
81  PyTypeObject * array_scalar_type = descr->typeobj;
82  PyTypeObject * src_obj_type = Py_TYPE(src_obj);
83 
84  if(array_scalar_type != src_obj_type)
85  {
86  return -1;
87  }
88 
89  bp::extract<T&> extract_src_obj(src_obj);
90  if(!extract_src_obj.check())
91  {
92  std::stringstream ss;
93  ss << "The input type is of wrong type. ";
94  ss << "The expected type is " << bp::type_info(typeid(T)).name() << std::endl;
95  eigenpy::Exception(ss.str());
96  return -1;
97  }
98 
99  const T & src = extract_src_obj();
100  T & dest = *static_cast<T*>(dest_ptr);
101  dest = src;
102 
103  return 0;
104  }
105 
106  inline static void copyswapn(void * dst, long dstride, void * src, long sstride,
107  long n, int swap, void * array)
108  {
109 // std::cout << "copyswapn" << std::endl;
110 
111  char *dstptr = static_cast<char*>(dst);
112  char *srcptr = static_cast<char*>(src);
113 
114  PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
115  PyArray_CopySwapFunc * copyswap = PyArray_DESCR(py_array)->f->copyswap;
116 
117  for (npy_intp i = 0; i < n; i++)
118  {
119  copyswap(dstptr, srcptr, swap, array);
120  dstptr += dstride;
121  srcptr += sstride;
122  }
123  }
124 
125  inline static npy_bool nonzero(void * ip, void * array)
126  {
127 // std::cout << "nonzero" << std::endl;
128  static const T ZeroValue = T(0);
129  PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
130  if(py_array == NULL || PyArray_ISBEHAVED_RO(py_array))
131  {
132  const T & value = *static_cast<T*>(ip);
133  return (npy_bool)(value != ZeroValue);
134  }
135  else
136  {
137  T tmp_value;
138  PyArray_DESCR(py_array)->f->copyswap(&tmp_value, ip, PyArray_ISBYTESWAPPED(py_array),
139  array);
140  return (npy_bool)(tmp_value != ZeroValue);
141  }
142  }
143 
144  inline static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
145  void * op, npy_intp n, void * /*arr*/)
146  {
147  T res = T(0);
148  char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_;
149  npy_intp i;
150  for(i = 0; i < n; i++)
151  {
152 
153  res += *static_cast<T*>(static_cast<void*>(ip0))
154  * *static_cast<T*>(static_cast<void*>(ip1));
155  ip0 += is0;
156  ip1 += is1;
157  }
158  *static_cast<T*>(op) = res;
159  }
160 
161 // static void cast(void * from, void * to, npy_intp n, void * fromarr, void * toarr)
162 // {
163 // }
164 
165  };
166 
167  } // namespace internal
168 
169  template<typename Scalar>
170  int registerNewType(PyTypeObject * py_type_ptr = NULL)
171  {
172  // Check whether the type is a Numpy native type.
173  // In this case, the registration is not required.
174  if(isNumpyNativeType<Scalar>())
176 
177  // Retrieve the registered type for the current Scalar
178  if(py_type_ptr == NULL)
179  { // retrive the type from Boost.Python
180  py_type_ptr = Register::getPyType<Scalar>();
181  }
182 
183  if(Register::isRegistered(py_type_ptr))
184  return Register::getTypeCode(py_type_ptr); // the type is already registered
185 
186  PyArray_GetItemFunc * getitem = &internal::SpecialMethods<Scalar>::getitem;
187  PyArray_SetItemFunc * setitem = &internal::SpecialMethods<Scalar>::setitem;
188  PyArray_NonzeroFunc * nonzero = &internal::SpecialMethods<Scalar>::nonzero;
189  PyArray_CopySwapFunc * copyswap = &internal::SpecialMethods<Scalar>::copyswap;
190  PyArray_CopySwapNFunc * copyswapn = reinterpret_cast<PyArray_CopySwapNFunc*>(&internal::SpecialMethods<Scalar>::copyswapn);
192 // PyArray_CastFunc * cast = &internal::SpecialMethods<Scalar>::cast;
193 
194  int code = Register::registerNewType(py_type_ptr,
195  &typeid(Scalar),
196  sizeof(Scalar),
197  getitem, setitem, nonzero,
198  copyswap, copyswapn,
199  dotfunc);
200 
202  code, NPY_NOSCALAR);
203 
204  return code;
205  }
206 
207 } // namespace eigenpy
208 
209 #endif // __eigenpy_user_type_hpp__
#define call_PyArray_DescrFromType(typenum)
Definition: numpy.hpp:65
static npy_bool nonzero(void *ip, void *array)
Definition: user-type.hpp:125
static PyObject * getitem(void *ip, void *ap)
Definition: user-type.hpp:51
static int setitem(PyObject *, void *, void *)
static npy_bool nonzero(void *, void *)
static int setitem(PyObject *src_obj, void *dest_ptr, void *array)
Definition: user-type.hpp:71
static int getTypeCode()
Definition: register.hpp:59
bn::ndarray array()
Definition: bnpy.cpp:10
static PyObject * getitem(void *, void *)
static void dotfunc(void *, npy_intp, void *, npy_intp, void *, npy_intp, void *)
static int registerNewType(PyTypeObject *py_type_ptr, const std::type_info *type_info_ptr, const int type_size, PyArray_GetItemFunc *getitem, PyArray_SetItemFunc *setitem, PyArray_NonzeroFunc *nonzero, PyArray_CopySwapFunc *copyswap, PyArray_CopySwapNFunc *copyswapn, PyArray_DotFunc *dotfunc)
Definition: register.cpp:36
static void dotfunc(void *ip0_, npy_intp is0, void *ip1_, npy_intp is1, void *op, npy_intp n, void *)
Definition: user-type.hpp:144
static void copyswapn(void *, long, void *, long, long, int, void *)
static void copyswap(void *, void *, int, void *)
static bool isRegistered()
Definition: register.hpp:27
#define call_PyArray_RegisterCanCast(descr, totype, scalar)
Definition: numpy.hpp:69
static void copyswap(void *dst, void *src, int swap, void *)
Definition: user-type.hpp:33
int registerNewType(PyTypeObject *py_type_ptr=NULL)
Definition: user-type.hpp:170
static void copyswapn(void *dst, long dstride, void *src, long sstride, long n, int swap, void *array)
Definition: user-type.hpp:106


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Sat Apr 17 2021 02:37:59