7 #ifndef __eigenpy_ufunc_hpp__
8 #define __eigenpy_ufunc_hpp__
17 #ifdef NPY_1_19_API_VERSION
18 #define EIGENPY_NPY_CONST_UFUNC_ARG const
20 #define EIGENPY_NPY_CONST_UFUNC_ARG
25 npy_intp
const *steps) {
32 npy_intp dm = dimensions[0];
33 npy_intp dn = dimensions[1];
34 npy_intp dp = dimensions[2];
37 npy_intp is1_m = steps[0];
38 npy_intp is1_n = steps[1];
39 npy_intp is2_n = steps[2];
40 npy_intp is2_p = steps[3];
41 npy_intp os_m = steps[4];
42 npy_intp os_p = steps[5];
48 for (
m = 0;
m < dm;
m++) {
49 for (p = 0; p < dp; p++) {
71 void *NPY_UNUSED(func)) {
76 npy_intp dN = dimensions[0];
79 npy_intp s0 = steps[0];
80 npy_intp s1 = steps[1];
81 npy_intp s2 = steps[2];
87 for (N_ = 0; N_ < dN; N_++, args[0] += s0, args[1] += s1, args[2] += s2) {
88 matrix_multiply<T>(args, dimensions + 1, steps + 3);
92 #define EIGENPY_REGISTER_BINARY_OPERATOR(name, op) \
93 template <typename T1, typename T2, typename R> \
94 void binary_op_##name( \
95 char **args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *dimensions, \
96 EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *steps, void * ) { \
97 npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions; \
98 char *i0 = args[0], *i1 = args[1], *o = args[2]; \
100 for (k = 0; k < n; k++) { \
101 T1 &x = *static_cast<T1 *>(static_cast<void *>(i0)); \
102 T2 &y = *static_cast<T2 *>(static_cast<void *>(i1)); \
103 R &res = *static_cast<R *>(static_cast<void *>(o)); \
111 template <typename T> \
112 void binary_op_##name( \
113 char **args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *dimensions, \
114 EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *steps, void *data) { \
115 binary_op_##name<T, T, T>(args, dimensions, steps, data); \
129 #define EIGENPY_REGISTER_UNARY_OPERATOR(name, op) \
130 template <typename T, typename R> \
131 void unary_op_##name( \
132 char **args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *dimensions, \
133 EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *steps, void * ) { \
134 npy_intp is = steps[0], os = steps[1], n = *dimensions; \
135 char *i = args[0], *o = args[1]; \
137 for (k = 0; k < n; k++) { \
138 T &x = *static_cast<T *>(static_cast<void *>(i)); \
139 R &res = *static_cast<R *>(static_cast<void *>(o)); \
146 template <typename T> \
147 void unary_op_##name( \
148 char **args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *dimensions, \
149 EIGENPY_NPY_CONST_UFUNC_ARG npy_intp *steps, void *data) { \
150 unary_op_##name<T, T>(args, dimensions, steps, data); \
157 #define EIGENPY_REGISTER_BINARY_UFUNC(name, code, T1, T2, R) \
159 PyUFuncObject *ufunc = \
160 (PyUFuncObject *)PyObject_GetAttrString(numpy, #name); \
161 int _types[3] = {Register::getTypeCode<T1>(), Register::getTypeCode<T2>(), \
162 Register::getTypeCode<R>()}; \
166 if (sizeof(_types) / sizeof(int) != ufunc->nargs) { \
167 PyErr_Format(PyExc_AssertionError, \
168 "ufunc %s takes %d arguments, our loop takes %lu", #name, \
170 (unsigned long)(sizeof(_types) / sizeof(int))); \
173 if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, code, \
174 internal::binary_op_##name<T1, T2, R>, \
182 #define EIGENPY_REGISTER_UNARY_UFUNC(name, code, T, R) \
184 PyUFuncObject *ufunc = \
185 (PyUFuncObject *)PyObject_GetAttrString(numpy, #name); \
186 int _types[2] = {Register::getTypeCode<T>(), Register::getTypeCode<R>()}; \
190 if (sizeof(_types) / sizeof(int) != ufunc->nargs) { \
191 PyErr_Format(PyExc_AssertionError, \
192 "ufunc %s takes %d arguments, our loop takes %lu", #name, \
194 (unsigned long)(sizeof(_types) / sizeof(int))); \
197 if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, code, \
198 internal::unary_op_##name<T, R>, _types, \
206 template <
typename Scalar>
208 const int type_code = Register::getTypeCode<Scalar>();
213 numpy = PyImport_Import(numpy_str);
214 Py_DECREF(numpy_str);
220 int types[3] = {type_code, type_code, type_code};
222 std::stringstream ss;
223 ss <<
"return result of multiplying two matrices of ";
225 PyUFuncObject *ufunc =
226 (PyUFuncObject *)PyObject_GetAttrString(numpy,
"matmul");
228 std::stringstream ss;
229 ss <<
"Impossible to define matrix_multiply for given type "
233 if (PyUFunc_RegisterLoopForType((PyUFuncObject *)ufunc, type_code,
234 &internal::gufunc_matrix_multiply<Scalar>,
236 std::stringstream ss;
237 ss <<
"Impossible to register matrix_multiply for given type "
267 #endif // __eigenpy_ufunc_hpp__